From 14d534c103d5f7df254dce2e36e2fa33d27e9c6a Mon Sep 17 00:00:00 2001 From: Greg Oliver Date: Fri, 21 Jul 2017 11:14:45 -0700 Subject: [PATCH 1/8] resource_arm_sql_server: switch dependency from riviera to azure-sdk-for-go --- azurerm/config.go | 7 ++ azurerm/resource_arm_sql_server.go | 133 +++++++++++++----------- azurerm/resource_arm_sql_server_test.go | 36 ++++--- 3 files changed, 98 insertions(+), 78 deletions(-) diff --git a/azurerm/config.go b/azurerm/config.go index 4688ebc5911b..e31fbf1fb47f 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -113,6 +113,7 @@ type ArmClient struct { keyVaultClient keyvault.VaultsClient sqlElasticPoolsClient sql.ElasticPoolsClient + sqlServersClient sql.ServersClient appInsightsClient appinsights.ComponentsClient @@ -526,6 +527,12 @@ func (c *Config) getArmClient() (*ArmClient, error) { sqlepc.Sender = autorest.CreateSender(withRequestLogging()) client.sqlElasticPoolsClient = sqlepc + sqlsrv := sql.NewServersClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&sqlsrv.Client) + sqlsrv.Authorizer = auth + sqlsrv.Sender = autorest.CreateSender(withRequestLogging()) + client.sqlServersClient = sqlsrv + ai := appinsights.NewComponentsClientWithBaseURI(endpoint, c.SubscriptionID) setUserAgent(&ai.Client) ai.Authorizer = auth diff --git a/azurerm/resource_arm_sql_server.go b/azurerm/resource_arm_sql_server.go index 8bf4aba0ff82..2a69e10ca1eb 100644 --- a/azurerm/resource_arm_sql_server.go +++ b/azurerm/resource_arm_sql_server.go @@ -2,18 +2,17 @@ package azurerm import ( "fmt" - "log" + "net/http" + "github.com/Azure/azure-sdk-for-go/arm/sql" "github.com/hashicorp/terraform/helper/schema" - "github.com/jen20/riviera/azure" - "github.com/jen20/riviera/sql" ) func resourceArmSqlServer() *schema.Resource { return &schema.Resource{ - Create: resourceArmSqlServerCreate, + Create: resourceArmSqlServerCreateOrUpdate, Read: resourceArmSqlServerRead, - Update: resourceArmSqlServerCreate, + Update: resourceArmSqlServerCreateOrUpdate, Delete: resourceArmSqlServerDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, @@ -60,101 +59,111 @@ func resourceArmSqlServer() *schema.Resource { } } -func resourceArmSqlServerCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient) - rivieraClient := client.rivieraClient +func resourceArmSqlServerCreateOrUpdate(d *schema.ResourceData, meta interface{}) error { + sqlServersClient := meta.(*ArmClient).sqlServersClient - tags := d.Get("tags").(map[string]interface{}) - expandedTags := expandTags(tags) - - createRequest := rivieraClient.NewRequest() - createRequest.Command = &sql.CreateOrUpdateServer{ - Name: d.Get("name").(string), - Location: d.Get("location").(string), - ResourceGroupName: d.Get("resource_group_name").(string), - AdministratorLogin: azure.String(d.Get("administrator_login").(string)), - AdministratorLoginPassword: azure.String(d.Get("administrator_login_password").(string)), - Version: azure.String(d.Get("version").(string)), - Tags: *expandedTags, - } + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + location := d.Get("location").(string) + admin := d.Get("administrator_login").(string) + adminPw := d.Get("administrator_login_password").(string) + fqdn := d.Get("fully_qualified_domain_name").(string) - createResponse, err := createRequest.Execute() - if err != nil { - return fmt.Errorf("Error creating SQL Server: %s", err) + version := d.Get("version").(string) + var serverVersion sql.ServerVersion + if version == string(sql.OneTwoFullStopZero) { + serverVersion = sql.OneTwoFullStopZero + } + if version == string(sql.TwoFullStopZero) { + serverVersion = sql.TwoFullStopZero } - if !createResponse.IsSuccessful() { - return fmt.Errorf("Error creating SQL Server: %s", createResponse.Error) + if serverVersion == "" { + return fmt.Errorf("Invalid server version provided. It must be one of 12.0 or 2.0, passed as string: %s", version) + } + + tags := d.Get("tags").(map[string]interface{}) + metadata := expandTags(tags) + + props := sql.ServerProperties{ + FullyQualifiedDomainName: &fqdn, + Version: serverVersion, + AdministratorLogin: &admin, + AdministratorLoginPassword: &adminPw, } - readRequest := rivieraClient.NewRequest() - readRequest.Command = &sql.GetServer{ - Name: d.Get("name").(string), - ResourceGroupName: d.Get("resource_group_name").(string), + parameters := sql.Server{ + Name: &name, + ServerProperties: &props, + Tags: metadata, + Location: &location, } - readResponse, err := readRequest.Execute() + //last parameter is set to empty to allow updates to records after creation + // (per SDK, set it to '*' to prevent updates, all other values are ignored) + result, err := sqlServersClient.CreateOrUpdate(resGroup, name, parameters) if err != nil { - return fmt.Errorf("Error reading SQL Server: %s", err) + return err } - if !readResponse.IsSuccessful() { - return fmt.Errorf("Error reading SQL Server: %s", readResponse.Error) + + if result.ID == nil { + return fmt.Errorf("Cannot create Sql Server %s (resource group %s) ID", name, resGroup) } - resp := readResponse.Parsed.(*sql.GetServerResponse) - d.SetId(*resp.ID) + d.SetId(*result.ID) return resourceArmSqlServerRead(d, meta) } func resourceArmSqlServerRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient) - rivieraClient := client.rivieraClient + sqlServersClient := meta.(*ArmClient).sqlServersClient id, err := parseAzureResourceID(d.Id()) if err != nil { return err } - readRequest := rivieraClient.NewRequestForURI(d.Id()) - readRequest.Command = &sql.GetServer{} + resGroup := id.ResourceGroup + name := id.Path["servers"] - readResponse, err := readRequest.Execute() + result, err := sqlServersClient.Get(resGroup, name) if err != nil { - return fmt.Errorf("Error reading SQL Server: %s", err) + return fmt.Errorf("Error reading SQL Server %s: %v", name, err) } - if !readResponse.IsSuccessful() { - log.Printf("[INFO] Error reading SQL Server %q - removing from state", d.Id()) + if result.Response.StatusCode == http.StatusNotFound { d.SetId("") - return fmt.Errorf("Error reading SQL Server: %s", readResponse.Error) + return nil } - resp := readResponse.Parsed.(*sql.GetServerResponse) + serverProperties := *result.ServerProperties - d.Set("name", id.Path["servers"]) - d.Set("resource_group_name", id.ResourceGroup) - d.Set("location", azureRMNormalizeLocation(*resp.Location)) - d.Set("fully_qualified_domain_name", resp.FullyQualifiedDomainName) - d.Set("administrator_login", resp.AdministratorLogin) - d.Set("version", resp.Version) + serverVersion := serverProperties.Version - flattenAndSetTags(d, resp.Tags) + d.Set("name", name) + d.Set("resource_group_name", resGroup) + d.Set("version", string(serverVersion)) + d.Set("location", *result.Location) + d.Set("administrator_login", *serverProperties.AdministratorLogin) + d.Set("fully_qualified_domain_name", *serverProperties.FullyQualifiedDomainName) + + flattenAndSetTags(d, result.Tags) return nil } func resourceArmSqlServerDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient) - rivieraClient := client.rivieraClient - - deleteRequest := rivieraClient.NewRequestForURI(d.Id()) - deleteRequest.Command = &sql.DeleteServer{} + sqlServersClient := meta.(*ArmClient).sqlServersClient - deleteResponse, err := deleteRequest.Execute() + id, err := parseAzureResourceID(d.Id()) if err != nil { - return fmt.Errorf("Error deleting SQL Server: %s", err) + return err } - if !deleteResponse.IsSuccessful() { - return fmt.Errorf("Error deleting SQL Server: %s", deleteResponse.Error) + + resGroup := id.ResourceGroup + name := id.Path["servers"] + + result, error := sqlServersClient.Delete(resGroup, name) + if result.Response.StatusCode != http.StatusOK { + return fmt.Errorf("Error deleting SQL Server %s: %s", name, error) } return nil diff --git a/azurerm/resource_arm_sql_server_test.go b/azurerm/resource_arm_sql_server_test.go index 02b78d6b1b8a..55f6de1f977f 100644 --- a/azurerm/resource_arm_sql_server_test.go +++ b/azurerm/resource_arm_sql_server_test.go @@ -2,12 +2,12 @@ package azurerm import ( "fmt" + "net/http" "testing" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" - "github.com/jen20/riviera/sql" ) func TestAccAzureRMSqlServer_basic(t *testing.T) { @@ -61,23 +61,25 @@ func TestAccAzureRMSqlServer_withTags(t *testing.T) { func testCheckAzureRMSqlServerExists(name string) resource.TestCheckFunc { return func(s *terraform.State) error { - + // Ensure we have enough information in state to look up in API rs, ok := s.RootModule().Resources[name] if !ok { return fmt.Errorf("Not found: %s", name) } - conn := testAccProvider.Meta().(*ArmClient).rivieraClient - - readRequest := conn.NewRequestForURI(rs.Primary.ID) - readRequest.Command = &sql.GetServer{} + sqlServerName := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for SQL Server: %s", sqlServerName) + } - readResponse, err := readRequest.Execute() + conn := testAccProvider.Meta().(*ArmClient).sqlServersClient + resp, err := conn.Get(resourceGroup, sqlServerName) if err != nil { - return fmt.Errorf("Bad: GetServer: %+v", err) + return fmt.Errorf("Bad: Get SQL Server: %v", err) } - if !readResponse.IsSuccessful() { - return fmt.Errorf("Bad: GetServer: %+v", readResponse.Error) + if resp.Response.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: SQL Server %s (resource group: %s) does not exist", sqlServerName, resourceGroup) } return nil @@ -85,24 +87,26 @@ func testCheckAzureRMSqlServerExists(name string) resource.TestCheckFunc { } func testCheckAzureRMSqlServerDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*ArmClient).rivieraClient + conn := testAccProvider.Meta().(*ArmClient).sqlServersClient for _, rs := range s.RootModule().Resources { if rs.Type != "azurerm_sql_server" { continue } - readRequest := conn.NewRequestForURI(rs.Primary.ID) - readRequest.Command = &sql.GetServer{} + sqlServerName := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(resourceGroup, sqlServerName) - readResponse, err := readRequest.Execute() if err != nil { return fmt.Errorf("Bad: GetServer: % +v", err) } - if readResponse.IsSuccessful() { - return fmt.Errorf("Bad: SQL Server still exists: %+v", readResponse.Error) + if resp.Response.StatusCode != http.StatusNotFound { + return fmt.Errorf("SQL Server still exists:\n%#v", resp.ServerProperties) } + } return nil From 39125ad36d907bd2d129eae090157557f5320108 Mon Sep 17 00:00:00 2001 From: Greg Oliver Date: Sat, 22 Jul 2017 14:11:52 -0700 Subject: [PATCH 2/8] response to PR feedback. --- azurerm/resource_arm_sql_server.go | 36 +++++++++++------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/azurerm/resource_arm_sql_server.go b/azurerm/resource_arm_sql_server.go index 2a69e10ca1eb..b8483cae473d 100644 --- a/azurerm/resource_arm_sql_server.go +++ b/azurerm/resource_arm_sql_server.go @@ -6,6 +6,7 @@ import ( "github.com/Azure/azure-sdk-for-go/arm/sql" "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" ) func resourceArmSqlServer() *schema.Resource { @@ -36,6 +37,10 @@ func resourceArmSqlServer() *schema.Resource { "version": &schema.Schema{ Type: schema.TypeString, Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(sql.OneTwoFullStopZero), + string(sql.TwoFullStopZero), + }, true), }, "administrator_login": &schema.Schema{ @@ -69,24 +74,12 @@ func resourceArmSqlServerCreateOrUpdate(d *schema.ResourceData, meta interface{} adminPw := d.Get("administrator_login_password").(string) fqdn := d.Get("fully_qualified_domain_name").(string) - version := d.Get("version").(string) - var serverVersion sql.ServerVersion - if version == string(sql.OneTwoFullStopZero) { - serverVersion = sql.OneTwoFullStopZero - } - if version == string(sql.TwoFullStopZero) { - serverVersion = sql.TwoFullStopZero - } - if serverVersion == "" { - return fmt.Errorf("Invalid server version provided. It must be one of 12.0 or 2.0, passed as string: %s", version) - } - tags := d.Get("tags").(map[string]interface{}) metadata := expandTags(tags) props := sql.ServerProperties{ FullyQualifiedDomainName: &fqdn, - Version: serverVersion, + Version: sql.ServerVersion(d.Get("version").(string)), AdministratorLogin: &admin, AdministratorLoginPassword: &adminPw, } @@ -98,8 +91,6 @@ func resourceArmSqlServerCreateOrUpdate(d *schema.ResourceData, meta interface{} Location: &location, } - //last parameter is set to empty to allow updates to records after creation - // (per SDK, set it to '*' to prevent updates, all other values are ignored) result, err := sqlServersClient.CreateOrUpdate(resGroup, name, parameters) if err != nil { return err @@ -134,16 +125,15 @@ func resourceArmSqlServerRead(d *schema.ResourceData, meta interface{}) error { return nil } - serverProperties := *result.ServerProperties - - serverVersion := serverProperties.Version + if serverProperties := result.ServerProperties; serverProperties != nil { + d.Set("version", string(serverProperties.Version)) + d.Set("administrator_login", serverProperties.AdministratorLogin) + d.Set("fully_qualified_domain_name", serverProperties.FullyQualifiedDomainName) + } d.Set("name", name) d.Set("resource_group_name", resGroup) - d.Set("version", string(serverVersion)) - d.Set("location", *result.Location) - d.Set("administrator_login", *serverProperties.AdministratorLogin) - d.Set("fully_qualified_domain_name", *serverProperties.FullyQualifiedDomainName) + d.Set("location", azureRMNormalizeLocation(*result.Location)) flattenAndSetTags(d, result.Tags) @@ -163,7 +153,7 @@ func resourceArmSqlServerDelete(d *schema.ResourceData, meta interface{}) error result, error := sqlServersClient.Delete(resGroup, name) if result.Response.StatusCode != http.StatusOK { - return fmt.Errorf("Error deleting SQL Server %s: %s", name, error) + return fmt.Errorf("Error deleting SQL Server %s: %+v", name, error) } return nil From 0cde1788ba33278d1b54fdbbbb20a41f69351668 Mon Sep 17 00:00:00 2001 From: Greg Oliver Date: Fri, 4 Aug 2017 12:37:39 -0700 Subject: [PATCH 3/8] fix error handler for check destroy --- azurerm/resource_arm_sql_server_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/azurerm/resource_arm_sql_server_test.go b/azurerm/resource_arm_sql_server_test.go index 55f6de1f977f..12b08fc24d29 100644 --- a/azurerm/resource_arm_sql_server_test.go +++ b/azurerm/resource_arm_sql_server_test.go @@ -5,6 +5,7 @@ import ( "net/http" "testing" + "github.com/Azure/go-autorest/autorest" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" From 9f0835f86cd3fa6aa5f5099edcafc0d9cda6358b Mon Sep 17 00:00:00 2001 From: Greg Oliver Date: Wed, 9 Aug 2017 08:46:23 -0700 Subject: [PATCH 4/8] fix response handling in test, make fmt. --- azurerm/resource_arm_sql_server_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/azurerm/resource_arm_sql_server_test.go b/azurerm/resource_arm_sql_server_test.go index 12b08fc24d29..64bbb4680dbb 100644 --- a/azurerm/resource_arm_sql_server_test.go +++ b/azurerm/resource_arm_sql_server_test.go @@ -5,7 +5,6 @@ import ( "net/http" "testing" - "github.com/Azure/go-autorest/autorest" "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" @@ -104,10 +103,12 @@ func testCheckAzureRMSqlServerDestroy(s *terraform.State) error { return fmt.Errorf("Bad: GetServer: % +v", err) } - if resp.Response.StatusCode != http.StatusNotFound { - return fmt.Errorf("SQL Server still exists:\n%#v", resp.ServerProperties) + if resp.StatusCode == http.StatusNotFound { + return nil } + return fmt.Errorf("sql server %s still exists", sqlServerName) + } return nil From f0cf0d4d96e033851a42309429959764901f1212 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 18 Aug 2017 11:13:30 +0200 Subject: [PATCH 5/8] Fixing up the tests --- azurerm/resource_arm_sql_server_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azurerm/resource_arm_sql_server_test.go b/azurerm/resource_arm_sql_server_test.go index 64bbb4680dbb..5349db7980dc 100644 --- a/azurerm/resource_arm_sql_server_test.go +++ b/azurerm/resource_arm_sql_server_test.go @@ -100,14 +100,14 @@ func testCheckAzureRMSqlServerDestroy(s *terraform.State) error { resp, err := conn.Get(resourceGroup, sqlServerName) if err != nil { - return fmt.Errorf("Bad: GetServer: % +v", err) - } + if resp.StatusCode == http.StatusNotFound { + return nil + } - if resp.StatusCode == http.StatusNotFound { - return nil + return fmt.Errorf("Bad: Get Server: %+v", err) } - return fmt.Errorf("sql server %s still exists", sqlServerName) + return fmt.Errorf("SQL Server %s still exists", sqlServerName) } From 0d51b2912d184996f0d8304e50c8069993b819b7 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 18 Aug 2017 11:54:59 +0200 Subject: [PATCH 6/8] Refactoring and making username force new --- azurerm/resource_arm_sql_server.go | 89 +++++++++++++------------ azurerm/resource_arm_sql_server_test.go | 9 ++- 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/azurerm/resource_arm_sql_server.go b/azurerm/resource_arm_sql_server.go index b8483cae473d..742ce38e7fd0 100644 --- a/azurerm/resource_arm_sql_server.go +++ b/azurerm/resource_arm_sql_server.go @@ -2,7 +2,6 @@ package azurerm import ( "fmt" - "net/http" "github.com/Azure/azure-sdk-for-go/arm/sql" "github.com/hashicorp/terraform/helper/schema" @@ -11,16 +10,16 @@ import ( func resourceArmSqlServer() *schema.Resource { return &schema.Resource{ - Create: resourceArmSqlServerCreateOrUpdate, + Create: resourceArmSqlServerCreateUpdate, Read: resourceArmSqlServerRead, - Update: resourceArmSqlServerCreateOrUpdate, + Update: resourceArmSqlServerCreateUpdate, Delete: resourceArmSqlServerDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, Schema: map[string]*schema.Schema{ - "name": &schema.Schema{ + "name": { Type: schema.TypeString, Required: true, ForceNew: true, @@ -28,33 +27,35 @@ func resourceArmSqlServer() *schema.Resource { "location": locationSchema(), - "resource_group_name": &schema.Schema{ + "resource_group_name": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "version": &schema.Schema{ + "version": { Type: schema.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(sql.OneTwoFullStopZero), string(sql.TwoFullStopZero), + string(sql.OneTwoFullStopZero), }, true), + // TODO: is this ForceNew? }, - "administrator_login": &schema.Schema{ + "administrator_login": { Type: schema.TypeString, Required: true, + ForceNew: true, }, - "administrator_login_password": &schema.Schema{ + "administrator_login_password": { Type: schema.TypeString, Required: true, Sensitive: true, }, - "fully_qualified_domain_name": &schema.Schema{ + "fully_qualified_domain_name": { Type: schema.TypeString, Computed: true, }, @@ -64,49 +65,45 @@ func resourceArmSqlServer() *schema.Resource { } } -func resourceArmSqlServerCreateOrUpdate(d *schema.ResourceData, meta interface{}) error { - sqlServersClient := meta.(*ArmClient).sqlServersClient +func resourceArmSqlServerCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).sqlServersClient name := d.Get("name").(string) resGroup := d.Get("resource_group_name").(string) location := d.Get("location").(string) - admin := d.Get("administrator_login").(string) - adminPw := d.Get("administrator_login_password").(string) - fqdn := d.Get("fully_qualified_domain_name").(string) + adminUsername := d.Get("administrator_login").(string) + adminPassword := d.Get("administrator_login_password").(string) + version := d.Get("version").(string) tags := d.Get("tags").(map[string]interface{}) metadata := expandTags(tags) - props := sql.ServerProperties{ - FullyQualifiedDomainName: &fqdn, - Version: sql.ServerVersion(d.Get("version").(string)), - AdministratorLogin: &admin, - AdministratorLoginPassword: &adminPw, - } - parameters := sql.Server{ - Name: &name, - ServerProperties: &props, - Tags: metadata, - Location: &location, + Location: &location, + Tags: metadata, + ServerProperties: &sql.ServerProperties{ + Version: sql.ServerVersion(version), + AdministratorLogin: &adminUsername, + AdministratorLoginPassword: &adminPassword, + }, } - result, err := sqlServersClient.CreateOrUpdate(resGroup, name, parameters) + response, err := client.CreateOrUpdate(resGroup, name, parameters) if err != nil { return err } - if result.ID == nil { - return fmt.Errorf("Cannot create Sql Server %s (resource group %s) ID", name, resGroup) + if response.ID == nil { + return fmt.Errorf("Cannot create SQL Server %s (resource group %s) ID", name, resGroup) } - d.SetId(*result.ID) + d.SetId(*response.ID) return resourceArmSqlServerRead(d, meta) } func resourceArmSqlServerRead(d *schema.ResourceData, meta interface{}) error { - sqlServersClient := meta.(*ArmClient).sqlServersClient + client := meta.(*ArmClient).sqlServersClient id, err := parseAzureResourceID(d.Id()) if err != nil { @@ -116,14 +113,18 @@ func resourceArmSqlServerRead(d *schema.ResourceData, meta interface{}) error { resGroup := id.ResourceGroup name := id.Path["servers"] - result, err := sqlServersClient.Get(resGroup, name) + result, err := client.Get(resGroup, name) if err != nil { + if responseWasNotFound(result.Response) { + d.SetId("") + return nil + } return fmt.Errorf("Error reading SQL Server %s: %v", name, err) } - if result.Response.StatusCode == http.StatusNotFound { - d.SetId("") - return nil - } + + d.Set("name", name) + d.Set("resource_group_name", resGroup) + d.Set("location", azureRMNormalizeLocation(*result.Location)) if serverProperties := result.ServerProperties; serverProperties != nil { d.Set("version", string(serverProperties.Version)) @@ -131,17 +132,13 @@ func resourceArmSqlServerRead(d *schema.ResourceData, meta interface{}) error { d.Set("fully_qualified_domain_name", serverProperties.FullyQualifiedDomainName) } - d.Set("name", name) - d.Set("resource_group_name", resGroup) - d.Set("location", azureRMNormalizeLocation(*result.Location)) - flattenAndSetTags(d, result.Tags) return nil } func resourceArmSqlServerDelete(d *schema.ResourceData, meta interface{}) error { - sqlServersClient := meta.(*ArmClient).sqlServersClient + client := meta.(*ArmClient).sqlServersClient id, err := parseAzureResourceID(d.Id()) if err != nil { @@ -151,9 +148,13 @@ func resourceArmSqlServerDelete(d *schema.ResourceData, meta interface{}) error resGroup := id.ResourceGroup name := id.Path["servers"] - result, error := sqlServersClient.Delete(resGroup, name) - if result.Response.StatusCode != http.StatusOK { - return fmt.Errorf("Error deleting SQL Server %s: %+v", name, error) + response, err := client.Delete(resGroup, name) + if err != nil { + if responseWasNotFound(response) { + return nil + } + + return fmt.Errorf("Error deleting SQL Server %s: %+v", name, err) } return nil diff --git a/azurerm/resource_arm_sql_server_test.go b/azurerm/resource_arm_sql_server_test.go index 5349db7980dc..eb681fff739b 100644 --- a/azurerm/resource_arm_sql_server_test.go +++ b/azurerm/resource_arm_sql_server_test.go @@ -2,7 +2,6 @@ package azurerm import ( "fmt" - "net/http" "testing" "github.com/hashicorp/terraform/helper/acctest" @@ -76,11 +75,11 @@ func testCheckAzureRMSqlServerExists(name string) resource.TestCheckFunc { conn := testAccProvider.Meta().(*ArmClient).sqlServersClient resp, err := conn.Get(resourceGroup, sqlServerName) if err != nil { + if responseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: SQL Server %s (resource group: %s) does not exist", sqlServerName, resourceGroup) + } return fmt.Errorf("Bad: Get SQL Server: %v", err) } - if resp.Response.StatusCode == http.StatusNotFound { - return fmt.Errorf("Bad: SQL Server %s (resource group: %s) does not exist", sqlServerName, resourceGroup) - } return nil } @@ -100,7 +99,7 @@ func testCheckAzureRMSqlServerDestroy(s *terraform.State) error { resp, err := conn.Get(resourceGroup, sqlServerName) if err != nil { - if resp.StatusCode == http.StatusNotFound { + if responseWasNotFound(resp.Response) { return nil } From 2c73509a1b276a4439c9da5d722ffd59bb011a9e Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 18 Aug 2017 11:55:28 +0200 Subject: [PATCH 7/8] Returning a more useful error for conflicts when creating a server --- azurerm/resource_arm_sql_server.go | 5 +++++ azurerm/response.go | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/azurerm/resource_arm_sql_server.go b/azurerm/resource_arm_sql_server.go index 742ce38e7fd0..a7d18d46fcb2 100644 --- a/azurerm/resource_arm_sql_server.go +++ b/azurerm/resource_arm_sql_server.go @@ -90,6 +90,11 @@ func resourceArmSqlServerCreateUpdate(d *schema.ResourceData, meta interface{}) response, err := client.CreateOrUpdate(resGroup, name, parameters) if err != nil { + // if the name is in-use, Azure returns a 409 "Unknown Service Error" which is a bad UX + if responseWasConflict(response.Response) { + return fmt.Errorf("SQL Server names need to be globally unique and '%s' is already in use.", name) + } + return err } diff --git a/azurerm/response.go b/azurerm/response.go index e3b01100b50b..bd0cc5da6ae3 100644 --- a/azurerm/response.go +++ b/azurerm/response.go @@ -6,9 +6,17 @@ import ( "github.com/Azure/go-autorest/autorest" ) +func responseWasConflict(resp autorest.Response) bool { + return responseWasStatusCode(resp, http.StatusConflict) +} + func responseWasNotFound(resp autorest.Response) bool { + return responseWasStatusCode(resp, http.StatusNotFound) +} + +func responseWasStatusCode(resp autorest.Response, statusCode int) bool { if r := resp.Response; r != nil { - if r.StatusCode == http.StatusNotFound { + if r.StatusCode == statusCode { return true } } From e3ce578e95ffa5b77e1f4a6f6149f59f6dd3da43 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Fri, 18 Aug 2017 11:59:40 +0200 Subject: [PATCH 8/8] Updating the documentation --- website/docs/r/sql_server.html.markdown | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/website/docs/r/sql_server.html.markdown b/website/docs/r/sql_server.html.markdown index 8af90f9dc67b..b1d791a52035 100644 --- a/website/docs/r/sql_server.html.markdown +++ b/website/docs/r/sql_server.html.markdown @@ -3,12 +3,13 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_sql_server" sidebar_current: "docs-azurerm-resource-sql-server" description: |- - Create a SQL Server. + Manages a SQL Azure Database Server. + --- # azurerm\_sql\_server -Allows you to manage an Azure SQL Database Server +Manages a SQL Azure Database Server. ~> **Note:** All arguments including the administrator login and password will be stored in the raw state as plain-text. [Read more about sensitive data in state](/docs/state/sensitive-data.html). @@ -17,14 +18,14 @@ Allows you to manage an Azure SQL Database Server ```hcl resource "azurerm_resource_group" "test" { - name = "acceptanceTestResourceGroup1" + name = "database-rg" location = "West US" } resource "azurerm_sql_server" "test" { name = "mysqlserver" resource_group_name = "${azurerm_resource_group.test.name}" - location = "West US" + location = "${azurerm_resource_group.test.location}" version = "12.0" administrator_login = "mradministrator" administrator_login_password = "thisIsDog11" @@ -38,18 +39,17 @@ resource "azurerm_sql_server" "test" { The following arguments are supported: -* `name` - (Required) The name of the SQL Server. +* `name` - (Required) The name of the SQL Server. This needs to be globally unique within Azure. -* `resource_group_name` - (Required) The name of the resource group in which to - create the sql server. +* `resource_group_name` - (Required) The name of the resource group in which to create the SQL Server. * `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. * `version` - (Required) The version for the new server. Valid values are: 2.0 (for v11 server) and 12.0 (for v12 server). -* `administrator_login` - (Required) The administrator login name for the new server. +* `administrator_login` - (Required) The administrator login name for the new server. Changing this forces a new resource to be created. -* `administrator_login_password` - (Required) The password for the new AdministratorLogin. Please following Azures [Password Policy](https://msdn.microsoft.com/library/ms161959.aspx) +* `administrator_login_password` - (Required) The password associated with the `administrator_login` user. Needs to comply with Azure's [Password Policy](https://msdn.microsoft.com/library/ms161959.aspx) * `tags` - (Optional) A mapping of tags to assign to the resource.