1// +build go1.7 2 3package sql 4 5// Copyright (c) Microsoft Corporation. All rights reserved. 6// Licensed under the MIT License. See License.txt in the project root for license information. 7 8import ( 9 "encoding/xml" 10 "fmt" 11 "time" 12 13 "github.com/Azure/azure-sdk-for-go/services/classic/management" 14) 15 16// Definitions of numerous constants representing API endpoints. 17const ( 18 azureCreateDatabaseServerURL = "services/sqlservers/servers" 19 azureListDatabaseServersURL = "services/sqlservers/servers" 20 azureDeleteDatabaseServerURL = "services/sqlservers/servers/%s" 21 22 azureCreateFirewallRuleURL = "services/sqlservers/servers/%s/firewallrules" 23 azureGetFirewallRuleURL = "services/sqlservers/servers/%s/firewallrules/%s" 24 azureListFirewallRulesURL = "services/sqlservers/servers/%s/firewallrules" 25 azureUpdateFirewallRuleURL = "services/sqlservers/servers/%s/firewallrules/%s" 26 azureDeleteFirewallRuleURL = "services/sqlservers/servers/%s/firewallrules/%s" 27 28 azureCreateDatabaseURL = "services/sqlservers/servers/%s/databases" 29 azureGetDatabaseURL = "services/sqlservers/servers/%s/databases/%s" 30 azureListDatabasesURL = "services/sqlservers/servers/%s/databases?contentview=generic" 31 azureUpdateDatabaseURL = "services/sqlservers/servers/%s/databases/%s" 32 azureDeleteDatabaseURL = "services/sqlservers/servers/%s/databases/%s" 33 34 errParamNotSpecified = "Parameter %s was not specified." 35 36 DatabaseStateCreating = "Creating" 37) 38 39// SQLDatabaseClient defines various database CRUD operations. 40// It contains a management.Client for making the actual http calls. 41type SQLDatabaseClient struct { 42 mgmtClient management.Client 43} 44 45// NewClient returns a new SQLDatabaseClient struct with the provided 46// management.Client as the underlying client. 47func NewClient(mgmtClient management.Client) SQLDatabaseClient { 48 return SQLDatabaseClient{mgmtClient} 49} 50 51// CreateServer creates a new Azure SQL Database server and return its name. 52// 53// https://msdn.microsoft.com/en-us/library/azure/dn505699.aspx 54func (c SQLDatabaseClient) CreateServer(params DatabaseServerCreateParams) (string, error) { 55 req, err := xml.Marshal(params) 56 if err != nil { 57 return "", err 58 } 59 60 resp, err := c.mgmtClient.SendAzurePostRequestWithReturnedResponse(azureCreateDatabaseServerURL, req) 61 if err != nil { 62 return "", err 63 } 64 65 var name string 66 err = xml.Unmarshal(resp, &name) 67 68 return name, err 69} 70 71// ListServers retrieves the Azure SQL Database servers for this subscription. 72// 73// https://msdn.microsoft.com/en-us/library/azure/dn505702.aspx 74func (c SQLDatabaseClient) ListServers() (ListServersResponse, error) { 75 var resp ListServersResponse 76 77 data, err := c.mgmtClient.SendAzureGetRequest(azureListDatabaseServersURL) 78 if err != nil { 79 return resp, err 80 } 81 82 err = xml.Unmarshal(data, &resp) 83 return resp, err 84} 85 86// DeleteServer deletes an Azure SQL Database server (including all its databases). 87// 88// https://msdn.microsoft.com/en-us/library/azure/dn505695.aspx 89func (c SQLDatabaseClient) DeleteServer(name string) error { 90 if name == "" { 91 return fmt.Errorf(errParamNotSpecified, "name") 92 } 93 94 url := fmt.Sprintf(azureDeleteDatabaseServerURL, name) 95 _, err := c.mgmtClient.SendAzureDeleteRequest(url) 96 return err 97} 98 99// CreateFirewallRule creates an Azure SQL Database server 100// firewall rule. 101// 102// https://msdn.microsoft.com/en-us/library/azure/dn505712.aspx 103func (c SQLDatabaseClient) CreateFirewallRule(server string, params FirewallRuleCreateParams) error { 104 if server == "" { 105 return fmt.Errorf(errParamNotSpecified, "server") 106 } 107 108 req, err := xml.Marshal(params) 109 if err != nil { 110 return err 111 } 112 113 url := fmt.Sprintf(azureCreateFirewallRuleURL, server) 114 115 _, err = c.mgmtClient.SendAzurePostRequest(url, req) 116 return err 117} 118 119// GetFirewallRule gets the details of an Azure SQL Database Server firewall rule. 120// 121// https://msdn.microsoft.com/en-us/library/azure/dn505698.aspx 122func (c SQLDatabaseClient) GetFirewallRule(server, ruleName string) (FirewallRuleResponse, error) { 123 var rule FirewallRuleResponse 124 125 if server == "" { 126 return rule, fmt.Errorf(errParamNotSpecified, "server") 127 } 128 if ruleName == "" { 129 return rule, fmt.Errorf(errParamNotSpecified, "ruleName") 130 } 131 132 url := fmt.Sprintf(azureGetFirewallRuleURL, server, ruleName) 133 resp, err := c.mgmtClient.SendAzureGetRequest(url) 134 if err != nil { 135 return rule, err 136 } 137 138 err = xml.Unmarshal(resp, &rule) 139 return rule, err 140} 141 142// ListFirewallRules retrieves the set of firewall rules for an Azure SQL 143// Database Server. 144// 145// https://msdn.microsoft.com/en-us/library/azure/dn505715.aspx 146func (c SQLDatabaseClient) ListFirewallRules(server string) (ListFirewallRulesResponse, error) { 147 var rules ListFirewallRulesResponse 148 149 if server == "" { 150 return rules, fmt.Errorf(errParamNotSpecified, "server") 151 } 152 153 url := fmt.Sprintf(azureListFirewallRulesURL, server) 154 resp, err := c.mgmtClient.SendAzureGetRequest(url) 155 if err != nil { 156 return rules, err 157 } 158 159 err = xml.Unmarshal(resp, &rules) 160 return rules, err 161} 162 163// UpdateFirewallRule update a firewall rule for an Azure SQL Database server. 164// 165// https://msdn.microsoft.com/en-us/library/azure/dn505707.aspx 166func (c SQLDatabaseClient) UpdateFirewallRule(server, ruleName string, params FirewallRuleUpdateParams) error { 167 if server == "" { 168 return fmt.Errorf(errParamNotSpecified, "server") 169 } 170 if ruleName == "" { 171 return fmt.Errorf(errParamNotSpecified, "ruleName") 172 } 173 174 req, err := xml.Marshal(params) 175 if err != nil { 176 return err 177 } 178 179 url := fmt.Sprintf(azureUpdateFirewallRuleURL, server, ruleName) 180 _, err = c.mgmtClient.SendAzurePutRequest(url, "text/xml", req) 181 return err 182} 183 184// DeleteFirewallRule deletes an Azure SQL Database server firewall rule. 185// 186// https://msdn.microsoft.com/en-us/library/azure/dn505706.aspx 187func (c SQLDatabaseClient) DeleteFirewallRule(server, ruleName string) error { 188 if server == "" { 189 return fmt.Errorf(errParamNotSpecified, "server") 190 } 191 if ruleName == "" { 192 return fmt.Errorf(errParamNotSpecified, "ruleName") 193 } 194 195 url := fmt.Sprintf(azureDeleteFirewallRuleURL, server, ruleName) 196 197 _, err := c.mgmtClient.SendAzureDeleteRequest(url) 198 return err 199} 200 201// CreateDatabase creates a new Microsoft Azure SQL Database on the given database server. 202// 203// https://msdn.microsoft.com/en-us/library/azure/dn505701.aspx 204func (c SQLDatabaseClient) CreateDatabase(server string, params DatabaseCreateParams) error { 205 if server == "" { 206 return fmt.Errorf(errParamNotSpecified, "server") 207 } 208 209 req, err := xml.Marshal(params) 210 if err != nil { 211 return err 212 } 213 214 target := fmt.Sprintf(azureCreateDatabaseURL, server) 215 _, err = c.mgmtClient.SendAzurePostRequest(target, req) 216 return err 217} 218 219// WaitForDatabaseCreation is a helper method which waits 220// for the creation of the database on the given server. 221func (c SQLDatabaseClient) WaitForDatabaseCreation( 222 server, database string, 223 cancel chan struct{}) error { 224 for { 225 stat, err := c.GetDatabase(server, database) 226 if err != nil { 227 return err 228 } 229 if stat.State != DatabaseStateCreating { 230 return nil 231 } 232 233 select { 234 case <-time.After(management.DefaultOperationPollInterval): 235 case <-cancel: 236 return management.ErrOperationCancelled 237 } 238 } 239} 240 241// GetDatabase gets the details for an Azure SQL Database. 242// 243// https://msdn.microsoft.com/en-us/library/azure/dn505708.aspx 244func (c SQLDatabaseClient) GetDatabase(server, database string) (ServiceResource, error) { 245 var db ServiceResource 246 247 if database == "" { 248 return db, fmt.Errorf(errParamNotSpecified, "database") 249 } 250 if server == "" { 251 return db, fmt.Errorf(errParamNotSpecified, "server") 252 } 253 254 url := fmt.Sprintf(azureGetDatabaseURL, server, database) 255 resp, err := c.mgmtClient.SendAzureGetRequest(url) 256 if err != nil { 257 return db, err 258 } 259 260 err = xml.Unmarshal(resp, &db) 261 return db, err 262} 263 264// ListDatabases returns a list of Azure SQL Databases on the given server. 265// 266// https://msdn.microsoft.com/en-us/library/azure/dn505711.aspx 267func (c SQLDatabaseClient) ListDatabases(server string) (ListDatabasesResponse, error) { 268 var databases ListDatabasesResponse 269 if server == "" { 270 return databases, fmt.Errorf(errParamNotSpecified, "server name") 271 } 272 273 url := fmt.Sprintf(azureListDatabasesURL, server) 274 resp, err := c.mgmtClient.SendAzureGetRequest(url) 275 if err != nil { 276 return databases, err 277 } 278 279 err = xml.Unmarshal(resp, &databases) 280 return databases, err 281} 282 283// UpdateDatabase updates the details of the given Database off the given server. 284// 285// https://msdn.microsoft.com/en-us/library/azure/dn505718.aspx 286func (c SQLDatabaseClient) UpdateDatabase( 287 server, database string, 288 params ServiceResourceUpdateParams) (management.OperationID, error) { 289 if database == "" { 290 return "", fmt.Errorf(errParamNotSpecified, "database") 291 } 292 if server == "" { 293 return "", fmt.Errorf(errParamNotSpecified, "server") 294 } 295 296 url := fmt.Sprintf(azureUpdateDatabaseURL, server, database) 297 req, err := xml.Marshal(params) 298 if err != nil { 299 return "", err 300 } 301 302 return c.mgmtClient.SendAzurePutRequest(url, "text/xml", req) 303} 304 305// DeleteDatabase deletes the Azure SQL Database off the given server. 306// 307// https://msdn.microsoft.com/en-us/library/azure/dn505705.aspx 308func (c SQLDatabaseClient) DeleteDatabase(server, database string) error { 309 if database == "" { 310 return fmt.Errorf(errParamNotSpecified, "database") 311 } 312 if server == "" { 313 return fmt.Errorf(errParamNotSpecified, "server") 314 } 315 316 url := fmt.Sprintf(azureDeleteDatabaseURL, server, database) 317 318 _, err := c.mgmtClient.SendAzureDeleteRequest(url) 319 320 return err 321} 322