From 663dfab14bccb290cd43d85c0238ce83b66329de Mon Sep 17 00:00:00 2001 From: aristosvo <8375124+aristosvo@users.noreply.github.com> Date: Fri, 22 Oct 2021 00:43:41 +0200 Subject: [PATCH] `azurerm_mysql_flexible_server_configuration`: New resource to support configuration on `mysql_flexible_server` (#13831) Fixes #13824 Functionality, docs and code is 99% copy of azurerm_mysql_configuration but for azurerm_mysql_flexible_server instead of azurerm_mysql_server. --- internal/services/mysql/client/client.go | 41 ++-- ..._flexible_server_configuration_resource.go | 153 ++++++++++++++ ...ible_server_configuration_resource_test.go | 192 ++++++++++++++++++ .../parse/flexible_server_configuration.go | 75 +++++++ .../flexible_server_configuration_test.go | 128 ++++++++++++ internal/services/mysql/registration.go | 1 + internal/services/mysql/resourceids.go | 1 + .../flexible_server_configuration_id.go | 23 +++ .../flexible_server_configuration_id_test.go | 88 ++++++++ ...lexible_server_configuration.html.markdown | 79 +++++++ 10 files changed, 763 insertions(+), 18 deletions(-) create mode 100644 internal/services/mysql/mysql_flexible_server_configuration_resource.go create mode 100644 internal/services/mysql/mysql_flexible_server_configuration_resource_test.go create mode 100644 internal/services/mysql/parse/flexible_server_configuration.go create mode 100644 internal/services/mysql/parse/flexible_server_configuration_test.go create mode 100644 internal/services/mysql/validate/flexible_server_configuration_id.go create mode 100644 internal/services/mysql/validate/flexible_server_configuration_id_test.go create mode 100644 website/docs/r/mysql_flexible_server_configuration.html.markdown diff --git a/internal/services/mysql/client/client.go b/internal/services/mysql/client/client.go index 647ddcf0ccb3..0834fd28c1f5 100644 --- a/internal/services/mysql/client/client.go +++ b/internal/services/mysql/client/client.go @@ -7,15 +7,16 @@ import ( ) type Client struct { - ConfigurationsClient *mysql.ConfigurationsClient - DatabasesClient *mysql.DatabasesClient - FirewallRulesClient *mysql.FirewallRulesClient - FlexibleServerClient *mysqlflexibleservers.ServersClient - ServersClient *mysql.ServersClient - ServerKeysClient *mysql.ServerKeysClient - ServerSecurityAlertPoliciesClient *mysql.ServerSecurityAlertPoliciesClient - VirtualNetworkRulesClient *mysql.VirtualNetworkRulesClient - ServerAdministratorsClient *mysql.ServerAdministratorsClient + ConfigurationsClient *mysql.ConfigurationsClient + DatabasesClient *mysql.DatabasesClient + FirewallRulesClient *mysql.FirewallRulesClient + FlexibleServerConfigurationsClient *mysqlflexibleservers.ConfigurationsClient + FlexibleServerClient *mysqlflexibleservers.ServersClient + ServersClient *mysql.ServersClient + ServerKeysClient *mysql.ServerKeysClient + ServerSecurityAlertPoliciesClient *mysql.ServerSecurityAlertPoliciesClient + VirtualNetworkRulesClient *mysql.VirtualNetworkRulesClient + ServerAdministratorsClient *mysql.ServerAdministratorsClient } func NewClient(o *common.ClientOptions) *Client { @@ -31,6 +32,9 @@ func NewClient(o *common.ClientOptions) *Client { flexibleServerClient := mysqlflexibleservers.NewServersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&flexibleServerClient.Client, o.ResourceManagerAuthorizer) + flexibleServerConfigurationsClient := mysqlflexibleservers.NewConfigurationsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&flexibleServerConfigurationsClient.Client, o.ResourceManagerAuthorizer) + ServersClient := mysql.NewServersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&ServersClient.Client, o.ResourceManagerAuthorizer) @@ -47,14 +51,15 @@ func NewClient(o *common.ClientOptions) *Client { o.ConfigureClient(&serverAdministratorsClient.Client, o.ResourceManagerAuthorizer) return &Client{ - ConfigurationsClient: &ConfigurationsClient, - DatabasesClient: &DatabasesClient, - FirewallRulesClient: &FirewallRulesClient, - FlexibleServerClient: &flexibleServerClient, - ServersClient: &ServersClient, - ServerKeysClient: &ServerKeysClient, - ServerSecurityAlertPoliciesClient: &serverSecurityAlertPoliciesClient, - VirtualNetworkRulesClient: &VirtualNetworkRulesClient, - ServerAdministratorsClient: &serverAdministratorsClient, + ConfigurationsClient: &ConfigurationsClient, + DatabasesClient: &DatabasesClient, + FirewallRulesClient: &FirewallRulesClient, + FlexibleServerClient: &flexibleServerClient, + FlexibleServerConfigurationsClient: &flexibleServerConfigurationsClient, + ServersClient: &ServersClient, + ServerKeysClient: &ServerKeysClient, + ServerSecurityAlertPoliciesClient: &serverSecurityAlertPoliciesClient, + VirtualNetworkRulesClient: &VirtualNetworkRulesClient, + ServerAdministratorsClient: &serverAdministratorsClient, } } diff --git a/internal/services/mysql/mysql_flexible_server_configuration_resource.go b/internal/services/mysql/mysql_flexible_server_configuration_resource.go new file mode 100644 index 000000000000..f6f8696a76be --- /dev/null +++ b/internal/services/mysql/mysql_flexible_server_configuration_resource.go @@ -0,0 +1,153 @@ +package mysql + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/mysql/mgmt/2021-05-01-preview/mysqlflexibleservers" + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +func resourceMySQLFlexibleServerConfiguration() *pluginsdk.Resource { + return &pluginsdk.Resource{ + Create: resourceMySQLFlexibleServerConfigurationCreate, + Read: resourceMySQLFlexibleServerConfigurationRead, + Delete: resourceMySQLFlexibleServerConfigurationDelete, + + Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { + _, err := parse.FlexibleServerConfigurationID(id) + return err + }), + + Timeouts: &pluginsdk.ResourceTimeout{ + Create: pluginsdk.DefaultTimeout(30 * time.Minute), + Read: pluginsdk.DefaultTimeout(5 * time.Minute), + Update: pluginsdk.DefaultTimeout(30 * time.Minute), + Delete: pluginsdk.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": azure.SchemaResourceGroupName(), + + "server_name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.ServerName, + }, + + "value": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +func resourceMySQLFlexibleServerConfigurationCreate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).MySQL.FlexibleServerConfigurationsClient + subscriptionId := meta.(*clients.Client).Account.SubscriptionId + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for AzureRM MySQL Configuration creation.") + + properties := mysqlflexibleservers.Configuration{ + ConfigurationProperties: &mysqlflexibleservers.ConfigurationProperties{ + Value: utils.String(d.Get("value").(string)), + }, + } + + // NOTE: this resource intentionally doesn't support Requires Import + // since a fallback route is created by default + + id := parse.NewFlexibleServerConfigurationID(subscriptionId, d.Get("resource_group_name").(string), d.Get("server_name").(string), d.Get("name").(string)) + future, err := client.Update(ctx, id.ResourceGroup, id.FlexibleServerName, id.ConfigurationName, properties) + if err != nil { + return fmt.Errorf("creating %s: %v", id, err) + } + + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for creation of %s: %v", id, err) + } + + d.SetId(id.ID()) + return resourceMySQLFlexibleServerConfigurationRead(d, meta) +} + +func resourceMySQLFlexibleServerConfigurationRead(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).MySQL.FlexibleServerConfigurationsClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.FlexibleServerConfigurationID(d.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, id.ResourceGroup, id.FlexibleServerName, id.ConfigurationName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + log.Printf("[WARN] %s was not found", id) + d.SetId("") + return nil + } + + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + d.Set("name", id.ConfigurationName) + d.Set("server_name", id.FlexibleServerName) + d.Set("resource_group_name", id.ResourceGroup) + value := "" + if props := resp.ConfigurationProperties; props != nil && props.Value != nil { + value = *props.Value + } + d.Set("value", value) + + return nil +} + +func resourceMySQLFlexibleServerConfigurationDelete(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).MySQL.FlexibleServerConfigurationsClient + ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) + defer cancel() + + id, err := parse.FlexibleServerConfigurationID(d.Id()) + if err != nil { + return err + } + // "delete" = resetting this to the default value + resp, err := client.Get(ctx, id.ResourceGroup, id.FlexibleServerName, id.ConfigurationName) + if err != nil { + return fmt.Errorf("retrieving %s: %+v", id, err) + } + + properties := mysqlflexibleservers.Configuration{ + ConfigurationProperties: &mysqlflexibleservers.ConfigurationProperties{ + // we can alternatively set `source: "system-default"` + Value: resp.DefaultValue, + }, + } + + future, err := client.Update(ctx, id.ResourceGroup, id.FlexibleServerName, id.ConfigurationName, properties) + if err != nil { + return err + } + + return future.WaitForCompletionRef(ctx, client.Client) +} diff --git a/internal/services/mysql/mysql_flexible_server_configuration_resource_test.go b/internal/services/mysql/mysql_flexible_server_configuration_resource_test.go new file mode 100644 index 000000000000..6bd0b278bcc4 --- /dev/null +++ b/internal/services/mysql/mysql_flexible_server_configuration_resource_test.go @@ -0,0 +1,192 @@ +package mysql_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/parse" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type MySQLFlexibleServerConfigurationResource struct { +} + +func TestAccMySQLFlexibleServerConfiguration_characterSetServer(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mysql_flexible_server_configuration", "test") + r := MySQLFlexibleServerConfigurationResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.characterSetServer(data), + Check: acceptance.ComposeTestCheckFunc( + data.CheckWithClient(r.checkValue("hebrew")), + ), + }, + data.ImportStep(), + { + Config: r.empty(data), + Check: acceptance.ComposeTestCheckFunc( + // "delete" resets back to the default value + data.CheckWithClientForResource(r.checkReset("character_set_server"), "azurerm_mysql_flexible_server.test"), + ), + }, + }) +} + +func TestAccMySQLFlexibleServerConfiguration_interactiveTimeout(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mysql_flexible_server_configuration", "test") + r := MySQLFlexibleServerConfigurationResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.interactiveTimeout(data), + Check: acceptance.ComposeTestCheckFunc( + data.CheckWithClient(r.checkValue("30")), + ), + }, + data.ImportStep(), + { + Config: r.empty(data), + Check: acceptance.ComposeTestCheckFunc( + // "delete" resets back to the default value + data.CheckWithClientForResource(r.checkReset("interactive_timeout"), "azurerm_mysql_flexible_server.test"), + ), + }, + }) +} + +func TestAccMySQLFlexibleServerConfiguration_logSlowAdminStatements(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mysql_flexible_server_configuration", "test") + r := MySQLFlexibleServerConfigurationResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.logSlowAdminStatements(data), + Check: acceptance.ComposeTestCheckFunc( + data.CheckWithClient(r.checkValue("on")), + ), + }, + data.ImportStep(), + { + Config: r.empty(data), + Check: acceptance.ComposeTestCheckFunc( + // "delete" resets back to the default value + data.CheckWithClientForResource(r.checkReset("log_slow_admin_statements"), "azurerm_mysql_flexible_server.test"), + ), + }, + }) +} + +func (t MySQLFlexibleServerConfigurationResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := parse.FlexibleServerConfigurationID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.MySQL.FlexibleServerConfigurationsClient.Get(ctx, id.ResourceGroup, id.FlexibleServerName, id.ConfigurationName) + if err != nil { + return nil, fmt.Errorf("reading %q: %+v", id, err) + } + + return utils.Bool(resp.ID != nil), nil +} + +func (r MySQLFlexibleServerConfigurationResource) checkReset(configurationName string) acceptance.ClientCheckFunc { + return func(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) error { + id, err := parse.FlexibleServerID(state.Attributes["id"]) + if err != nil { + return err + } + + resp, err := clients.MySQL.FlexibleServerConfigurationsClient.Get(ctx, id.ResourceGroup, id.Name, configurationName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("%q does not exist", id) + } + return fmt.Errorf("Bad: Get on mysqlConfigurationsClient: %+v", err) + } + + actualValue := *resp.Value + defaultValue := *resp.DefaultValue + + if defaultValue != actualValue { + return fmt.Errorf("MySQL Flexible Server Configuration wasn't set to the default value. Expected '%s' - got '%s': \n%+v", defaultValue, actualValue, resp) + } + + return nil + } +} + +func (r MySQLFlexibleServerConfigurationResource) checkValue(value string) acceptance.ClientCheckFunc { + return func(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) error { + id, err := parse.FlexibleServerConfigurationID(state.Attributes["id"]) + if err != nil { + return err + } + + resp, err := clients.MySQL.FlexibleServerConfigurationsClient.Get(ctx, id.ResourceGroup, id.FlexibleServerName, id.ConfigurationName) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("%q does not exist", id.ConfigurationName) + } + + return fmt.Errorf("Get on MySQL.FlexibleServerConfigurationsClient: %+v", err) + } + + if *resp.Value != value { + return fmt.Errorf("MySQL Flexible Server Configuration wasn't set. Expected '%s' - got '%s': \n%+v", value, *resp.Value, resp) + } + + return nil + } +} + +func (r MySQLFlexibleServerConfigurationResource) characterSetServer(data acceptance.TestData) string { + return r.template(data, "character_set_server", "hebrew") +} + +func (r MySQLFlexibleServerConfigurationResource) interactiveTimeout(data acceptance.TestData) string { + return r.template(data, "interactive_timeout", "30") +} + +func (r MySQLFlexibleServerConfigurationResource) logSlowAdminStatements(data acceptance.TestData) string { + return r.template(data, "log_slow_admin_statements", "on") +} + +func (r MySQLFlexibleServerConfigurationResource) template(data acceptance.TestData, name string, value string) string { + config := fmt.Sprintf(` +resource "azurerm_mysql_flexible_server_configuration" "test" { + name = "%s" + resource_group_name = "${azurerm_resource_group.test.name}" + server_name = "${azurerm_mysql_flexible_server.test.name}" + value = "%s" +} +`, name, value) + return r.empty(data) + config +} + +func (MySQLFlexibleServerConfigurationResource) empty(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_mysql_flexible_server" "test" { + name = "acctest-fs-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + administrator_login = "adminTerraform" + administrator_password = "QAZwsx123" + sku_name = "B_Standard_B1s" +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +} diff --git a/internal/services/mysql/parse/flexible_server_configuration.go b/internal/services/mysql/parse/flexible_server_configuration.go new file mode 100644 index 000000000000..0ca38d508bda --- /dev/null +++ b/internal/services/mysql/parse/flexible_server_configuration.go @@ -0,0 +1,75 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + "strings" + + "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" +) + +type FlexibleServerConfigurationId struct { + SubscriptionId string + ResourceGroup string + FlexibleServerName string + ConfigurationName string +} + +func NewFlexibleServerConfigurationID(subscriptionId, resourceGroup, flexibleServerName, configurationName string) FlexibleServerConfigurationId { + return FlexibleServerConfigurationId{ + SubscriptionId: subscriptionId, + ResourceGroup: resourceGroup, + FlexibleServerName: flexibleServerName, + ConfigurationName: configurationName, + } +} + +func (id FlexibleServerConfigurationId) String() string { + segments := []string{ + fmt.Sprintf("Configuration Name %q", id.ConfigurationName), + fmt.Sprintf("Flexible Server Name %q", id.FlexibleServerName), + fmt.Sprintf("Resource Group %q", id.ResourceGroup), + } + segmentsStr := strings.Join(segments, " / ") + return fmt.Sprintf("%s: (%s)", "Flexible Server Configuration", segmentsStr) +} + +func (id FlexibleServerConfigurationId) ID() string { + fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.DBforMySQL/flexibleServers/%s/configurations/%s" + return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.FlexibleServerName, id.ConfigurationName) +} + +// FlexibleServerConfigurationID parses a FlexibleServerConfiguration ID into an FlexibleServerConfigurationId struct +func FlexibleServerConfigurationID(input string) (*FlexibleServerConfigurationId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, err + } + + resourceId := FlexibleServerConfigurationId{ + SubscriptionId: id.SubscriptionID, + ResourceGroup: id.ResourceGroup, + } + + if resourceId.SubscriptionId == "" { + return nil, fmt.Errorf("ID was missing the 'subscriptions' element") + } + + if resourceId.ResourceGroup == "" { + return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") + } + + if resourceId.FlexibleServerName, err = id.PopSegment("flexibleServers"); err != nil { + return nil, err + } + if resourceId.ConfigurationName, err = id.PopSegment("configurations"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &resourceId, nil +} diff --git a/internal/services/mysql/parse/flexible_server_configuration_test.go b/internal/services/mysql/parse/flexible_server_configuration_test.go new file mode 100644 index 000000000000..ef2df17b1387 --- /dev/null +++ b/internal/services/mysql/parse/flexible_server_configuration_test.go @@ -0,0 +1,128 @@ +package parse + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "testing" + + "github.com/hashicorp/terraform-provider-azurerm/internal/resourceid" +) + +var _ resourceid.Formatter = FlexibleServerConfigurationId{} + +func TestFlexibleServerConfigurationIDFormatter(t *testing.T) { + actual := NewFlexibleServerConfigurationID("12345678-1234-9876-4563-123456789012", "resGroup1", "flexibleServer1", "config1").ID() + expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/configurations/config1" + if actual != expected { + t.Fatalf("Expected %q but got %q", expected, actual) + } +} + +func TestFlexibleServerConfigurationID(t *testing.T) { + testData := []struct { + Input string + Error bool + Expected *FlexibleServerConfigurationId + }{ + + { + // empty + Input: "", + Error: true, + }, + + { + // missing SubscriptionId + Input: "/", + Error: true, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Error: true, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Error: true, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Error: true, + }, + + { + // missing FlexibleServerName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/", + Error: true, + }, + + { + // missing value for FlexibleServerName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/", + Error: true, + }, + + { + // missing ConfigurationName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/", + Error: true, + }, + + { + // missing value for ConfigurationName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/configurations/", + Error: true, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/configurations/config1", + Expected: &FlexibleServerConfigurationId{ + SubscriptionId: "12345678-1234-9876-4563-123456789012", + ResourceGroup: "resGroup1", + FlexibleServerName: "flexibleServer1", + ConfigurationName: "config1", + }, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.DBFORMYSQL/FLEXIBLESERVERS/FLEXIBLESERVER1/CONFIGURATIONS/CONFIG1", + Error: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Input) + + actual, err := FlexibleServerConfigurationID(v.Input) + if err != nil { + if v.Error { + continue + } + + t.Fatalf("Expect a value but got an error: %s", err) + } + if v.Error { + t.Fatal("Expect an error but didn't get one") + } + + if actual.SubscriptionId != v.Expected.SubscriptionId { + t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) + } + if actual.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) + } + if actual.FlexibleServerName != v.Expected.FlexibleServerName { + t.Fatalf("Expected %q but got %q for FlexibleServerName", v.Expected.FlexibleServerName, actual.FlexibleServerName) + } + if actual.ConfigurationName != v.Expected.ConfigurationName { + t.Fatalf("Expected %q but got %q for ConfigurationName", v.Expected.ConfigurationName, actual.ConfigurationName) + } + } +} diff --git a/internal/services/mysql/registration.go b/internal/services/mysql/registration.go index fcdbbc84f05b..23a6b31fdeb2 100644 --- a/internal/services/mysql/registration.go +++ b/internal/services/mysql/registration.go @@ -32,6 +32,7 @@ func (r Registration) SupportedResources() map[string]*pluginsdk.Resource { "azurerm_mysql_database": resourceMySqlDatabase(), "azurerm_mysql_firewall_rule": resourceMySqlFirewallRule(), "azurerm_mysql_flexible_server": resourceMysqlFlexibleServer(), + "azurerm_mysql_flexible_server_configuration": resourceMySQLFlexibleServerConfiguration(), "azurerm_mysql_server": resourceMySqlServer(), "azurerm_mysql_server_key": resourceMySQLServerKey(), "azurerm_mysql_virtual_network_rule": resourceMySQLVirtualNetworkRule(), diff --git a/internal/services/mysql/resourceids.go b/internal/services/mysql/resourceids.go index 03aa3646b845..05abfff21a4a 100644 --- a/internal/services/mysql/resourceids.go +++ b/internal/services/mysql/resourceids.go @@ -5,6 +5,7 @@ package mysql //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Database -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/servers/server1/databases/database1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FirewallRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/servers/server1/firewallRules/firewallRule1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FlexibleServer -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1 +//go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=FlexibleServerConfiguration -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/configurations/config1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Key -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/servers/server1/keys/key1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=Server -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/servers/server1 //go:generate go run ../../tools/generator-resource-id/main.go -path=./ -name=VirtualNetworkRule -id=/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/servers/server1/virtualNetworkRules/virtualNetworkRule1 diff --git a/internal/services/mysql/validate/flexible_server_configuration_id.go b/internal/services/mysql/validate/flexible_server_configuration_id.go new file mode 100644 index 000000000000..54c43bef9b37 --- /dev/null +++ b/internal/services/mysql/validate/flexible_server_configuration_id.go @@ -0,0 +1,23 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import ( + "fmt" + + "github.com/hashicorp/terraform-provider-azurerm/internal/services/mysql/parse" +) + +func FlexibleServerConfigurationID(input interface{}, key string) (warnings []string, errors []error) { + v, ok := input.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected %q to be a string", key)) + return + } + + if _, err := parse.FlexibleServerConfigurationID(v); err != nil { + errors = append(errors, err) + } + + return +} diff --git a/internal/services/mysql/validate/flexible_server_configuration_id_test.go b/internal/services/mysql/validate/flexible_server_configuration_id_test.go new file mode 100644 index 000000000000..fe6ac125d9a2 --- /dev/null +++ b/internal/services/mysql/validate/flexible_server_configuration_id_test.go @@ -0,0 +1,88 @@ +package validate + +// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten + +import "testing" + +func TestFlexibleServerConfigurationID(t *testing.T) { + cases := []struct { + Input string + Valid bool + }{ + + { + // empty + Input: "", + Valid: false, + }, + + { + // missing SubscriptionId + Input: "/", + Valid: false, + }, + + { + // missing value for SubscriptionId + Input: "/subscriptions/", + Valid: false, + }, + + { + // missing ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", + Valid: false, + }, + + { + // missing value for ResourceGroup + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", + Valid: false, + }, + + { + // missing FlexibleServerName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/", + Valid: false, + }, + + { + // missing value for FlexibleServerName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/", + Valid: false, + }, + + { + // missing ConfigurationName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/", + Valid: false, + }, + + { + // missing value for ConfigurationName + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/configurations/", + Valid: false, + }, + + { + // valid + Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/configurations/config1", + Valid: true, + }, + + { + // upper-cased + Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.DBFORMYSQL/FLEXIBLESERVERS/FLEXIBLESERVER1/CONFIGURATIONS/CONFIG1", + Valid: false, + }, + } + for _, tc := range cases { + t.Logf("[DEBUG] Testing Value %s", tc.Input) + _, errors := FlexibleServerConfigurationID(tc.Input, "test") + valid := len(errors) == 0 + + if tc.Valid != valid { + t.Fatalf("Expected %t but got %t", tc.Valid, valid) + } + } +} diff --git a/website/docs/r/mysql_flexible_server_configuration.html.markdown b/website/docs/r/mysql_flexible_server_configuration.html.markdown new file mode 100644 index 000000000000..0593ec3923c9 --- /dev/null +++ b/website/docs/r/mysql_flexible_server_configuration.html.markdown @@ -0,0 +1,79 @@ +--- +subcategory: "Database" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_mysql_flexible_server_configuration" +description: |- + Sets a MySQL Flexible Server Configuration value on a MySQL Flexible Server. +--- + +# azurerm_mysql_flexible_server_configuration + +Sets a MySQL Flexible Server Configuration value on a MySQL Flexible Server. + +## Disclaimers + +~> **Note:** Since this resource is provisioned by default, the Azure Provider will not check for the presence of an existing resource prior to attempting to create it. + +## Example Usage + +```hcl +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_mysql_flexible_server" "example" { + name = "example-fs" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + administrator_login = "adminTerraform" + administrator_password = "H@Sh1CoR3!" + sku_name = "GP_Standard_D2ds_v4" +} + +resource "azurerm_mysql_flexible_server_configuration" "example" { + name = "interactive_timeout" + resource_group_name = azurerm_resource_group.example.name + server_name = azurerm_mysql_server.example.name + value = "600" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the MySQL Flexible Server Configuration, which needs [to be a valid MySQL configuration name](https://dev.mysql.com/doc/refman/5.7/en/server-configuration.html). Changing this forces a new resource to be created. + +* `server_name` - (Required) Specifies the name of the MySQL Flexible Server. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the MySQL Flexible Server exists. Changing this forces a new resource to be created. + +* `value` - (Required) Specifies the value of the MySQL Flexible Server Configuration. See the MySQL documentation for valid values. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the MySQL Flexible Server Configuration. + +## 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 Flexible Server Configuration. +* `update` - (Defaults to 30 minutes) Used when updating the MySQL Flexible Server Configuration. +* `read` - (Defaults to 5 minutes) Used when retrieving the MySQL Flexible Server Configuration. +* `delete` - (Defaults to 30 minutes) Used when deleting the MySQL Flexible Server Configuration. + +## Import + +MySQL Flexible Server Configurations can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_mysql_flexible_server_configuration.interactive_timeout /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.DBforMySQL/flexibleServers/flexibleServer1/configurations/interactive_timeout +```