From c8b0ba7485894b493cb187039c423f00ac92246a Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Mon, 3 Aug 2020 16:33:29 +0800 Subject: [PATCH 01/13] Support identity in mysql server --- .teamcity/components/generated/services.kt | 1 + .../services/mysql/mysql_server_resource.go | 69 +++++++++++++++++++ .../mysql/tests/mysql_server_resource_test.go | 49 +++++++++++++ 3 files changed, 119 insertions(+) diff --git a/.teamcity/components/generated/services.kt b/.teamcity/components/generated/services.kt index dfca6b2f203f..69be66a697d0 100644 --- a/.teamcity/components/generated/services.kt +++ b/.teamcity/components/generated/services.kt @@ -73,6 +73,7 @@ var services = mapOf( "storage" to "Storage", "streamanalytics" to "Stream Analytics", "subscription" to "Subscription", + "synapse" to "Synapse", "iottimeseriesinsights" to "Time Series Insights", "trafficmanager" to "Traffic Manager", "web" to "Web" diff --git a/azurerm/internal/services/mysql/mysql_server_resource.go b/azurerm/internal/services/mysql/mysql_server_resource.go index b52b6cef5c2b..51b4693c8a8f 100644 --- a/azurerm/internal/services/mysql/mysql_server_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_resource.go @@ -168,6 +168,33 @@ func resourceArmMySqlServer() *schema.Resource { }, false), }, + "identity": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(mysql.SystemAssigned), + }, false), + }, + + "principal_id": { + Type: schema.TypeString, + Computed: true, + }, + + "tenant_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "ssl_enforcement": { Type: schema.TypeString, Optional: true, @@ -487,6 +514,7 @@ func resourceArmMySqlServerCreate(d *schema.ResourceData, meta interface{}) erro } server := mysql.ServerForCreate{ + Identity: expandServerIdentity(d.Get("identity").([]interface{})), Location: &location, Properties: props, Sku: sku, @@ -563,6 +591,7 @@ func resourceArmMySqlServerUpdate(d *schema.ResourceData, meta interface{}) erro storageProfile := expandMySQLStorageProfile(d) properties := mysql.ServerUpdateParameters{ + Identity: expandServerIdentity(d.Get("identity").([]interface{})), ServerUpdateParametersProperties: &mysql.ServerUpdateParametersProperties{ AdministratorLoginPassword: utils.String(d.Get("administrator_login_password").(string)), PublicNetworkAccess: publicAccess, @@ -647,6 +676,10 @@ func resourceArmMySqlServerRead(d *schema.ResourceData, meta interface{}) error tier = sku.Tier } + if err := d.Set("identity", flattenServerIdentity(resp.Identity)); err != nil { + return fmt.Errorf("setting `identity`: %+v", err) + } + if props := resp.ServerProperties; props != nil { d.Set("administrator_login", props.AdministratorLogin) d.Set("infrastructure_encryption_enabled", props.InfrastructureEncryption == mysql.InfrastructureEncryptionEnabled) @@ -888,3 +921,39 @@ func flattenSecurityAlertPolicy(props *mysql.SecurityAlertPolicyProperties, acce return []interface{}{block} } + +func expandServerIdentity(input []interface{}) *mysql.ResourceIdentity { + if len(input) == 0 { + return nil + } + + v := input[0].(map[string]interface{}) + + return &mysql.ResourceIdentity{ + Type: mysql.IdentityType(v["type"].(string)), + } +} + +func flattenServerIdentity(input *mysql.ResourceIdentity) []interface{} { + if input == nil { + return []interface{}{} + } + + principalID := "" + if input.PrincipalID != nil { + principalID = input.PrincipalID.String() + } + + tenantID := "" + if input.TenantID != nil { + tenantID = input.TenantID.String() + } + + return []interface{}{ + map[string]interface{}{ + "type": string(input.Type), + "principal_id": principalID, + "tenant_id": tenantID, + }, + } +} diff --git a/azurerm/internal/services/mysql/tests/mysql_server_resource_test.go b/azurerm/internal/services/mysql/tests/mysql_server_resource_test.go index 27c8b3566960..e4cdb3759cf1 100644 --- a/azurerm/internal/services/mysql/tests/mysql_server_resource_test.go +++ b/azurerm/internal/services/mysql/tests/mysql_server_resource_test.go @@ -31,6 +31,25 @@ func TestAccAzureRMMySQLServer_basicFiveSix(t *testing.T) { }) } +func TestAccAzureRMMySQLServer_basicFiveSixWithIdentity(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mysql_server", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMySQLServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMySQLServer_basicWithIdentity(data, "5.6"), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMySQLServerExists(data.ResourceName), + ), + }, + data.ImportStep("administrator_login_password"), // not returned as sensitive + }, + }) +} + func TestAccAzureRMMySQLServer_basicFiveSixDeprecated(t *testing.T) { // remove in v3.0 data := acceptance.BuildTestData(t, "azurerm_mysql_server", "test") @@ -451,6 +470,36 @@ resource "azurerm_mysql_server" "test" { `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) } +func testAccAzureRMMySQLServer_basicWithIdentity(data acceptance.TestData, version string) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_mysql_server" "test" { + name = "acctestmysqlsvr-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "GP_Gen5_2" + administrator_login = "acctestun" + administrator_login_password = "H@Sh1CoR3!" + ssl_enforcement_enabled = true + ssl_minimal_tls_version_enforced = "TLS1_1" + storage_mb = 51200 + version = "%s" + +identity { +type = "SystemAssigned" +} +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) +} + func testAccAzureRMMySQLServer_complete(data acceptance.TestData, version string) string { return fmt.Sprintf(` provider "azurerm" { From fa4f3e3e0c78c125f26702be43dada63efb621aa Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Mon, 3 Aug 2020 16:36:16 +0800 Subject: [PATCH 02/13] Update doc --- website/docs/r/mysql_server.html.markdown | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/website/docs/r/mysql_server.html.markdown b/website/docs/r/mysql_server.html.markdown index 01a13b471fd0..27be23d2440d 100644 --- a/website/docs/r/mysql_server.html.markdown +++ b/website/docs/r/mysql_server.html.markdown @@ -14,10 +14,6 @@ Manages a MySQL Server. ## Example Usage ```hcl -provider "azurerm" { - features {} -} - resource "azurerm_resource_group" "example" { name = "example-resources" location = "West Europe" @@ -73,6 +69,8 @@ The following arguments are supported: * `geo_redundant_backup_enabled` - (Optional) Turn Geo-redundant server backups on/off. This allows you to choose between locally redundant or geo-redundant backup storage in the General Purpose and Memory Optimized tiers. When the backups are stored in geo-redundant backup storage, they are not only stored within the region in which your server is hosted, but are also replicated to a paired data center. This provides better protection and ability to restore your server in a different region in the event of a disaster. This is not supported for the Basic tier. +* `identity` - (Optional) An `identity` block as defined below. + * `infrastructure_encryption_enabled` - (Optional) Whether or not infrastructure is encrypted for this server. Defaults to `false`. Changing this forces a new resource to be created. * `public_network_access_enabled` - (Optional) Whether or not public network access is allowed for this server. Defaults to `true`. @@ -91,6 +89,12 @@ The following arguments are supported: --- +A `identity` block supports the following: + +* `type` - (Required) The Type of Identity which should be used for this MySQL Server. At this time the only possible value is `SystemAssigned`. + +--- + a `threat_detection_policy` block supports the following: * `enabled` - (Required) Is the policy enabled? @@ -116,6 +120,14 @@ The following attributes are exported: * `fqdn` - The FQDN of the MySQL Server. +--- + +A `identity` block exports the following: + +* `principal_id` - The (Client) ID of the Service Principal. + +* `tenant_id` - The ID of the Tenant the Service Principal is assigned in. + ## Timeouts The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: From b13adb5a96306e04fe48f99f69e38067140698d0 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Mon, 3 Aug 2020 16:53:21 +0800 Subject: [PATCH 03/13] Terrafmt --- .../services/mysql/tests/mysql_server_resource_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/internal/services/mysql/tests/mysql_server_resource_test.go b/azurerm/internal/services/mysql/tests/mysql_server_resource_test.go index e4cdb3759cf1..6cef2ab54abd 100644 --- a/azurerm/internal/services/mysql/tests/mysql_server_resource_test.go +++ b/azurerm/internal/services/mysql/tests/mysql_server_resource_test.go @@ -493,9 +493,9 @@ resource "azurerm_mysql_server" "test" { storage_mb = 51200 version = "%s" -identity { -type = "SystemAssigned" -} + identity { + type = "SystemAssigned" + } } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) } From 0dfa5597a9d05c6818345b01f37450924e027d0c Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Fri, 7 Aug 2020 10:29:21 +0800 Subject: [PATCH 04/13] Initial implementation of CMK in MySQL --- .../internal/services/mysql/client/client.go | 5 + .../mysql/mysql_server_key_resource.go | 186 ++++++++++++++++++ .../services/mysql/parse/mysql_server_key.go | 36 ++++ .../internal/services/mysql/registration.go | 1 + 4 files changed, 228 insertions(+) create mode 100644 azurerm/internal/services/mysql/mysql_server_key_resource.go create mode 100644 azurerm/internal/services/mysql/parse/mysql_server_key.go diff --git a/azurerm/internal/services/mysql/client/client.go b/azurerm/internal/services/mysql/client/client.go index fca16a5ad81f..d5d78689d17a 100644 --- a/azurerm/internal/services/mysql/client/client.go +++ b/azurerm/internal/services/mysql/client/client.go @@ -10,6 +10,7 @@ type Client struct { DatabasesClient *mysql.DatabasesClient FirewallRulesClient *mysql.FirewallRulesClient ServersClient *mysql.ServersClient + ServerKeysClient *mysql.ServerKeysClient ServerSecurityAlertPoliciesClient *mysql.ServerSecurityAlertPoliciesClient VirtualNetworkRulesClient *mysql.VirtualNetworkRulesClient ServerAdministratorsClient *mysql.ServerAdministratorsClient @@ -28,6 +29,9 @@ func NewClient(o *common.ClientOptions) *Client { ServersClient := mysql.NewServersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&ServersClient.Client, o.ResourceManagerAuthorizer) + ServerKeysClient := mysql.NewServerKeysClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&ServerKeysClient.Client, o.ResourceManagerAuthorizer) + serverSecurityAlertPoliciesClient := mysql.NewServerSecurityAlertPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&serverSecurityAlertPoliciesClient.Client, o.ResourceManagerAuthorizer) @@ -42,6 +46,7 @@ func NewClient(o *common.ClientOptions) *Client { DatabasesClient: &DatabasesClient, FirewallRulesClient: &FirewallRulesClient, ServersClient: &ServersClient, + ServerKeysClient: &ServerKeysClient, ServerSecurityAlertPoliciesClient: &serverSecurityAlertPoliciesClient, VirtualNetworkRulesClient: &VirtualNetworkRulesClient, ServerAdministratorsClient: &serverAdministratorsClient, diff --git a/azurerm/internal/services/mysql/mysql_server_key_resource.go b/azurerm/internal/services/mysql/mysql_server_key_resource.go new file mode 100644 index 000000000000..3bc62aa7d582 --- /dev/null +++ b/azurerm/internal/services/mysql/mysql_server_key_resource.go @@ -0,0 +1,186 @@ +package mysql + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" + "github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2020-01-01/mysql" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + keyVaultParse "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mysql/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mysql/validate" + azSchema "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tf/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmMySQLServerKey() *schema.Resource { + return &schema.Resource{ + Create: resourceArmMySQLServerKeyCreateUpdate, + Read: resourceArmMySQLServerKeyRead, + Update: resourceArmMySQLServerKeyCreateUpdate, + Delete: resourceArmMySQLServerKeyDelete, + + Importer: azSchema.ValidateResourceIDPriorToImport(func(id string) error { + _, err := parse.MySQLServerKeyID(id) + return err + }), + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "server_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.MysqlServerServerID, + }, + + "key_vault_key_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateKeyVaultChildId, + }, + }, + } +} + +func getMySQLServerKeyName(ctx context.Context, vaultsClient *keyvault.VaultsClient, keyVaultKeyURI string) (string, error) { + keyVaultKeyID, err := azure.ParseKeyVaultChildID(keyVaultKeyURI) + if err != nil { + return "", err + } + keyVaultIDRaw, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultsClient, keyVaultKeyID.KeyVaultBaseUrl) + if err != nil { + return "", err + } + keyVaultID, err := keyVaultParse.KeyVaultID(*keyVaultIDRaw) + if err != nil { + return "", err + } + return fmt.Sprintf("%s_%s_%s", keyVaultID.Name, keyVaultKeyID.Name, keyVaultKeyID.Version), nil +} + +func resourceArmMySQLServerKeyCreateUpdate(d *schema.ResourceData, meta interface{}) error { + keysClient := meta.(*clients.Client).MySQL.ServerKeysClient + vaultsClient := meta.(*clients.Client).KeyVault.VaultsClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + serverID, err := parse.MysqlServerServerID(d.Get("server_id").(string)) + if err != nil { + return err + } + keyVaultKeyURI := d.Get("key_vault_key_id").(string) + name, err := getMySQLServerKeyName(ctx, vaultsClient, keyVaultKeyURI) + if err != nil { + return fmt.Errorf("cannot compose name for MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) + } + + if d.IsNewResource() { + existing, err := keysClient.Get(ctx, serverID.ResourceGroup, serverID.Name, name) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("checking for presence of MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_mysql_server_key", *existing.ID) + } + } + + param := mysql.ServerKey{ + ServerKeyProperties: &mysql.ServerKeyProperties{ + ServerKeyType: utils.String("AzureKeyVault"), + URI: &keyVaultKeyURI, + }, + } + + future, err := keysClient.CreateOrUpdate(ctx, serverID.Name, name, param, serverID.ResourceGroup) + if err != nil { + return fmt.Errorf("creating/updating MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) + } + if err := future.WaitForCompletionRef(ctx, keysClient.Client); err != nil { + return fmt.Errorf("waiting for creation/update of MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) + } + + resp, err := keysClient.Get(ctx, serverID.ResourceGroup, serverID.Name, name) + if err != nil { + return fmt.Errorf("retrieving MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) + } + if resp.ID == nil || *resp.ID == "" { + return fmt.Errorf("empty or nil ID returned for MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) + } + + d.SetId(*resp.ID) + + return resourceArmMySQLServerKeyRead(d, meta) +} + +func resourceArmMySQLServerKeyRead(d *schema.ResourceData, meta interface{}) error { + serversClient := meta.(*clients.Client).MySQL.ServersClient + keysClient := meta.(*clients.Client).MySQL.ServerKeysClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.MySQLServerKeyID(d.Id()) + if err != nil { + return err + } + + resp, err := keysClient.Get(ctx, id.ResourceGroup, id.ServerName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[WARN] MySQL Server Key %q was not found (Resource Group %q / Server %q)", id.Name, id.ResourceGroup, id.ServerName) + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving MySQL Server Key %q (Resource Group %q / Server %q): %+v", id.Name, id.ResourceGroup, id.ServerName, err) + } + + respServer, err := serversClient.Get(ctx, id.ResourceGroup, id.ServerName) + if err != nil { + return fmt.Errorf("cannot get MySQL Server ID: %+v", err) + } + + d.Set("server_id", respServer.ID) + if props := resp.ServerKeyProperties; props != nil { + d.Set("key_vault_key_id", props.URI) + } + + return nil +} + +func resourceArmMySQLServerKeyDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).MySQL.ServerKeysClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.MySQLServerKeyID(d.Id()) + if err != nil { + return err + } + + future, err := client.Delete(ctx, id.ServerName, id.Name, id.ResourceGroup) + if err != nil { + return fmt.Errorf("deleting MySQL Server Key %q (Resource Group %q / Server %q): %+v", id.Name, id.ResourceGroup, id.ServerName, err) + } + if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for deletion of MySQL Server Key %q (Resource Group %q / Server %q): %+v", id.Name, id.ResourceGroup, id.ServerName) + } + + return nil +} diff --git a/azurerm/internal/services/mysql/parse/mysql_server_key.go b/azurerm/internal/services/mysql/parse/mysql_server_key.go new file mode 100644 index 000000000000..7dff9344cf7d --- /dev/null +++ b/azurerm/internal/services/mysql/parse/mysql_server_key.go @@ -0,0 +1,36 @@ +package parse + +import ( + "fmt" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type MySQLServerKeyId struct { + ResourceGroup string + ServerName string + Name string +} + +func MySQLServerKeyID(input string) (*MySQLServerKeyId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, fmt.Errorf("unable to parse MySQL Server Key ID %q: %+v", input, err) + } + + key := MySQLServerKeyId{ + ResourceGroup: id.ResourceGroup, + } + + if key.ServerName, err = id.PopSegment("servers"); err != nil { + return nil, err + } + if key.Name, err = id.PopSegment("keys"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &key, nil +} diff --git a/azurerm/internal/services/mysql/registration.go b/azurerm/internal/services/mysql/registration.go index 86a2652e5492..4accd4672648 100644 --- a/azurerm/internal/services/mysql/registration.go +++ b/azurerm/internal/services/mysql/registration.go @@ -30,6 +30,7 @@ func (r Registration) SupportedResources() map[string]*schema.Resource { "azurerm_mysql_database": resourceArmMySqlDatabase(), "azurerm_mysql_firewall_rule": resourceArmMySqlFirewallRule(), "azurerm_mysql_server": resourceArmMySqlServer(), + "azurerm_mysql_server_key": resourceArmMySQLServerKey(), "azurerm_mysql_virtual_network_rule": resourceArmMySSQLVirtualNetworkRule(), "azurerm_mysql_active_directory_administrator": resourceArmMySQLAdministrator()} } From 6699197812f88916fe5d341541092d35a410835d Mon Sep 17 00:00:00 2001 From: arcturusZhang Date: Mon, 10 Aug 2020 12:48:37 +0800 Subject: [PATCH 05/13] Add tests and docs --- .../mysql/mysql_server_key_resource.go | 18 +- .../tests/mysql_server_key_resource_test.go | 250 ++++++++++++++++++ website/docs/r/mysql_server_key.html.markdown | 115 ++++++++ 3 files changed, 376 insertions(+), 7 deletions(-) create mode 100644 azurerm/internal/services/mysql/tests/mysql_server_key_resource_test.go create mode 100644 website/docs/r/mysql_server_key.html.markdown diff --git a/azurerm/internal/services/mysql/mysql_server_key_resource.go b/azurerm/internal/services/mysql/mysql_server_key_resource.go index 3bc62aa7d582..c58ba0781c13 100644 --- a/azurerm/internal/services/mysql/mysql_server_key_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_key_resource.go @@ -89,15 +89,19 @@ func resourceArmMySQLServerKeyCreateUpdate(d *schema.ResourceData, meta interfac } if d.IsNewResource() { - existing, err := keysClient.Get(ctx, serverID.ResourceGroup, serverID.Name, name) + // This resource is a singleton, but its name can be anything. + // If you create a new key with different name with the old key, the service will not give you any warning but directly replace the old key with the new key. + // Therefore sometimes you cannot get the old key using the GET API since you may not know the name of the old key + resp, err := keysClient.List(ctx, serverID.ResourceGroup, serverID.Name) if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("checking for presence of MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) - } + return fmt.Errorf("listing existing MySQL Server Keys in Resource Group %q / Server %q: %+v", serverID.ResourceGroup, serverID.Name, err) } - - if existing.ID != nil && *existing.ID != "" { - return tf.ImportAsExistsError("azurerm_mysql_server_key", *existing.ID) + keys := resp.Values() + if len(keys) > 1 { + return fmt.Errorf("expecting at most one MySQL Server Key, but got %q", len(keys)) + } + if len(keys) == 1 && keys[0].ID != nil && *keys[0].ID != "" { + return tf.ImportAsExistsError("azurerm_mysql_server_key", *keys[0].ID) } } diff --git a/azurerm/internal/services/mysql/tests/mysql_server_key_resource_test.go b/azurerm/internal/services/mysql/tests/mysql_server_key_resource_test.go new file mode 100644 index 000000000000..624b1d91339c --- /dev/null +++ b/azurerm/internal/services/mysql/tests/mysql_server_key_resource_test.go @@ -0,0 +1,250 @@ +package tests + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mysql/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" + "testing" +) + +func TestAccAzureRMMySQLServerKey_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mysql_server_key", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMySQLServerKeyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMySQLServerKey_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMySQLServerKeyExists(data.ResourceName), + ), + }, + }, + }) +} + +func TestAccAzureRMMySQLServerKey_updateKey(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mysql_server_key", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMySQLServerKeyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMySQLServerKey_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMySQLServerKeyExists(data.ResourceName), + ), + }, + data.ImportStep(), + { + Config: testAccAzureRMMySQLServerKey_updated(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMySQLServerKeyExists(data.ResourceName), + ), + }, + data.ImportStep(), + }, + }) +} + +func TestAccAzureRMMySQLServerKey_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mysql_server_key", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMySQLServerKeyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMySQLServerKey_basic(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMySQLServerKeyExists(data.ResourceName), + ), + }, + data.RequiresImportErrorStep(testAccAzureRMMySQLServerKey_requiresImport), + }, + }) +} + +func testCheckAzureRMMySQLServerKeyDestroy(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).MySQL.ServerKeysClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_mysql_server_key" { + continue + } + + id, err := parse.MySQLServerKeyID(rs.Primary.ID) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.ServerName, id.Name) + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("retrieving MySQL Server Key: %+v", err) + } + return nil + } + + return fmt.Errorf("MySQL Server Key still exists:\n%#v", resp) + } + + return nil +} + +func testCheckAzureRMMySQLServerKeyExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).MySQL.ServerKeysClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + id, err := parse.MySQLServerKeyID(rs.Primary.ID) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.ServerName, id.Name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: MySQL Server Key %q (Resource Group %q / Server %q) does not exist", id.Name, id.ResourceGroup, id.ServerName) + } + return fmt.Errorf("Bad: Get on MySQLServerKeysClient: %+v", err) + } + + return nil + } +} + +func testAccAzureRMMySQLServerKey_template(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features { + key_vault { + purge_soft_delete_on_destroy = false + } + } +} + +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_key_vault" "test" { + name = "acctestkv%s" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "standard" + soft_delete_enabled = true + purge_protection_enabled = true +} + +resource "azurerm_key_vault_access_policy" "server" { + key_vault_id = azurerm_key_vault.test.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = azurerm_mysql_server.test.identity.0.principal_id + key_permissions = ["get", "unwrapkey", "wrapkey"] + secret_permissions = ["get"] +} + +resource "azurerm_key_vault_access_policy" "client" { + key_vault_id = azurerm_key_vault.test.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id + key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"] + secret_permissions = ["get"] +} + +resource "azurerm_key_vault_key" "first" { + name = "first" + key_vault_id = azurerm_key_vault.test.id + key_type = "RSA" + key_size = 2048 + key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] + depends_on = [ + azurerm_key_vault_access_policy.client, + azurerm_key_vault_access_policy.server, + ] +} + +resource "azurerm_mysql_server" "test" { + name = "acctestmysqlsvr-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "GP_Gen5_2" + administrator_login = "acctestun" + administrator_login_password = "H@Sh1CoR3!" + ssl_enforcement_enabled = true + ssl_minimal_tls_version_enforced = "TLS1_1" + storage_mb = 51200 + version = "5.6" + + identity { + type = "SystemAssigned" + } +} +`, data.RandomInteger, data.Locations.Primary, data.RandomString, data.RandomInteger) +} + +func testAccAzureRMMySQLServerKey_basic(data acceptance.TestData) string { + template := testAccAzureRMMySQLServerKey_template(data) + return fmt.Sprintf(` +%s + +resource "azurerm_mysql_server_key" "test" { +server_id = azurerm_mysql_server.test.id +key_vault_key_id = azurerm_key_vault_key.first.id +} +`, template) +} + +func testAccAzureRMMySQLServerKey_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMMySQLServerKey_basic(data) + return fmt.Sprintf(` +%s + +resource "azurerm_mysql_server_key" "import" { +server_id = azurerm_mysql_server_key.test.server_id +key_vault_key_id = azurerm_mysql_server_key.test.key_vault_key_id +} +`, template) +} + +func testAccAzureRMMySQLServerKey_updated(data acceptance.TestData) string { + template := testAccAzureRMMySQLServerKey_template(data) + return fmt.Sprintf(` +%s +resource "azurerm_key_vault_key" "second" { + name = "second" + key_vault_id = azurerm_key_vault.test.id + key_type = "RSA" + key_size = 2048 + key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] + depends_on = [ + azurerm_key_vault_access_policy.client, + azurerm_key_vault_access_policy.server, + ] +} +resource "azurerm_mysql_server_key" "test" { + server_id = azurerm_mysql_server.test.id + key_vault_key_id = azurerm_key_vault_key.second.id +} +`, template) +} diff --git a/website/docs/r/mysql_server_key.html.markdown b/website/docs/r/mysql_server_key.html.markdown new file mode 100644 index 000000000000..23262344396a --- /dev/null +++ b/website/docs/r/mysql_server_key.html.markdown @@ -0,0 +1,115 @@ +--- +subcategory: "Database" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_mysql_server_key" +description: |- + Manages a MySQL Server Key. +--- + +# azurerm_mysql_server_key + +Manages a Customer Managed Key for a MySQL Server. + +## Example Usage + +```hcl +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_key_vault" "example" { + name = "examplekv" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "premium" + soft_delete_enabled = true + purge_protection_enabled = true +} + +resource "azurerm_key_vault_access_policy" "server" { + key_vault_id = azurerm_key_vault.example.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = azurerm_mysql_server.example.identity.0.principal_id + key_permissions = ["get", "unwrapkey", "wrapkey"] + secret_permissions = ["get"] +} + +resource "azurerm_key_vault_access_policy" "client" { + key_vault_id = azurerm_key_vault.example.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id + key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"] + secret_permissions = ["get"] +} + +resource "azurerm_key_vault_key" "example" { + name = "tfex-key" + key_vault_id = azurerm_key_vault.example.id + key_type = "RSA" + key_size = 2048 + key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] + depends_on = [ + azurerm_key_vault_access_policy.client, + azurerm_key_vault_access_policy.server, + ] +} + +resource "azurerm_mysql_server" "example" { + name = "example-mysql-server" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + sku_name = "GP_Gen5_2" + administrator_login = "acctestun" + administrator_login_password = "H@Sh1CoR3!" + ssl_enforcement_enabled = true + ssl_minimal_tls_version_enforced = "TLS1_1" + storage_mb = 51200 + version = "5.6" + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_mysql_server_key" "example" { + server_id = azurerm_mysql_server.example.id + key_vault_key_id = azurerm_key_vault_key.example.id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `server_id` - (Required) The ID of the MySQL Server. Changing this forces a new resource to be created. + +* `key_vault_key_id` - (Required) The URL to a Key Vault Key. + +## Attributes Reference + +The following attributes are exported in addition to the arguments listed above: + +* `id` - The ID of the MySQL Server Key. + +--- + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the MySQL Server Key. +* `update` - (Defaults to 30 minutes) Used when updating the MySQL Server Key. +* `read` - (Defaults to 5 minutes) Used when retrieving the MySQL Server Key. +* `delete` - (Defaults to 30 minutes) Used when deleting the MySQL Server Key. + +## Import + +A MySQL Server Key can be imported using the `resource id` of the MySQL Server Key, e.g. + +```shell +terraform import azurerm_mysql_server_key.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.DBforMySQL/servers/server1/keys/keyvaultname_key-name_keyversion +``` \ No newline at end of file From ecd0013c0b9286b5c799d390a712e4aa8b7866b9 Mon Sep 17 00:00:00 2001 From: arcturusZhang Date: Mon, 10 Aug 2020 13:09:16 +0800 Subject: [PATCH 06/13] Fix CI --- .../tests/mysql_server_key_resource_test.go | 23 +- website/docs/r/mysql_server_key.html.markdown | 230 +++++++++--------- 2 files changed, 127 insertions(+), 126 deletions(-) diff --git a/azurerm/internal/services/mysql/tests/mysql_server_key_resource_test.go b/azurerm/internal/services/mysql/tests/mysql_server_key_resource_test.go index 624b1d91339c..584dbf7acb4c 100644 --- a/azurerm/internal/services/mysql/tests/mysql_server_key_resource_test.go +++ b/azurerm/internal/services/mysql/tests/mysql_server_key_resource_test.go @@ -2,13 +2,14 @@ package tests import ( "fmt" + "testing" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mysql/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" - "testing" ) func TestAccAzureRMMySQLServerKey_basic(t *testing.T) { @@ -157,17 +158,17 @@ resource "azurerm_key_vault" "test" { } resource "azurerm_key_vault_access_policy" "server" { - key_vault_id = azurerm_key_vault.test.id - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = azurerm_mysql_server.test.identity.0.principal_id + key_vault_id = azurerm_key_vault.test.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = azurerm_mysql_server.test.identity.0.principal_id key_permissions = ["get", "unwrapkey", "wrapkey"] secret_permissions = ["get"] } resource "azurerm_key_vault_access_policy" "client" { - key_vault_id = azurerm_key_vault.test.id - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id + key_vault_id = azurerm_key_vault.test.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"] secret_permissions = ["get"] } @@ -209,8 +210,8 @@ func testAccAzureRMMySQLServerKey_basic(data acceptance.TestData) string { %s resource "azurerm_mysql_server_key" "test" { -server_id = azurerm_mysql_server.test.id -key_vault_key_id = azurerm_key_vault_key.first.id + server_id = azurerm_mysql_server.test.id + key_vault_key_id = azurerm_key_vault_key.first.id } `, template) } @@ -221,8 +222,8 @@ func testAccAzureRMMySQLServerKey_requiresImport(data acceptance.TestData) strin %s resource "azurerm_mysql_server_key" "import" { -server_id = azurerm_mysql_server_key.test.server_id -key_vault_key_id = azurerm_mysql_server_key.test.key_vault_key_id + server_id = azurerm_mysql_server_key.test.server_id + key_vault_key_id = azurerm_mysql_server_key.test.key_vault_key_id } `, template) } diff --git a/website/docs/r/mysql_server_key.html.markdown b/website/docs/r/mysql_server_key.html.markdown index 23262344396a..eda4c1de8a8c 100644 --- a/website/docs/r/mysql_server_key.html.markdown +++ b/website/docs/r/mysql_server_key.html.markdown @@ -1,115 +1,115 @@ ---- -subcategory: "Database" -layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_mysql_server_key" -description: |- - Manages a MySQL Server Key. ---- - -# azurerm_mysql_server_key - -Manages a Customer Managed Key for a MySQL Server. - -## Example Usage - -```hcl -data "azurerm_client_config" "current" {} - -resource "azurerm_resource_group" "example" { - name = "example-resources" - location = "West Europe" -} - -resource "azurerm_key_vault" "example" { - name = "examplekv" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - tenant_id = data.azurerm_client_config.current.tenant_id - sku_name = "premium" - soft_delete_enabled = true - purge_protection_enabled = true -} - -resource "azurerm_key_vault_access_policy" "server" { - key_vault_id = azurerm_key_vault.example.id - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = azurerm_mysql_server.example.identity.0.principal_id - key_permissions = ["get", "unwrapkey", "wrapkey"] - secret_permissions = ["get"] -} - -resource "azurerm_key_vault_access_policy" "client" { - key_vault_id = azurerm_key_vault.example.id - tenant_id = data.azurerm_client_config.current.tenant_id - object_id = data.azurerm_client_config.current.object_id - key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"] - secret_permissions = ["get"] -} - -resource "azurerm_key_vault_key" "example" { - name = "tfex-key" - key_vault_id = azurerm_key_vault.example.id - key_type = "RSA" - key_size = 2048 - key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] - depends_on = [ - azurerm_key_vault_access_policy.client, - azurerm_key_vault_access_policy.server, - ] -} - -resource "azurerm_mysql_server" "example" { - name = "example-mysql-server" - location = azurerm_resource_group.example.location - resource_group_name = azurerm_resource_group.example.name - sku_name = "GP_Gen5_2" - administrator_login = "acctestun" - administrator_login_password = "H@Sh1CoR3!" - ssl_enforcement_enabled = true - ssl_minimal_tls_version_enforced = "TLS1_1" - storage_mb = 51200 - version = "5.6" - - identity { - type = "SystemAssigned" - } -} - -resource "azurerm_mysql_server_key" "example" { - server_id = azurerm_mysql_server.example.id - key_vault_key_id = azurerm_key_vault_key.example.id -} -``` - -## Argument Reference - -The following arguments are supported: - -* `server_id` - (Required) The ID of the MySQL Server. Changing this forces a new resource to be created. - -* `key_vault_key_id` - (Required) The URL to a Key Vault Key. - -## Attributes Reference - -The following attributes are exported in addition to the arguments listed above: - -* `id` - The ID of the MySQL Server Key. - ---- - -## Timeouts - -The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: - -* `create` - (Defaults to 30 minutes) Used when creating the MySQL Server Key. -* `update` - (Defaults to 30 minutes) Used when updating the MySQL Server Key. -* `read` - (Defaults to 5 minutes) Used when retrieving the MySQL Server Key. -* `delete` - (Defaults to 30 minutes) Used when deleting the MySQL Server Key. - -## Import - -A MySQL Server Key can be imported using the `resource id` of the MySQL Server Key, e.g. - -```shell -terraform import azurerm_mysql_server_key.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.DBforMySQL/servers/server1/keys/keyvaultname_key-name_keyversion -``` \ No newline at end of file +--- +subcategory: "Database" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_mysql_server_key" +description: |- + Manages a MySQL Server Key. +--- + +# azurerm_mysql_server_key + +Manages a Customer Managed Key for a MySQL Server. + +## Example Usage + +```hcl +data "azurerm_client_config" "current" {} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_key_vault" "example" { + name = "examplekv" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + tenant_id = data.azurerm_client_config.current.tenant_id + sku_name = "premium" + soft_delete_enabled = true + purge_protection_enabled = true +} + +resource "azurerm_key_vault_access_policy" "server" { + key_vault_id = azurerm_key_vault.example.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = azurerm_mysql_server.example.identity.0.principal_id + key_permissions = ["get", "unwrapkey", "wrapkey"] + secret_permissions = ["get"] +} + +resource "azurerm_key_vault_access_policy" "client" { + key_vault_id = azurerm_key_vault.example.id + tenant_id = data.azurerm_client_config.current.tenant_id + object_id = data.azurerm_client_config.current.object_id + key_permissions = ["get", "create", "delete", "list", "restore", "recover", "unwrapkey", "wrapkey", "purge", "encrypt", "decrypt", "sign", "verify"] + secret_permissions = ["get"] +} + +resource "azurerm_key_vault_key" "example" { + name = "tfex-key" + key_vault_id = azurerm_key_vault.example.id + key_type = "RSA" + key_size = 2048 + key_opts = ["decrypt", "encrypt", "sign", "unwrapKey", "verify", "wrapKey"] + depends_on = [ + azurerm_key_vault_access_policy.client, + azurerm_key_vault_access_policy.server, + ] +} + +resource "azurerm_mysql_server" "example" { + name = "example-mysql-server" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + sku_name = "GP_Gen5_2" + administrator_login = "acctestun" + administrator_login_password = "H@Sh1CoR3!" + ssl_enforcement_enabled = true + ssl_minimal_tls_version_enforced = "TLS1_1" + storage_mb = 51200 + version = "5.6" + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_mysql_server_key" "example" { + server_id = azurerm_mysql_server.example.id + key_vault_key_id = azurerm_key_vault_key.example.id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `server_id` - (Required) The ID of the MySQL Server. Changing this forces a new resource to be created. + +* `key_vault_key_id` - (Required) The URL to a Key Vault Key. + +## Attributes Reference + +The following attributes are exported in addition to the arguments listed above: + +* `id` - The ID of the MySQL Server Key. + +--- + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/docs/configuration/resources.html#timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the MySQL Server Key. +* `update` - (Defaults to 30 minutes) Used when updating the MySQL Server Key. +* `read` - (Defaults to 5 minutes) Used when retrieving the MySQL Server Key. +* `delete` - (Defaults to 30 minutes) Used when deleting the MySQL Server Key. + +## Import + +A MySQL Server Key can be imported using the `resource id` of the MySQL Server Key, e.g. + +```shell +terraform import azurerm_mysql_server_key.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.DBforMySQL/servers/server1/keys/keyvaultname_key-name_keyversion +``` From 25cad7f571dc225627586d7ebcd8ca46f7d98777 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Tue, 11 Aug 2020 16:34:49 +0800 Subject: [PATCH 07/13] Fix CI --- azurerm/internal/services/mysql/mysql_server_key_resource.go | 2 +- azurerm/internal/services/mysql/parse/mysql_server_key.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/azurerm/internal/services/mysql/mysql_server_key_resource.go b/azurerm/internal/services/mysql/mysql_server_key_resource.go index c58ba0781c13..02749903e74c 100644 --- a/azurerm/internal/services/mysql/mysql_server_key_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_key_resource.go @@ -183,7 +183,7 @@ func resourceArmMySQLServerKeyDelete(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("deleting MySQL Server Key %q (Resource Group %q / Server %q): %+v", id.Name, id.ResourceGroup, id.ServerName, err) } if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for deletion of MySQL Server Key %q (Resource Group %q / Server %q): %+v", id.Name, id.ResourceGroup, id.ServerName) + return fmt.Errorf("waiting for deletion of MySQL Server Key %q (Resource Group %q / Server %q): %+v", id.Name, id.ResourceGroup, id.ServerName, err) } return nil diff --git a/azurerm/internal/services/mysql/parse/mysql_server_key.go b/azurerm/internal/services/mysql/parse/mysql_server_key.go index 7dff9344cf7d..70f76b7ece8f 100644 --- a/azurerm/internal/services/mysql/parse/mysql_server_key.go +++ b/azurerm/internal/services/mysql/parse/mysql_server_key.go @@ -2,6 +2,7 @@ package parse import ( "fmt" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" ) From 30ff39545583270340ddabecfacf115ee046c668 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Thu, 13 Aug 2020 14:38:07 +0800 Subject: [PATCH 08/13] Resolve comments --- azurerm/internal/services/mysql/mysql_server_key_resource.go | 4 ++++ azurerm/internal/services/mysql/mysql_server_resource.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/azurerm/internal/services/mysql/mysql_server_key_resource.go b/azurerm/internal/services/mysql/mysql_server_key_resource.go index 02749903e74c..65d473b5f92e 100644 --- a/azurerm/internal/services/mysql/mysql_server_key_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_key_resource.go @@ -3,6 +3,7 @@ package mysql import ( "context" "fmt" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" "log" "time" @@ -88,6 +89,9 @@ func resourceArmMySQLServerKeyCreateUpdate(d *schema.ResourceData, meta interfac return fmt.Errorf("cannot compose name for MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) } + locks.ByName(serverID.Name, mySQLServerResourceName) + defer locks.UnlockByName(serverID.Name, mySQLServerResourceName) + if d.IsNewResource() { // This resource is a singleton, but its name can be anything. // If you create a new key with different name with the old key, the service will not give you any warning but directly replace the old key with the new key. diff --git a/azurerm/internal/services/mysql/mysql_server_resource.go b/azurerm/internal/services/mysql/mysql_server_resource.go index 0760e3d246b3..9cf076418d59 100644 --- a/azurerm/internal/services/mysql/mysql_server_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_resource.go @@ -24,6 +24,10 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) +const ( + mySQLServerResourceName = "azurerm_mysql_server" +) + func resourceArmMySqlServer() *schema.Resource { return &schema.Resource{ Create: resourceArmMySqlServerCreate, From 9a482a008f532627e6fa0ad92f261cec915c2ae5 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Thu, 13 Aug 2020 15:02:59 +0800 Subject: [PATCH 09/13] Goimports --- azurerm/internal/services/mysql/mysql_server_key_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/mysql/mysql_server_key_resource.go b/azurerm/internal/services/mysql/mysql_server_key_resource.go index 65d473b5f92e..f2d41d7ce368 100644 --- a/azurerm/internal/services/mysql/mysql_server_key_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_key_resource.go @@ -3,7 +3,6 @@ package mysql import ( "context" "fmt" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" "log" "time" @@ -13,6 +12,7 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/locks" keyVaultParse "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/keyvault/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mysql/parse" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mysql/validate" From 369ac4280a659c2c3345ea8a7758b84a559fdb01 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Tue, 25 Aug 2020 13:01:29 +0800 Subject: [PATCH 10/13] Add tests for key id --- .../mysql/parse/mysql_server_key_test.go | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 azurerm/internal/services/mysql/parse/mysql_server_key_test.go diff --git a/azurerm/internal/services/mysql/parse/mysql_server_key_test.go b/azurerm/internal/services/mysql/parse/mysql_server_key_test.go new file mode 100644 index 000000000000..976fb53f3ad0 --- /dev/null +++ b/azurerm/internal/services/mysql/parse/mysql_server_key_test.go @@ -0,0 +1,81 @@ +package parse + +import "testing" + +func TestMySQLServerKeyID(t *testing.T) { + testData := []struct { + Name string + Input string + Expected *MySQLServerKeyId + }{ + { + Name: "Empty resource ID", + Input: "", + Expected: nil, + }, + { + Name: "No resourceGroups segment", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000", + Expected: nil, + }, + { + Name: "No resource group name", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/", + Expected: nil, + }, + { + Name: "Resource group", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/", + Expected: nil, + }, + { + Name: "Missing server name", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/servers/", + Expected: nil, + }, + { + Name: "MySQL Server ID", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/servers/test-mysql/", + Expected: nil, + }, + { + Name: "Missing key name", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/servers/test-mysql/keys/", + Expected: nil, + }, + { + Name: "Valid", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/servers/test-mysql/keys/key1", + Expected: &MySQLServerKeyId{ + Name: "key1", + ResourceGroup: "test-rg", + ServerName: "test-mysql", + }, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Name) + + actual, err := MySQLServerKeyID(v.Input) + if err != nil { + if v.Expected == nil { + continue + } + + t.Fatalf("Expected a value but got an error: %s", err) + } + + if actual.Name != v.Expected.Name { + t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) + } + + if actual.ServerName != v.Expected.ServerName { + t.Fatalf("Expected %q but got %q for ServerName", v.Expected.ServerName, actual.ServerName) + } + + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for Resource Group", v.Expected.ResourceGroup, actual.ResourceGroup) + } + } +} From 8df77e41d2b1f83ef585b5c2678eb77186f28181 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Tue, 25 Aug 2020 13:18:38 +0800 Subject: [PATCH 11/13] Some refactor --- .../services/mysql/mysql_configuration_resource.go | 2 +- .../services/mysql/mysql_database_resource.go | 2 +- .../services/mysql/mysql_firewall_rule_resource.go | 2 +- .../services/mysql/mysql_server_key_resource.go | 4 ++-- .../internal/services/mysql/mysql_server_resource.go | 12 ++++++------ .../mysql/mysql_virtual_network_rule_resource.go | 2 +- .../mysql/parse/{mysql.go => mysql_server.go} | 6 +++--- .../parse/{mysql_test.go => mysql_server_test.go} | 8 ++++---- .../mysql/validate/{mysql.go => mysql_server.go} | 6 +++--- .../validate/{mysql_test.go => mysql_server_test.go} | 4 ++-- 10 files changed, 24 insertions(+), 24 deletions(-) rename azurerm/internal/services/mysql/parse/{mysql.go => mysql_server.go} (79%) rename azurerm/internal/services/mysql/parse/{mysql_test.go => mysql_server_test.go} (90%) rename azurerm/internal/services/mysql/validate/{mysql.go => mysql_server.go} (78%) rename azurerm/internal/services/mysql/validate/{mysql_test.go => mysql_server_test.go} (94%) diff --git a/azurerm/internal/services/mysql/mysql_configuration_resource.go b/azurerm/internal/services/mysql/mysql_configuration_resource.go index 3bb2cfb03d3c..2c5f443da8be 100644 --- a/azurerm/internal/services/mysql/mysql_configuration_resource.go +++ b/azurerm/internal/services/mysql/mysql_configuration_resource.go @@ -44,7 +44,7 @@ func resourceArmMySQLConfiguration() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.MysqlServerServerName, + ValidateFunc: validate.MySQLServerName, }, "value": { diff --git a/azurerm/internal/services/mysql/mysql_database_resource.go b/azurerm/internal/services/mysql/mysql_database_resource.go index 99412a20830f..ef052055c632 100644 --- a/azurerm/internal/services/mysql/mysql_database_resource.go +++ b/azurerm/internal/services/mysql/mysql_database_resource.go @@ -47,7 +47,7 @@ func resourceArmMySqlDatabase() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.MysqlServerServerName, + ValidateFunc: validate.MySQLServerName, }, "charset": { diff --git a/azurerm/internal/services/mysql/mysql_firewall_rule_resource.go b/azurerm/internal/services/mysql/mysql_firewall_rule_resource.go index 75658d9ccbc4..d2e104521b6e 100644 --- a/azurerm/internal/services/mysql/mysql_firewall_rule_resource.go +++ b/azurerm/internal/services/mysql/mysql_firewall_rule_resource.go @@ -47,7 +47,7 @@ func resourceArmMySqlFirewallRule() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.MysqlServerServerName, + ValidateFunc: validate.MySQLServerName, }, "start_ip_address": { diff --git a/azurerm/internal/services/mysql/mysql_server_key_resource.go b/azurerm/internal/services/mysql/mysql_server_key_resource.go index f2d41d7ce368..298b696af8c4 100644 --- a/azurerm/internal/services/mysql/mysql_server_key_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_key_resource.go @@ -45,7 +45,7 @@ func resourceArmMySQLServerKey() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.MysqlServerServerID, + ValidateFunc: validate.MySQLServerID, }, "key_vault_key_id": { @@ -79,7 +79,7 @@ func resourceArmMySQLServerKeyCreateUpdate(d *schema.ResourceData, meta interfac ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - serverID, err := parse.MysqlServerServerID(d.Get("server_id").(string)) + serverID, err := parse.MySQLServerID(d.Get("server_id").(string)) if err != nil { return err } diff --git a/azurerm/internal/services/mysql/mysql_server_resource.go b/azurerm/internal/services/mysql/mysql_server_resource.go index 9cf076418d59..e5342575dac0 100644 --- a/azurerm/internal/services/mysql/mysql_server_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_resource.go @@ -37,7 +37,7 @@ func resourceArmMySqlServer() *schema.Resource { Importer: &schema.ResourceImporter{ State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - if _, err := parse.MysqlServerServerID(d.Id()); err != nil { + if _, err := parse.MySQLServerID(d.Id()); err != nil { return []*schema.ResourceData{d}, err } @@ -62,7 +62,7 @@ func resourceArmMySqlServer() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.MysqlServerServerName, + ValidateFunc: validate.MySQLServerName, }, "administrator_login": { @@ -108,7 +108,7 @@ func resourceArmMySqlServer() *schema.Resource { "creation_source_server_id": { Type: schema.TypeString, Optional: true, - ValidateFunc: validate.MysqlServerServerID, + ValidateFunc: validate.MySQLServerID, }, "fqdn": { @@ -576,7 +576,7 @@ func resourceArmMySqlServerUpdate(d *schema.ResourceData, meta interface{}) erro log.Printf("[INFO] preparing arguments for AzureRM MySQL Server update.") - id, err := parse.MysqlServerServerID(d.Id()) + id, err := parse.MySQLServerID(d.Id()) if err != nil { return fmt.Errorf("parsing MySQL Server ID : %v", err) } @@ -655,7 +655,7 @@ func resourceArmMySqlServerRead(d *schema.ResourceData, meta interface{}) error ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.MysqlServerServerID(d.Id()) + id, err := parse.MySQLServerID(d.Id()) if err != nil { return fmt.Errorf("parsing MySQL Server ID : %v", err) } @@ -735,7 +735,7 @@ func resourceArmMySqlServerDelete(d *schema.ResourceData, meta interface{}) erro ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.MysqlServerServerID(d.Id()) + id, err := parse.MySQLServerID(d.Id()) if err != nil { return fmt.Errorf("parsing MySQL Server ID : %v", err) } diff --git a/azurerm/internal/services/mysql/mysql_virtual_network_rule_resource.go b/azurerm/internal/services/mysql/mysql_virtual_network_rule_resource.go index 7ce997a93393..ed3280308c0f 100644 --- a/azurerm/internal/services/mysql/mysql_virtual_network_rule_resource.go +++ b/azurerm/internal/services/mysql/mysql_virtual_network_rule_resource.go @@ -51,7 +51,7 @@ func resourceArmMySSQLVirtualNetworkRule() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.MysqlServerServerName, + ValidateFunc: validate.MySQLServerName, }, "subnet_id": { diff --git a/azurerm/internal/services/mysql/parse/mysql.go b/azurerm/internal/services/mysql/parse/mysql_server.go similarity index 79% rename from azurerm/internal/services/mysql/parse/mysql.go rename to azurerm/internal/services/mysql/parse/mysql_server.go index a8a370133682..d1d14f12a25e 100644 --- a/azurerm/internal/services/mysql/parse/mysql.go +++ b/azurerm/internal/services/mysql/parse/mysql_server.go @@ -6,18 +6,18 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" ) -type MysqlServerServerId struct { +type MySQLServerId struct { ResourceGroup string Name string } -func MysqlServerServerID(input string) (*MysqlServerServerId, error) { +func MySQLServerID(input string) (*MySQLServerId, error) { id, err := azure.ParseAzureResourceID(input) if err != nil { return nil, fmt.Errorf("[ERROR] Unable to parse MySQL Server ID %q: %+v", input, err) } - server := MysqlServerServerId{ + server := MySQLServerId{ ResourceGroup: id.ResourceGroup, } diff --git a/azurerm/internal/services/mysql/parse/mysql_test.go b/azurerm/internal/services/mysql/parse/mysql_server_test.go similarity index 90% rename from azurerm/internal/services/mysql/parse/mysql_test.go rename to azurerm/internal/services/mysql/parse/mysql_server_test.go index c3ccf38972ea..c01099bf2ba4 100644 --- a/azurerm/internal/services/mysql/parse/mysql_test.go +++ b/azurerm/internal/services/mysql/parse/mysql_server_test.go @@ -4,11 +4,11 @@ import ( "testing" ) -func TestValidateMysqlServerServerID(t *testing.T) { +func TestMySQLServerID(t *testing.T) { testData := []struct { Name string Input string - Expected *MysqlServerServerId + Expected *MySQLServerId }{ { Name: "Empty resource ID", @@ -38,7 +38,7 @@ func TestValidateMysqlServerServerID(t *testing.T) { { Name: "Valid", Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/servers/test-mysql", - Expected: &MysqlServerServerId{ + Expected: &MySQLServerId{ Name: "test-mysql", ResourceGroup: "test-rg", }, @@ -48,7 +48,7 @@ func TestValidateMysqlServerServerID(t *testing.T) { for _, v := range testData { t.Logf("[DEBUG] Testing %q", v.Name) - actual, err := MysqlServerServerID(v.Input) + actual, err := MySQLServerID(v.Input) if err != nil { if v.Expected == nil { continue diff --git a/azurerm/internal/services/mysql/validate/mysql.go b/azurerm/internal/services/mysql/validate/mysql_server.go similarity index 78% rename from azurerm/internal/services/mysql/validate/mysql.go rename to azurerm/internal/services/mysql/validate/mysql_server.go index e5abee8309ba..fb9579230a66 100644 --- a/azurerm/internal/services/mysql/validate/mysql.go +++ b/azurerm/internal/services/mysql/validate/mysql_server.go @@ -7,21 +7,21 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mysql/parse" ) -func MysqlServerServerID(i interface{}, k string) (warnings []string, errors []error) { +func MySQLServerID(i interface{}, k string) (warnings []string, errors []error) { v, ok := i.(string) if !ok { errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) return warnings, errors } - if _, err := parse.MysqlServerServerID(v); err != nil { + if _, err := parse.MySQLServerID(v); err != nil { errors = append(errors, fmt.Errorf("Can not parse %q as a MySQL Server resource id: %v", k, err)) } return warnings, errors } -func MysqlServerServerName(i interface{}, k string) (_ []string, errors []error) { +func MySQLServerName(i interface{}, k string) (_ []string, errors []error) { if m, regexErrs := validate.RegExHelper(i, k, `^[0-9a-z][-0-9a-z]{1,61}[0-9a-z]$`); !m { return nil, append(regexErrs, fmt.Errorf("%q can contain only lowercase letters, numbers, and '-', but can't start or end with '-', and must be at least 3 characters and no more than 63 characters long.", k)) } diff --git a/azurerm/internal/services/mysql/validate/mysql_test.go b/azurerm/internal/services/mysql/validate/mysql_server_test.go similarity index 94% rename from azurerm/internal/services/mysql/validate/mysql_test.go rename to azurerm/internal/services/mysql/validate/mysql_server_test.go index 3e919164fb37..4c198d842b85 100644 --- a/azurerm/internal/services/mysql/validate/mysql_test.go +++ b/azurerm/internal/services/mysql/validate/mysql_server_test.go @@ -29,7 +29,7 @@ func TestValidateMysqlServerServerID(t *testing.T) { for _, v := range testData { t.Logf("[DEBUG] Testing %q..", v.input) - _, errors := MysqlServerServerID(v.input, "name") + _, errors := MySQLServerID(v.input, "name") actual := len(errors) == 0 if v.expected != actual { t.Fatalf("Expected %t but got %t", v.expected, actual) @@ -97,7 +97,7 @@ func TestValidateMysqlServerServerName(t *testing.T) { for _, v := range testData { t.Logf("[DEBUG] Testing %q..", v.input) - _, errors := MysqlServerServerName(v.input, "name") + _, errors := MySQLServerName(v.input, "name") actual := len(errors) == 0 if v.expected != actual { t.Fatalf("Expected %t but got %t", v.expected, actual) From 18fd376a1fae479c1002db219d83fe2312bba228 Mon Sep 17 00:00:00 2001 From: Dapeng Zhang Date: Tue, 25 Aug 2020 13:50:29 +0800 Subject: [PATCH 12/13] Resolve comments --- .../mysql/mysql_server_key_resource.go | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/azurerm/internal/services/mysql/mysql_server_key_resource.go b/azurerm/internal/services/mysql/mysql_server_key_resource.go index 298b696af8c4..94075401d976 100644 --- a/azurerm/internal/services/mysql/mysql_server_key_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_key_resource.go @@ -34,10 +34,10 @@ func resourceArmMySQLServerKey() *schema.Resource { }), Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(30 * time.Minute), + Create: schema.DefaultTimeout(60 * time.Minute), Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(30 * time.Minute), - Delete: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(60 * time.Minute), + Delete: schema.DefaultTimeout(60 * time.Minute), }, Schema: map[string]*schema.Schema{ @@ -57,20 +57,20 @@ func resourceArmMySQLServerKey() *schema.Resource { } } -func getMySQLServerKeyName(ctx context.Context, vaultsClient *keyvault.VaultsClient, keyVaultKeyURI string) (string, error) { +func getMySQLServerKeyName(ctx context.Context, vaultsClient *keyvault.VaultsClient, keyVaultKeyURI string) (*string, error) { keyVaultKeyID, err := azure.ParseKeyVaultChildID(keyVaultKeyURI) if err != nil { - return "", err + return nil, err } keyVaultIDRaw, err := azure.GetKeyVaultIDFromBaseUrl(ctx, vaultsClient, keyVaultKeyID.KeyVaultBaseUrl) if err != nil { - return "", err + return nil, err } keyVaultID, err := keyVaultParse.KeyVaultID(*keyVaultIDRaw) if err != nil { - return "", err + return nil, err } - return fmt.Sprintf("%s_%s_%s", keyVaultID.Name, keyVaultKeyID.Name, keyVaultKeyID.Version), nil + return utils.String(fmt.Sprintf("%s_%s_%s", keyVaultID.Name, keyVaultKeyID.Name, keyVaultKeyID.Version)), nil } func resourceArmMySQLServerKeyCreateUpdate(d *schema.ResourceData, meta interface{}) error { @@ -116,7 +116,7 @@ func resourceArmMySQLServerKeyCreateUpdate(d *schema.ResourceData, meta interfac }, } - future, err := keysClient.CreateOrUpdate(ctx, serverID.Name, name, param, serverID.ResourceGroup) + future, err := keysClient.CreateOrUpdate(ctx, serverID.Name, *name, param, serverID.ResourceGroup) if err != nil { return fmt.Errorf("creating/updating MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) } @@ -124,7 +124,7 @@ func resourceArmMySQLServerKeyCreateUpdate(d *schema.ResourceData, meta interfac return fmt.Errorf("waiting for creation/update of MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) } - resp, err := keysClient.Get(ctx, serverID.ResourceGroup, serverID.Name, name) + resp, err := keysClient.Get(ctx, serverID.ResourceGroup, serverID.Name, *name) if err != nil { return fmt.Errorf("retrieving MySQL Server Key (Resource Group %q / Server %q): %+v", serverID.ResourceGroup, serverID.Name, err) } @@ -182,6 +182,9 @@ func resourceArmMySQLServerKeyDelete(d *schema.ResourceData, meta interface{}) e return err } + locks.ByName(id.ServerName, mySQLServerResourceName) + defer locks.UnlockByName(id.ServerName, mySQLServerResourceName) + future, err := client.Delete(ctx, id.ServerName, id.Name, id.ResourceGroup) if err != nil { return fmt.Errorf("deleting MySQL Server Key %q (Resource Group %q / Server %q): %+v", id.Name, id.ResourceGroup, id.ServerName, err) From 5886bafe57da02a5ca47989409ad5726213e797d Mon Sep 17 00:00:00 2001 From: arcturusZhang Date: Wed, 16 Sep 2020 10:51:28 +0800 Subject: [PATCH 13/13] Update keyvault package api-version --- azurerm/internal/services/mysql/mysql_server_key_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/internal/services/mysql/mysql_server_key_resource.go b/azurerm/internal/services/mysql/mysql_server_key_resource.go index 94075401d976..6b916847321d 100644 --- a/azurerm/internal/services/mysql/mysql_server_key_resource.go +++ b/azurerm/internal/services/mysql/mysql_server_key_resource.go @@ -6,7 +6,7 @@ import ( "log" "time" - "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2018-02-14/keyvault" + "github.com/Azure/azure-sdk-for-go/services/keyvault/mgmt/2019-09-01/keyvault" "github.com/Azure/azure-sdk-for-go/services/mysql/mgmt/2020-01-01/mysql" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"