diff --git a/glide.lock b/glide.lock index 92236b574..daec23aac 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 8349c21c53c639aa79752c4e4b07e323ddb4f05be783564d7de687afbb6f2d67 -updated: 2017-04-07T10:06:47.901457262+01:00 +hash: fa4c40400ed94e105a9a1a0d163ac9c4ecea4598ad4ee4fef5237a39d4f28d0a +updated: 2017-04-07T10:50:34.091189379+01:00 imports: - name: bitbucket.org/ww/goautoneg version: 75cd24fc2f2c2a2088577d12123ddee5f54e0675 @@ -53,17 +53,16 @@ imports: - service/route53 - service/sts - name: github.com/Azure/azure-sdk-for-go - version: 1620af6b32398bfc91827ceae54a8cc1f55df04d + version: 088007b3b08cc02b27f2eadfdcd870958460ce7e subpackages: - arm/dns - name: github.com/Azure/go-autorest - version: 32cc2321122a649b7ba4e323527bcb145134fd47 + version: a2fdd780c9a50455cecd249b00bdc3eb73a78e31 subpackages: - autorest - autorest/azure - autorest/date - autorest/to - - autorest/validation - name: github.com/beorn7/perks version: b965b613227fddccbfffe13eae360ed3fa822f8d subpackages: @@ -129,6 +128,10 @@ imports: version: f6b1d56f1c048bd94d7e42ac36efb4d57b069b6f - name: github.com/dgrijalva/jwt-go version: 9ed569b5d1ac936e6494082958d63a6aa4fff99a +- name: github.com/dnsimple/dnsimple-go + version: 5a5b427618a76f9eed5ede0f3e6306fbd9311d2e + subpackages: + - dnsimple - name: github.com/docker/distribution version: 325b0804fef3a66309d962357aac3c2ce3f4d329 subpackages: @@ -415,12 +418,8 @@ imports: - plugin - plugin/rewrite - router -- name: github.com/weppos/dnsimple-go - version: 65c1ca73cb19baf0f8b2b33219b7f57595a3ccb0 - subpackages: - - dnsimple - name: github.com/xenolf/lego - version: ce8fb060cb8361a9ff8b5fb7c2347fa907b6fcac + version: 5dfe609afb1ebe9da97c9846d97a55415e5a5ccd subpackages: - acme - providers/dns diff --git a/glide.yaml b/glide.yaml index f3e3a747e..98bd95acb 100644 --- a/glide.yaml +++ b/glide.yaml @@ -60,7 +60,7 @@ import: subpackages: - plugin/rewrite - package: github.com/xenolf/lego - version: ce8fb060cb8361a9ff8b5fb7c2347fa907b6fcac + version: 5dfe609afb1ebe9da97c9846d97a55415e5a5ccd subpackages: - acme - package: gopkg.in/fsnotify.v1 diff --git a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/client.go b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/client.go old mode 100644 new mode 100755 index 4bcc2b914..05ef36995 --- a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/client.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/client.go @@ -17,7 +17,7 @@ package dns // See the License for the specific language governing permissions and // limitations under the License. // -// Code generated by Microsoft (R) AutoRest Code Generator 0.17.0.0 +// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0 // Changes may cause incorrect behavior and will be lost if the code is // regenerated. @@ -26,9 +26,6 @@ import ( ) const ( - // APIVersion is the version of the Dns - APIVersion = "2016-04-01" - // DefaultBaseURI is the default URI used for the service Dns DefaultBaseURI = "https://management.azure.com" ) @@ -37,7 +34,6 @@ const ( type ManagementClient struct { autorest.Client BaseURI string - APIVersion string SubscriptionID string } @@ -51,7 +47,6 @@ func NewWithBaseURI(baseURI string, subscriptionID string) ManagementClient { return ManagementClient{ Client: autorest.NewClientWithUserAgent(UserAgent()), BaseURI: baseURI, - APIVersion: APIVersion, SubscriptionID: subscriptionID, } } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/models.go b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/models.go old mode 100644 new mode 100755 index fb8681393..a95db4a29 --- a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/models.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/models.go @@ -14,7 +14,7 @@ package dns // See the License for the specific language governing permissions and // limitations under the License. // -// Code generated by Microsoft (R) AutoRest Code Generator 0.17.0.0 +// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0 // Changes may cause incorrect behavior and will be lost if the code is // regenerated. @@ -42,8 +42,8 @@ const ( Continue HTTPStatusCode = "Continue" // Created specifies the created state for http status code. Created HTTPStatusCode = "Created" - // ExpectationFailed specifies the expectation failed state for http - // status code. + // ExpectationFailed specifies the expectation failed state for http status + // code. ExpectationFailed HTTPStatusCode = "ExpectationFailed" // Forbidden specifies the forbidden state for http status code. Forbidden HTTPStatusCode = "Forbidden" @@ -126,13 +126,13 @@ const ( // SwitchingProtocols specifies the switching protocols state for http // status code. SwitchingProtocols HTTPStatusCode = "SwitchingProtocols" - // TemporaryRedirect specifies the temporary redirect state for http - // status code. + // TemporaryRedirect specifies the temporary redirect state for http status + // code. TemporaryRedirect HTTPStatusCode = "TemporaryRedirect" // Unauthorized specifies the unauthorized state for http status code. Unauthorized HTTPStatusCode = "Unauthorized" - // UnsupportedMediaType specifies the unsupported media type state for - // http status code. + // UnsupportedMediaType specifies the unsupported media type state for http + // status code. UnsupportedMediaType HTTPStatusCode = "UnsupportedMediaType" // Unused specifies the unused state for http status code. Unused HTTPStatusCode = "Unused" @@ -259,14 +259,14 @@ type RecordSetProperties struct { Metadata *map[string]*string `json:"metadata,omitempty"` TTL *int64 `json:"TTL,omitempty"` ARecords *[]ARecord `json:"ARecords,omitempty"` - AAAARecords *[]AaaaRecord `json:"AAAARecords,omitempty"` - MXRecords *[]MxRecord `json:"MXRecords,omitempty"` - NSRecords *[]NsRecord `json:"NSRecords,omitempty"` - PTRRecords *[]PtrRecord `json:"PTRRecords,omitempty"` - SRVRecords *[]SrvRecord `json:"SRVRecords,omitempty"` - TXTRecords *[]TxtRecord `json:"TXTRecords,omitempty"` - CNAMERecord *CnameRecord `json:"CNAMERecord,omitempty"` - SOARecord *SoaRecord `json:"SOARecord,omitempty"` + AaaaRecords *[]AaaaRecord `json:"AAAARecords,omitempty"` + MxRecords *[]MxRecord `json:"MXRecords,omitempty"` + NsRecords *[]NsRecord `json:"NSRecords,omitempty"` + PtrRecords *[]PtrRecord `json:"PTRRecords,omitempty"` + SrvRecords *[]SrvRecord `json:"SRVRecords,omitempty"` + TxtRecords *[]TxtRecord `json:"TXTRecords,omitempty"` + CnameRecord *CnameRecord `json:"CNAMERecord,omitempty"` + SoaRecord *SoaRecord `json:"SOARecord,omitempty"` } // RecordSetUpdateParameters is parameters supplied to update a record set. diff --git a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/recordsets.go b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/recordsets.go old mode 100644 new mode 100755 index 7280a4dc1..240c42660 --- a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/recordsets.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/recordsets.go @@ -14,7 +14,7 @@ package dns // See the License for the specific language governing permissions and // limitations under the License. // -// Code generated by Microsoft (R) AutoRest Code Generator 0.17.0.0 +// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0 // Changes may cause incorrect behavior and will be lost if the code is // regenerated. @@ -42,18 +42,17 @@ func NewRecordSetsClientWithBaseURI(baseURI string, subscriptionID string) Recor // CreateOrUpdate creates or updates a record set within a DNS zone. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). relativeRecordSetName is the -// name of the record set, relative to the name of the zone. recordType is -// the type of DNS record in this record set. Record sets of type SOA can be -// updated but not created (they are created when the DNS zone is created). -// Possible values include: 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', -// 'SRV', 'TXT' parameters is parameters supplied to the CreateOrUpdate -// operation. ifMatch is the etag of the record set. Omit this value to -// always overwrite the current record set. Specify the last-seen etag value -// to prevent accidentally overwritting any concurrent changes. ifNoneMatch -// is set to '*' to allow a new record set to be created, but to prevent -// updating an existing record set. Other values will be ignored. +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). relativeRecordSetName is the name +// of the record set, relative to the name of the zone. recordType is the type +// of DNS record in this record set. Record sets of type SOA can be updated but +// not created (they are created when the DNS zone is created). parameters is +// parameters supplied to the CreateOrUpdate operation. ifMatch is the etag of +// the record set. Omit this value to always overwrite the current record set. +// Specify the last-seen etag value to prevent accidentally overwritting any +// concurrent changes. ifNoneMatch is set to '*' to allow a new record set to +// be created, but to prevent updating an existing record set. Other values +// will be ignored. func (client RecordSetsClient) CreateOrUpdate(resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, parameters RecordSet, ifMatch string, ifNoneMatch string) (result RecordSet, err error) { req, err := client.CreateOrUpdatePreparer(resourceGroupName, zoneName, relativeRecordSetName, recordType, parameters, ifMatch, ifNoneMatch) if err != nil { @@ -84,8 +83,9 @@ func (client RecordSetsClient) CreateOrUpdatePreparer(resourceGroupName string, "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } preparer := autorest.CreatePreparer( @@ -128,15 +128,14 @@ func (client RecordSetsClient) CreateOrUpdateResponder(resp *http.Response) (res // Delete deletes a record set from a DNS zone. This operation cannot be // undone. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). relativeRecordSetName is the -// name of the record set, relative to the name of the zone. recordType is -// the type of DNS record in this record set. Record sets of type SOA cannot -// be deleted (they are deleted when the DNS zone is deleted). Possible -// values include: 'A', 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', -// 'TXT' ifMatch is the etag of the record set. Omit this value to always -// delete the current record set. Specify the last-seen etag value to prevent -// accidentally deleting any concurrent changes. +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). relativeRecordSetName is the name +// of the record set, relative to the name of the zone. recordType is the type +// of DNS record in this record set. Record sets of type SOA cannot be deleted +// (they are deleted when the DNS zone is deleted). ifMatch is the etag of the +// record set. Omit this value to always delete the current record set. Specify +// the last-seen etag value to prevent accidentally deleting any concurrent +// changes. func (client RecordSetsClient) Delete(resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, ifMatch string) (result autorest.Response, err error) { req, err := client.DeletePreparer(resourceGroupName, zoneName, relativeRecordSetName, recordType, ifMatch) if err != nil { @@ -167,8 +166,9 @@ func (client RecordSetsClient) DeletePreparer(resourceGroupName string, zoneName "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } preparer := autorest.CreatePreparer( @@ -203,11 +203,10 @@ func (client RecordSetsClient) DeleteResponder(resp *http.Response) (result auto // Get gets a record set. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). relativeRecordSetName is the -// name of the record set, relative to the name of the zone. recordType is -// the type of DNS record in this record set. Possible values include: 'A', -// 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). relativeRecordSetName is the name +// of the record set, relative to the name of the zone. recordType is the type +// of DNS record in this record set. func (client RecordSetsClient) Get(resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType) (result RecordSet, err error) { req, err := client.GetPreparer(resourceGroupName, zoneName, relativeRecordSetName, recordType) if err != nil { @@ -238,8 +237,9 @@ func (client RecordSetsClient) GetPreparer(resourceGroupName string, zoneName st "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } preparer := autorest.CreatePreparer( @@ -271,8 +271,8 @@ func (client RecordSetsClient) GetResponder(resp *http.Response) (result RecordS // ListByDNSZone lists all record sets in a DNS zone. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). top is the maximum number of +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). top is the maximum number of // record sets to return. If not specified, returns up to 100 record sets. func (client RecordSetsClient) ListByDNSZone(resourceGroupName string, zoneName string, top *int32) (result RecordSetListResult, err error) { req, err := client.ListByDNSZonePreparer(resourceGroupName, zoneName, top) @@ -302,8 +302,9 @@ func (client RecordSetsClient) ListByDNSZonePreparer(resourceGroupName string, z "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } if top != nil { queryParameters["$top"] = autorest.Encode("query", *top) @@ -362,11 +363,10 @@ func (client RecordSetsClient) ListByDNSZoneNextResults(lastResults RecordSetLis // ListByType lists the record sets of a specified type in a DNS zone. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). recordType is the type of -// record sets to enumerate. Possible values include: 'A', 'AAAA', 'CNAME', -// 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' top is the maximum number of record -// sets to return. If not specified, returns up to 100 record sets. +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). recordType is the type of record +// sets to enumerate. top is the maximum number of record sets to return. If +// not specified, returns up to 100 record sets. func (client RecordSetsClient) ListByType(resourceGroupName string, zoneName string, recordType RecordType, top *int32) (result RecordSetListResult, err error) { req, err := client.ListByTypePreparer(resourceGroupName, zoneName, recordType, top) if err != nil { @@ -396,8 +396,9 @@ func (client RecordSetsClient) ListByTypePreparer(resourceGroupName string, zone "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } if top != nil { queryParameters["$top"] = autorest.Encode("query", *top) @@ -456,15 +457,13 @@ func (client RecordSetsClient) ListByTypeNextResults(lastResults RecordSetListRe // Update updates a record set within a DNS zone. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). relativeRecordSetName is the -// name of the record set, relative to the name of the zone. recordType is -// the type of DNS record in this record set. Possible values include: 'A', -// 'AAAA', 'CNAME', 'MX', 'NS', 'PTR', 'SOA', 'SRV', 'TXT' parameters is -// parameters supplied to the Update operation. ifMatch is the etag of the -// record set. Omit this value to always overwrite the current record set. -// Specify the last-seen etag value to prevent accidentally overwritting -// concurrent changes. +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). relativeRecordSetName is the name +// of the record set, relative to the name of the zone. recordType is the type +// of DNS record in this record set. parameters is parameters supplied to the +// Update operation. ifMatch is the etag of the record set. Omit this value to +// always overwrite the current record set. Specify the last-seen etag value to +// prevent accidentally overwritting concurrent changes. func (client RecordSetsClient) Update(resourceGroupName string, zoneName string, relativeRecordSetName string, recordType RecordType, parameters RecordSet, ifMatch string) (result RecordSet, err error) { req, err := client.UpdatePreparer(resourceGroupName, zoneName, relativeRecordSetName, recordType, parameters, ifMatch) if err != nil { @@ -495,8 +494,9 @@ func (client RecordSetsClient) UpdatePreparer(resourceGroupName string, zoneName "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } preparer := autorest.CreatePreparer( diff --git a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/version.go b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/version.go old mode 100644 new mode 100755 index d0c89328c..530508bf7 --- a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/version.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/version.go @@ -14,30 +14,16 @@ package dns // See the License for the specific language governing permissions and // limitations under the License. // -// Code generated by Microsoft (R) AutoRest Code Generator 0.17.0.0 +// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0 // Changes may cause incorrect behavior and will be lost if the code is // regenerated. -import ( - "fmt" -) - -const ( - major = "7" - minor = "0" - patch = "1" - // Always begin a "tag" with a dash (as per http://semver.org) - tag = "-beta" - semVerFormat = "%s.%s.%s%s" - userAgentFormat = "Azure-SDK-for-Go/%s arm-%s/%s" -) - // UserAgent returns the UserAgent string to use when sending http.Requests. func UserAgent() string { - return fmt.Sprintf(userAgentFormat, Version(), "dns", "2016-04-01") + return "Azure-SDK-For-Go/v9.0.0-beta arm-dns/2016-04-01" } // Version returns the semantic version (see http://semver.org) of the client. func Version() string { - return fmt.Sprintf(semVerFormat, major, minor, patch, tag) + return "v9.0.0-beta" } diff --git a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/zones.go b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/zones.go old mode 100644 new mode 100755 index 487f29db2..e421f8d9c --- a/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/zones.go +++ b/vendor/github.com/Azure/azure-sdk-for-go/arm/dns/zones.go @@ -14,14 +14,13 @@ package dns // See the License for the specific language governing permissions and // limitations under the License. // -// Code generated by Microsoft (R) AutoRest Code Generator 0.17.0.0 +// Code generated by Microsoft (R) AutoRest Code Generator 1.0.1.0 // Changes may cause incorrect behavior and will be lost if the code is // regenerated. import ( "github.com/Azure/go-autorest/autorest" "github.com/Azure/go-autorest/autorest/azure" - "github.com/Azure/go-autorest/autorest/validation" "net/http" ) @@ -43,21 +42,14 @@ func NewZonesClientWithBaseURI(baseURI string, subscriptionID string) ZonesClien // CreateOrUpdate creates or updates a DNS zone. Does not modify DNS records // within the zone. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). parameters is parameters -// supplied to the CreateOrUpdate operation. ifMatch is the etag of the DNS -// zone. Omit this value to always overwrite the current zone. Specify the -// last-seen etag value to prevent accidentally overwritting any concurrent -// changes. ifNoneMatch is set to '*' to allow a new DNS zone to be created, -// but to prevent updating an existing zone. Other values will be ignored. +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). parameters is parameters supplied +// to the CreateOrUpdate operation. ifMatch is the etag of the DNS zone. Omit +// this value to always overwrite the current zone. Specify the last-seen etag +// value to prevent accidentally overwritting any concurrent changes. +// ifNoneMatch is set to '*' to allow a new DNS zone to be created, but to +// prevent updating an existing zone. Other values will be ignored. func (client ZonesClient) CreateOrUpdate(resourceGroupName string, zoneName string, parameters Zone, ifMatch string, ifNoneMatch string) (result Zone, err error) { - if err := validation.Validate([]validation.Validation{ - {TargetValue: parameters, - Constraints: []validation.Constraint{{Target: "parameters.ZoneProperties", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ZoneProperties.NameServers", Name: validation.ReadOnly, Rule: true, Chain: nil}}}}}}); err != nil { - return result, validation.NewErrorWithValidationError(err, "dns.ZonesClient", "CreateOrUpdate") - } - req, err := client.CreateOrUpdatePreparer(resourceGroupName, zoneName, parameters, ifMatch, ifNoneMatch) if err != nil { return result, autorest.NewErrorWithError(err, "dns.ZonesClient", "CreateOrUpdate", nil, "Failure preparing request") @@ -85,8 +77,9 @@ func (client ZonesClient) CreateOrUpdatePreparer(resourceGroupName string, zoneN "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } preparer := autorest.CreatePreparer( @@ -126,15 +119,15 @@ func (client ZonesClient) CreateOrUpdateResponder(resp *http.Response) (result Z return } -// Delete deletes a DNS zone. WARNING: All DNS records in the zone will also -// be deleted. This operation cannot be undone. This method may poll for -// completion. Polling can be canceled by passing the cancel channel -// argument. The channel will be used to cancel polling and any outstanding -// HTTP requests. +// Delete deletes a DNS zone. WARNING: All DNS records in the zone will also be +// deleted. This operation cannot be undone. This method may poll for +// completion. Polling can be canceled by passing the cancel channel argument. +// The channel will be used to cancel polling and any outstanding HTTP +// requests. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). ifMatch is the etag of the -// DNS zone. Omit this value to always delete the current zone. Specify the +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). ifMatch is the etag of the DNS +// zone. Omit this value to always delete the current zone. Specify the // last-seen etag value to prevent accidentally deleting any concurrent // changes. func (client ZonesClient) Delete(resourceGroupName string, zoneName string, ifMatch string, cancel <-chan struct{}) (result autorest.Response, err error) { @@ -165,8 +158,9 @@ func (client ZonesClient) DeletePreparer(resourceGroupName string, zoneName stri "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } preparer := autorest.CreatePreparer( @@ -204,8 +198,8 @@ func (client ZonesClient) DeleteResponder(resp *http.Response) (result autorest. // Get gets a DNS zone. Retrieves the zone properties, but not the record sets // within the zone. // -// resourceGroupName is the name of the resource group. zoneName is the name -// of the DNS zone (without a terminating dot). +// resourceGroupName is the name of the resource group. zoneName is the name of +// the DNS zone (without a terminating dot). func (client ZonesClient) Get(resourceGroupName string, zoneName string) (result Zone, err error) { req, err := client.GetPreparer(resourceGroupName, zoneName) if err != nil { @@ -234,8 +228,9 @@ func (client ZonesClient) GetPreparer(resourceGroupName string, zoneName string) "zoneName": autorest.Encode("path", zoneName), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } preparer := autorest.CreatePreparer( @@ -295,8 +290,9 @@ func (client ZonesClient) ListPreparer(top *int32) (*http.Request, error) { "subscriptionId": autorest.Encode("path", client.SubscriptionID), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } if top != nil { queryParameters["$top"] = autorest.Encode("query", *top) @@ -356,8 +352,8 @@ func (client ZonesClient) ListNextResults(lastResults ZoneListResult) (result Zo // ListByResourceGroup lists the DNS zones within a resource group. // // resourceGroupName is the name of the resource group. top is the maximum -// number of record sets to return. If not specified, returns up to 100 -// record sets. +// number of record sets to return. If not specified, returns up to 100 record +// sets. func (client ZonesClient) ListByResourceGroup(resourceGroupName string, top *int32) (result ZoneListResult, err error) { req, err := client.ListByResourceGroupPreparer(resourceGroupName, top) if err != nil { @@ -385,8 +381,9 @@ func (client ZonesClient) ListByResourceGroupPreparer(resourceGroupName string, "subscriptionId": autorest.Encode("path", client.SubscriptionID), } + const APIVersion = "2016-04-01" queryParameters := map[string]interface{}{ - "api-version": client.APIVersion, + "api-version": APIVersion, } if top != nil { queryParameters["$top"] = autorest.Encode("query", *top) diff --git a/vendor/github.com/Azure/go-autorest/autorest/autorest.go b/vendor/github.com/Azure/go-autorest/autorest/autorest.go index 9804f401e..51f1c4bbc 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/autorest.go +++ b/vendor/github.com/Azure/go-autorest/autorest/autorest.go @@ -16,6 +16,7 @@ and Responding. A typical pattern is: DoRetryForAttempts(5, time.Second)) err = Respond(resp, + ByDiscardingBody(), ByClosing()) Each phase relies on decorators to modify and / or manage processing. Decorators may first modify diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go b/vendor/github.com/Azure/go-autorest/autorest/azure/async.go index 280d32a61..6e076981f 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/async.go +++ b/vendor/github.com/Azure/go-autorest/autorest/azure/async.go @@ -3,12 +3,13 @@ package azure import ( "bytes" "fmt" - "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/date" "io/ioutil" "net/http" "strings" "time" + + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/date" ) const ( diff --git a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go index 3af1b48d2..4701b4376 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go +++ b/vendor/github.com/Azure/go-autorest/autorest/azure/environments.go @@ -35,6 +35,7 @@ type Environment struct { ServiceBusEndpointSuffix string `json:"serviceBusEndpointSuffix"` ServiceManagementVMDNSSuffix string `json:"serviceManagementVMDNSSuffix"` ResourceManagerVMDNSSuffix string `json:"resourceManagerVMDNSSuffix"` + ContainerRegistryDNSSuffix string `json:"containerRegistryDNSSuffix"` } var ( @@ -56,6 +57,7 @@ var ( ServiceBusEndpointSuffix: "servicebus.azure.com", ServiceManagementVMDNSSuffix: "cloudapp.net", ResourceManagerVMDNSSuffix: "cloudapp.azure.com", + ContainerRegistryDNSSuffix: "azurecr.io", } // USGovernmentCloud is the cloud environment for the US Government @@ -76,6 +78,7 @@ var ( ServiceBusEndpointSuffix: "servicebus.usgovcloudapi.net", ServiceManagementVMDNSSuffix: "usgovcloudapp.net", ResourceManagerVMDNSSuffix: "cloudapp.windowsazure.us", + ContainerRegistryDNSSuffix: "azurecr.io", } // ChinaCloud is the cloud environment operated in China @@ -85,7 +88,7 @@ var ( PublishSettingsURL: "https://manage.chinacloudapi.com/publishsettings/index", ServiceManagementEndpoint: "https://management.core.chinacloudapi.cn/", ResourceManagerEndpoint: "https://management.chinacloudapi.cn/", - ActiveDirectoryEndpoint: "https://login.chinacloudapi.cn/?api-version=1.0", + ActiveDirectoryEndpoint: "https://login.chinacloudapi.cn/", GalleryEndpoint: "https://gallery.chinacloudapi.cn/", KeyVaultEndpoint: "https://vault.azure.cn/", GraphEndpoint: "https://graph.chinacloudapi.cn/", @@ -96,6 +99,7 @@ var ( ServiceBusEndpointSuffix: "servicebus.chinacloudapi.net", ServiceManagementVMDNSSuffix: "chinacloudapp.cn", ResourceManagerVMDNSSuffix: "cloudapp.azure.cn", + ContainerRegistryDNSSuffix: "azurecr.io", } // GermanCloud is the cloud environment operated in Germany @@ -116,6 +120,7 @@ var ( ServiceBusEndpointSuffix: "servicebus.cloudapi.de", ServiceManagementVMDNSSuffix: "azurecloudapp.de", ResourceManagerVMDNSSuffix: "cloudapp.microsoftazure.de", + ContainerRegistryDNSSuffix: "azurecr.io", } ) diff --git a/vendor/github.com/Azure/go-autorest/autorest/client.go b/vendor/github.com/Azure/go-autorest/autorest/client.go index b55b3d103..b5f94b5c3 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/client.go +++ b/vendor/github.com/Azure/go-autorest/autorest/client.go @@ -8,6 +8,7 @@ import ( "log" "net/http" "net/http/cookiejar" + "runtime" "time" ) @@ -22,13 +23,24 @@ const ( DefaultRetryAttempts = 3 ) -var statusCodesForRetry = []int{ - http.StatusRequestTimeout, // 408 - http.StatusInternalServerError, // 500 - http.StatusBadGateway, // 502 - http.StatusServiceUnavailable, // 503 - http.StatusGatewayTimeout, // 504 -} +var ( + // defaultUserAgent builds a string containing the Go version, system archityecture and OS, + // and the go-autorest version. + defaultUserAgent = fmt.Sprintf("Go/%s (%s-%s) go-autorest/%s", + runtime.Version(), + runtime.GOARCH, + runtime.GOOS, + Version(), + ) + + statusCodesForRetry = []int{ + http.StatusRequestTimeout, // 408 + http.StatusInternalServerError, // 500 + http.StatusBadGateway, // 502 + http.StatusServiceUnavailable, // 503 + http.StatusGatewayTimeout, // 504 + } +) const ( requestFormat = `HTTP Request Begin =================================================== @@ -140,13 +152,24 @@ type Client struct { // NewClientWithUserAgent returns an instance of a Client with the UserAgent set to the passed // string. func NewClientWithUserAgent(ua string) Client { - return Client{ + c := Client{ PollingDelay: DefaultPollingDelay, PollingDuration: DefaultPollingDuration, RetryAttempts: DefaultRetryAttempts, RetryDuration: 30 * time.Second, - UserAgent: ua, + UserAgent: defaultUserAgent, } + c.AddToUserAgent(ua) + return c +} + +// AddToUserAgent adds an extension to the current user agent +func (c *Client) AddToUserAgent(extension string) error { + if extension != "" { + c.UserAgent = fmt.Sprintf("%s %s", c.UserAgent, extension) + return nil + } + return fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent) } // Do implements the Sender interface by invoking the active Sender after applying authorization. diff --git a/vendor/github.com/Azure/go-autorest/autorest/preparer.go b/vendor/github.com/Azure/go-autorest/autorest/preparer.go index 5b2c52704..c9deb261a 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/preparer.go +++ b/vendor/github.com/Azure/go-autorest/autorest/preparer.go @@ -183,6 +183,16 @@ func WithBaseURL(baseURL string) PrepareDecorator { } } +// WithCustomBaseURL returns a PrepareDecorator that replaces brace-enclosed keys within the +// request base URL (i.e., http.Request.URL) with the corresponding values from the passed map. +func WithCustomBaseURL(baseURL string, urlParameters map[string]interface{}) PrepareDecorator { + parameters := ensureValueStrings(urlParameters) + for key, value := range parameters { + baseURL = strings.Replace(baseURL, "{"+key+"}", value, -1) + } + return WithBaseURL(baseURL) +} + // WithFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) into the // http.Request body. func WithFormData(v url.Values) PrepareDecorator { diff --git a/vendor/github.com/Azure/go-autorest/autorest/responder.go b/vendor/github.com/Azure/go-autorest/autorest/responder.go index 07cd7ef5c..87f71e585 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/responder.go +++ b/vendor/github.com/Azure/go-autorest/autorest/responder.go @@ -5,6 +5,7 @@ import ( "encoding/json" "encoding/xml" "fmt" + "io" "io/ioutil" "net/http" "strings" @@ -87,6 +88,24 @@ func ByCopying(b *bytes.Buffer) RespondDecorator { } } +// ByDiscardingBody returns a RespondDecorator that first invokes the passed Responder after which +// it copies the remaining bytes (if any) in the response body to ioutil.Discard. Since the passed +// Responder is invoked prior to discarding the response body, the decorator may occur anywhere +// within the set. +func ByDiscardingBody() RespondDecorator { + return func(r Responder) Responder { + return ResponderFunc(func(resp *http.Response) error { + err := r.Respond(resp) + if err == nil && resp != nil && resp.Body != nil { + if _, err := io.Copy(ioutil.Discard, resp.Body); err != nil { + return fmt.Errorf("Error discarding the response body: %v", err) + } + } + return err + }) + } +} + // ByClosing returns a RespondDecorator that first invokes the passed Responder after which it // closes the response body. Since the passed Responder is invoked prior to closing the response // body, the decorator may occur anywhere within the set. @@ -128,6 +147,8 @@ func ByUnmarshallingJSON(v interface{}) RespondDecorator { err := r.Respond(resp) if err == nil { b, errInner := ioutil.ReadAll(resp.Body) + // Some responses might include a BOM, remove for successful unmarshalling + b = bytes.TrimPrefix(b, []byte("\xef\xbb\xbf")) if errInner != nil { err = fmt.Errorf("Error occurred reading http.Response#Body - Error = '%v'", errInner) } else if len(strings.Trim(string(b), " ")) > 0 { diff --git a/vendor/github.com/Azure/go-autorest/autorest/sender.go b/vendor/github.com/Azure/go-autorest/autorest/sender.go index 93e6489e9..9c0697815 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/sender.go +++ b/vendor/github.com/Azure/go-autorest/autorest/sender.go @@ -73,7 +73,7 @@ func SendWithSender(s Sender, r *http.Request, decorators ...SendDecorator) (*ht func AfterDelay(d time.Duration) SendDecorator { return func(s Sender) Sender { return SenderFunc(func(r *http.Request) (*http.Response, error) { - if !DelayForBackoff(d, 1, r.Cancel) { + if !DelayForBackoff(d, 0, r.Cancel) { return nil, fmt.Errorf("autorest: AfterDelay canceled before full delay") } return s.Do(r) @@ -97,7 +97,7 @@ func DoCloseIfError() SendDecorator { return SenderFunc(func(r *http.Request) (*http.Response, error) { resp, err := s.Do(r) if err != nil { - Respond(resp, ByClosing()) + Respond(resp, ByDiscardingBody(), ByClosing()) } return resp, err }) @@ -156,6 +156,7 @@ func DoPollForStatusCodes(duration time.Duration, delay time.Duration, codes ... for err == nil && ResponseHasStatusCode(resp, codes...) { Respond(resp, + ByDiscardingBody(), ByClosing()) resp, err = SendWithSender(s, r, AfterDelay(GetRetryAfter(resp, delay))) @@ -257,6 +258,8 @@ func WithLogging(logger *log.Logger) SendDecorator { // passed attempt (i.e., an exponential backoff delay). Backoff duration is in seconds and can set // to zero for no delay. The delay may be canceled by closing the passed channel. If terminated early, // returns false. +// Note: Passing attempt 1 will result in doubling "backoff" duration. Treat this as a zero-based attempt +// count. func DelayForBackoff(backoff time.Duration, attempt int, cancel <-chan struct{}) bool { select { case <-time.After(time.Duration(backoff.Seconds()*math.Pow(2, float64(attempt))) * time.Second): diff --git a/vendor/github.com/Azure/go-autorest/autorest/validation/validation.go b/vendor/github.com/Azure/go-autorest/autorest/validation/validation.go deleted file mode 100644 index d7b0eadc5..000000000 --- a/vendor/github.com/Azure/go-autorest/autorest/validation/validation.go +++ /dev/null @@ -1,373 +0,0 @@ -/* -Package validation provides methods for validating parameter value using reflection. -*/ -package validation - -import ( - "fmt" - "reflect" - "regexp" - "strings" -) - -// Constraint stores constraint name, target field name -// Rule and chain validations. -type Constraint struct { - - // Target field name for validation. - Target string - - // Constraint name e.g. minLength, MaxLength, Pattern, etc. - Name string - - // Rule for constraint e.g. greater than 10, less than 5 etc. - Rule interface{} - - // Chain Validations for struct type - Chain []Constraint -} - -// Validation stores parameter-wise validation. -type Validation struct { - TargetValue interface{} - Constraints []Constraint -} - -// Constraint list -const ( - Empty = "Empty" - Null = "Null" - ReadOnly = "ReadOnly" - Pattern = "Pattern" - MaxLength = "MaxLength" - MinLength = "MinLength" - MaxItems = "MaxItems" - MinItems = "MinItems" - MultipleOf = "MultipleOf" - UniqueItems = "UniqueItems" - InclusiveMaximum = "InclusiveMaximum" - ExclusiveMaximum = "ExclusiveMaximum" - ExclusiveMinimum = "ExclusiveMinimum" - InclusiveMinimum = "InclusiveMinimum" -) - -// Validate method validates constraints on parameter -// passed in validation array. -func Validate(m []Validation) error { - for _, item := range m { - v := reflect.ValueOf(item.TargetValue) - for _, constraint := range item.Constraints { - var err error - switch v.Kind() { - case reflect.Ptr: - err = validatePtr(v, constraint) - case reflect.String: - err = validateString(v, constraint) - case reflect.Struct: - err = validateStruct(v, constraint) - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - err = validateInt(v, constraint) - case reflect.Float32, reflect.Float64: - err = validateFloat(v, constraint) - case reflect.Array, reflect.Slice, reflect.Map: - err = validateArrayMap(v, constraint) - default: - err = createError(v, constraint, fmt.Sprintf("unknown type %v", v.Kind())) - } - - if err != nil { - return err - } - } - } - return nil -} - -func validateStruct(x reflect.Value, v Constraint, name ...string) error { - //Get field name from target name which is in format a.b.c - s := strings.Split(v.Target, ".") - f := x.FieldByName(s[len(s)-1]) - if isZero(f) { - return createError(x, v, fmt.Sprintf("field %q doesn't exist", v.Target)) - } - - if err := Validate([]Validation{ - { - TargetValue: getInterfaceValue(f), - Constraints: []Constraint{v}, - }, - }); err != nil { - return err - } - return nil -} - -func validatePtr(x reflect.Value, v Constraint) error { - if v.Name == ReadOnly { - if !x.IsNil() { - return createError(x.Elem(), v, "readonly parameter; must send as nil or empty in request") - } - return nil - } - if x.IsNil() { - return checkNil(x, v) - } - if v.Chain != nil { - return Validate([]Validation{ - { - TargetValue: getInterfaceValue(x.Elem()), - Constraints: v.Chain, - }, - }) - } - return nil -} - -func validateInt(x reflect.Value, v Constraint) error { - i := x.Int() - r, ok := v.Rule.(int) - if !ok { - return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule)) - } - switch v.Name { - case MultipleOf: - if i%int64(r) != 0 { - return createError(x, v, fmt.Sprintf("value must be a multiple of %v", r)) - } - case ExclusiveMinimum: - if i <= int64(r) { - return createError(x, v, fmt.Sprintf("value must be greater than %v", r)) - } - case ExclusiveMaximum: - if i >= int64(r) { - return createError(x, v, fmt.Sprintf("value must be less than %v", r)) - } - case InclusiveMinimum: - if i < int64(r) { - return createError(x, v, fmt.Sprintf("value must be greater than or equal to %v", r)) - } - case InclusiveMaximum: - if i > int64(r) { - return createError(x, v, fmt.Sprintf("value must be less than or equal to %v", r)) - } - default: - return createError(x, v, fmt.Sprintf("constraint %v is not applicable for type integer", v.Name)) - } - return nil -} - -func validateFloat(x reflect.Value, v Constraint) error { - f := x.Float() - r, ok := v.Rule.(float64) - if !ok { - return createError(x, v, fmt.Sprintf("rule must be float value for %v constraint; got: %v", v.Name, v.Rule)) - } - switch v.Name { - case ExclusiveMinimum: - if f <= r { - return createError(x, v, fmt.Sprintf("value must be greater than %v", r)) - } - case ExclusiveMaximum: - if f >= r { - return createError(x, v, fmt.Sprintf("value must be less than %v", r)) - } - case InclusiveMinimum: - if f < r { - return createError(x, v, fmt.Sprintf("value must be greater than or equal to %v", r)) - } - case InclusiveMaximum: - if f > r { - return createError(x, v, fmt.Sprintf("value must be less than or equal to %v", r)) - } - default: - return createError(x, v, fmt.Sprintf("constraint %s is not applicable for type float", v.Name)) - } - return nil -} - -func validateString(x reflect.Value, v Constraint) error { - s := x.String() - switch v.Name { - case Empty: - if len(s) == 0 { - return checkEmpty(x, v) - } - case Pattern: - reg, err := regexp.Compile(v.Rule.(string)) - if err != nil { - return createError(x, v, err.Error()) - } - if !reg.MatchString(s) { - return createError(x, v, fmt.Sprintf("value doesn't match pattern %v", v.Rule)) - } - case MaxLength: - if _, ok := v.Rule.(int); !ok { - return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule)) - } - if len(s) > v.Rule.(int) { - return createError(x, v, fmt.Sprintf("value length must be less than %v", v.Rule)) - } - case MinLength: - if _, ok := v.Rule.(int); !ok { - return createError(x, v, fmt.Sprintf("rule must be integer value for %v constraint; got: %v", v.Name, v.Rule)) - } - if len(s) < v.Rule.(int) { - return createError(x, v, fmt.Sprintf("value length must be greater than %v", v.Rule)) - } - case ReadOnly: - if len(s) > 0 { - return createError(reflect.ValueOf(s), v, "readonly parameter; must send as nil or empty in request") - } - default: - return createError(x, v, fmt.Sprintf("constraint %s is not applicable to string type", v.Name)) - } - - if v.Chain != nil { - return Validate([]Validation{ - { - TargetValue: getInterfaceValue(x), - Constraints: v.Chain, - }, - }) - } - return nil -} - -func validateArrayMap(x reflect.Value, v Constraint) error { - switch v.Name { - case Null: - if x.IsNil() { - return checkNil(x, v) - } - case Empty: - if x.IsNil() || x.Len() == 0 { - return checkEmpty(x, v) - } - case MaxItems: - if _, ok := v.Rule.(int); !ok { - return createError(x, v, fmt.Sprintf("rule must be integer for %v constraint; got: %v", v.Name, v.Rule)) - } - if x.Len() > v.Rule.(int) { - return createError(x, v, fmt.Sprintf("maximum item limit is %v; got: %v", v.Rule, x.Len())) - } - case MinItems: - if _, ok := v.Rule.(int); !ok { - return createError(x, v, fmt.Sprintf("rule must be integer for %v constraint; got: %v", v.Name, v.Rule)) - } - if x.Len() < v.Rule.(int) { - return createError(x, v, fmt.Sprintf("minimum item limit is %v; got: %v", v.Rule, x.Len())) - } - case UniqueItems: - if x.Kind() == reflect.Array || x.Kind() == reflect.Slice { - if !checkForUniqueInArray(x) { - return createError(x, v, fmt.Sprintf("all items in parameter %q must be unique; got:%v", v.Target, x)) - } - } else if x.Kind() == reflect.Map { - if !checkForUniqueInMap(x) { - return createError(x, v, fmt.Sprintf("all items in parameter %q must be unique; got:%v", v.Target, x)) - } - } else { - return createError(x, v, fmt.Sprintf("type must be array, slice or map for constraint %v; got: %v", v.Name, x.Kind())) - } - case ReadOnly: - if x.Len() != 0 { - return createError(x, v, "readonly parameter; must send as nil or empty in request") - } - default: - return createError(x, v, fmt.Sprintf("constraint %v is not applicable to array, slice and map type", v.Name)) - } - - if v.Chain != nil { - return Validate([]Validation{ - { - TargetValue: getInterfaceValue(x), - Constraints: v.Chain, - }, - }) - } - return nil -} - -func checkNil(x reflect.Value, v Constraint) error { - if _, ok := v.Rule.(bool); !ok { - return createError(x, v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule)) - } - if v.Rule.(bool) { - return createError(x, v, "value can not be null; required parameter") - } - return nil -} - -func checkEmpty(x reflect.Value, v Constraint) error { - if _, ok := v.Rule.(bool); !ok { - return createError(x, v, fmt.Sprintf("rule must be bool value for %v constraint; got: %v", v.Name, v.Rule)) - } - - if v.Rule.(bool) { - return createError(x, v, "value can not be null or empty; required parameter") - } - return nil -} - -func checkForUniqueInArray(x reflect.Value) bool { - if x == reflect.Zero(reflect.TypeOf(x)) || x.Len() == 0 { - return false - } - arrOfInterface := make([]interface{}, x.Len()) - - for i := 0; i < x.Len(); i++ { - arrOfInterface[i] = x.Index(i).Interface() - } - - m := make(map[interface{}]bool) - for _, val := range arrOfInterface { - if m[val] { - return false - } - m[val] = true - } - return true -} - -func checkForUniqueInMap(x reflect.Value) bool { - if x == reflect.Zero(reflect.TypeOf(x)) || x.Len() == 0 { - return false - } - mapOfInterface := make(map[interface{}]interface{}, x.Len()) - - keys := x.MapKeys() - for _, k := range keys { - mapOfInterface[k.Interface()] = x.MapIndex(k).Interface() - } - - m := make(map[interface{}]bool) - for _, val := range mapOfInterface { - if m[val] { - return false - } - m[val] = true - } - return true -} - -func getInterfaceValue(x reflect.Value) interface{} { - if x.Kind() == reflect.Invalid { - return nil - } - return x.Interface() -} - -func isZero(x interface{}) bool { - return x == reflect.Zero(reflect.TypeOf(x)).Interface() -} - -func createError(x reflect.Value, v Constraint, err string) error { - return fmt.Errorf("autorest/validation: validation failed: parameter=%s constraint=%s value=%#v details: %s", - v.Target, v.Name, getInterfaceValue(x), err) -} - -// NewErrorWithValidationError appends package type and method name in -// validation error. -func NewErrorWithValidationError(err error, packageType, method string) error { - return fmt.Errorf("%s#%s: Invalid input: %v", packageType, method, err) -} diff --git a/vendor/github.com/Azure/go-autorest/autorest/version.go b/vendor/github.com/Azure/go-autorest/autorest/version.go index 8031a332c..e325f4ce2 100644 --- a/vendor/github.com/Azure/go-autorest/autorest/version.go +++ b/vendor/github.com/Azure/go-autorest/autorest/version.go @@ -2,17 +2,28 @@ package autorest import ( "fmt" + "strings" + "sync" ) const ( - major = "7" - minor = "0" - patch = "0" - tag = "" - semVerFormat = "%s.%s.%s%s" + major = 7 + minor = 3 + patch = 1 + tag = "" ) +var versionLock sync.Once +var version string + // Version returns the semantic version (see http://semver.org). func Version() string { - return fmt.Sprintf(semVerFormat, major, minor, patch, tag) + versionLock.Do(func() { + version = fmt.Sprintf("v%d.%d.%d", major, minor, patch) + + if trimmed := strings.TrimPrefix(tag, "-"); trimmed != "" { + version = fmt.Sprintf("%s-%s", version, trimmed) + } + }) + return version } diff --git a/vendor/github.com/dnsimple/dnsimple-go/LICENSE.txt b/vendor/github.com/dnsimple/dnsimple-go/LICENSE.txt new file mode 100644 index 000000000..9d8e840fa --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2017 Aetrion LLC dba DNSimple + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/accounts.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/accounts.go new file mode 100644 index 000000000..aaadef0ff --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/accounts.go @@ -0,0 +1,44 @@ +package dnsimple + +import ( +) + +type AccountsService struct { + client *Client +} + +// Account represents a DNSimple account. +type Account struct { + ID int `json:"id,omitempty"` + Email string `json:"email,omitempty"` + PlanIdentifier string `json:"plan_identifier,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +// accountsResponse represents a response from an API method that returns a collection of Account struct. +type accountsResponse struct { + Response + Data []Account `json:"data"` +} + +// ListAccounts list the accounts for an user. +// +// See https://developer.dnsimple.com/v2/accounts/#list +func (s *AccountsService) ListAccounts(options *ListOptions) (*accountsResponse, error) { + path := versioned("/accounts") + accountsResponse := &accountsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, accountsResponse) + if err != nil { + return accountsResponse, err + } + + accountsResponse.HttpResponse = resp + return accountsResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/authentication.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/authentication.go new file mode 100644 index 000000000..48e375a7e --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/authentication.go @@ -0,0 +1,68 @@ +package dnsimple + +import ( + "encoding/base64" +) + +const ( + httpHeaderDomainToken = "X-DNSimple-Domain-Token" + httpHeaderApiToken = "X-DNSimple-Token" + httpHeaderAuthorization = "Authorization" +) + +// Provides credentials that can be used for authenticating with DNSimple. +// +// See https://developer.dnsimple.com/v2/#authentication +type Credentials interface { + // Returns the HTTP headers that should be set + // to authenticate the HTTP Request. + Headers() map[string]string +} + +// Domain token authentication +type domainTokenCredentials struct { + domainToken string +} + +// NewDomainTokenCredentials construct Credentials using the DNSimple Domain Token method. +func NewDomainTokenCredentials(domainToken string) Credentials { + return &domainTokenCredentials{domainToken: domainToken} +} + +func (c *domainTokenCredentials) Headers() map[string]string { + return map[string]string{httpHeaderDomainToken: c.domainToken} +} + +// HTTP basic authentication +type httpBasicCredentials struct { + email string + password string +} + +// NewHTTPBasicCredentials construct Credentials using HTTP Basic Auth. +func NewHTTPBasicCredentials(email, password string) Credentials { + return &httpBasicCredentials{email, password} +} + +func (c *httpBasicCredentials) Headers() map[string]string { + return map[string]string{httpHeaderAuthorization: "Basic " + c.basicAuth(c.email, c.password)} +} + +func (c *httpBasicCredentials) basicAuth(username, password string) string { + auth := username + ":" + password + return base64.StdEncoding.EncodeToString([]byte(auth)) +} + +// OAuth token authentication +type oauthTokenCredentials struct { + oauthToken string +} + +// NewOauthTokenCredentials construct Credentials using the OAuth access token. +func NewOauthTokenCredentials(oauthToken string) Credentials { + return &oauthTokenCredentials{oauthToken: oauthToken} +} + +func (c *oauthTokenCredentials) Headers() map[string]string { + return map[string]string{httpHeaderAuthorization: "Bearer " + c.oauthToken} +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/certificates.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/certificates.go new file mode 100644 index 000000000..8e62d6c44 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/certificates.go @@ -0,0 +1,134 @@ +package dnsimple + +import ( + "fmt" + "strconv" +) + +// CertificatesService handles communication with the certificate related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/domains/certificates +type CertificatesService struct { + client *Client +} + +// Certificate represents a Certificate in DNSimple. +type Certificate struct { + ID int `json:"id,omitempty"` + DomainID int `json:"domain_id,omitempty"` + CommonName string `json:"common_name,omitempty"` + Years int `json:"years,omitempty"` + State string `json:"state,omitempty"` + AuthorityIdentifier string `json:"authority_identifier,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + ExpiresOn string `json:"expires_on,omitempty"` + CertificateRequest string `json:"csr,omitempty"` +} + +// CertificateBundle represents a container for all the PEM-encoded X509 certificate entities, +// such as the private key, the server certificate and the intermediate chain. +type CertificateBundle struct { + // CertificateRequest string `json:"csr,omitempty"` + PrivateKey string `json:"private_key,omitempty"` + ServerCertificate string `json:"server,omitempty"` + RootCertificate string `json:"root,omitempty"` + IntermediateCertificates []string `json:"chain,omitempty"` +} + +func certificatePath(accountID, domainIdentifier, certificateID string) (path string) { + path = fmt.Sprintf("%v/certificates", domainPath(accountID, domainIdentifier)) + if certificateID != "" { + path += fmt.Sprintf("/%v", certificateID) + } + return +} + +// certificateResponse represents a response from an API method that returns a Certificate struct. +type certificateResponse struct { + Response + Data *Certificate `json:"data"` +} + +// certificateBundleResponse represents a response from an API method that returns a CertificatBundle struct. +type certificateBundleResponse struct { + Response + Data *CertificateBundle `json:"data"` +} + +// certificatesResponse represents a response from an API method that returns a collection of Certificate struct. +type certificatesResponse struct { + Response + Data []Certificate `json:"data"` +} + +// ListCertificates list the certificates for a domain. +// +// See https://developer.dnsimple.com/v2/domains/certificates#list +func (s *CertificatesService) ListCertificates(accountID, domainIdentifier string, options *ListOptions) (*certificatesResponse, error) { + path := versioned(certificatePath(accountID, domainIdentifier, "")) + certificatesResponse := &certificatesResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, certificatesResponse) + if err != nil { + return certificatesResponse, err + } + + certificatesResponse.HttpResponse = resp + return certificatesResponse, nil +} + +// GetCertificate fetches the certificate. +// +// See https://developer.dnsimple.com/v2/domains/certificates#get +func (s *CertificatesService) GetCertificate(accountID, domainIdentifier string, certificateID int) (*certificateResponse, error) { + path := versioned(certificatePath(accountID, domainIdentifier, strconv.Itoa(certificateID))) + certificateResponse := &certificateResponse{} + + resp, err := s.client.get(path, certificateResponse) + if err != nil { + return nil, err + } + + certificateResponse.HttpResponse = resp + return certificateResponse, nil +} + +// DownloadCertificate download the issued server certificate, +// as well the root certificate and the intermediate chain. +// +// See https://developer.dnsimple.com/v2/domains/certificates#download +func (s *CertificatesService) DownloadCertificate(accountID, domainIdentifier string, certificateID int) (*certificateBundleResponse, error) { + path := versioned(certificatePath(accountID, domainIdentifier, strconv.Itoa(certificateID)) + "/download") + certificateBundleResponse := &certificateBundleResponse{} + + resp, err := s.client.get(path, certificateBundleResponse) + if err != nil { + return nil, err + } + + certificateBundleResponse.HttpResponse = resp + return certificateBundleResponse, nil +} + +// GetCertificatePrivateKey fetches the certificate private key. +// +// See https://developer.dnsimple.com/v2/domains/certificates#get-private-key +func (s *CertificatesService) GetCertificatePrivateKey(accountID, domainIdentifier string, certificateID int) (*certificateBundleResponse, error) { + path := versioned(certificatePath(accountID, domainIdentifier, strconv.Itoa(certificateID)) + "/private_key") + certificateBundleResponse := &certificateBundleResponse{} + + resp, err := s.client.get(path, certificateBundleResponse) + if err != nil { + return nil, err + } + + certificateBundleResponse.HttpResponse = resp + return certificateBundleResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/contacts.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/contacts.go new file mode 100644 index 000000000..a09f38d87 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/contacts.go @@ -0,0 +1,140 @@ +package dnsimple + +import ( + "fmt" +) + +// ContactsService handles communication with the contact related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/contacts/ +type ContactsService struct { + client *Client +} + +// Contact represents a Contact in DNSimple. +type Contact struct { + ID int `json:"id,omitempty"` + AccountID int `json:"account_id,omitempty"` + Label string `json:"label,omitempty"` + FirstName string `json:"first_name,omitempty"` + LastName string `json:"last_name,omitempty"` + JobTitle string `json:"job_title,omitempty"` + Organization string `json:"organization_name,omitempty"` + Address1 string `json:"address1,omitempty"` + Address2 string `json:"address2,omitempty"` + City string `json:"city,omitempty"` + StateProvince string `json:"state_province,omitempty"` + PostalCode string `json:"postal_code,omitempty"` + Country string `json:"country,omitempty"` + Phone string `json:"phone,omitempty"` + Fax string `json:"fax,omitempty"` + Email string `json:"email,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +func contactPath(accountID string, contactID int) (path string) { + path = fmt.Sprintf("/%v/contacts", accountID) + if contactID != 0 { + path += fmt.Sprintf("/%v", contactID) + } + return +} + +// contactResponse represents a response from an API method that returns a Contact struct. +type contactResponse struct { + Response + Data *Contact `json:"data"` +} + +// contactsResponse represents a response from an API method that returns a collection of Contact struct. +type contactsResponse struct { + Response + Data []Contact `json:"data"` +} + +// ListContacts list the contacts for an account. +// +// See https://developer.dnsimple.com/v2/contacts/#list +func (s *ContactsService) ListContacts(accountID string, options *ListOptions) (*contactsResponse, error) { + path := versioned(contactPath(accountID, 0)) + contactsResponse := &contactsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, contactsResponse) + if err != nil { + return contactsResponse, err + } + + contactsResponse.HttpResponse = resp + return contactsResponse, nil +} + +// CreateContact creates a new contact. +// +// See https://developer.dnsimple.com/v2/contacts/#create +func (s *ContactsService) CreateContact(accountID string, contactAttributes Contact) (*contactResponse, error) { + path := versioned(contactPath(accountID, 0)) + contactResponse := &contactResponse{} + + resp, err := s.client.post(path, contactAttributes, contactResponse) + if err != nil { + return nil, err + } + + contactResponse.HttpResponse = resp + return contactResponse, nil +} + +// GetContact fetches a contact. +// +// See https://developer.dnsimple.com/v2/contacts/#get +func (s *ContactsService) GetContact(accountID string, contactID int) (*contactResponse, error) { + path := versioned(contactPath(accountID, contactID)) + contactResponse := &contactResponse{} + + resp, err := s.client.get(path, contactResponse) + if err != nil { + return nil, err + } + + contactResponse.HttpResponse = resp + return contactResponse, nil +} + +// UpdateContact updates a contact. +// +// See https://developer.dnsimple.com/v2/contacts/#update +func (s *ContactsService) UpdateContact(accountID string, contactID int, contactAttributes Contact) (*contactResponse, error) { + path := versioned(contactPath(accountID, contactID)) + contactResponse := &contactResponse{} + + resp, err := s.client.patch(path, contactAttributes, contactResponse) + if err != nil { + return nil, err + } + + contactResponse.HttpResponse = resp + return contactResponse, nil +} + +// DeleteContact PERMANENTLY deletes a contact from the account. +// +// See https://developer.dnsimple.com/v2/contacts/#delete +func (s *ContactsService) DeleteContact(accountID string, contactID int) (*contactResponse, error) { + path := versioned(contactPath(accountID, contactID)) + contactResponse := &contactResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + contactResponse.HttpResponse = resp + return contactResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/dnsimple.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/dnsimple.go new file mode 100644 index 000000000..909480ff6 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/dnsimple.go @@ -0,0 +1,341 @@ +// Package dnsimple provides a client for the DNSimple API. +// In order to use this package you will need a DNSimple account. +package dnsimple + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "net/url" + "reflect" + "strconv" + "strings" + "time" + + "github.com/google/go-querystring/query" +) + +const ( + // Version identifies the current library version. + // This is a pro-forma convention given that Go dependencies + // tends to be fetched directly from the repo. + // It is also used in the user-agent identify the client. + Version = "0.14.0" + + // defaultBaseURL to the DNSimple production API. + defaultBaseURL = "https://api.dnsimple.com" + + // userAgent represents the default user agent used + // when no other user agent is set. + defaultUserAgent = "dnsimple-go/" + Version + + apiVersion = "v2" +) + +// Client represents a client to the DNSimple API. +type Client struct { + // HttpClient is the underlying HTTP client + // used to communicate with the API. + HttpClient *http.Client + + // Credentials used for accessing the DNSimple API + Credentials Credentials + + // BaseURL for API requests. + // Defaults to the public DNSimple API, but can be set to a different endpoint (e.g. the sandbox). + BaseURL string + + // UserAgent used when communicating with the DNSimple API. + UserAgent string + + // Services used for talking to different parts of the DNSimple API. + Identity *IdentityService + Accounts *AccountsService + Certificates *CertificatesService + Contacts *ContactsService + Domains *DomainsService + Oauth *OauthService + Registrar *RegistrarService + Services *ServicesService + Templates *TemplatesService + Tlds *TldsService + VanityNameServers *VanityNameServersService + Webhooks *WebhooksService + Zones *ZonesService + + // Set to true to output debugging logs during API calls + Debug bool +} + +// ListOptions contains the common options you can pass to a List method +// in order to control parameters such as paginations and page number. +type ListOptions struct { + // The page to return + Page int `url:"page,omitempty"` + + // The number of entries to return per page + PerPage int `url:"per_page,omitempty"` + + // The order criteria to sort the results. + // The value is a comma-separated list of field[:direction], + // eg. name | name:desc | name:desc,expiration:desc + Sort string `url:"sort,omitempty"` +} + +// NewClient returns a new DNSimple API client using the given credentials. +func NewClient(credentials Credentials) *Client { + c := &Client{Credentials: credentials, HttpClient: &http.Client{}, BaseURL: defaultBaseURL} + c.Identity = &IdentityService{client: c} + c.Accounts = &AccountsService{client: c} + c.Certificates = &CertificatesService{client: c} + c.Contacts = &ContactsService{client: c} + c.Domains = &DomainsService{client: c} + c.Oauth = &OauthService{client: c} + c.Registrar = &RegistrarService{client: c} + c.Services = &ServicesService{client: c} + c.Templates = &TemplatesService{client: c} + c.Tlds = &TldsService{client: c} + c.VanityNameServers = &VanityNameServersService{client: c} + c.Webhooks = &WebhooksService{client: c} + c.Zones = &ZonesService{client: c} + return c +} + +// NewRequest creates an API request. +// The path is expected to be a relative path and will be resolved +// according to the BaseURL of the Client. Paths should always be specified without a preceding slash. +func (c *Client) NewRequest(method, path string, payload interface{}) (*http.Request, error) { + url := c.BaseURL + path + + body := new(bytes.Buffer) + if payload != nil { + err := json.NewEncoder(body).Encode(payload) + if err != nil { + return nil, err + } + } + + req, err := http.NewRequest(method, url, body) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Add("Accept", "application/json") + req.Header.Add("User-Agent", formatUserAgent(c.UserAgent)) + for key, value := range c.Credentials.Headers() { + req.Header.Add(key, value) + } + + return req, nil +} + +// formatUserAgent builds the final user agent to use for HTTP requests. +// +// If no custom user agent is provided, the default user agent is used. +// +// dnsimple-go/1.0 +// +// If a custom user agent is provided, the final user agent is the combination of the custom user agent +// prepended by the default user agent. +// +// dnsimple-go/1.0 customAgentFlag +// +func formatUserAgent(customUserAgent string) string { + if customUserAgent == "" { + return defaultUserAgent + } + + return fmt.Sprintf("%s %s", defaultUserAgent, customUserAgent) +} + +func versioned(path string) string { + return fmt.Sprintf("/%s/%s", apiVersion, strings.Trim(path, "/")) +} + +func (c *Client) get(path string, obj interface{}) (*http.Response, error) { + req, err := c.NewRequest("GET", path, nil) + if err != nil { + return nil, err + } + + return c.Do(req, obj) +} + +func (c *Client) post(path string, payload, obj interface{}) (*http.Response, error) { + req, err := c.NewRequest("POST", path, payload) + if err != nil { + return nil, err + } + + return c.Do(req, obj) +} + +func (c *Client) put(path string, payload, obj interface{}) (*http.Response, error) { + req, err := c.NewRequest("PUT", path, payload) + if err != nil { + return nil, err + } + + return c.Do(req, obj) +} + +func (c *Client) patch(path string, payload, obj interface{}) (*http.Response, error) { + req, err := c.NewRequest("PATCH", path, payload) + if err != nil { + return nil, err + } + + return c.Do(req, obj) +} + +func (c *Client) delete(path string, payload interface{}, obj interface{}) (*http.Response, error) { + req, err := c.NewRequest("DELETE", path, payload) + if err != nil { + return nil, err + } + + return c.Do(req, obj) +} + +// Do sends an API request and returns the API response. +// +// The API response is JSON decoded and stored in the value pointed by obj, +// or returned as an error if an API error has occurred. +// If obj implements the io.Writer interface, the raw response body will be written to obj, +// without attempting to decode it. +func (c *Client) Do(req *http.Request, obj interface{}) (*http.Response, error) { + if c.Debug { + log.Printf("Executing request (%v): %#v", req.URL, req) + } + + resp, err := c.HttpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if c.Debug { + log.Printf("Response received: %#v", resp) + } + + err = CheckResponse(resp) + if err != nil { + return resp, err + } + + // If obj implements the io.Writer, + // the response body is decoded into v. + if obj != nil { + if w, ok := obj.(io.Writer); ok { + io.Copy(w, resp.Body) + } else { + err = json.NewDecoder(resp.Body).Decode(obj) + } + } + + return resp, err +} + +// A Response represents an API response. +type Response struct { + // HTTP response + HttpResponse *http.Response + + // If the response is paginated, the Pagination will store them. + Pagination *Pagination `json:"pagination"` +} + +// RateLimit returns the maximum amount of requests this account can send in an hour. +func (r *Response) RateLimit() int { + value, _ := strconv.Atoi(r.HttpResponse.Header.Get("X-RateLimit-Limit")) + return value +} + +// RateLimitRemaining returns the remaining amount of requests this account can send within this hour window. +func (r *Response) RateLimitRemaining() int { + value, _ := strconv.Atoi(r.HttpResponse.Header.Get("X-RateLimit-Remaining")) + return value +} + +// RateLimitReset returns when the throttling window will be reset for this account. +func (r *Response) RateLimitReset() time.Time { + value, _ := strconv.ParseInt(r.HttpResponse.Header.Get("X-RateLimit-Reset"), 10, 64) + return time.Unix(value, 0) +} + +// If the response is paginated, Pagination represents the pagination information. +type Pagination struct { + CurrentPage int `json:"current_page"` + PerPage int `json:"per_page"` + TotalPages int `json:"total_pages"` + TotalEntries int `json:"total_entries"` +} + +// An ErrorResponse represents an API response that generated an error. +type ErrorResponse struct { + Response + + // human-readable message + Message string `json:"message"` +} + +// Error implements the error interface. +func (r *ErrorResponse) Error() string { + return fmt.Sprintf("%v %v: %v %v", + r.HttpResponse.Request.Method, r.HttpResponse.Request.URL, + r.HttpResponse.StatusCode, r.Message) +} + +// CheckResponse checks the API response for errors, and returns them if present. +// A response is considered an error if the status code is different than 2xx. Specific requests +// may have additional requirements, but this is sufficient in most of the cases. +func CheckResponse(resp *http.Response) error { + if code := resp.StatusCode; 200 <= code && code <= 299 { + return nil + } + + errorResponse := &ErrorResponse{} + errorResponse.HttpResponse = resp + + err := json.NewDecoder(resp.Body).Decode(errorResponse) + if err != nil { + return err + } + + return errorResponse +} + +// addOptions adds the parameters in opt as URL query parameters to s. opt +// must be a struct whose fields may contain "url" tags. +func addURLQueryOptions(path string, options interface{}) (string, error) { + opt := reflect.ValueOf(options) + + // options is a pointer + // return if the value of the pointer is nil, + if opt.Kind() == reflect.Ptr && opt.IsNil() { + return path, nil + } + + // append the options to the URL + u, err := url.Parse(path) + if err != nil { + return path, err + } + + qs, err := query.Values(options) + if err != nil { + return path, err + } + + uqs := u.Query() + for k, _ := range qs { + uqs.Set(k, qs.Get(k)) + } + u.RawQuery = uqs.Encode() + + return u.String(), nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains.go new file mode 100644 index 000000000..8b3bc25e0 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains.go @@ -0,0 +1,146 @@ +package dnsimple + +import ( + "fmt" +) + +// DomainsService handles communication with the domain related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/domains/ +type DomainsService struct { + client *Client +} + +// Domain represents a domain in DNSimple. +type Domain struct { + ID int `json:"id,omitempty"` + AccountID int `json:"account_id,omitempty"` + RegistrantID int `json:"registrant_id,omitempty"` + Name string `json:"name,omitempty"` + UnicodeName string `json:"unicode_name,omitempty"` + Token string `json:"token,omitempty"` + State string `json:"state,omitempty"` + AutoRenew bool `json:"auto_renew,omitempty"` + PrivateWhois bool `json:"private_whois,omitempty"` + ExpiresOn string `json:"expires_on,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +func domainPath(accountID string, domainIdentifier string) (path string) { + path = fmt.Sprintf("/%v/domains", accountID) + if domainIdentifier != "" { + path += fmt.Sprintf("/%v", domainIdentifier) + } + return +} + +// domainResponse represents a response from an API method that returns a Domain struct. +type domainResponse struct { + Response + Data *Domain `json:"data"` +} + +// domainsResponse represents a response from an API method that returns a collection of Domain struct. +type domainsResponse struct { + Response + Data []Domain `json:"data"` +} + +// DomainListOptions specifies the optional parameters you can provide +// to customize the DomainsService.ListDomains method. +type DomainListOptions struct { + // Select domains where the name contains given string. + NameLike string `url:"name_like,omitempty"` + + // Select domains where the registrant matches given ID. + RegistrantID int `url:"registrant_id,omitempty"` + + ListOptions +} + +// ListDomains lists the domains for an account. +// +// See https://developer.dnsimple.com/v2/domains/#list +func (s *DomainsService) ListDomains(accountID string, options *DomainListOptions) (*domainsResponse, error) { + path := versioned(domainPath(accountID, "")) + domainsResponse := &domainsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, domainsResponse) + if err != nil { + return nil, err + } + + domainsResponse.HttpResponse = resp + return domainsResponse, nil +} + +// CreateDomain creates a new domain in the account. +// +// See https://developer.dnsimple.com/v2/domains/#create +func (s *DomainsService) CreateDomain(accountID string, domainAttributes Domain) (*domainResponse, error) { + path := versioned(domainPath(accountID, "")) + domainResponse := &domainResponse{} + + resp, err := s.client.post(path, domainAttributes, domainResponse) + if err != nil { + return nil, err + } + + domainResponse.HttpResponse = resp + return domainResponse, nil +} + +// GetDomain fetches a domain. +// +// See https://developer.dnsimple.com/v2/domains/#get +func (s *DomainsService) GetDomain(accountID string, domainIdentifier string) (*domainResponse, error) { + path := versioned(domainPath(accountID, domainIdentifier)) + domainResponse := &domainResponse{} + + resp, err := s.client.get(path, domainResponse) + if err != nil { + return nil, err + } + + domainResponse.HttpResponse = resp + return domainResponse, nil +} + +// DeleteDomain PERMANENTLY deletes a domain from the account. +// +// See https://developer.dnsimple.com/v2/domains/#delete +func (s *DomainsService) DeleteDomain(accountID string, domainIdentifier string) (*domainResponse, error) { + path := versioned(domainPath(accountID, domainIdentifier)) + domainResponse := &domainResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + domainResponse.HttpResponse = resp + return domainResponse, nil +} + +// ResetDomainToken resets the domain token. +// +// See https://developer.dnsimple.com/v2/domains/#reset-token +func (s *DomainsService) ResetDomainToken(accountID string, domainIdentifier string) (*domainResponse, error) { + path := versioned(domainPath(accountID, domainIdentifier) + "/token") + domainResponse := &domainResponse{} + + resp, err := s.client.post(path, nil, domainResponse) + if err != nil { + return nil, err + } + + domainResponse.HttpResponse = resp + return domainResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_collaborators.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_collaborators.go new file mode 100644 index 000000000..a6a23f406 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_collaborators.go @@ -0,0 +1,96 @@ +package dnsimple + +import ( + "fmt" +) + +// Collaborator represents a Collaborator in DNSimple. +type Collaborator struct { + ID int `json:"id,omitempty"` + DomainID int `json:"domain_id,omitempty"` + DomainName string `json:"domain_name,omitempty"` + UserID int `json:"user_id,omitempty"` + UserEmail string `json:"user_email,omitempty"` + Invitation bool `json:"invitation,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + AcceptedAt string `json:"accepted_at,omitempty"` +} + +func collaboratorPath(accountID, domainIdentifier, collaboratorID string) (path string) { + path = fmt.Sprintf("%v/collaborators", domainPath(accountID, domainIdentifier)) + if collaboratorID != "" { + path += fmt.Sprintf("/%v", collaboratorID) + } + return +} + +// CollaboratorAttributes represents Collaborator attributes for AddCollaborator operation. +type CollaboratorAttributes struct { + Email string `json:"email,omitempty"` +} + +// collaboratorResponse represents a response from an API method that returns a Collaborator struct. +type collaboratorResponse struct { + Response + Data *Collaborator `json:"data"` +} + +// collaboratorsResponse represents a response from an API method that returns a collection of Collaborator struct. +type collaboratorsResponse struct { + Response + Data []Collaborator `json:"data"` +} + +// ListCollaborators list the collaborators for a domain. +// +// See https://developer.dnsimple.com/v2/domains/collaborators#list +func (s *DomainsService) ListCollaborators(accountID, domainIdentifier string, options *ListOptions) (*collaboratorsResponse, error) { + path := versioned(collaboratorPath(accountID, domainIdentifier, "")) + collaboratorsResponse := &collaboratorsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, collaboratorsResponse) + if err != nil { + return collaboratorsResponse, err + } + + collaboratorsResponse.HttpResponse = resp + return collaboratorsResponse, nil +} + +// AddCollaborator adds a new collaborator to the domain in the account. +// +// See https://developer.dnsimple.com/v2/domains/collaborators#add +func (s *DomainsService) AddCollaborator(accountID string, domainIdentifier string, attributes CollaboratorAttributes) (*collaboratorResponse, error) { + path := versioned(collaboratorPath(accountID, domainIdentifier, "")) + collaboratorResponse := &collaboratorResponse{} + + resp, err := s.client.post(path, attributes, collaboratorResponse) + if err != nil { + return nil, err + } + + collaboratorResponse.HttpResponse = resp + return collaboratorResponse, nil +} + +// RemoveCollaborator PERMANENTLY deletes a domain from the account. +// +// See https://developer.dnsimple.com/v2/domains/collaborators#add +func (s *DomainsService) RemoveCollaborator(accountID string, domainIdentifier string, collaboratorID string) (*collaboratorResponse, error) { + path := versioned(collaboratorPath(accountID, domainIdentifier, collaboratorID)) + collaboratorResponse := &collaboratorResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + collaboratorResponse.HttpResponse = resp + return collaboratorResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_delegation_signer_records.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_delegation_signer_records.go new file mode 100644 index 000000000..a4df814bf --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_delegation_signer_records.go @@ -0,0 +1,105 @@ +package dnsimple + +import "fmt" + +// DelegationSignerRecord represents a delegation signer record for a domain in DNSimple. +type DelegationSignerRecord struct { + ID int `json:"id,omitempty"` + DomainID int `json:"domain_id,omitempty"` + Algorithm string `json:"algorithm"` + Digest string `json:"digest"` + DigestType string `json:"digest_type"` + Keytag string `json:"keytag"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +func delegationSignerRecordPath(accountID string, domainIdentifier string, dsRecordID int) (path string) { + path = fmt.Sprintf("%v/ds_records", domainPath(accountID, domainIdentifier)) + if dsRecordID != 0 { + path += fmt.Sprintf("/%d", dsRecordID) + } + return +} + +// delegationSignerRecordResponse represents a response from an API method that returns a DelegationSignerRecord struct. +type delegationSignerRecordResponse struct { + Response + Data *DelegationSignerRecord `json:"data"` +} + +// delegationSignerRecordResponse represents a response from an API method that returns a DelegationSignerRecord struct. +type delegationSignerRecordsResponse struct { + Response + Data []DelegationSignerRecord `json:"data"` +} + +// ListDelegationSignerRecords lists the delegation signer records for a domain. +// +// See https://developer.dnsimple.com/v2/domains/dnssec/#ds-record-list +func (s *DomainsService) ListDelegationSignerRecords(accountID string, domainIdentifier string, options *ListOptions) (*delegationSignerRecordsResponse, error) { + path := versioned(delegationSignerRecordPath(accountID, domainIdentifier, 0)) + dsRecordsResponse := &delegationSignerRecordsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, dsRecordsResponse) + if err != nil { + return nil, err + } + + dsRecordsResponse.HttpResponse = resp + return dsRecordsResponse, nil +} + +// CreateDelegationSignerRecord creates a new delegation signer record. +// +// See https://developer.dnsimple.com/v2/domains/dnssec/#ds-record-create +func (s *DomainsService) CreateDelegationSignerRecord(accountID string, domainIdentifier string, dsRecordAttributes DelegationSignerRecord) (*delegationSignerRecordResponse, error) { + path := versioned(delegationSignerRecordPath(accountID, domainIdentifier, 0)) + dsRecordResponse := &delegationSignerRecordResponse{} + + resp, err := s.client.post(path, dsRecordAttributes, dsRecordResponse) + if err != nil { + return nil, err + } + + dsRecordResponse.HttpResponse = resp + return dsRecordResponse, nil +} + +// GetDelegationSignerRecord fetches a delegation signer record. +// +// See https://developer.dnsimple.com/v2/domains/dnssec/#ds-record-get +func (s *DomainsService) GetDelegationSignerRecord(accountID string, domainIdentifier string, dsRecordID int) (*delegationSignerRecordResponse, error) { + path := versioned(delegationSignerRecordPath(accountID, domainIdentifier, dsRecordID)) + dsRecordResponse := &delegationSignerRecordResponse{} + + resp, err := s.client.get(path, dsRecordResponse) + if err != nil { + return nil, err + } + + dsRecordResponse.HttpResponse = resp + return dsRecordResponse, nil +} + +// DeleteDelegationSignerRecord PERMANENTLY deletes a delegation signer record +// from the domain. +// +// See https://developer.dnsimple.com/v2/domains/dnssec/#ds-record-delete +func (s *DomainsService) DeleteDelegationSignerRecord(accountID string, domainIdentifier string, dsRecordID int) (*delegationSignerRecordResponse, error) { + path := versioned(delegationSignerRecordPath(accountID, domainIdentifier, dsRecordID)) + dsRecordResponse := &delegationSignerRecordResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + dsRecordResponse.HttpResponse = resp + return dsRecordResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_dnssec.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_dnssec.go new file mode 100644 index 000000000..d8d1cf06c --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_dnssec.go @@ -0,0 +1,68 @@ +package dnsimple + +import "fmt" + +// Dnssec represents the current DNSSEC settings for a domain in DNSimple. +type Dnssec struct { + Enabled bool `json:"enabled"` +} + +func dnssecPath(accountID string, domainIdentifier string) (path string) { + path = fmt.Sprintf("%v/dnssec", domainPath(accountID, domainIdentifier)) + return +} + +// dnssecResponse represents a response from an API method that returns a Dnssec struct. +type dnssecResponse struct { + Response + Data *Dnssec `json:"data"` +} + +// EnableDnssec enables DNSSEC on the domain. +// +// See https://developer.dnsimple.com/v2/domains/dnssec/#enable + +func (s *DomainsService) EnableDnssec(accountID string, domainIdentifier string) (*dnssecResponse, error) { + path := versioned(dnssecPath(accountID, domainIdentifier)) + dnssecResponse := &dnssecResponse{} + + resp, err := s.client.post(path, dnssecResponse, nil) + if err != nil { + return nil, err + } + + dnssecResponse.HttpResponse = resp + return dnssecResponse, nil +} + +// DisableDnssec disables DNSSEC on the domain. +// +// See https://developer.dnsimple.com/v2/domains/dnssec/#disable +func (s *DomainsService) DisableDnssec(accountID string, domainIdentifier string) (*dnssecResponse, error) { + path := versioned(dnssecPath(accountID, domainIdentifier)) + dnssecResponse := &dnssecResponse{} + + resp, err := s.client.delete(path, dnssecResponse, nil) + if err != nil { + return nil, err + } + + dnssecResponse.HttpResponse = resp + return dnssecResponse, nil +} + +// GetDnssec retrieves the current status of DNSSEC on the domain. +// +// See https://developer.dnsimple.com/v2/domains/dnssec/#get +func (s *DomainsService) GetDnssec(accountID string, domainIdentifier string) (*dnssecResponse, error) { + path := versioned(dnssecPath(accountID, domainIdentifier)) + dnssecResponse := &dnssecResponse{} + + resp, err := s.client.get(path, dnssecResponse) + if err != nil { + return nil, err + } + + dnssecResponse.HttpResponse = resp + return dnssecResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_email_forwards.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_email_forwards.go new file mode 100644 index 000000000..599f86b08 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_email_forwards.go @@ -0,0 +1,104 @@ +package dnsimple + +import ( + "fmt" +) + +// EmailForward represents an email forward in DNSimple. +type EmailForward struct { + ID int `json:"id,omitempty"` + DomainID int `json:"domain_id,omitempty"` + From string `json:"from,omitempty"` + To string `json:"to,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +func emailForwardPath(accountID string, domainIdentifier string, forwardID int) (path string) { + path = fmt.Sprintf("%v/email_forwards", domainPath(accountID, domainIdentifier)) + if forwardID != 0 { + path += fmt.Sprintf("/%d", forwardID) + } + return +} + +// emailForwardResponse represents a response from an API method that returns an EmailForward struct. +type emailForwardResponse struct { + Response + Data *EmailForward `json:"data"` +} + +// emailForwardsResponse represents a response from an API method that returns a collection of EmailForward struct. +type emailForwardsResponse struct { + Response + Data []EmailForward `json:"data"` +} + +// ListEmailForwards lists the email forwards for a domain. +// +// See https://developer.dnsimple.com/v2/domains/email-forwards/#list +func (s *DomainsService) ListEmailForwards(accountID string, domainIdentifier string, options *ListOptions) (*emailForwardsResponse, error) { + path := versioned(emailForwardPath(accountID, domainIdentifier , 0)) + forwardsResponse := &emailForwardsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, forwardsResponse) + if err != nil { + return nil, err + } + + forwardsResponse.HttpResponse = resp + return forwardsResponse, nil +} + +// CreateEmailForward creates a new email forward. +// +// See https://developer.dnsimple.com/v2/domains/email-forwards/#create +func (s *DomainsService) CreateEmailForward(accountID string, domainIdentifier string, forwardAttributes EmailForward) (*emailForwardResponse, error) { + path := versioned(emailForwardPath(accountID, domainIdentifier, 0)) + forwardResponse := &emailForwardResponse{} + + resp, err := s.client.post(path, forwardAttributes, forwardResponse) + if err != nil { + return nil, err + } + + forwardResponse.HttpResponse = resp + return forwardResponse, nil +} + +// GetEmailForward fetches an email forward. +// +// See https://developer.dnsimple.com/v2/domains/email-forwards/#get +func (s *DomainsService) GetEmailForward(accountID string, domainIdentifier string, forwardID int) (*emailForwardResponse, error) { + path := versioned(emailForwardPath(accountID, domainIdentifier, forwardID)) + forwardResponse := &emailForwardResponse{} + + resp, err := s.client.get(path, forwardResponse) + if err != nil { + return nil, err + } + + forwardResponse.HttpResponse = resp + return forwardResponse, nil +} + +// DeleteEmailForward PERMANENTLY deletes an email forward from the domain. +// +// See https://developer.dnsimple.com/v2/domains/email-forwards/#delete +func (s *DomainsService) DeleteEmailForward(accountID string, domainIdentifier string, forwardID int) (*emailForwardResponse, error) { + path := versioned(emailForwardPath(accountID, domainIdentifier, forwardID)) + forwardResponse := &emailForwardResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + forwardResponse.HttpResponse = resp + return forwardResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_pushes.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_pushes.go new file mode 100644 index 000000000..93c75be36 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/domains_pushes.go @@ -0,0 +1,111 @@ +package dnsimple + +import ( + "fmt" +) + +// DomainPush represents a domain push in DNSimple. +type DomainPush struct { + ID int `json:"id,omitempty"` + DomainID int `json:"domain_id,omitempty"` + ContactID int `json:"contact_id,omitempty"` + AccountID int `json:"account_id,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + AcceptedAt string `json:"accepted_at,omitempty"` +} + +func domainPushPath(accountID string, pushID int) (path string) { + path = fmt.Sprintf("/%v/pushes", accountID) + if pushID != 0 { + path += fmt.Sprintf("/%d", pushID) + } + return +} + +// domainPushResponse represents a response from an API method that returns a DomainPush struct. +type domainPushResponse struct { + Response + Data *DomainPush `json:"data"` +} + +// domainPushesResponse represents a response from an API method that returns a collection of DomainPush struct. +type domainPushesResponse struct { + Response + Data []DomainPush `json:"data"` +} + +// DomainPushAttributes represent a domain push payload (see initiate). +type DomainPushAttributes struct { + NewAccountEmail string `json:"new_account_email,omitempty"` + ContactID string `json:"contact_id,omitempty"` +} + +// InitiatePush initiate a new domain push. +// +// See https://developer.dnsimple.com/v2/domains/pushes/#initiate +func (s *DomainsService) InitiatePush(accountID string, domainID string, pushAttributes DomainPushAttributes) (*domainPushResponse, error) { + path := versioned(fmt.Sprintf("/%v/pushes", domainPath(accountID, domainID))) + pushResponse := &domainPushResponse{} + + resp, err := s.client.post(path, pushAttributes, pushResponse) + if err != nil { + return nil, err + } + + pushResponse.HttpResponse = resp + return pushResponse, nil +} + +// ListPushes lists the pushes for an account. +// +// See https://developer.dnsimple.com/v2/domains/pushes/#list +func (s *DomainsService) ListPushes(accountID string, options *ListOptions) (*domainPushesResponse, error) { + path := versioned(domainPushPath(accountID, 0)) + pushesResponse := &domainPushesResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, pushesResponse) + if err != nil { + return nil, err + } + + pushesResponse.HttpResponse = resp + return pushesResponse, nil +} + +// AcceptPush accept a push for a domain. +// +// See https://developer.dnsimple.com/v2/domains/pushes/#accept +func (s *DomainsService) AcceptPush(accountID string, pushID int, pushAttributes DomainPushAttributes) (*domainPushResponse, error) { + path := versioned(domainPushPath(accountID, pushID)) + pushResponse := &domainPushResponse{} + + resp, err := s.client.post(path, pushAttributes, nil) + if err != nil { + return nil, err + } + + pushResponse.HttpResponse = resp + return pushResponse, nil +} + +// RejectPush reject a push for a domain. +// +// See https://developer.dnsimple.com/v2/domains/pushes/#reject +func (s *DomainsService) RejectPush(accountID string, pushID int) (*domainPushResponse, error) { + path := versioned(domainPushPath(accountID, pushID)) + pushResponse := &domainPushResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + pushResponse.HttpResponse = resp + return pushResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/identity.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/identity.go new file mode 100644 index 000000000..be7ca9ea8 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/identity.go @@ -0,0 +1,48 @@ +package dnsimple + +// IdentityService handles communication with several authentication identity +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/identity/ +type IdentityService struct { + client *Client +} + +// WhoamiData represents an authenticated context +// that contains information about the current logged User and/or Account. +type WhoamiData struct { + User *User `json:"user,omitempty"` + Account *Account `json:"account,omitempty"` +} + +// whoamiResponse represents a response from an API method that returns a Whoami struct. +type whoamiResponse struct { + Response + Data *WhoamiData `json:"data"` +} + +// Whoami gets the current authenticate context. +// +// See https://developer.dnsimple.com/v2/whoami +func (s *IdentityService) Whoami() (*whoamiResponse, error) { + path := versioned("/whoami") + whoamiResponse := &whoamiResponse{} + + resp, err := s.client.get(path, whoamiResponse) + if err != nil { + return nil, err + } + + whoamiResponse.HttpResponse = resp + return whoamiResponse, nil +} + +// Whoami is a state-less shortcut to client.Whoami() +// that returns only the relevant Data. +func Whoami(c *Client) (data *WhoamiData, err error) { + resp, err := c.Identity.Whoami() + if resp != nil { + data = resp.Data + } + return +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/oauth.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/oauth.go new file mode 100644 index 000000000..fc209891c --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/oauth.go @@ -0,0 +1,113 @@ +package dnsimple + +import ( + "encoding/json" + "fmt" + "net/http" + "net/url" + "strings" +) + +// GrantType is a string that identifies a particular grant type in the exchange request. +type GrantType string + +const ( + // AuthorizationCodeGrant is the type of access token request + // for an Authorization Code Grant flow. + // https://tools.ietf.org/html/rfc6749#section-4.1 + AuthorizationCodeGrant = GrantType("authorization_code") +) + +// OauthService handles communication with the authorization related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/oauth/ +type OauthService struct { + client *Client +} + +// AccessToken represents a DNSimple Oauth access token. +type AccessToken struct { + Token string `json:"access_token"` + Type string `json:"token_type"` + AccountID int `json:"account_id"` +} + +// ExchangeAuthorizationRequest represents a request to exchange +// an authorization code for an access token. +// RedirectURI is optional, all the other fields are mandatory. +type ExchangeAuthorizationRequest struct { + Code string `json:"code"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` + RedirectURI string `json:"redirect_uri,omitempty"` + State string `json:"state,omitempty"` + GrantType GrantType `json:"grant_type,omitempty"` +} + +// ExchangeAuthorizationError represents a failed request to exchange +// an authorization code for an access token. +type ExchangeAuthorizationError struct { + // HTTP response + HttpResponse *http.Response + + ErrorCode string `json:"error"` + ErrorDescription string `json:"error_description"` +} + +// Error implements the error interface. +func (r *ExchangeAuthorizationError) Error() string { + return fmt.Sprintf("%v %v: %v %v", + r.HttpResponse.Request.Method, r.HttpResponse.Request.URL, + r.ErrorCode, r.ErrorDescription) +} + +// ExchangeAuthorizationForToken exchanges the short-lived authorization code for an access token +// you can use to authenticate your API calls. +func (s *OauthService) ExchangeAuthorizationForToken(authorization *ExchangeAuthorizationRequest) (*AccessToken, error) { + path := versioned("/oauth/access_token") + + req, err := s.client.NewRequest("POST", path, authorization) + if err != nil { + return nil, err + } + + resp, err := s.client.HttpClient.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != 200 { + errorResponse := &ExchangeAuthorizationError{} + errorResponse.HttpResponse = resp + json.NewDecoder(resp.Body).Decode(errorResponse) + return nil, errorResponse + } + + accessToken := &AccessToken{} + err = json.NewDecoder(resp.Body).Decode(accessToken) + + return accessToken, err +} + +// AuthorizationOptions represents the option you can use to generate an authorization URL. +type AuthorizationOptions struct { + RedirectURI string `url:"redirect_uri,omitempty"` + // A randomly generated string to verify the validity of the request. + // Currently "state" is required by the DNSimple OAuth implementation, so you must specify it. + State string `url:"state,omitempty"` +} + +// AuthorizeURL generates the URL to authorize an user for an application via the OAuth2 flow. +func (s *OauthService) AuthorizeURL(clientID string, options *AuthorizationOptions) string { + uri, _ := url.Parse(strings.Replace(s.client.BaseURL, "api.", "", 1)) + uri.Path = "/oauth/authorize" + query := uri.Query() + query.Add("client_id", clientID) + query.Add("response_type", "code") + uri.RawQuery = query.Encode() + + path, _ := addURLQueryOptions(uri.String(), options) + return path +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar.go new file mode 100644 index 000000000..e89b1a429 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar.go @@ -0,0 +1,258 @@ +package dnsimple + +import ( + "fmt" +) + +// RegistrarService handles communication with the registrar related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/registrar/ +type RegistrarService struct { + client *Client +} + +// DomainCheck represents the result of a domain check. +type DomainCheck struct { + Domain string `json:"domain"` + Available bool `json:"available"` + Premium bool `json:"premium"` +} + +// domainCheckResponse represents a response from a domain check request. +type domainCheckResponse struct { + Response + Data *DomainCheck `json:"data"` +} + +// CheckDomain checks a domain name. +// +// See https://developer.dnsimple.com/v2/registrar/#check +func (s *RegistrarService) CheckDomain(accountID, domainName string) (*domainCheckResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/check", accountID, domainName)) + checkResponse := &domainCheckResponse{} + + resp, err := s.client.get(path, checkResponse) + if err != nil { + return nil, err + } + + checkResponse.HttpResponse = resp + return checkResponse, nil +} + +// DomainPremiumPrice represents the premium price for a premium domain. +type DomainPremiumPrice struct { + // The domain premium price + PremiumPrice string `json:"premium_price"` + // The registrar action. + // Possible values are registration|transfer|renewal + Action string `json:"action"` +} + +// domainPremiumPriceResponse represents a response from a domain premium price request. +type domainPremiumPriceResponse struct { + Response + Data *DomainPremiumPrice `json:"data"` +} + +// DomainPremiumPriceOptions specifies the optional parameters you can provide +// to customize the RegistrarService.GetDomainPremiumPrice method. +type DomainPremiumPriceOptions struct { + Action string `url:"action,omitempty"` +} + +// Gets the premium price for a domain. +// +// You must specify an action to get the price for. Valid actions are: +// - registration +// - transfer +// - renewal +// +// See https://developer.dnsimple.com/v2/registrar/#premium-price +func (s *RegistrarService) GetDomainPremiumPrice(accountID, domainName string, options *DomainPremiumPriceOptions) (*domainPremiumPriceResponse, error) { + var err error + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/premium_price", accountID, domainName)) + priceResponse := &domainPremiumPriceResponse{} + + if options != nil { + path, err = addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + } + + resp, err := s.client.get(path, priceResponse) + if err != nil { + return nil, err + } + + priceResponse.HttpResponse = resp + return priceResponse, nil +} + +// DomainRegistration represents the result of a domain renewal call. +type DomainRegistration struct { + ID int `json:"id"` + DomainID int `json:"domain_id"` + RegistrantID int `json:"registrant_id"` + Period int `json:"period"` + State string `json:"state"` + AutoRenew bool `json:"auto_renew"` + WhoisPrivacy bool `json:"whois_privacy"` + PremiumPrice string `json:"premium_price"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +// domainRegistrationResponse represents a response from an API method that results in a domain registration. +type domainRegistrationResponse struct { + Response + Data *DomainRegistration `json:"data"` +} + +// DomainRegisterRequest represents the attributes you can pass to a register API request. +// Some attributes are mandatory. +type DomainRegisterRequest struct { + // The ID of the Contact to use as registrant for the domain + RegistrantID int `json:"registrant_id"` + // Set to true to enable the whois privacy service. An extra cost may apply. + // Default to false. + EnableWhoisPrivacy bool `json:"whois_privacy,omitempty"` + // Set to true to enable the auto-renewal of the domain. + // Default to true. + EnableAutoRenewal bool `json:"auto_renew,omitempty"` +} + +// RegisterDomain registers a domain name. +// +// See https://developer.dnsimple.com/v2/registrar/#register +func (s *RegistrarService) RegisterDomain(accountID string, domainName string, request *DomainRegisterRequest) (*domainRegistrationResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/registrations", accountID, domainName)) + registrationResponse := &domainRegistrationResponse{} + + // TODO: validate mandatory attributes RegistrantID + + resp, err := s.client.post(path, request, registrationResponse) + if err != nil { + return nil, err + } + + registrationResponse.HttpResponse = resp + return registrationResponse, nil +} + +// DomainTransfer represents the result of a domain renewal call. +type DomainTransfer struct { + ID int `json:"id"` + DomainID int `json:"domain_id"` + RegistrantID int `json:"registrant_id"` + State string `json:"state"` + AutoRenew bool `json:"auto_renew"` + WhoisPrivacy bool `json:"whois_privacy"` + PremiumPrice string `json:"premium_price"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +// domainTransferResponse represents a response from an API method that results in a domain transfer. +type domainTransferResponse struct { + Response + Data *DomainTransfer `json:"data"` +} + +// DomainTransferRequest represents the attributes you can pass to a transfer API request. +// Some attributes are mandatory. +type DomainTransferRequest struct { + // The ID of the Contact to use as registrant for the domain + RegistrantID int `json:"registrant_id"` + // The Auth-Code required to transfer the domain. + // This is provided by the current registrar of the domain. + AuthCode string `json:"auth_code,omitempty"` + // Set to true to enable the whois privacy service. An extra cost may apply. + // Default to false. + EnableWhoisPrivacy bool `json:"whois_privacy,omitempty"` + // Set to true to enable the auto-renewal of the domain. + // Default to true. + EnableAutoRenewal bool `json:"auto_renew,omitempty"` +} + +// TransferDomain transfers a domain name. +// +// See https://developer.dnsimple.com/v2/registrar/#transfer +func (s *RegistrarService) TransferDomain(accountID string, domainName string, request *DomainTransferRequest) (*domainTransferResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/transfers", accountID, domainName)) + transferResponse := &domainTransferResponse{} + + // TODO: validate mandatory attributes RegistrantID + + resp, err := s.client.post(path, request, transferResponse) + if err != nil { + return nil, err + } + + transferResponse.HttpResponse = resp + return transferResponse, nil +} + +// domainTransferOutResponse represents a response from an API method that results in a domain transfer out. +type domainTransferOutResponse struct { + Response + Data *Domain `json:"data"` +} + +// Transfer out a domain name. +// +// See https://developer.dnsimple.com/v2/registrar/#transfer-out +func (s *RegistrarService) TransferDomainOut(accountID string, domainName string) (*domainTransferOutResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/authorize_transfer_out", accountID, domainName)) + transferResponse := &domainTransferOutResponse{} + + resp, err := s.client.post(path, nil, nil) + if err != nil { + return nil, err + } + + transferResponse.HttpResponse = resp + return transferResponse, nil +} + +// DomainRenewal represents the result of a domain renewal call. +type DomainRenewal struct { + ID int `json:"id"` + DomainID int `json:"domain_id"` + Period int `json:"period"` + State string `json:"state"` + PremiumPrice string `json:"premium_price"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +// domainRenewalResponse represents a response from an API method that returns a domain renewal. +type domainRenewalResponse struct { + Response + Data *DomainRenewal `json:"data"` +} + +// DomainRenewRequest represents the attributes you can pass to a renew API request. +// Some attributes are mandatory. +type DomainRenewRequest struct { + // The number of years + Period int `json:"period"` +} + +// RenewDomain renews a domain name. +// +// See https://developer.dnsimple.com/v2/registrar/#register +func (s *RegistrarService) RenewDomain(accountID string, domainName string, request *DomainRenewRequest) (*domainRenewalResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/renewals", accountID, domainName)) + renewalResponse := &domainRenewalResponse{} + + resp, err := s.client.post(path, request, renewalResponse) + if err != nil { + return nil, err + } + + renewalResponse.HttpResponse = resp + return renewalResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_auto_renewal.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_auto_renewal.go new file mode 100644 index 000000000..c98f8d5cd --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_auto_renewal.go @@ -0,0 +1,37 @@ +package dnsimple + +import ( + "fmt" +) + +// EnableDomainAutoRenewal enables auto-renewal for the domain. +// +// See https://developer.dnsimple.com/v2/registrar/auto-renewal/#enable +func (s *RegistrarService) EnableDomainAutoRenewal(accountID string, domainName string) (*domainResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/auto_renewal", accountID, domainName)) + domainResponse := &domainResponse{} + + resp, err := s.client.put(path, nil, nil) + if err != nil { + return nil, err + } + + domainResponse.HttpResponse = resp + return domainResponse, nil +} + +// DisableDomainAutoRenewal disables auto-renewal for the domain. +// +// See https://developer.dnsimple.com/v2/registrar/auto-renewal/#enable +func (s *RegistrarService) DisableDomainAutoRenewal(accountID string, domainName string) (*domainResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/auto_renewal", accountID, domainName)) + domainResponse := &domainResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + domainResponse.HttpResponse = resp + return domainResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_delegation.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_delegation.go new file mode 100644 index 000000000..4ebd3454c --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_delegation.go @@ -0,0 +1,84 @@ +package dnsimple + +import ( + "fmt" +) + +// Delegation represents a list of name servers that correspond to a domain delegation. +type Delegation []string + +// delegationResponse represents a response from an API method that returns a delegation struct. +type delegationResponse struct { + Response + Data *Delegation `json:"data"` +} + +// vanityDelegationResponse represents a response for vanity name server enable and disable operations. +type vanityDelegationResponse struct { + Response + Data []VanityNameServer `json:"data"` +} + +// GetDomainDelegation gets the current delegated name servers for the domain. +// +// See https://developer.dnsimple.com/v2/registrar/delegation/#get +func (s *RegistrarService) GetDomainDelegation(accountID string, domainName string) (*delegationResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/delegation", accountID, domainName)) + delegationResponse := &delegationResponse{} + + resp, err := s.client.get(path, delegationResponse) + if err != nil { + return nil, err + } + + delegationResponse.HttpResponse = resp + return delegationResponse, nil +} + +// ChangeDomainDelegation updates the delegated name severs for the domain. +// +// See https://developer.dnsimple.com/v2/registrar/delegation/#get +func (s *RegistrarService) ChangeDomainDelegation(accountID string, domainName string, newDelegation *Delegation) (*delegationResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/delegation", accountID, domainName)) + delegationResponse := &delegationResponse{} + + resp, err := s.client.put(path, newDelegation, delegationResponse) + if err != nil { + return nil, err + } + + delegationResponse.HttpResponse = resp + return delegationResponse, nil +} + +// ChangeDomainDelegationToVanity enables vanity name servers for the given domain. +// +// See https://developer.dnsimple.com/v2/registrar/delegation/#delegateToVanity +func (s *RegistrarService) ChangeDomainDelegationToVanity(accountID string, domainName string, newDelegation *Delegation) (*vanityDelegationResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/delegation/vanity", accountID, domainName)) + delegationResponse := &vanityDelegationResponse{} + + resp, err := s.client.put(path, newDelegation, delegationResponse) + if err != nil { + return nil, err + } + + delegationResponse.HttpResponse = resp + return delegationResponse, nil +} + +// ChangeDomainDelegationFromVanity disables vanity name servers for the given domain. +// +// See https://developer.dnsimple.com/v2/registrar/delegation/#dedelegateFromVanity +func (s *RegistrarService) ChangeDomainDelegationFromVanity(accountID string, domainName string) (*vanityDelegationResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/delegation/vanity", accountID, domainName)) + delegationResponse := &vanityDelegationResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + delegationResponse.HttpResponse = resp + return delegationResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_whois_privacy.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_whois_privacy.go new file mode 100644 index 000000000..9e0e96931 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/registrar_whois_privacy.go @@ -0,0 +1,69 @@ +package dnsimple + +import ( + "fmt" +) + +// WhoisPrivacy represents a whois privacy in DNSimple. +type WhoisPrivacy struct { + ID int `json:"id,omitempty"` + DomainID int `json:"domain_id,omitempty"` + Enabled bool `json:"enabled,omitempty"` + ExpiresOn string `json:"expires_on,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +// whoisPrivacyResponse represents a response from an API method that returns a WhoisPrivacy struct. +type whoisPrivacyResponse struct { + Response + Data *WhoisPrivacy `json:"data"` +} + +// GetWhoisPrivacy gets the whois privacy for the domain. +// +// See https://developer.dnsimple.com/v2/registrar/whois-privacy/#get +func (s *RegistrarService) GetWhoisPrivacy(accountID string, domainName string) (*whoisPrivacyResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/whois_privacy", accountID, domainName)) + privacyResponse := &whoisPrivacyResponse{} + + resp, err := s.client.get(path, privacyResponse) + if err != nil { + return nil, err + } + + privacyResponse.HttpResponse = resp + return privacyResponse, nil +} + +// EnableWhoisPrivacy enables the whois privacy for the domain. +// +// See https://developer.dnsimple.com/v2/registrar/whois-privacy/#enable +func (s *RegistrarService) EnableWhoisPrivacy(accountID string, domainName string) (*whoisPrivacyResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/whois_privacy", accountID, domainName)) + privacyResponse := &whoisPrivacyResponse{} + + resp, err := s.client.put(path, nil, privacyResponse) + if err != nil { + return nil, err + } + + privacyResponse.HttpResponse = resp + return privacyResponse, nil +} + +// DisablePrivacy disables the whois privacy for the domain. +// +// See https://developer.dnsimple.com/v2/registrar/whois-privacy/#enable +func (s *RegistrarService) DisableWhoisPrivacy(accountID string, domainName string) (*whoisPrivacyResponse, error) { + path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/whois_privacy", accountID, domainName)) + privacyResponse := &whoisPrivacyResponse{} + + resp, err := s.client.delete(path, nil, privacyResponse) + if err != nil { + return nil, err + } + + privacyResponse.HttpResponse = resp + return privacyResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/services.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/services.go new file mode 100644 index 000000000..1d63d05c5 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/services.go @@ -0,0 +1,94 @@ +package dnsimple + +import ( + "fmt" +) + +// ServicesService handles communication with the service related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/services/ +type ServicesService struct { + client *Client +} + +// Service represents a Service in DNSimple. +type Service struct { + ID int `json:"id,omitempty"` + SID string `json:"sid,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + SetupDescription string `json:"setup_description,omitempty"` + RequiresSetup bool `json:"requires_setup,omitempty"` + DefaultSubdomain string `json:"default_subdomain,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` + Settings []ServiceSetting `json:"settings,omitempty"` +} + +// ServiceSetting represents a single group of settings for a DNSimple Service. +type ServiceSetting struct { + Name string `json:"name,omitempty"` + Label string `json:"label,omitempty"` + Append string `json:"append,omitempty"` + Description string `json:"description,omitempty"` + Example string `json:"example,omitempty"` + Password bool `json:"password,omitempty"` +} + +func servicePath(serviceID string) (path string) { + path = "/services" + if serviceID != "" { + path += fmt.Sprintf("/%v", serviceID) + } + return +} + +// serviceResponse represents a response from an API method that returns a Service struct. +type serviceResponse struct { + Response + Data *Service `json:"data"` +} + +// servicesResponse represents a response from an API method that returns a collection of Service struct. +type servicesResponse struct { + Response + Data []Service `json:"data"` +} + +// ListServices lists the one-click services available in DNSimple. +// +// See https://developer.dnsimple.com/v2/services/#list +func (s *ServicesService) ListServices(options *ListOptions) (*servicesResponse, error) { + path := versioned(servicePath("")) + servicesResponse := &servicesResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, servicesResponse) + if err != nil { + return servicesResponse, err + } + + servicesResponse.HttpResponse = resp + return servicesResponse, nil +} + +// GetService fetches a one-click service. +// +// See https://developer.dnsimple.com/v2/services/#get +func (s *ServicesService) GetService(serviceIdentifier string) (*serviceResponse, error) { + path := versioned(servicePath(serviceIdentifier)) + serviceResponse := &serviceResponse{} + + resp, err := s.client.get(path, serviceResponse) + if err != nil { + return nil, err + } + + serviceResponse.HttpResponse = resp + return serviceResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/services_domains.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/services_domains.go new file mode 100644 index 000000000..f9889e5a3 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/services_domains.go @@ -0,0 +1,70 @@ +package dnsimple + +import ( + "fmt" +) + +func domainServicesPath(accountID string, domainID string, serviceIdentifier string) string { + if serviceIdentifier != "" { + return fmt.Sprintf("/%v/domains/%v/services/%v", accountID, domainID, serviceIdentifier) + } + return fmt.Sprintf("/%v/domains/%v/services", accountID, domainID) +} + +// DomainServiceSettings represents optional settings when applying a DNSimple one-click service to a domain. +type DomainServiceSettings struct { + Settings map[string]string `url:"settings,omitempty"` +} + +// AppliedServices lists the applied one-click services for a domain. +// +// See https://developer.dnsimple.com/v2/services/domains/#applied +func (s *ServicesService) AppliedServices(accountID string, domainID string, options *ListOptions) (*servicesResponse, error) { + path := versioned(domainServicesPath(accountID, domainID, "")) + servicesResponse := &servicesResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, servicesResponse) + if err != nil { + return servicesResponse, err + } + + servicesResponse.HttpResponse = resp + return servicesResponse, nil +} + +// ApplyService applies a one-click services to a domain. +// +// See https://developer.dnsimple.com/v2/services/domains/#apply +func (s *ServicesService) ApplyService(accountID string, serviceIdentifier string, domainID string, settings DomainServiceSettings) (*serviceResponse, error) { + path := versioned(domainServicesPath(accountID, domainID, serviceIdentifier)) + serviceResponse := &serviceResponse{} + + resp, err := s.client.post(path, settings, nil) + if err != nil { + return nil, err + } + + serviceResponse.HttpResponse = resp + return serviceResponse, nil +} + +// UnapplyService unapplies a one-click services from a domain. +// +// See https://developer.dnsimple.com/v2/services/domains/#unapply +func (s *ServicesService) UnapplyService(accountID string, serviceIdentifier string, domainID string) (*serviceResponse, error) { + path := versioned(domainServicesPath(accountID, domainID, serviceIdentifier)) + serviceResponse := &serviceResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + serviceResponse.HttpResponse = resp + return serviceResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates.go new file mode 100644 index 000000000..2b2503def --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates.go @@ -0,0 +1,129 @@ +package dnsimple + +import ( + "fmt" +) + +// TemplatesService handles communication with the template related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/templates/ +type TemplatesService struct { + client *Client +} + +// Template represents a Template in DNSimple. +type Template struct { + ID int `json:"id,omitempty"` + SID string `json:"sid,omitempty"` + AccountID int `json:"account_id,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +func templatePath(accountID string, templateIdentifier string) (path string) { + path = fmt.Sprintf("/%v/templates", accountID) + if templateIdentifier != "" { + path += fmt.Sprintf("/%v", templateIdentifier) + } + return +} + +// templateResponse represents a response from an API method that returns a Template struct. +type templateResponse struct { + Response + Data *Template `json:"data"` +} + +// templatesResponse represents a response from an API method that returns a collection of Template struct. +type templatesResponse struct { + Response + Data []Template `json:"data"` +} + +// ListTemplates list the templates for an account. +// +// See https://developer.dnsimple.com/v2/templates/#list +func (s *TemplatesService) ListTemplates(accountID string, options *ListOptions) (*templatesResponse, error) { + path := versioned(templatePath(accountID, "")) + templatesResponse := &templatesResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, templatesResponse) + if err != nil { + return templatesResponse, err + } + + templatesResponse.HttpResponse = resp + return templatesResponse, nil +} + +// CreateTemplate creates a new template. +// +// See https://developer.dnsimple.com/v2/templates/#create +func (s *TemplatesService) CreateTemplate(accountID string, templateAttributes Template) (*templateResponse, error) { + path := versioned(templatePath(accountID, "")) + templateResponse := &templateResponse{} + + resp, err := s.client.post(path, templateAttributes, templateResponse) + if err != nil { + return nil, err + } + + templateResponse.HttpResponse = resp + return templateResponse, nil +} + +// GetTemplate fetches a template. +// +// See https://developer.dnsimple.com/v2/templates/#get +func (s *TemplatesService) GetTemplate(accountID string, templateIdentifier string) (*templateResponse, error) { + path := versioned(templatePath(accountID, templateIdentifier)) + templateResponse := &templateResponse{} + + resp, err := s.client.get(path, templateResponse) + if err != nil { + return nil, err + } + + templateResponse.HttpResponse = resp + return templateResponse, nil +} + +// UpdateTemplate updates a template. +// +// See https://developer.dnsimple.com/v2/templates/#update +func (s *TemplatesService) UpdateTemplate(accountID string, templateIdentifier string, templateAttributes Template) (*templateResponse, error) { + path := versioned(templatePath(accountID, templateIdentifier)) + templateResponse := &templateResponse{} + + resp, err := s.client.patch(path, templateAttributes, templateResponse) + if err != nil { + return nil, err + } + + templateResponse.HttpResponse = resp + return templateResponse, nil +} + +// DeleteTemplate deletes a template. +// +// See https://developer.dnsimple.com/v2/templates/#delete +func (s *TemplatesService) DeleteTemplate(accountID string, templateIdentifier string) (*templateResponse, error) { + path := versioned(templatePath(accountID, templateIdentifier)) + templateResponse := &templateResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + templateResponse.HttpResponse = resp + return templateResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates_domains.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates_domains.go new file mode 100644 index 000000000..85ca6678e --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates_domains.go @@ -0,0 +1,21 @@ +package dnsimple + +import ( + "fmt" +) + +// ApplyTemplate applies a template to the given domain. +// +// See https://developer.dnsimple.com/v2/templates/domains/#apply +func (s *TemplatesService) ApplyTemplate(accountID string, templateIdentifier string, domainID string) (*templateResponse, error) { + path := versioned(fmt.Sprintf("%v/templates/%v", domainPath(accountID, domainID), templateIdentifier)) + templateResponse := &templateResponse{} + + resp, err := s.client.post(path, nil, nil) + if err != nil { + return nil, err + } + + templateResponse.HttpResponse = resp + return templateResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates_records.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates_records.go new file mode 100644 index 000000000..e9e717da7 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/templates_records.go @@ -0,0 +1,107 @@ +package dnsimple + +import ( + "fmt" +) + +// TemplateRecord represents a DNS record for a template in DNSimple. +type TemplateRecord struct { + ID int `json:"id,omitempty"` + TemplateID int `json:"template_id,omitempty"` + Name string `json:"name"` + Content string `json:"content,omitempty"` + TTL int `json:"ttl,omitempty"` + Type string `json:"type,omitempty"` + Priority int `json:"priority,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +func templateRecordPath(accountID string, templateIdentifier string, templateRecordID string) string { + if templateRecordID != "" { + return fmt.Sprintf("%v/records/%v", templatePath(accountID, templateIdentifier), templateRecordID) + } + + return templatePath(accountID, templateIdentifier) + "/records" +} + +// templateRecordResponse represents a response from an API method that returns a TemplateRecord struct. +type templateRecordResponse struct { + Response + Data *TemplateRecord `json:"data"` +} + +// templateRecordsResponse represents a response from an API method that returns a collection of TemplateRecord struct. +type templateRecordsResponse struct { + Response + Data []TemplateRecord `json:"data"` +} + +// ListTemplateRecords list the templates for an account. +// +// See https://developer.dnsimple.com/v2/templates/records/#list +func (s *TemplatesService) ListTemplateRecords(accountID string, templateIdentifier string, options *ListOptions) (*templateRecordsResponse, error) { + path := versioned(templateRecordPath(accountID, templateIdentifier, "")) + templateRecordsResponse := &templateRecordsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, templateRecordsResponse) + if err != nil { + return templateRecordsResponse, err + } + + templateRecordsResponse.HttpResponse = resp + return templateRecordsResponse, nil +} + +// CreateTemplateRecord creates a new template record. +// +// See https://developer.dnsimple.com/v2/templates/records/#create +func (s *TemplatesService) CreateTemplateRecord(accountID string, templateIdentifier string, templateRecordAttributes TemplateRecord) (*templateRecordResponse, error) { + path := versioned(templateRecordPath(accountID, templateIdentifier, "")) + templateRecordResponse := &templateRecordResponse{} + + resp, err := s.client.post(path, templateRecordAttributes, templateRecordResponse) + if err != nil { + return nil, err + } + + templateRecordResponse.HttpResponse = resp + return templateRecordResponse, nil +} + +// GetTemplateRecord fetches a template record. +// +// See https://developer.dnsimple.com/v2/templates/records/#get +func (s *TemplatesService) GetTemplateRecord(accountID string, templateIdentifier string, templateRecordID string) (*templateRecordResponse, error) { + path := versioned(templateRecordPath(accountID, templateIdentifier, templateRecordID)) + templateRecordResponse := &templateRecordResponse{} + + resp, err := s.client.get(path, templateRecordResponse) + if err != nil { + return nil, err + } + + templateRecordResponse.HttpResponse = resp + return templateRecordResponse, nil +} + +// DeleteTemplateRecord deletes a template record. +// +// See https://developer.dnsimple.com/v2/templates/records/#delete +func (s *TemplatesService) DeleteTemplateRecord(accountID string, templateIdentifier string, templateRecordID string) (*templateRecordResponse, error) { + path := versioned(templateRecordPath(accountID, templateIdentifier, templateRecordID)) + templateRecordResponse := &templateRecordResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + templateRecordResponse.HttpResponse = resp + return templateRecordResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/tlds.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/tlds.go new file mode 100644 index 000000000..ee0da04fe --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/tlds.go @@ -0,0 +1,117 @@ +package dnsimple + +import ( + "fmt" +) + +// TldsService handles communication with the Tld related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/tlds/ +type TldsService struct { + client *Client +} + +// Tld represents a TLD in DNSimple. +type Tld struct { + Tld string `json:"tld"` + TldType int `json:"tld_type"` + WhoisPrivacy bool `json:"whois_privacy"` + AutoRenewOnly bool `json:"auto_renew_only"` + MinimumRegistration int `json:"minimum_registration"` + RegistrationEnabled bool `json:"registration_enabled"` + RenewalEnabled bool `json:"renewal_enabled"` + TransferEnabled bool `json:"transfer_enabled"` +} + +// TldExtendedAttribute represents an extended attributes supported or required +// by a specific TLD. +// +// See https://developer.dnsimple.com/v2/tlds/ +type TldExtendedAttribute struct { + Name string `json:"name"` + Description string `json:"description"` + Required bool `json:"required"` + Options []TldExtendedAttributeOption `json:"options"` +} + +// TldExtendedAttributeOption represents a single option you can assign to an extended attributes. +// +// See https://developer.dnsimple.com/v2/tlds/ +type TldExtendedAttributeOption struct { + Title string `json:"title"` + Value string `json:"value"` + Description string `json:"description"` +} + +// tldResponse represents a response from an API method that returns a Tld struct. +type tldResponse struct { + Response + Data *Tld `json:"data"` +} + +// tldsResponse represents a response from an API method that returns a collection of Tld struct. +type tldsResponse struct { + Response + Data []Tld `json:"data"` +} + +// tldExtendedAttributesResponse represents a response from an API method that returns +// a collection of Tld extended attributes. +type tldExtendedAttributesResponse struct { + Response + Data []TldExtendedAttribute `json:"data"` +} + +// ListTlds lists the supported TLDs. +// +// See https://developer.dnsimple.com/v2/tlds/#list +func (s *TldsService) ListTlds(options *ListOptions) (*tldsResponse, error) { + path := versioned("/tlds") + tldsResponse := &tldsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, tldsResponse) + if err != nil { + return tldsResponse, err + } + + tldsResponse.HttpResponse = resp + return tldsResponse, nil +} + +// GetTld fetches a TLD. +// +// See https://developer.dnsimple.com/v2/tlds/#get +func (s *TldsService) GetTld(tld string) (*tldResponse, error) { + path := versioned(fmt.Sprintf("/tlds/%s", tld)) + tldResponse := &tldResponse{} + + resp, err := s.client.get(path, tldResponse) + if err != nil { + return nil, err + } + + tldResponse.HttpResponse = resp + return tldResponse, nil +} + +// GetTld fetches the extended attributes of a TLD. +// +// See https://developer.dnsimple.com/v2/tlds/#get +func (s *TldsService) GetTldExtendedAttributes(tld string) (*tldExtendedAttributesResponse, error) { + path := versioned(fmt.Sprintf("/tlds/%s/extended_attributes", tld)) + tldResponse := &tldExtendedAttributesResponse{} + + resp, err := s.client.get(path, tldResponse) + if err != nil { + return nil, err + } + + tldResponse.HttpResponse = resp + return tldResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/users.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/users.go new file mode 100644 index 000000000..90cd25b90 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/users.go @@ -0,0 +1,7 @@ +package dnsimple + +// User represents a DNSimple user. +type User struct { + ID int `json:"id,omitempty"` + Email string `json:"email,omitempty"` +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/vanity_name_server.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/vanity_name_server.go new file mode 100644 index 000000000..f5d786cbb --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/vanity_name_server.go @@ -0,0 +1,65 @@ +package dnsimple + +import ( + "fmt" +) + +// VanityNameServersService handles communication with Vanity Name Servers +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/vanity/ +type VanityNameServersService struct { + client *Client +} + +// VanityNameServer represents data for a single vanity name server +type VanityNameServer struct { + ID int `json:"id,omitempty"` + Name string `json:"name,omitempty"` + IPv4 string `json:"ipv4,omitempty"` + IPv6 string `json:"ipv6,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +func vanityNameServerPath(accountID string, domainID string) string { + return fmt.Sprintf("/%v/vanity/%v", accountID, domainID) +} + +// vanityNameServerResponse represents a response for vanity name server enable and disable operations. +type vanityNameServerResponse struct { + Response + Data []VanityNameServer `json:"data"` +} + +// EnableVanityNameServers Vanity Name Servers for the given domain +// +// See https://developer.dnsimple.com/v2/vanity/#enable +func (s *VanityNameServersService) EnableVanityNameServers(accountID string, domainID string) (*vanityNameServerResponse, error) { + path := versioned(vanityNameServerPath(accountID, domainID)) + vanityNameServerResponse := &vanityNameServerResponse{} + + resp, err := s.client.put(path, nil, vanityNameServerResponse) + if err != nil { + return nil, err + } + + vanityNameServerResponse.HttpResponse = resp + return vanityNameServerResponse, nil +} + +// DisableVanityNameServers Vanity Name Servers for the given domain +// +// See https://developer.dnsimple.com/v2/vanity/#disable +func (s *VanityNameServersService) DisableVanityNameServers(accountID string, domainID string) (*vanityNameServerResponse, error) { + path := versioned(vanityNameServerPath(accountID, domainID)) + vanityNameServerResponse := &vanityNameServerResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + vanityNameServerResponse.HttpResponse = resp + return vanityNameServerResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/webhooks.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/webhooks.go new file mode 100644 index 000000000..a5614944b --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/webhooks.go @@ -0,0 +1,103 @@ +package dnsimple + +import ( + "fmt" +) + +// WebhooksService handles communication with the webhook related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/webhooks +type WebhooksService struct { + client *Client +} + +// Webhook represents a DNSimple webhook. +type Webhook struct { + ID int `json:"id,omitempty"` + URL string `json:"url,omitempty"` +} + +func webhookPath(accountID string, webhookID int) (path string) { + path = fmt.Sprintf("/%v/webhooks", accountID) + if webhookID != 0 { + path = fmt.Sprintf("%v/%v", path, webhookID) + } + return +} + +// webhookResponse represents a response from an API method that returns a Webhook struct. +type webhookResponse struct { + Response + Data *Webhook `json:"data"` +} + +// webhookResponse represents a response from an API method that returns a collection of Webhook struct. +type webhooksResponse struct { + Response + Data []Webhook `json:"data"` +} + +// ListWebhooks lists the webhooks for an account. +// +// See https://developer.dnsimple.com/v2/webhooks#list +func (s *WebhooksService) ListWebhooks(accountID string, _ *ListOptions) (*webhooksResponse, error) { + path := versioned(webhookPath(accountID, 0)) + webhooksResponse := &webhooksResponse{} + + resp, err := s.client.get(path, webhooksResponse) + if err != nil { + return webhooksResponse, err + } + + webhooksResponse.HttpResponse = resp + return webhooksResponse, nil +} + +// CreateWebhook creates a new webhook. +// +// See https://developer.dnsimple.com/v2/webhooks#create +func (s *WebhooksService) CreateWebhook(accountID string, webhookAttributes Webhook) (*webhookResponse, error) { + path := versioned(webhookPath(accountID, 0)) + webhookResponse := &webhookResponse{} + + resp, err := s.client.post(path, webhookAttributes, webhookResponse) + if err != nil { + return nil, err + } + + webhookResponse.HttpResponse = resp + return webhookResponse, nil +} + +// GetWebhook fetches a webhook. +// +// See https://developer.dnsimple.com/v2/webhooks#get +func (s *WebhooksService) GetWebhook(accountID string, webhookID int) (*webhookResponse, error) { + path := versioned(webhookPath(accountID, webhookID)) + webhookResponse := &webhookResponse{} + + resp, err := s.client.get(path, webhookResponse) + if err != nil { + return nil, err + } + + webhookResponse.HttpResponse = resp + return webhookResponse, nil +} + +// DeleteWebhook PERMANENTLY deletes a webhook from the account. +// +// See https://developer.dnsimple.com/v2/webhooks#delete +func (s *WebhooksService) DeleteWebhook(accountID string, webhookID int) (*webhookResponse, error) { + path := versioned(webhookPath(accountID, webhookID)) + webhookResponse := &webhookResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + webhookResponse.HttpResponse = resp + return webhookResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/zones.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/zones.go new file mode 100644 index 000000000..80652cb99 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/zones.go @@ -0,0 +1,108 @@ +package dnsimple + +import ( + "fmt" +) + +// ZonesService handles communication with the zone related +// methods of the DNSimple API. +// +// See https://developer.dnsimple.com/v2/zones/ +type ZonesService struct { + client *Client +} + +// Zone represents a Zone in DNSimple. +type Zone struct { + ID int `json:"id,omitempty"` + AccountID int `json:"account_id,omitempty"` + Name string `json:"name,omitempty"` + Reverse bool `json:"reverse,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +// ZoneFile represents a Zone File in DNSimple. +type ZoneFile struct { + Zone string `json:"zone,omitempty"` +} + +// zoneResponse represents a response from an API method that returns a Zone struct. +type zoneResponse struct { + Response + Data *Zone `json:"data"` +} + +// zonesResponse represents a response from an API method that returns a collection of Zone struct. +type zonesResponse struct { + Response + Data []Zone `json:"data"` +} + +// zoneFileResponse represents a response from an API method that returns a ZoneFile struct. +type zoneFileResponse struct { + Response + Data *ZoneFile `json:"data"` +} + +// ZoneListOptions specifies the optional parameters you can provide +// to customize the ZonesService.ListZones method. +type ZoneListOptions struct { + // Select domains where the name contains given string. + NameLike string `url:"name_like,omitempty"` + + ListOptions +} + +// ListZones the zones for an account. +// +// See https://developer.dnsimple.com/v2/zones/#list +func (s *ZonesService) ListZones(accountID string, options *ZoneListOptions) (*zonesResponse, error) { + path := versioned(fmt.Sprintf("/%v/zones", accountID)) + zonesResponse := &zonesResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, zonesResponse) + if err != nil { + return zonesResponse, err + } + + zonesResponse.HttpResponse = resp + return zonesResponse, nil +} + +// GetZone fetches a zone. +// +// See https://developer.dnsimple.com/v2/zones/#get +func (s *ZonesService) GetZone(accountID string, zoneName string) (*zoneResponse, error) { + path := versioned(fmt.Sprintf("/%v/zones/%v", accountID, zoneName)) + zoneResponse := &zoneResponse{} + + resp, err := s.client.get(path, zoneResponse) + if err != nil { + return nil, err + } + + zoneResponse.HttpResponse = resp + return zoneResponse, nil +} + +// GetZoneFile fetches a zone file. +// +// See https://developer.dnsimple.com/v2/zones/#get-file +func (s *ZonesService) GetZoneFile(accountID string, zoneName string) (*zoneFileResponse, error) { + path := versioned(fmt.Sprintf("/%v/zones/%v/file", accountID, zoneName)) + zoneFileResponse := &zoneFileResponse{} + + resp, err := s.client.get(path, zoneFileResponse) + if err != nil { + return nil, err + } + + zoneFileResponse.HttpResponse = resp + return zoneFileResponse, nil +} diff --git a/vendor/github.com/dnsimple/dnsimple-go/dnsimple/zones_records.go b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/zones_records.go new file mode 100644 index 000000000..99d099277 --- /dev/null +++ b/vendor/github.com/dnsimple/dnsimple-go/dnsimple/zones_records.go @@ -0,0 +1,142 @@ +package dnsimple + +import ( + "fmt" +) + +// ZoneRecord represents a DNS record in DNSimple. +type ZoneRecord struct { + ID int `json:"id,omitempty"` + ZoneID string `json:"zone_id,omitempty"` + ParentID int `json:"parent_id,omitempty"` + Type string `json:"type,omitempty"` + Name string `json:"name"` + Content string `json:"content,omitempty"` + TTL int `json:"ttl,omitempty"` + Priority int `json:"priority,omitempty"` + SystemRecord bool `json:"system_record,omitempty"` + Regions []string `json:"regions,omitempty"` + CreatedAt string `json:"created_at,omitempty"` + UpdatedAt string `json:"updated_at,omitempty"` +} + +func zoneRecordPath(accountID string, zoneID string, recordID int) (path string) { + path = fmt.Sprintf("/%v/zones/%v/records", accountID, zoneID) + if recordID != 0 { + path += fmt.Sprintf("/%d", recordID) + } + return +} + +// zoneRecordResponse represents a response from an API method that returns a ZoneRecord struct. +type zoneRecordResponse struct { + Response + Data *ZoneRecord `json:"data"` +} + +// zoneRecordsResponse represents a response from an API method that returns a collection of ZoneRecord struct. +type zoneRecordsResponse struct { + Response + Data []ZoneRecord `json:"data"` +} + +// ZoneRecordListOptions specifies the optional parameters you can provide +// to customize the ZonesService.ListZoneRecords method. +type ZoneRecordListOptions struct { + // Select records where the name matches given string. + Name string `url:"name,omitempty"` + + // Select records where the name contains given string. + NameLike string `url:"name_like,omitempty"` + + // Select records of given type. + // Eg. TXT, A, NS. + Type string `url:"record_type,omitempty"` + + ListOptions +} + +// ListRecords lists the zone records for a zone. +// +// See https://developer.dnsimple.com/v2/zones/#list +func (s *ZonesService) ListRecords(accountID string, zoneID string, options *ZoneRecordListOptions) (*zoneRecordsResponse, error) { + path := versioned(zoneRecordPath(accountID, zoneID, 0)) + recordsResponse := &zoneRecordsResponse{} + + path, err := addURLQueryOptions(path, options) + if err != nil { + return nil, err + } + + resp, err := s.client.get(path, recordsResponse) + if err != nil { + return nil, err + } + + recordsResponse.HttpResponse = resp + return recordsResponse, nil +} + +// CreateRecord creates a zone record. +// +// See https://developer.dnsimple.com/v2/zones/#create +func (s *ZonesService) CreateRecord(accountID string, zoneID string, recordAttributes ZoneRecord) (*zoneRecordResponse, error) { + path := versioned(zoneRecordPath(accountID, zoneID, 0)) + recordResponse := &zoneRecordResponse{} + + resp, err := s.client.post(path, recordAttributes, recordResponse) + if err != nil { + return nil, err + } + + recordResponse.HttpResponse = resp + return recordResponse, nil +} + +// GetRecord fetches a zone record. +// +// See https://developer.dnsimple.com/v2/zones/#get +func (s *ZonesService) GetRecord(accountID string, zoneID string, recordID int) (*zoneRecordResponse, error) { + path := versioned(zoneRecordPath(accountID, zoneID, recordID)) + recordResponse := &zoneRecordResponse{} + + resp, err := s.client.get(path, recordResponse) + if err != nil { + return nil, err + } + + recordResponse.HttpResponse = resp + return recordResponse, nil +} + +// UpdateRecord updates a zone record. +// +// See https://developer.dnsimple.com/v2/zones/#update +func (s *ZonesService) UpdateRecord(accountID string, zoneID string, recordID int, recordAttributes ZoneRecord) (*zoneRecordResponse, error) { + path := versioned(zoneRecordPath(accountID, zoneID, recordID)) + recordResponse := &zoneRecordResponse{} + resp, err := s.client.patch(path, recordAttributes, recordResponse) + + if err != nil { + return nil, err + } + + recordResponse.HttpResponse = resp + return recordResponse, nil +} + +// DeleteRecord PERMANENTLY deletes a zone record from the zone. +// +// See https://developer.dnsimple.com/v2/zones/#delete +func (s *ZonesService) DeleteRecord(accountID string, zoneID string, recordID int) (*zoneRecordResponse, error) { + path := versioned(zoneRecordPath(accountID, zoneID, recordID)) + recordResponse := &zoneRecordResponse{} + + resp, err := s.client.delete(path, nil, nil) + if err != nil { + return nil, err + } + + recordResponse.HttpResponse = resp + return recordResponse, nil +} diff --git a/vendor/github.com/weppos/dnsimple-go/LICENSE b/vendor/github.com/weppos/dnsimple-go/LICENSE deleted file mode 100644 index 5377f6dae..000000000 --- a/vendor/github.com/weppos/dnsimple-go/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Scott Barron - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/weppos/dnsimple-go/dnsimple/authentication.go b/vendor/github.com/weppos/dnsimple-go/dnsimple/authentication.go deleted file mode 100644 index cd3a823c4..000000000 --- a/vendor/github.com/weppos/dnsimple-go/dnsimple/authentication.go +++ /dev/null @@ -1,73 +0,0 @@ -package dnsimple - -import ( - "encoding/base64" - "fmt" -) - -const ( - httpHeaderDomainToken = "X-DNSimple-Domain-Token" - httpHeaderApiToken = "X-DNSimple-Token" - httpHeaderAuthorization = "Authorization" -) - -// Provides credentials that can be used for authenticating with DNSimple -// -// More information on credentials may be found here: -// http://developer.dnsimple.com/v2/#authentication -type Credentials interface { - // Get the HTTP header key and value to use for authentication. - HttpHeader() (string, string) -} - -// Domain token authentication - -type domainTokenCredentials struct { - domainToken string -} - -// Construct Credentials using the DNSimple Domain Token method -func NewDomainTokenCredentials(domainToken string) Credentials { - return &domainTokenCredentials{domainToken: domainToken} -} - -func (c *domainTokenCredentials) HttpHeader() (string, string) { - return httpHeaderDomainToken, c.domainToken -} - -// HTTP basic authentication - -type httpBasicCredentials struct { - email string - password string -} - -// Construct Credentials using HTTP Basic Auth -func NewHttpBasicCredentials(email, password string) Credentials { - return &httpBasicCredentials{email, password} -} - -func (c *httpBasicCredentials) HttpHeader() (string, string) { - return httpHeaderAuthorization, "Basic " + basicAuth(c.email, c.password) -} - -func basicAuth(username, password string) string { - auth := username + ":" + password - return base64.StdEncoding.EncodeToString([]byte(auth)) -} - -// API token authentication - -type apiTokenCredentials struct { - email string - apiToken string -} - -// Construct Credentials using the API Token method. -func NewApiTokenCredentials(email, apiToken string) Credentials { - return &apiTokenCredentials{email: email, apiToken: apiToken} -} - -func (c *apiTokenCredentials) HttpHeader() (string, string) { - return httpHeaderApiToken, fmt.Sprintf("%v:%v", c.email, c.apiToken) -} diff --git a/vendor/github.com/weppos/dnsimple-go/dnsimple/contacts.go b/vendor/github.com/weppos/dnsimple-go/dnsimple/contacts.go deleted file mode 100644 index 6a53be767..000000000 --- a/vendor/github.com/weppos/dnsimple-go/dnsimple/contacts.go +++ /dev/null @@ -1,121 +0,0 @@ -package dnsimple - -import ( - "fmt" - "time" -) - -// ContactsService handles communication with the contact related -// methods of the DNSimple API. -// -// DNSimple API docs: http://developer.dnsimple.com/contacts/ -type ContactsService struct { - client *Client -} - -type Contact struct { - Id int `json:"id,omitempty"` - Label string `json:"label,omitempty"` - FirstName string `json:"first_name,omitempty"` - LastName string `json:"last_name,omitempty"` - JobTitle string `json:"job_title,omitempty"` - Organization string `json:"organization_name,omitempty"` - Email string `json:"email_address,omitempty"` - Phone string `json:"phone,omitempty"` - Fax string `json:"fax,omitempty"` - Address1 string `json:"address1,omitempty"` - Address2 string `json:"address2,omitempty"` - City string `json:"city,omitempty"` - Zip string `json:"postal_code,omitempty"` - Country string `json:"country,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` -} - -type contactWrapper struct { - Contact Contact `json:"contact"` -} - -// contactPath generates the resource path for given contact. -func contactPath(contact interface{}) string { - if contact != nil { - return fmt.Sprintf("contacts/%d", contact) - } - return "contacts" -} - -// List the contacts. -// -// DNSimple API docs: http://developer.dnsimple.com/contacts/#list -func (s *ContactsService) List() ([]Contact, *Response, error) { - path := contactPath(nil) - wrappedContacts := []contactWrapper{} - - res, err := s.client.get(path, &wrappedContacts) - if err != nil { - return []Contact{}, res, err - } - - contacts := []Contact{} - for _, contact := range wrappedContacts { - contacts = append(contacts, contact.Contact) - } - - return contacts, res, nil -} - -// Create a new contact. -// -// DNSimple API docs: http://developer.dnsimple.com/contacts/#create -func (s *ContactsService) Create(contactAttributes Contact) (Contact, *Response, error) { - path := contactPath(nil) - wrappedContact := contactWrapper{Contact: contactAttributes} - returnedContact := contactWrapper{} - - res, err := s.client.post(path, wrappedContact, &returnedContact) - if err != nil { - return Contact{}, res, err - } - - return returnedContact.Contact, res, nil -} - -// Get fetches a contact. -// -// DNSimple API docs: http://developer.dnsimple.com/contacts/#get -func (s *ContactsService) Get(contactID int) (Contact, *Response, error) { - path := contactPath(contactID) - wrappedContact := contactWrapper{} - - res, err := s.client.get(path, &wrappedContact) - if err != nil { - return Contact{}, res, err - } - - return wrappedContact.Contact, res, nil -} - -// Update a contact. -// -// DNSimple API docs: http://developer.dnsimple.com/contacts/#update -func (s *ContactsService) Update(contactID int, contactAttributes Contact) (Contact, *Response, error) { - path := contactPath(contactID) - wrappedContact := contactWrapper{Contact: contactAttributes} - returnedContact := contactWrapper{} - - res, err := s.client.put(path, wrappedContact, &returnedContact) - if err != nil { - return Contact{}, res, err - } - - return returnedContact.Contact, res, nil -} - -// Delete a contact. -// -// DNSimple API docs: http://developer.dnsimple.com/contacts/#delete -func (s *ContactsService) Delete(contactID int) (*Response, error) { - path := contactPath(contactID) - - return s.client.delete(path, nil) -} diff --git a/vendor/github.com/weppos/dnsimple-go/dnsimple/dnsimple.go b/vendor/github.com/weppos/dnsimple-go/dnsimple/dnsimple.go deleted file mode 100644 index d2cfd6270..000000000 --- a/vendor/github.com/weppos/dnsimple-go/dnsimple/dnsimple.go +++ /dev/null @@ -1,192 +0,0 @@ -// Package dnsimple implements a client for the DNSimple API. -// -// In order to use this package you will need a DNSimple account and your API Token. -package dnsimple - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/http" - "time" -) - -const ( - libraryVersion = "0.1" - baseURL = "https://api.dnsimple.com/" - userAgent = "dnsimple-go/" + libraryVersion - - apiVersion = "v1" -) - -type Client struct { - // HTTP client used to communicate with the API. - HttpClient *http.Client - - // Credentials used for accessing the DNSimple API - Credentials Credentials - - // Base URL for API requests. - // Defaults to the public DNSimple API, but can be set to a different endpoint (e.g. the sandbox). - // BaseURL should always be specified with a trailing slash. - BaseURL string - - // User agent used when communicating with the DNSimple API. - UserAgent string - - // Services used for talking to different parts of the DNSimple API. - Contacts *ContactsService - Domains *DomainsService - Registrar *RegistrarService - Users *UsersService -} - -// NewClient returns a new DNSimple API client. -func NewClient(apiToken, email string) *Client { - return NewAuthenticatedClient(NewApiTokenCredentials(email, apiToken)) - -} - -// NewAuthenticatedClient returns a new DNSimple API client using the given -// credentials. -func NewAuthenticatedClient(credentials Credentials) *Client { - c := &Client{Credentials: credentials, HttpClient: &http.Client{}, BaseURL: baseURL, UserAgent: userAgent} - c.Contacts = &ContactsService{client: c} - c.Domains = &DomainsService{client: c} - c.Registrar = &RegistrarService{client: c} - c.Users = &UsersService{client: c} - return c -} - -// NewRequest creates an API request. -// The path is expected to be a relative path and will be resolved -// according to the BaseURL of the Client. Paths should always be specified without a preceding slash. -func (client *Client) NewRequest(method, path string, payload interface{}) (*http.Request, error) { - url := client.BaseURL + fmt.Sprintf("%s/%s", apiVersion, path) - - body := new(bytes.Buffer) - if payload != nil { - err := json.NewEncoder(body).Encode(payload) - if err != nil { - return nil, err - } - } - - req, err := http.NewRequest(method, url, body) - if err != nil { - return nil, err - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Add("Accept", "application/json") - req.Header.Add("User-Agent", client.UserAgent) - req.Header.Add(client.Credentials.HttpHeader()) - - return req, nil -} - -func (c *Client) get(path string, v interface{}) (*Response, error) { - return c.Do("GET", path, nil, v) -} - -func (c *Client) post(path string, payload, v interface{}) (*Response, error) { - return c.Do("POST", path, payload, v) -} - -func (c *Client) put(path string, payload, v interface{}) (*Response, error) { - return c.Do("PUT", path, payload, v) -} - -func (c *Client) delete(path string, payload interface{}) (*Response, error) { - return c.Do("DELETE", path, payload, nil) -} - -// Do sends an API request and returns the API response. -// The API response is JSON decoded and stored in the value pointed by v, -// or returned as an error if an API error has occurred. -// If v implements the io.Writer interface, the raw response body will be written to v, -// without attempting to decode it. -func (c *Client) Do(method, path string, payload, v interface{}) (*Response, error) { - req, err := c.NewRequest(method, path, payload) - if err != nil { - return nil, err - } - - res, err := c.HttpClient.Do(req) - if err != nil { - return nil, err - } - defer res.Body.Close() - - response := &Response{Response: res} - - err = CheckResponse(res) - if err != nil { - return response, err - } - - if v != nil { - if w, ok := v.(io.Writer); ok { - io.Copy(w, res.Body) - } else { - err = json.NewDecoder(res.Body).Decode(v) - } - } - - return response, err -} - -// A Response represents an API response. -type Response struct { - *http.Response -} - -// An ErrorResponse represents an error caused by an API request. -type ErrorResponse struct { - Response *http.Response // HTTP response that caused this error - Message string `json:"message"` // human-readable message -} - -// Error implements the error interface. -func (r *ErrorResponse) Error() string { - return fmt.Sprintf("%v %v: %d %v", - r.Response.Request.Method, r.Response.Request.URL, - r.Response.StatusCode, r.Message) -} - -// CheckResponse checks the API response for errors, and returns them if present. -// A response is considered an error if the status code is different than 2xx. Specific requests -// may have additional requirements, but this is sufficient in most of the cases. -func CheckResponse(r *http.Response) error { - if code := r.StatusCode; 200 <= code && code <= 299 { - return nil - } - - errorResponse := &ErrorResponse{Response: r} - err := json.NewDecoder(r.Body).Decode(errorResponse) - if err != nil { - return err - } - - return errorResponse -} - -// Date custom type. -type Date struct { - time.Time -} - -// UnmarshalJSON handles the deserialization of the custom Date type. -func (d *Date) UnmarshalJSON(data []byte) error { - var s string - if err := json.Unmarshal(data, &s); err != nil { - return fmt.Errorf("date should be a string, got %s", data) - } - t, err := time.Parse("2006-01-02", s) - if err != nil { - return fmt.Errorf("invalid date: %v", err) - } - d.Time = t - return nil -} diff --git a/vendor/github.com/weppos/dnsimple-go/dnsimple/domains.go b/vendor/github.com/weppos/dnsimple-go/dnsimple/domains.go deleted file mode 100644 index 317a7a79a..000000000 --- a/vendor/github.com/weppos/dnsimple-go/dnsimple/domains.go +++ /dev/null @@ -1,121 +0,0 @@ -package dnsimple - -import ( - "fmt" - "time" -) - -// DomainsService handles communication with the domain related -// methods of the DNSimple API. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/ -type DomainsService struct { - client *Client -} - -type Domain struct { - Id int `json:"id,omitempty"` - UserId int `json:"user_id,omitempty"` - RegistrantId int `json:"registrant_id,omitempty"` - Name string `json:"name,omitempty"` - UnicodeName string `json:"unicode_name,omitempty"` - Token string `json:"token,omitempty"` - State string `json:"state,omitempty"` - Language string `json:"language,omitempty"` - Lockable bool `json:"lockable,omitempty"` - AutoRenew bool `json:"auto_renew,omitempty"` - WhoisProtected bool `json:"whois_protected,omitempty"` - RecordCount int `json:"record_count,omitempty"` - ServiceCount int `json:"service_count,omitempty"` - ExpiresOn *Date `json:"expires_on,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` -} - -type domainWrapper struct { - Domain Domain `json:"domain"` -} - -// domainRequest represents a generic wrapper for a domain request, -// when domainWrapper cannot be used because of type constraint on Domain. -type domainRequest struct { - Domain interface{} `json:"domain"` -} - -func domainIdentifier(value interface{}) string { - switch value := value.(type) { - case string: - return value - case int: - return fmt.Sprintf("%d", value) - } - return "" -} - -// domainPath generates the resource path for given domain. -func domainPath(domain interface{}) string { - if domain != nil { - return fmt.Sprintf("domains/%s", domainIdentifier(domain)) - } - return "domains" -} - -// List the domains. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/#list -func (s *DomainsService) List() ([]Domain, *Response, error) { - path := domainPath(nil) - returnedDomains := []domainWrapper{} - - res, err := s.client.get(path, &returnedDomains) - if err != nil { - return []Domain{}, res, err - } - - domains := []Domain{} - for _, domain := range returnedDomains { - domains = append(domains, domain.Domain) - } - - return domains, res, nil -} - -// Create a new domain. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/#create -func (s *DomainsService) Create(domainAttributes Domain) (Domain, *Response, error) { - path := domainPath(nil) - wrappedDomain := domainWrapper{Domain: domainAttributes} - returnedDomain := domainWrapper{} - - res, err := s.client.post(path, wrappedDomain, &returnedDomain) - if err != nil { - return Domain{}, res, err - } - - return returnedDomain.Domain, res, nil -} - -// Get fetches a domain. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/#get -func (s *DomainsService) Get(domain interface{}) (Domain, *Response, error) { - path := domainPath(domain) - returnedDomain := domainWrapper{} - - res, err := s.client.get(path, &returnedDomain) - if err != nil { - return Domain{}, res, err - } - - return returnedDomain.Domain, res, nil -} - -// Delete a domain. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/#delete -func (s *DomainsService) Delete(domain interface{}) (*Response, error) { - path := domainPath(domain) - - return s.client.delete(path, nil) -} diff --git a/vendor/github.com/weppos/dnsimple-go/dnsimple/domains_records.go b/vendor/github.com/weppos/dnsimple-go/dnsimple/domains_records.go deleted file mode 100644 index 8a6e35b23..000000000 --- a/vendor/github.com/weppos/dnsimple-go/dnsimple/domains_records.go +++ /dev/null @@ -1,136 +0,0 @@ -package dnsimple - -import ( - "fmt" - "net/url" - "time" -) - -type Record struct { - Id int `json:"id,omitempty"` - DomainId int `json:"domain_id,omitempty"` - Name string `json:"name,omitempty"` - Content string `json:"content,omitempty"` - TTL int `json:"ttl,omitempty"` - Priority int `json:"prio,omitempty"` - Type string `json:"record_type,omitempty"` - CreatedAt *time.Time `json:"created_at,omitempty"` - UpdatedAt *time.Time `json:"updated_at,omitempty"` -} - -type recordWrapper struct { - Record Record `json:"record"` -} - -// recordPath generates the resource path for given record that belongs to a domain. -func recordPath(domain interface{}, record interface{}) string { - path := fmt.Sprintf("domains/%s/records", domainIdentifier(domain)) - - if record != nil { - path += fmt.Sprintf("/%d", record) - } - - return path -} - -// List the domain records. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/records/#list -func (s *DomainsService) ListRecords(domain interface{}, recordName, recordType string) ([]Record, *Response, error) { - reqStr := recordPath(domain, nil) - v := url.Values{} - - if recordName != "" { - v.Add("name", recordName) - } - if recordType != "" { - v.Add("type", recordType) - } - reqStr += "?" + v.Encode() - - wrappedRecords := []recordWrapper{} - - res, err := s.client.get(reqStr, &wrappedRecords) - if err != nil { - return []Record{}, res, err - } - - records := []Record{} - for _, record := range wrappedRecords { - records = append(records, record.Record) - } - - return records, res, nil -} - -// CreateRecord creates a domain record. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/records/#create -func (s *DomainsService) CreateRecord(domain interface{}, recordAttributes Record) (Record, *Response, error) { - path := recordPath(domain, nil) - wrappedRecord := recordWrapper{Record: recordAttributes} - returnedRecord := recordWrapper{} - - res, err := s.client.post(path, wrappedRecord, &returnedRecord) - if err != nil { - return Record{}, res, err - } - - return returnedRecord.Record, res, nil -} - -// GetRecord fetches the domain record. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/records/#get -func (s *DomainsService) GetRecord(domain interface{}, recordID int) (Record, *Response, error) { - path := recordPath(domain, recordID) - wrappedRecord := recordWrapper{} - - res, err := s.client.get(path, &wrappedRecord) - if err != nil { - return Record{}, res, err - } - - return wrappedRecord.Record, res, nil -} - -// UpdateRecord updates a domain record. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/records/#update -func (s *DomainsService) UpdateRecord(domain interface{}, recordID int, recordAttributes Record) (Record, *Response, error) { - path := recordPath(domain, recordID) - // name, content, ttl, priority - wrappedRecord := recordWrapper{ - Record: Record{ - Name: recordAttributes.Name, - Content: recordAttributes.Content, - TTL: recordAttributes.TTL, - Priority: recordAttributes.Priority}} - returnedRecord := recordWrapper{} - - res, err := s.client.put(path, wrappedRecord, &returnedRecord) - if err != nil { - return Record{}, res, err - } - - return returnedRecord.Record, res, nil -} - -// DeleteRecord deletes a domain record. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/records/#delete -func (s *DomainsService) DeleteRecord(domain interface{}, recordID int) (*Response, error) { - path := recordPath(domain, recordID) - - return s.client.delete(path, nil) -} - -// UpdateIP updates the IP of specific A record. -// -// This is not part of the standard API. However, -// this is useful for Dynamic DNS (DDNS or DynDNS). -func (record *Record) UpdateIP(client *Client, IP string) error { - newRecord := Record{Content: IP, Name: record.Name} - _, _, err := client.Domains.UpdateRecord(record.DomainId, record.Id, newRecord) - return err -} diff --git a/vendor/github.com/weppos/dnsimple-go/dnsimple/domains_zones.go b/vendor/github.com/weppos/dnsimple-go/dnsimple/domains_zones.go deleted file mode 100644 index 8765bfde6..000000000 --- a/vendor/github.com/weppos/dnsimple-go/dnsimple/domains_zones.go +++ /dev/null @@ -1,24 +0,0 @@ -package dnsimple - -import ( - "fmt" -) - -type zoneResponse struct { - Zone string `json:"zone,omitempty"` -} - -// GetZone downloads the Bind-like zone file. -// -// DNSimple API docs: http://developer.dnsimple.com/domains/zones/#get -func (s *DomainsService) GetZone(domain interface{}) (string, *Response, error) { - path := fmt.Sprintf("%s/zone", domainPath(domain)) - zoneResponse := zoneResponse{} - - res, err := s.client.get(path, &zoneResponse) - if err != nil { - return "", res, err - } - - return zoneResponse.Zone, res, nil -} diff --git a/vendor/github.com/weppos/dnsimple-go/dnsimple/registrar.go b/vendor/github.com/weppos/dnsimple-go/dnsimple/registrar.go deleted file mode 100644 index 38cd85ea9..000000000 --- a/vendor/github.com/weppos/dnsimple-go/dnsimple/registrar.go +++ /dev/null @@ -1,131 +0,0 @@ -package dnsimple - -import ( - "fmt" -) - -// RegistrarService handles communication with the registrar related -// methods of the DNSimple API. -// -// DNSimple API docs: http://developer.dnsimple.com/registrar/ -type RegistrarService struct { - client *Client -} - -// ExtendedAttributes maps the additional attributes required by some registries. -type ExtendedAttributes map[string]string - -// ExtendedAttributes represents the transfer information. -type TransferOrder struct { - AuthCode string `json:"authinfo,omitempty"` -} - -// registrationRequest represents the body of a register or transfer request. -type registrationRequest struct { - Domain Domain `json:"domain"` - ExtendedAttributes *ExtendedAttributes `json:"extended_attribute,omitempty"` - TransferOrder *TransferOrder `json:"transfer_order,omitempty"` -} - -// IsAvailable checks if the domain is available or registered. -// -// See: http://developer.dnsimple.com/registrar/#check -func (s *RegistrarService) IsAvailable(domain string) (bool, error) { - path := fmt.Sprintf("%s/check", domainPath(domain)) - - res, err := s.client.get(path, nil) - if err != nil && res != nil && res.StatusCode != 404 { - return false, err - } - - return res.StatusCode == 404, nil -} - -// Register a domain. -// -// DNSimple API docs: http://developer.dnsimple.com/registrar/#register -func (s *RegistrarService) Register(domain string, registrantID int, extendedAttributes *ExtendedAttributes) (Domain, *Response, error) { - request := registrationRequest{ - Domain: Domain{Name: domain, RegistrantId: registrantID}, - ExtendedAttributes: extendedAttributes, - } - returnedDomain := domainWrapper{} - - res, err := s.client.post("domain_registrations", request, &returnedDomain) - if err != nil { - return Domain{}, res, err - } - - return returnedDomain.Domain, res, nil -} - -// Transfer a domain. -// -// DNSimple API docs: http://developer.dnsimple.com/registrar/#transfer -func (s *RegistrarService) Transfer(domain string, registrantID int, authCode string, extendedAttributes *ExtendedAttributes) (Domain, *Response, error) { - request := registrationRequest{ - Domain: Domain{Name: domain, RegistrantId: registrantID}, - ExtendedAttributes: extendedAttributes, - TransferOrder: &TransferOrder{AuthCode: authCode}, - } - returnedDomain := domainWrapper{} - - res, err := s.client.post("domain_transfers", request, &returnedDomain) - if err != nil { - return Domain{}, res, err - } - - return returnedDomain.Domain, res, nil -} - -// renewDomain represents the body of a Renew request. -type renewDomain struct { - Name string `json:"name,omitempty"` - RenewWhoisPrivacy bool `json:"renew_whois_privacy,omitempty"` -} - -// Renew the domain, optionally renewing WHOIS privacy service. -// -// DNSimple API docs: http://developer.dnsimple.com/registrar/#renew -func (s *RegistrarService) Renew(domain string, renewWhoisPrivacy bool) (Domain, *Response, error) { - request := domainRequest{Domain: renewDomain{ - Name: domain, - RenewWhoisPrivacy: renewWhoisPrivacy, - }} - returnedDomain := domainWrapper{} - - res, err := s.client.post("domain_renewals", request, &returnedDomain) - if err != nil { - return Domain{}, res, err - } - - return returnedDomain.Domain, res, nil -} - -// EnableAutoRenewal enables the auto-renewal feature for the domain. -// -// DNSimple API docs: http://developer.dnsimple.com/registrar/autorenewal/#enable -func (s *RegistrarService) EnableAutoRenewal(domain interface{}) (*Response, error) { - path := fmt.Sprintf("%s/auto_renewal", domainPath(domain)) - - res, err := s.client.post(path, nil, nil) - if err != nil { - return res, err - } - - return res, nil -} - -// DisableAutoRenewal disables the auto-renewal feature for the domain. -// -// DNSimple API docs: http://developer.dnsimple.com/registrar/autorenewal/#disable -func (s *RegistrarService) DisableAutoRenewal(domain interface{}) (*Response, error) { - path := fmt.Sprintf("%s/auto_renewal", domainPath(domain)) - - res, err := s.client.delete(path, nil) - if err != nil { - return res, err - } - - return res, nil -} diff --git a/vendor/github.com/weppos/dnsimple-go/dnsimple/users.go b/vendor/github.com/weppos/dnsimple-go/dnsimple/users.go deleted file mode 100644 index 601fb09f9..000000000 --- a/vendor/github.com/weppos/dnsimple-go/dnsimple/users.go +++ /dev/null @@ -1,35 +0,0 @@ -package dnsimple - -import () - -// UsersService handles communication with the uer related -// methods of the DNSimple API. -// -// DNSimple API docs: http://developer.dnsimple.com/users/ -type UsersService struct { - client *Client -} - -// User represents a DNSimple user. -type User struct { - Id int `json:"id,omitempty"` - Email string `json:"email,omitempty"` -} - -type userWrapper struct { - User User `json:"user"` -} - -// User gets the logged in user. -// -// DNSimple API docs: http://developer.dnsimple.com/users/ -func (s *UsersService) User() (User, *Response, error) { - wrappedUser := userWrapper{} - - res, err := s.client.get("user", &wrappedUser) - if err != nil { - return User{}, res, err - } - - return wrappedUser.User, res, nil -} diff --git a/vendor/github.com/xenolf/lego/acme/client.go b/vendor/github.com/xenolf/lego/acme/client.go index e758d24f6..ef0f80b7f 100644 --- a/vendor/github.com/xenolf/lego/acme/client.go +++ b/vendor/github.com/xenolf/lego/acme/client.go @@ -11,6 +11,7 @@ import ( "io/ioutil" "log" "net" + "net/http" "regexp" "strconv" "strings" @@ -22,6 +23,16 @@ var ( Logger *log.Logger ) +const ( + // maxBodySize is the maximum size of body that we will read. + maxBodySize = 1024 * 1024 + + // overallRequestLimit is the overall number of request per second limited on the + // “new-reg”, “new-authz” and “new-cert” endpoints. From the documentation the + // limitation is 20 requests per second, but using 20 as value doesn't work but 18 do + overallRequestLimit = 18 +) + // logf writes a log entry. It uses Logger if not // nil, otherwise it uses the default log.Logger. func logf(format string, args ...interface{}) { @@ -518,7 +529,11 @@ func (c *Client) chooseSolvers(auth authorization, domain string) map[int]solver func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[string]error) { resc, errc := make(chan authorizationResource), make(chan domainError) + delay := time.Second / overallRequestLimit + for _, domain := range domains { + time.Sleep(delay) + go func(domain string) { authMsg := authorization{Resource: "new-authz", Identifier: identifier{Type: "dns", Value: domain}} var authz authorization @@ -531,6 +546,7 @@ func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[s links := parseLinks(hdr["Link"]) if links["next"] == "" { logf("[ERROR][%s] acme: Server did not provide next link to proceed", domain) + errc <- domainError{Domain: domain, Error: errors.New("Server did not provide next link to proceed")} return } @@ -556,12 +572,20 @@ func (c *Client) getChallenges(domains []string) ([]authorizationResource, map[s } } + logAuthz(challenges) + close(resc) close(errc) return challenges, failures } +func logAuthz(authz []authorizationResource) { + for _, auth := range authz { + logf("[INFO][%s] AuthURL: %s", auth.Domain, auth.AuthURL) + } +} + func (c *Client) requestCertificate(authz []authorizationResource, bundle bool, privKey crypto.PrivateKey, mustStaple bool) (CertificateResource, error) { if len(authz) == 0 { return CertificateResource{}, errors.New("Passed no authorizations to requestCertificate!") @@ -610,73 +634,95 @@ func (c *Client) requestCertificateForCsr(authz []authorizationResource, bundle return CertificateResource{}, err } - cerRes := CertificateResource{ + certRes := CertificateResource{ Domain: commonName.Domain, CertURL: resp.Header.Get("Location"), - PrivateKey: privateKeyPem} + PrivateKey: privateKeyPem, + } - for { - switch resp.StatusCode { - case 201, 202: - cert, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024)) - resp.Body.Close() - if err != nil { - return CertificateResource{}, err - } - - // The server returns a body with a length of zero if the - // certificate was not ready at the time this request completed. - // Otherwise the body is the certificate. - if len(cert) > 0 { - - cerRes.CertStableURL = resp.Header.Get("Content-Location") - cerRes.AccountRef = c.user.GetRegistration().URI - - issuedCert := pemEncode(derCertificateBytes(cert)) - - // The issuer certificate link is always supplied via an "up" link - // in the response headers of a new certificate. - links := parseLinks(resp.Header["Link"]) - issuerCert, err := c.getIssuerCertificate(links["up"]) - if err != nil { - // If we fail to acquire the issuer cert, return the issued certificate - do not fail. - logf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", commonName.Domain, err) - } else { - issuerCert = pemEncode(derCertificateBytes(issuerCert)) - - // If bundle is true, we want to return a certificate bundle. - // To do this, we append the issuer cert to the issued cert. - if bundle { - issuedCert = append(issuedCert, issuerCert...) - } - } - - cerRes.Certificate = issuedCert - cerRes.IssuerCertificate = issuerCert - logf("[INFO][%s] Server responded with a certificate.", commonName.Domain) - return cerRes, nil - } - - // The certificate was granted but is not yet issued. - // Check retry-after and loop. - ra := resp.Header.Get("Retry-After") - retryAfter, err := strconv.Atoi(ra) - if err != nil { - return CertificateResource{}, err - } - - logf("[INFO][%s] acme: Server responded with status 202; retrying after %ds", commonName.Domain, retryAfter) - time.Sleep(time.Duration(retryAfter) * time.Second) - - break - default: - return CertificateResource{}, handleHTTPError(resp) - } - - resp, err = httpGet(cerRes.CertURL) + maxChecks := 1000 + for i := 0; i < maxChecks; i++ { + done, err := c.checkCertResponse(resp, &certRes, bundle) + resp.Body.Close() if err != nil { return CertificateResource{}, err } + if done { + break + } + if i == maxChecks-1 { + return CertificateResource{}, fmt.Errorf("polled for certificate %d times; giving up", i) + } + resp, err = httpGet(certRes.CertURL) + if err != nil { + return CertificateResource{}, err + } + } + + return certRes, nil +} + +// checkCertResponse checks resp to see if a certificate is contained in the +// response, and if so, loads it into certRes and returns true. If the cert +// is not yet ready, it returns false. This function honors the waiting period +// required by the Retry-After header of the response, if specified. This +// function may read from resp.Body but does NOT close it. The certRes input +// should already have the Domain (common name) field populated. If bundle is +// true, the certificate will be bundled with the issuer's cert. +func (c *Client) checkCertResponse(resp *http.Response, certRes *CertificateResource, bundle bool) (bool, error) { + switch resp.StatusCode { + case 201, 202: + cert, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize)) + if err != nil { + return false, err + } + + // The server returns a body with a length of zero if the + // certificate was not ready at the time this request completed. + // Otherwise the body is the certificate. + if len(cert) > 0 { + certRes.CertStableURL = resp.Header.Get("Content-Location") + certRes.AccountRef = c.user.GetRegistration().URI + + issuedCert := pemEncode(derCertificateBytes(cert)) + + // The issuer certificate link is always supplied via an "up" link + // in the response headers of a new certificate. + links := parseLinks(resp.Header["Link"]) + issuerCert, err := c.getIssuerCertificate(links["up"]) + if err != nil { + // If we fail to acquire the issuer cert, return the issued certificate - do not fail. + logf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err) + } else { + issuerCert = pemEncode(derCertificateBytes(issuerCert)) + + // If bundle is true, we want to return a certificate bundle. + // To do this, we append the issuer cert to the issued cert. + if bundle { + issuedCert = append(issuedCert, issuerCert...) + } + } + + certRes.Certificate = issuedCert + certRes.IssuerCertificate = issuerCert + logf("[INFO][%s] Server responded with a certificate.", certRes.Domain) + return true, nil + } + + // The certificate was granted but is not yet issued. + // Check retry-after and loop. + ra := resp.Header.Get("Retry-After") + retryAfter, err := strconv.Atoi(ra) + if err != nil { + return false, err + } + + logf("[INFO][%s] acme: Server responded with status 202; retrying after %ds", certRes.Domain, retryAfter) + time.Sleep(time.Duration(retryAfter) * time.Second) + + return false, nil + default: + return false, handleHTTPError(resp) } } @@ -689,7 +735,7 @@ func (c *Client) getIssuerCertificate(url string) ([]byte, error) { } defer resp.Body.Close() - issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024)) + issuerBytes, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize)) if err != nil { return nil, err } diff --git a/vendor/github.com/xenolf/lego/acme/error.go b/vendor/github.com/xenolf/lego/acme/error.go index 2aa690b33..e4bc934c2 100644 --- a/vendor/github.com/xenolf/lego/acme/error.go +++ b/vendor/github.com/xenolf/lego/acme/error.go @@ -10,6 +10,7 @@ import ( const ( tosAgreementError = "Must agree to subscriber agreement before any further actions" + invalidNonceError = "JWS has invalid anti-replay nonce" ) // RemoteError is the base type for all errors specific to the ACME protocol. @@ -30,6 +31,12 @@ type TOSError struct { RemoteError } +// NonceError represents the error which is returned if the +// nonce sent by the client was not accepted by the server. +type NonceError struct { + RemoteError +} + type domainError struct { Domain string Error error @@ -54,20 +61,17 @@ func (c challengeError) Error() string { func handleHTTPError(resp *http.Response) error { var errorDetail RemoteError - contenType := resp.Header.Get("Content-Type") - // try to decode the content as JSON - if contenType == "application/json" || contenType == "application/problem+json" { - decoder := json.NewDecoder(resp.Body) - err := decoder.Decode(&errorDetail) + contentType := resp.Header.Get("Content-Type") + if contentType == "application/json" || contentType == "application/problem+json" { + err := json.NewDecoder(resp.Body).Decode(&errorDetail) if err != nil { return err } } else { - detailBytes, err := ioutil.ReadAll(limitReader(resp.Body, 1024*1024)) + detailBytes, err := ioutil.ReadAll(limitReader(resp.Body, maxBodySize)) if err != nil { return err } - errorDetail.Detail = string(detailBytes) } @@ -78,6 +82,10 @@ func handleHTTPError(resp *http.Response) error { return TOSError{errorDetail} } + if errorDetail.StatusCode == http.StatusBadRequest && strings.HasPrefix(errorDetail.Detail, invalidNonceError) { + return NonceError{errorDetail} + } + return errorDetail } diff --git a/vendor/github.com/xenolf/lego/acme/http.go b/vendor/github.com/xenolf/lego/acme/http.go index 180db786d..a858b5a75 100644 --- a/vendor/github.com/xenolf/lego/acme/http.go +++ b/vendor/github.com/xenolf/lego/acme/http.go @@ -31,14 +31,14 @@ const ( func httpHead(url string) (resp *http.Response, err error) { req, err := http.NewRequest("HEAD", url, nil) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to head %q: %v", url, err) } req.Header.Set("User-Agent", userAgent()) resp, err = HTTPClient.Do(req) if err != nil { - return resp, err + return resp, fmt.Errorf("failed to do head %q: %v", url, err) } resp.Body.Close() return resp, err @@ -49,7 +49,7 @@ func httpHead(url string) (resp *http.Response, err error) { func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, err error) { req, err := http.NewRequest("POST", url, body) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to post %q: %v", url, err) } req.Header.Set("Content-Type", bodyType) req.Header.Set("User-Agent", userAgent()) @@ -62,7 +62,7 @@ func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, func httpGet(url string) (resp *http.Response, err error) { req, err := http.NewRequest("GET", url, nil) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to get %q: %v", url, err) } req.Header.Set("User-Agent", userAgent()) @@ -74,7 +74,7 @@ func httpGet(url string) (resp *http.Response, err error) { func getJSON(uri string, respBody interface{}) (http.Header, error) { resp, err := httpGet(uri) if err != nil { - return nil, fmt.Errorf("failed to get %q: %v", uri, err) + return nil, fmt.Errorf("failed to get json %q: %v", uri, err) } defer resp.Body.Close() @@ -97,10 +97,41 @@ func postJSON(j *jws, uri string, reqBody, respBody interface{}) (http.Header, e if err != nil { return nil, fmt.Errorf("Failed to post JWS message. -> %v", err) } + defer resp.Body.Close() if resp.StatusCode >= http.StatusBadRequest { - return resp.Header, handleHTTPError(resp) + + err := handleHTTPError(resp) + + switch err.(type) { + + case NonceError: + + // Retry once if the nonce was invalidated + + retryResp, err := j.post(uri, jsonBytes) + if err != nil { + return nil, fmt.Errorf("Failed to post JWS message. -> %v", err) + } + + defer retryResp.Body.Close() + + if retryResp.StatusCode >= http.StatusBadRequest { + return retryResp.Header, handleHTTPError(retryResp) + } + + if respBody == nil { + return retryResp.Header, nil + } + + return retryResp.Header, json.NewDecoder(retryResp.Body).Decode(respBody) + + default: + return resp.Header, err + + } + } if respBody == nil { diff --git a/vendor/github.com/xenolf/lego/acme/jws.go b/vendor/github.com/xenolf/lego/acme/jws.go index 80296081f..a39434342 100644 --- a/vendor/github.com/xenolf/lego/acme/jws.go +++ b/vendor/github.com/xenolf/lego/acme/jws.go @@ -16,8 +16,7 @@ import ( type jws struct { directoryURL string privKey crypto.PrivateKey - nonces []string - sync.Mutex + nonces nonceManager } func keyAsJWK(key interface{}) *jose.JsonWebKey { @@ -32,23 +31,26 @@ func keyAsJWK(key interface{}) *jose.JsonWebKey { } } -// Posts a JWS signed message to the specified URL +// Posts a JWS signed message to the specified URL. +// It does NOT close the response body, so the caller must +// do that if no error was returned. func (j *jws) post(url string, content []byte) (*http.Response, error) { signedContent, err := j.signContent(content) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to sign content -> %s", err.Error()) } resp, err := httpPost(url, "application/jose+json", bytes.NewBuffer([]byte(signedContent.FullSerialize()))) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to HTTP POST to %s -> %s", url, err.Error()) } - j.Lock() - defer j.Unlock() - j.getNonceFromResponse(resp) + nonce, nonceErr := getNonceFromResponse(resp) + if nonceErr == nil { + j.nonces.Push(nonce) + } - return resp, err + return resp, nil } func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { @@ -67,49 +69,63 @@ func (j *jws) signContent(content []byte) (*jose.JsonWebSignature, error) { signer, err := jose.NewSigner(alg, j.privKey) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to create jose signer -> %s", err.Error()) } signer.SetNonceSource(j) signed, err := signer.Sign(content) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to sign content -> %s", err.Error()) } return signed, nil } -func (j *jws) getNonceFromResponse(resp *http.Response) error { +func (j *jws) Nonce() (string, error) { + if nonce, ok := j.nonces.Pop(); ok { + return nonce, nil + } + + return getNonce(j.directoryURL) +} + +type nonceManager struct { + nonces []string + sync.Mutex +} + +func (n *nonceManager) Pop() (string, bool) { + n.Lock() + defer n.Unlock() + + if len(n.nonces) == 0 { + return "", false + } + + nonce := n.nonces[len(n.nonces)-1] + n.nonces = n.nonces[:len(n.nonces)-1] + return nonce, true +} + +func (n *nonceManager) Push(nonce string) { + n.Lock() + defer n.Unlock() + n.nonces = append(n.nonces, nonce) +} + +func getNonce(url string) (string, error) { + resp, err := httpHead(url) + if err != nil { + return "", fmt.Errorf("Failed to get nonce from HTTP HEAD -> %s", err.Error()) + } + + return getNonceFromResponse(resp) +} + +func getNonceFromResponse(resp *http.Response) (string, error) { nonce := resp.Header.Get("Replay-Nonce") if nonce == "" { - return fmt.Errorf("Server did not respond with a proper nonce header.") + return "", fmt.Errorf("Server did not respond with a proper nonce header.") } - j.nonces = append(j.nonces, nonce) - return nil -} - -func (j *jws) getNonce() error { - resp, err := httpHead(j.directoryURL) - if err != nil { - return err - } - - return j.getNonceFromResponse(resp) -} - -func (j *jws) Nonce() (string, error) { - j.Lock() - defer j.Unlock() - nonce := "" - if len(j.nonces) == 0 { - err := j.getNonce() - if err != nil { - return nonce, err - } - } - if len(j.nonces) == 0 { - return "", fmt.Errorf("Can't get nonce") - } - nonce, j.nonces = j.nonces[len(j.nonces)-1], j.nonces[:len(j.nonces)-1] return nonce, nil } diff --git a/vendor/github.com/xenolf/lego/cli.go b/vendor/github.com/xenolf/lego/cli.go index 61c08d455..03589a233 100644 --- a/vendor/github.com/xenolf/lego/cli.go +++ b/vendor/github.com/xenolf/lego/cli.go @@ -205,7 +205,7 @@ Here is an example bash command using the CloudFlare DNS provider: fmt.Fprintln(w, "\tauroradns:\tAURORA_USER_ID, AURORA_KEY, AURORA_ENDPOINT") fmt.Fprintln(w, "\tcloudflare:\tCLOUDFLARE_EMAIL, CLOUDFLARE_API_KEY") fmt.Fprintln(w, "\tdigitalocean:\tDO_AUTH_TOKEN") - fmt.Fprintln(w, "\tdnsimple:\tDNSIMPLE_EMAIL, DNSIMPLE_API_KEY") + fmt.Fprintln(w, "\tdnsimple:\tDNSIMPLE_EMAIL, DNSIMPLE_OAUTH_TOKEN") fmt.Fprintln(w, "\tdnsmadeeasy:\tDNSMADEEASY_API_KEY, DNSMADEEASY_API_SECRET") fmt.Fprintln(w, "\texoscale:\tEXOSCALE_API_KEY, EXOSCALE_API_SECRET, EXOSCALE_ENDPOINT") fmt.Fprintln(w, "\tgandi:\tGANDI_API_KEY") diff --git a/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go b/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go index 9d281cd69..d079d5e13 100644 --- a/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go +++ b/vendor/github.com/xenolf/lego/providers/dns/azure/azure.go @@ -10,10 +10,11 @@ import ( "github.com/Azure/azure-sdk-for-go/arm/dns" + "strings" + "github.com/Azure/go-autorest/autorest/azure" "github.com/Azure/go-autorest/autorest/to" "github.com/xenolf/lego/acme" - "strings" ) // DNSProvider is an implementation of the acme.ChallengeProvider interface @@ -74,7 +75,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error { Name: &relative, RecordSetProperties: &dns.RecordSetProperties{ TTL: to.Int64Ptr(60), - TXTRecords: &[]dns.TxtRecord{dns.TxtRecord{Value: &[]string{value}}}, + TxtRecords: &[]dns.TxtRecord{dns.TxtRecord{Value: &[]string{value}}}, }, } _, err = rsc.CreateOrUpdate(c.resourceGroup, zone, relative, dns.TXT, rec, "", "") diff --git a/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go b/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go index c903a35ce..e3fea79ec 100644 --- a/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go +++ b/vendor/github.com/xenolf/lego/providers/dns/dnsimple/dnsimple.go @@ -5,9 +5,10 @@ package dnsimple import ( "fmt" "os" + "strconv" "strings" - "github.com/weppos/dnsimple-go/dnsimple" + "github.com/dnsimple/dnsimple-go/dnsimple" "github.com/xenolf/lego/acme" ) @@ -17,37 +18,50 @@ type DNSProvider struct { } // NewDNSProvider returns a DNSProvider instance configured for dnsimple. -// Credentials must be passed in the environment variables: DNSIMPLE_EMAIL -// and DNSIMPLE_API_KEY. +// Credentials must be passed in the environment variables: DNSIMPLE_OAUTH_TOKEN. +// +// See: https://developer.dnsimple.com/v2/#authentication func NewDNSProvider() (*DNSProvider, error) { - email := os.Getenv("DNSIMPLE_EMAIL") - key := os.Getenv("DNSIMPLE_API_KEY") - return NewDNSProviderCredentials(email, key) + accessToken := os.Getenv("DNSIMPLE_OAUTH_TOKEN") + baseUrl := os.Getenv("DNSIMPLE_BASE_URL") + + return NewDNSProviderCredentials(accessToken, baseUrl) } // NewDNSProviderCredentials uses the supplied credentials to return a // DNSProvider instance configured for dnsimple. -func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) { - if email == "" || key == "" { - return nil, fmt.Errorf("DNSimple credentials missing") +func NewDNSProviderCredentials(accessToken, baseUrl string) (*DNSProvider, error) { + if accessToken == "" { + return nil, fmt.Errorf("DNSimple OAuth token is missing") } - return &DNSProvider{ - client: dnsimple.NewClient(key, email), - }, nil + client := dnsimple.NewClient(dnsimple.NewOauthTokenCredentials(accessToken)) + client.UserAgent = "lego" + + if baseUrl != "" { + client.BaseURL = baseUrl + } + + return &DNSProvider{client: client}, nil } // Present creates a TXT record to fulfil the dns-01 challenge. func (c *DNSProvider) Present(domain, token, keyAuth string) error { fqdn, value, ttl := acme.DNS01Record(domain, keyAuth) - zoneID, zoneName, err := c.getHostedZone(domain) + zoneName, err := c.getHostedZone(domain) + + if err != nil { + return err + } + + accountID, err := c.getAccountID() if err != nil { return err } recordAttributes := c.newTxtRecord(zoneName, fqdn, value, ttl) - _, _, err = c.client.Domains.CreateRecord(zoneID, *recordAttributes) + _, err = c.client.Zones.CreateRecord(accountID, zoneName, *recordAttributes) if err != nil { return fmt.Errorf("DNSimple API call failed: %v", err) } @@ -64,67 +78,79 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error { return err } + accountID, err := c.getAccountID() + if err != nil { + return err + } + for _, rec := range records { - _, err := c.client.Domains.DeleteRecord(rec.DomainId, rec.Id) + _, err := c.client.Zones.DeleteRecord(accountID, rec.ZoneID, rec.ID) if err != nil { return err } } + return nil } -func (c *DNSProvider) getHostedZone(domain string) (string, string, error) { - zones, _, err := c.client.Domains.List() - if err != nil { - return "", "", fmt.Errorf("DNSimple API call failed: %v", err) - } - +func (c *DNSProvider) getHostedZone(domain string) (string, error) { authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers) if err != nil { - return "", "", err + return "", err } - var hostedZone dnsimple.Domain - for _, zone := range zones { - if zone.Name == acme.UnFqdn(authZone) { + accountID, err := c.getAccountID() + if err != nil { + return "", err + } + + zoneName := acme.UnFqdn(authZone) + + zones, err := c.client.Zones.ListZones(accountID, &dnsimple.ZoneListOptions{NameLike: zoneName}) + if err != nil { + return "", fmt.Errorf("DNSimple API call failed: %v", err) + } + + var hostedZone dnsimple.Zone + for _, zone := range zones.Data { + if zone.Name == zoneName { hostedZone = zone } } - if hostedZone.Id == 0 { - return "", "", fmt.Errorf("Zone %s not found in DNSimple for domain %s", authZone, domain) + if hostedZone.ID == 0 { + return "", fmt.Errorf("Zone %s not found in DNSimple for domain %s", authZone, domain) } - return fmt.Sprintf("%v", hostedZone.Id), hostedZone.Name, nil + return hostedZone.Name, nil } -func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.Record, error) { - zoneID, zoneName, err := c.getHostedZone(domain) +func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord, error) { + zoneName, err := c.getHostedZone(domain) if err != nil { return nil, err } - var records []dnsimple.Record - result, _, err := c.client.Domains.ListRecords(zoneID, "", "TXT") + accountID, err := c.getAccountID() if err != nil { - return records, fmt.Errorf("DNSimple API call has failed: %v", err) + return nil, err } recordName := c.extractRecordName(fqdn, zoneName) - for _, record := range result { - if record.Name == recordName { - records = append(records, record) - } + + result, err := c.client.Zones.ListRecords(accountID, zoneName, &dnsimple.ZoneRecordListOptions{Name: recordName, Type: "TXT", ListOptions: dnsimple.ListOptions{}}) + if err != nil { + return []dnsimple.ZoneRecord{}, fmt.Errorf("DNSimple API call has failed: %v", err) } - return records, nil + return result.Data, nil } -func (c *DNSProvider) newTxtRecord(zone, fqdn, value string, ttl int) *dnsimple.Record { - name := c.extractRecordName(fqdn, zone) +func (c *DNSProvider) newTxtRecord(zoneName, fqdn, value string, ttl int) *dnsimple.ZoneRecord { + name := c.extractRecordName(fqdn, zoneName) - return &dnsimple.Record{ + return &dnsimple.ZoneRecord{ Type: "TXT", Name: name, Content: value, @@ -139,3 +165,16 @@ func (c *DNSProvider) extractRecordName(fqdn, domain string) string { } return name } + +func (c *DNSProvider) getAccountID() (string, error) { + whoamiResponse, err := c.client.Identity.Whoami() + if err != nil { + return "", err + } + + if whoamiResponse.Data.Account == nil { + return "", fmt.Errorf("DNSimple user tokens are not supported, please use an account token.") + } + + return strconv.Itoa(whoamiResponse.Data.Account.ID), nil +}