1// +build go1.7 2 3// Package management provides the main API client to construct other clients 4// and make requests to the Microsoft Azure Service Management REST API. 5package management 6 7// Copyright 2017 Microsoft Corporation 8// 9// Licensed under the Apache License, Version 2.0 (the "License"); 10// you may not use this file except in compliance with the License. 11// You may obtain a copy of the License at 12// 13// http://www.apache.org/licenses/LICENSE-2.0 14// 15// Unless required by applicable law or agreed to in writing, software 16// distributed under the License is distributed on an "AS IS" BASIS, 17// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18// See the License for the specific language governing permissions and 19// limitations under the License. 20 21import ( 22 "errors" 23 "fmt" 24 "runtime" 25 "time" 26 27 "github.com/Azure/azure-sdk-for-go/version" 28) 29 30var ( 31 DefaultUserAgent = userAgent() 32) 33 34const ( 35 DefaultAzureManagementURL = "https://management.core.windows.net" 36 DefaultOperationPollInterval = time.Second * 30 37 DefaultAPIVersion = "2014-10-01" 38 39 errPublishSettingsConfiguration = "PublishSettingsFilePath is set. Consequently ManagementCertificatePath and SubscriptionId must not be set." 40 errManagementCertificateConfiguration = "Both ManagementCertificatePath and SubscriptionId should be set, and PublishSettingsFilePath must not be set." 41 errParamNotSpecified = "Parameter %s is not specified." 42) 43 44type client struct { 45 publishSettings publishSettings 46 config ClientConfig 47} 48 49// Client is the base Azure Service Management API client instance that 50// can be used to construct client instances for various services. 51type Client interface { 52 // SendAzureGetRequest sends a request to the management API using the HTTP GET method 53 // and returns the response body or an error. 54 SendAzureGetRequest(url string) ([]byte, error) 55 56 // SendAzurePostRequest sends a request to the management API using the HTTP POST method 57 // and returns the request ID or an error. 58 SendAzurePostRequest(url string, data []byte) (OperationID, error) 59 60 // SendAzurePostRequestWithReturnedResponse sends a request to the management API using 61 // the HTTP POST method and returns the response body or an error. 62 SendAzurePostRequestWithReturnedResponse(url string, data []byte) ([]byte, error) 63 64 // SendAzurePutRequest sends a request to the management API using the HTTP PUT method 65 // and returns the request ID or an error. The content type can be specified, however 66 // if an empty string is passed, the default of "application/xml" will be used. 67 SendAzurePutRequest(url, contentType string, data []byte) (OperationID, error) 68 69 // SendAzureDeleteRequest sends a request to the management API using the HTTP DELETE method 70 // and returns the request ID or an error. 71 SendAzureDeleteRequest(url string) (OperationID, error) 72 73 // GetOperationStatus gets the status of operation with given Operation ID. 74 // WaitForOperation utility method can be used for polling for operation status. 75 GetOperationStatus(operationID OperationID) (GetOperationStatusResponse, error) 76 77 // WaitForOperation polls the Azure API for given operation ID indefinitely 78 // until the operation is completed with either success or failure. 79 // It is meant to be used for waiting for the result of the methods that 80 // return an OperationID value (meaning a long running operation has started). 81 // 82 // Cancellation of the polling loop (for instance, timing out) is done through 83 // cancel channel. If the user does not want to cancel, a nil chan can be provided. 84 // To cancel the method, it is recommended to close the channel provided to this 85 // method. 86 // 87 // If the operation was not successful or cancelling is signaled, an error 88 // is returned. 89 WaitForOperation(operationID OperationID, cancel chan struct{}) error 90} 91 92// ClientConfig provides a configuration for use by a Client. 93type ClientConfig struct { 94 ManagementURL string 95 OperationPollInterval time.Duration 96 UserAgent string 97 APIVersion string 98} 99 100// NewAnonymousClient creates a new azure.Client with no credentials set. 101func NewAnonymousClient() Client { 102 return client{} 103} 104 105// DefaultConfig returns the default client configuration used to construct 106// a client. This value can be used to make modifications on the default API 107// configuration. 108func DefaultConfig() ClientConfig { 109 return ClientConfig{ 110 ManagementURL: DefaultAzureManagementURL, 111 OperationPollInterval: DefaultOperationPollInterval, 112 APIVersion: DefaultAPIVersion, 113 UserAgent: DefaultUserAgent, 114 } 115} 116 117// NewClient creates a new Client using the given subscription ID and 118// management certificate. 119func NewClient(subscriptionID string, managementCert []byte) (Client, error) { 120 return NewClientFromConfig(subscriptionID, managementCert, DefaultConfig()) 121} 122 123// NewClientFromConfig creates a new Client using a given ClientConfig. 124func NewClientFromConfig(subscriptionID string, managementCert []byte, config ClientConfig) (Client, error) { 125 return makeClient(subscriptionID, managementCert, config) 126} 127 128func makeClient(subscriptionID string, managementCert []byte, config ClientConfig) (Client, error) { 129 var c client 130 131 if subscriptionID == "" { 132 return c, errors.New("azure: subscription ID required") 133 } 134 135 if len(managementCert) == 0 { 136 return c, errors.New("azure: management certificate required") 137 } 138 139 publishSettings := publishSettings{ 140 SubscriptionID: subscriptionID, 141 SubscriptionCert: managementCert, 142 SubscriptionKey: managementCert, 143 } 144 145 // Validate client configuration 146 switch { 147 case config.ManagementURL == "": 148 return c, errors.New("azure: base URL required") 149 case config.OperationPollInterval <= 0: 150 return c, errors.New("azure: operation polling interval must be a positive duration") 151 case config.APIVersion == "": 152 return c, errors.New("azure: client configuration must specify an API version") 153 case config.UserAgent == "": 154 config.UserAgent = DefaultUserAgent 155 } 156 157 return client{ 158 publishSettings: publishSettings, 159 config: config, 160 }, nil 161} 162 163func userAgent() string { 164 return fmt.Sprintf("Go/%s (%s-%s) Azure-SDK-For-Go/%s asm/%s", 165 runtime.Version(), 166 runtime.GOARCH, 167 runtime.GOOS, 168 version.Number, 169 DefaultAPIVersion) 170} 171