From 2db44ac80081e6047f163144c66cb0b4cd5bf015 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Mon, 11 May 2020 16:53:41 +0100 Subject: [PATCH] New attributes, flatten `storage_profile` block - `create_mode`, `creation_source_server_id` - Support replicas and point-in-time restores - Use booleans for toggle properties, renaming * `auto_grow` -> `auto_grow_enabled` * `geo_redundant_backup` -> `geo_redundant_backup_enabled` * `ssl_enforcement` -> `ssl_enforcement_enabled` - Remove redundant `storage_profile` block and move all properties within to top level - Remove unpopulated attribute `administrator_login_password` from `mariadb_server` data source Fixes: #4296, #6521 Related: #6459 --- azurerm/helpers/validate/database.go | 23 - azurerm/helpers/validate/mariadb.go | 28 - .../mariadb/mariadb_configuration_resource.go | 14 +- .../mariadb/mariadb_database_resource.go | 25 +- .../mariadb/mariadb_firewall_rule_resource.go | 23 +- .../mariadb/mariadb_server_data_source.go | 6 - .../mariadb/mariadb_server_resource.go | 519 ++++++++++++------ .../mariadb_virtual_network_rule_resource.go | 9 +- .../services/mariadb/parse/mariadb.go | 33 ++ .../services/mariadb/parse/mariadb_test.go | 68 +++ .../mariadb_configuration_resource_test.go | 16 +- .../tests/mariadb_server_resource_test.go | 402 +++++++------- .../services/mariadb/validate/mariadb.go | 30 + .../services/mariadb/validate/mariadb_test.go | 106 ++++ website/docs/d/mariadb_server.html.markdown | 2 - website/docs/r/mariadb_server.html.markdown | 50 +- 16 files changed, 891 insertions(+), 463 deletions(-) delete mode 100644 azurerm/helpers/validate/database.go delete mode 100644 azurerm/helpers/validate/mariadb.go create mode 100644 azurerm/internal/services/mariadb/parse/mariadb.go create mode 100644 azurerm/internal/services/mariadb/parse/mariadb_test.go create mode 100644 azurerm/internal/services/mariadb/validate/mariadb.go create mode 100644 azurerm/internal/services/mariadb/validate/mariadb_test.go diff --git a/azurerm/helpers/validate/database.go b/azurerm/helpers/validate/database.go deleted file mode 100644 index d531faca7937e..0000000000000 --- a/azurerm/helpers/validate/database.go +++ /dev/null @@ -1,23 +0,0 @@ -package validate - -import ( - "fmt" - "regexp" -) - -func MariaDatabaseCollation(i interface{}, k string) (warnings []string, errors []error) { - v, ok := i.(string) - if !ok { - errors = append(errors, fmt.Errorf("expected type of %s to be string", k)) - return - } - - matched, _ := regexp.MatchString(`^[A-Za-z0-9_. ]+$`, v) - - if !matched { - errors = append(errors, fmt.Errorf("%s contains invalid characters, only alphanumeric, underscore, space characters are supported, got %s", k, v)) - return - } - - return warnings, errors -} diff --git a/azurerm/helpers/validate/mariadb.go b/azurerm/helpers/validate/mariadb.go deleted file mode 100644 index 0cd951947bf63..0000000000000 --- a/azurerm/helpers/validate/mariadb.go +++ /dev/null @@ -1,28 +0,0 @@ -package validate - -import ( - "fmt" - "regexp" -) - -func MariaDBFirewallRuleName(v interface{}, _ string) (warnings []string, errors []error) { - value := v.(string) - - // Firewall rule name can contain alphanumeric characters and hyphens and must be 1 - 128 characters long - if matched := regexp.MustCompile("^[-a-z0-9]{1,128}$").Match([]byte(value)); !matched { - errors = append(errors, fmt.Errorf("Firewall rule name must be 1 - 128 characters long, contain only letters, numbers and hyphens.")) - } - - return warnings, errors -} - -func MariaDBServerName(v interface{}, _ string) (warnings []string, errors []error) { - value := v.(string) - - // MariaDB server name can contain alphanumeric characters and hyphens and must be 3 - 63 characters long - if matched := regexp.MustCompile("^[-a-z0-9]{3,63}$").Match([]byte(value)); !matched { - errors = append(errors, fmt.Errorf("Server name must be 3 - 63 characters long, contain only letters, numbers and hyphens.")) - } - - return warnings, errors -} diff --git a/azurerm/internal/services/mariadb/mariadb_configuration_resource.go b/azurerm/internal/services/mariadb/mariadb_configuration_resource.go index c109c0896f657..67606cd545eb6 100644 --- a/azurerm/internal/services/mariadb/mariadb_configuration_resource.go +++ b/azurerm/internal/services/mariadb/mariadb_configuration_resource.go @@ -3,9 +3,10 @@ package mariadb import ( "fmt" "log" - "regexp" "time" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb/validate" + "github.com/Azure/azure-sdk-for-go/services/mariadb/mgmt/2018-06-01/mariadb" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" @@ -43,13 +44,10 @@ func resourceArmMariaDbConfiguration() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), "server_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile("^[-a-zA-Z0-9]{3,50}$"), - "server_name must be 3 - 50 characters long, and contain only letters, numbers and hyphens", - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.MariaDbServerServerName, }, "value": { diff --git a/azurerm/internal/services/mariadb/mariadb_database_resource.go b/azurerm/internal/services/mariadb/mariadb_database_resource.go index 21c5ee6e2ff42..f585ddfb149d1 100644 --- a/azurerm/internal/services/mariadb/mariadb_database_resource.go +++ b/azurerm/internal/services/mariadb/mariadb_database_resource.go @@ -6,13 +6,14 @@ import ( "regexp" "time" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb/validate" + "github.com/Azure/azure-sdk-for-go/services/mariadb/mgmt/2018-06-01/mariadb" "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "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/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" @@ -49,13 +50,10 @@ func resourceArmMariaDbDatabase() *schema.Resource { "resource_group_name": azure.SchemaResourceGroupName(), "server_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile("^[-a-zA-Z0-9]{3,50}$"), - "server_name must be 3 - 50 characters long, and contain only letters, numbers and hyphens", - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.MariaDbServerServerName, }, "charset": { @@ -69,10 +67,13 @@ func resourceArmMariaDbDatabase() *schema.Resource { }, "collation": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.MariaDatabaseCollation, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile("^[A-Za-z0-9_. ]+$"), + "collation must contain only alphanumeric, underscore, space and dot characters", + ), }, }, } diff --git a/azurerm/internal/services/mariadb/mariadb_firewall_rule_resource.go b/azurerm/internal/services/mariadb/mariadb_firewall_rule_resource.go index 60c2217c04ff6..4dd7f822216c2 100644 --- a/azurerm/internal/services/mariadb/mariadb_firewall_rule_resource.go +++ b/azurerm/internal/services/mariadb/mariadb_firewall_rule_resource.go @@ -3,13 +3,17 @@ package mariadb import ( "fmt" "log" + "regexp" "time" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb/validate" + "github.com/Azure/azure-sdk-for-go/services/mariadb/mgmt/2018-06-01/mariadb" "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/helpers/validate" + azValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" @@ -35,10 +39,13 @@ func resourceArmMariaDBFirewallRule() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validate.MariaDBFirewallRuleName, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile("^[-a-z0-9]{1,128}$"), + "name must be 1-128 characters long and contain only letters, numbers and hyphens", + ), }, "resource_group_name": azure.SchemaResourceGroupName(), @@ -47,19 +54,19 @@ func resourceArmMariaDBFirewallRule() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.MariaDBServerName, + ValidateFunc: validate.MariaDbServerServerName, }, "start_ip_address": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.IPv4Address, + ValidateFunc: azValidate.IPv4Address, }, "end_ip_address": { Type: schema.TypeString, Required: true, - ValidateFunc: validate.IPv4Address, + ValidateFunc: azValidate.IPv4Address, }, }, } diff --git a/azurerm/internal/services/mariadb/mariadb_server_data_source.go b/azurerm/internal/services/mariadb/mariadb_server_data_source.go index 038dd21ffb694..616c05cdc0b3b 100644 --- a/azurerm/internal/services/mariadb/mariadb_server_data_source.go +++ b/azurerm/internal/services/mariadb/mariadb_server_data_source.go @@ -46,12 +46,6 @@ func dataSourceMariaDbServer() *schema.Resource { Computed: true, }, - "administrator_login_password": { - Type: schema.TypeString, - Computed: true, - Sensitive: true, - }, - "version": { Type: schema.TypeString, Computed: true, diff --git a/azurerm/internal/services/mariadb/mariadb_server_resource.go b/azurerm/internal/services/mariadb/mariadb_server_resource.go index 251889db4847e..1678f76cf3003 100644 --- a/azurerm/internal/services/mariadb/mariadb_server_resource.go +++ b/azurerm/internal/services/mariadb/mariadb_server_resource.go @@ -3,11 +3,15 @@ package mariadb import ( "fmt" "log" - "regexp" "strconv" "strings" "time" + "github.com/Azure/go-autorest/autorest/date" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb/parse" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb/validate" + "github.com/Azure/azure-sdk-for-go/services/mariadb/mgmt/2018-06-01/mariadb" "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" @@ -23,12 +27,24 @@ import ( func resourceArmMariaDbServer() *schema.Resource { return &schema.Resource{ - Create: resourceArmMariaDbServerCreateUpdate, + Create: resourceArmMariaDbServerCreate, Read: resourceArmMariaDbServerRead, - Update: resourceArmMariaDbServerCreateUpdate, + Update: resourceArmMariaDbServerUpdate, Delete: resourceArmMariaDbServerDelete, + Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + if _, err := parse.MariaDbServerServerID(d.Id()); err != nil { + return []*schema.ResourceData{d}, err + } + + d.Set("create_mode", "Default") + if v, ok := d.GetOk("create_mode"); ok && v.(string) != "" { + d.Set("create_mode", v) + } + + return []*schema.ResourceData{d}, nil + }, }, Timeouts: &schema.ResourceTimeout{ @@ -40,19 +56,86 @@ func resourceArmMariaDbServer() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.MariaDbServerServerName, + }, + + "administrator_login": { Type: schema.TypeString, - Required: true, + Optional: true, + Computed: true, ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile("^[-a-zA-Z0-9]{3,50}$"), - "MariaDB server name must be 3 - 50 characters long, contain only letters, numbers and hyphens.", - ), + }, + + "administrator_login_password": { + Type: schema.TypeString, + Optional: true, + Sensitive: true, + }, + + "auto_grow_enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, // TODO: remove in 3.0 and default to true + ConflictsWith: []string{"storage_profile", "storage_profile.0.auto_grow"}, + }, + + "backup_retention_days": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ConflictsWith: []string{"storage_profile", "storage_profile.0.backup_retention_days"}, + ValidateFunc: validation.IntBetween(7, 35), + }, + + "create_mode": { + Type: schema.TypeString, + Optional: true, + Default: string(mariadb.CreateModeDefault), + ValidateFunc: validation.StringInSlice([]string{ + string(mariadb.CreateModeDefault), + string(mariadb.CreateModeGeoRestore), + string(mariadb.CreateModePointInTimeRestore), + string(mariadb.CreateModeReplica), + }, false), + }, + + "creation_source_server_id": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.MariaDbServerServerID, + }, + + "fqdn": { + Type: schema.TypeString, + Computed: true, + }, + + "geo_redundant_backup_enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + ConflictsWith: []string{"storage_profile", "storage_profile.0.geo_redundant_backup"}, }, "location": azure.SchemaLocation(), + "public_network_access_enabled": { + Type: schema.TypeBool, + Optional: true, + Default: true, + }, + "resource_group_name": azure.SchemaResourceGroupName(), + "restore_point_in_time": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.IsRFC3339Time, + }, + "sku_name": { Type: schema.TypeString, Required: true, @@ -71,94 +154,111 @@ func resourceArmMariaDbServer() *schema.Resource { }, false), }, - "administrator_login": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, + "ssl_enforcement": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Deprecated: "this has been moved to the boolean attribute `ssl_enforcement_enabled` and will be removed in version 3.0 of the provider.", + ExactlyOneOf: []string{"ssl_enforcement", "ssl_enforcement_enabled"}, + DiffSuppressFunc: suppress.CaseDifference, + ValidateFunc: validation.StringInSlice([]string{ + string(mariadb.SslEnforcementEnumDisabled), + string(mariadb.SslEnforcementEnumEnabled), + }, false), }, - "administrator_login_password": { - Type: schema.TypeString, - Required: true, - Sensitive: true, - ValidateFunc: validation.StringIsNotEmpty, + "ssl_enforcement_enabled": { + Type: schema.TypeBool, + Optional: true, // required in 3.0 + Computed: true, // remove computed in 3.0 + ExactlyOneOf: []string{"ssl_enforcement", "ssl_enforcement_enabled"}, }, - "version": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringInSlice([]string{ - "10.2", - "10.3", - }, false), + "storage_mb": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ConflictsWith: []string{"storage_profile", "storage_profile.0.storage_mb"}, + ValidateFunc: validation.All( + validation.IntBetween(5120, 4194304), + validation.IntDivisibleBy(1024), + ), }, "storage_profile": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Deprecated: "all storage_profile properties have been moved to the top level. This block will be removed in version 3.0 of the provider.", Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "storage_mb": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validation.All( - validation.IntBetween(5120, 4096000), - validation.IntDivisibleBy(1024), - ), + "auto_grow": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"auto_grow_enabled"}, + Deprecated: "this has been moved to the top level boolean attribute `auto_grow_enabled` and will be removed in version 3.0 of the provider.", + DiffSuppressFunc: suppress.CaseDifference, + ValidateFunc: validation.StringInSlice([]string{ + string(mariadb.StorageAutogrowEnabled), + string(mariadb.StorageAutogrowDisabled), + }, false), }, "backup_retention_days": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(7, 35), + Type: schema.TypeInt, + Optional: true, + Computed: true, + ConflictsWith: []string{"backup_retention_days"}, + Deprecated: "this has been moved to the top level and will be removed in version 3.0 of the provider.", + ValidateFunc: validation.IntBetween(7, 35), }, "geo_redundant_backup": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: []string{"geo_redundant_backup_enabled"}, + Deprecated: "this has been moved to the top level boolean attribute `geo_redundant_backup_enabled` and will be removed in version 3.0 of the provider.", + DiffSuppressFunc: suppress.CaseDifference, ValidateFunc: validation.StringInSlice([]string{ string(mariadb.Enabled), string(mariadb.Disabled), }, false), }, - "auto_grow": { - Type: schema.TypeString, - Optional: true, - Default: string(mariadb.StorageAutogrowEnabled), - ValidateFunc: validation.StringInSlice([]string{ - string(mariadb.StorageAutogrowEnabled), - string(mariadb.StorageAutogrowDisabled), - }, false), + "storage_mb": { + Type: schema.TypeInt, + Optional: true, + ConflictsWith: []string{"storage_mb"}, + Deprecated: "this has been moved to the top level and will be removed in version 3.0 of the provider.", + ValidateFunc: validation.All( + validation.IntBetween(5120, 4096000), + validation.IntDivisibleBy(1024), + ), }, }, }, }, - "ssl_enforcement": { + "tags": tags.Schema(), + + "version": { Type: schema.TypeString, Required: true, + ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ - string(mariadb.SslEnforcementEnumDisabled), - string(mariadb.SslEnforcementEnumEnabled), + "10.2", + "10.3", }, false), }, - - "fqdn": { - Type: schema.TypeString, - Computed: true, - }, - - "tags": tags.Schema(), }, } } -func resourceArmMariaDbServerCreateUpdate(d *schema.ResourceData, meta interface{}) error { +func resourceArmMariaDbServerCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*clients.Client).MariaDB.ServersClient ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() @@ -166,6 +266,7 @@ func resourceArmMariaDbServerCreateUpdate(d *schema.ResourceData, meta interface log.Printf("[INFO] preparing arguments for AzureRM MariaDB Server creation.") name := d.Get("name").(string) + location := azure.NormalizeLocation(d.Get("location").(string)) resourceGroup := d.Get("resource_group_name").(string) if features.ShouldResourcesBeImported() && d.IsNewResource() { @@ -181,97 +282,183 @@ func resourceArmMariaDbServerCreateUpdate(d *schema.ResourceData, meta interface } } - location := azure.NormalizeLocation(d.Get("location").(string)) - - storageProfile := expandAzureRmMariaDbStorageProfile(d) + mode := mariadb.CreateMode(d.Get("create_mode").(string)) + source := d.Get("creation_source_server_id").(string) + version := mariadb.ServerVersion(d.Get("version").(string)) sku, err := expandServerSkuName(d.Get("sku_name").(string)) if err != nil { return fmt.Errorf("error expanding sku_name for MariaDB Server %q (Resource Group %q): %v", name, resourceGroup, err) } - skuName := sku.Name - capacity := sku.Capacity - tier := string(sku.Tier) - storageMB := storageProfile.StorageMB + publicAccess := mariadb.PublicNetworkAccessEnumEnabled + if v := d.Get("public_network_access_enabled"); !v.(bool) { + publicAccess = mariadb.PublicNetworkAccessEnumDisabled + } - // General sku validation for all sku's - if !strings.HasSuffix(*skuName, strconv.Itoa(int(*capacity))) { - return fmt.Errorf("the value in the capacity property must match the capacity value defined in the sku name (sku.capacity: %d, sku.name: %s)", *capacity, *skuName) + ssl := mariadb.SslEnforcementEnumEnabled + if v, ok := d.GetOk("ssl_enforcement"); ok && strings.EqualFold(v.(string), string(mariadb.SslEnforcementEnumDisabled)) { + ssl = mariadb.SslEnforcementEnumDisabled + } + if v, ok := d.GetOkExists("ssl_enforcement_enabled"); ok && !v.(bool) { + ssl = mariadb.SslEnforcementEnumDisabled } - // Specific validation based on sku's pricing tier - // Basic - if strings.ToLower(tier) == "basic" { - if !strings.HasPrefix(*skuName, "B_") { - return fmt.Errorf("the basic pricing tier sku name must begin with the letter B (sku.name: %s)", *skuName) - } + storage := expandMariaDbStorageProfile(d) + + var props mariadb.BasicServerPropertiesForCreate + switch mode { + case mariadb.CreateModeDefault: + admin := d.Get("administrator_login").(string) + pass := d.Get("administrator_login_password").(string) - if *storageMB > 1024000 { - return fmt.Errorf("basic pricing tier only supports upto 1,024,000 MB (1TB) of storage (storageProfile.StorageMB: %d)", *storageMB) + if admin == "" { + return fmt.Errorf("`administrator_login` must not be empty when `create_mode` is `default`") + } + if pass == "" { + return fmt.Errorf("`administrator_login_password` must not be empty when `create_mode` is `default`") } - if *capacity > 2 { - return fmt.Errorf("basic pricing tier only supports upto 2 vCores (sku.capacity: %d)", *capacity) + if _, ok := d.GetOk("restore_point_in_time"); ok { + return fmt.Errorf("`restore_point_in_time` cannot be set when `create_mode` is `default`") } - } - // General Purpose - if strings.ToLower(tier) == "generalpurpose" { - if !strings.HasPrefix(*skuName, "GP_") { - return fmt.Errorf("the general purpose pricing tier sku name must begin with the letters GP (sku.name: %s)", *skuName) + props = &mariadb.ServerPropertiesForDefaultCreate{ + AdministratorLogin: &admin, + AdministratorLoginPassword: &pass, + CreateMode: mode, + PublicNetworkAccess: publicAccess, + SslEnforcement: ssl, + StorageProfile: storage, + Version: version, + } + case mariadb.CreateModePointInTimeRestore: + v, ok := d.GetOk("restore_point_in_time") + if !ok || v.(string) == "" { + return fmt.Errorf("restore_point_in_time must be set when create_mode is PointInTimeRestore") } + time, _ := time.Parse(time.RFC3339, v.(string)) // should be validated by the schema - if *capacity < 2 { - return fmt.Errorf("general purpose pricing tier must have at least 2 vCores (sku.capacity: %d)", *capacity) + props = &mariadb.ServerPropertiesForRestore{ + CreateMode: mode, + SourceServerID: &source, + RestorePointInTime: &date.Time{ + Time: time, + }, + PublicNetworkAccess: publicAccess, + SslEnforcement: ssl, + StorageProfile: storage, + Version: version, + } + case mariadb.CreateModeGeoRestore: + props = &mariadb.ServerPropertiesForGeoRestore{ + CreateMode: mode, + SourceServerID: &source, + PublicNetworkAccess: publicAccess, + SslEnforcement: ssl, + StorageProfile: storage, + Version: version, + } + case mariadb.CreateModeReplica: + props = &mariadb.ServerPropertiesForReplica{ + CreateMode: mode, + SourceServerID: &source, + PublicNetworkAccess: publicAccess, + SslEnforcement: ssl, + Version: version, } } - // Memory Optimized - if strings.ToLower(tier) == "memoryoptimized" { - if !strings.HasPrefix(*skuName, "MO_") { - return fmt.Errorf("the memory optimized pricing tier sku name must begin with the letters MO (sku.name: %s)", *skuName) - } + server := mariadb.ServerForCreate{ + Location: &location, + Properties: props, + Sku: sku, + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + } - if *capacity < 2 { - return fmt.Errorf("memory optimized pricing tier must have at least 2 vCores (sku.capacity: %d)", *capacity) - } + future, err := client.Create(ctx, resourceGroup, name, server) + if err != nil { + return fmt.Errorf("creating MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + } - if *capacity > 16 { - return fmt.Errorf("memory optimized pricing tier only supports upto 16 vCores (sku.capacity: %d)", *capacity) - } + if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("waiting for creation of MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return fmt.Errorf("retrieving MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + if read.ID == nil { + return fmt.Errorf("cannot read MariaDB Server %q (Resource Group %q) ID", name, resourceGroup) } - properties := mariadb.ServerForCreate{ - Location: &location, - Properties: &mariadb.ServerPropertiesForDefaultCreate{ - AdministratorLogin: utils.String(d.Get("administrator_login").(string)), + d.SetId(*read.ID) + + return resourceArmMariaDbServerRead(d, meta) +} + +func resourceArmMariaDbServerUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).MariaDB.ServersClient + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for AzureRM MariaDB Server update.") + + id, err := parse.MariaDbServerServerID(d.Id()) + if err != nil { + return fmt.Errorf("parsing MariaDB Server ID : %v", err) + } + + sku, err := expandServerSkuName(d.Get("sku_name").(string)) + if err != nil { + return fmt.Errorf("expanding sku_name for MariaDB Server %q (Resource Group %q): %v", id.Name, id.ResourceGroup, err) + } + + publicAccess := mariadb.PublicNetworkAccessEnumEnabled + if v := d.Get("public_network_access_enabled").(bool); !v { + publicAccess = mariadb.PublicNetworkAccessEnumDisabled + } + + ssl := mariadb.SslEnforcementEnumEnabled + if v := d.Get("ssl_enforcement"); strings.EqualFold(v.(string), string(mariadb.SslEnforcementEnumDisabled)) { + ssl = mariadb.SslEnforcementEnumDisabled + } + if v := d.Get("ssl_enforcement_enabled").(bool); !v { + ssl = mariadb.SslEnforcementEnumDisabled + } + + storageProfile := expandMariaDbStorageProfile(d) + + properties := mariadb.ServerUpdateParameters{ + ServerUpdateParametersProperties: &mariadb.ServerUpdateParametersProperties{ AdministratorLoginPassword: utils.String(d.Get("administrator_login_password").(string)), - Version: mariadb.ServerVersion(d.Get("version").(string)), - SslEnforcement: mariadb.SslEnforcementEnum(d.Get("ssl_enforcement").(string)), + PublicNetworkAccess: publicAccess, + SslEnforcement: ssl, StorageProfile: storageProfile, - CreateMode: mariadb.CreateModeDefault, + Version: mariadb.ServerVersion(d.Get("version").(string)), }, Sku: sku, Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } - future, err := client.Create(ctx, resourceGroup, name, properties) + future, err := client.Update(ctx, id.ResourceGroup, id.Name, properties) if err != nil { - return fmt.Errorf("Error creating MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("updating MariaDB Server %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("Error waiting for creation of MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("waiting for MariaDB Server %q (Resource Group %q) to finish updating: %+v", id.Name, id.ResourceGroup, err) } - read, err := client.Get(ctx, resourceGroup, name) + read, err := client.Get(ctx, id.ResourceGroup, id.Name) if err != nil { - return fmt.Errorf("Error retrieving MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("retrieving MariaDB Server %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } if read.ID == nil { - return fmt.Errorf("Cannot read MariaDB Server %q (Resource Group %q) ID", name, resourceGroup) + return fmt.Errorf("cannot read MariaDB Server %q (Resource Group %q) ID", id.Name, id.ResourceGroup) } d.SetId(*read.ID) @@ -284,26 +471,24 @@ func resourceArmMariaDbServerRead(d *schema.ResourceData, meta interface{}) erro ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := azure.ParseAzureResourceID(d.Id()) + id, err := parse.MariaDbServerServerID(d.Id()) if err != nil { - return err + return fmt.Errorf("parsing MariaDB Server ID : %v", err) } - resourceGroup := id.ResourceGroup - name := id.Path["servers"] - resp, err := client.Get(ctx, resourceGroup, name) + resp, err := client.Get(ctx, id.ResourceGroup, id.Name) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[WARN] MariaDB Server %q was not found (Resource Group %q)", name, resourceGroup) + log.Printf("[WARN] MariaDB Server %q was not found (Resource Group %q)", id.Name, id.ResourceGroup) d.SetId("") return nil } - return fmt.Errorf("Error making Read request on Azure MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("making Read request on Azure MariaDB Server %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } d.Set("name", resp.Name) - d.Set("resource_group_name", resourceGroup) + d.Set("resource_group_name", id.ResourceGroup) if location := resp.Location; location != nil { d.Set("location", azure.NormalizeLocation(*location)) @@ -313,16 +498,26 @@ func resourceArmMariaDbServerRead(d *schema.ResourceData, meta interface{}) erro d.Set("sku_name", sku.Name) } - if properties := resp.ServerProperties; properties != nil { - d.Set("administrator_login", properties.AdministratorLogin) - d.Set("version", string(properties.Version)) - d.Set("ssl_enforcement", string(properties.SslEnforcement)) - // Computed - d.Set("fqdn", properties.FullyQualifiedDomainName) + if props := resp.ServerProperties; props != nil { + d.Set("administrator_login", props.AdministratorLogin) + d.Set("public_network_access_enabled", props.PublicNetworkAccess == mariadb.PublicNetworkAccessEnumEnabled) + d.Set("ssl_enforcement", string(props.SslEnforcement)) + d.Set("ssl_enforcement_enabled", props.SslEnforcement == mariadb.SslEnforcementEnumEnabled) + d.Set("version", string(props.Version)) - if err := d.Set("storage_profile", flattenMariaDbStorageProfile(properties.StorageProfile)); err != nil { - return fmt.Errorf("Error setting `storage_profile`: %+v", err) + if err := d.Set("storage_profile", flattenMariaDbStorageProfile(resp.StorageProfile)); err != nil { + return fmt.Errorf("setting `storage_profile`: %+v", err) } + + if storage := props.StorageProfile; storage != nil { + d.Set("auto_grow_enabled", storage.StorageAutogrow == mariadb.StorageAutogrowEnabled) + d.Set("backup_retention_days", storage.BackupRetentionDays) + d.Set("geo_redundant_backup_enabled", storage.GeoRedundantBackup == mariadb.Enabled) + d.Set("storage_mb", storage.StorageMB) + } + + // Computed + d.Set("fqdn", props.FullyQualifiedDomainName) } return tags.FlattenAndSet(d, resp.Tags) @@ -333,20 +528,18 @@ func resourceArmMariaDbServerDelete(d *schema.ResourceData, meta interface{}) er ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := azure.ParseAzureResourceID(d.Id()) + id, err := parse.MariaDbServerServerID(d.Id()) if err != nil { - return err + return fmt.Errorf("parsing MariaDB Server ID : %v", err) } - resourceGroup := id.ResourceGroup - name := id.Path["servers"] - future, err := client.Delete(ctx, resourceGroup, name) + future, err := client.Delete(ctx, id.ResourceGroup, id.Name) if err != nil { if response.WasNotFound(future.Response()) { return nil } - return fmt.Errorf("Error deleting MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("deleting MariaDB Server %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { @@ -354,7 +547,7 @@ func resourceArmMariaDbServerDelete(d *schema.ResourceData, meta interface{}) er return nil } - return fmt.Errorf("Error waiting for deletion of MariaDB Server %q (Resource Group %q): %+v", name, resourceGroup, err) + return fmt.Errorf("waiting for deletion of MariaDB Server %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) } return nil @@ -363,7 +556,7 @@ func resourceArmMariaDbServerDelete(d *schema.ResourceData, meta interface{}) er func expandServerSkuName(skuName string) (*mariadb.Sku, error) { parts := strings.Split(skuName, "_") if len(parts) != 3 { - return nil, fmt.Errorf("sku_name (%s) has the worng number of parts (%d) after splitting on _", skuName, len(parts)) + return nil, fmt.Errorf("sku_name (%s) has the wrong number of parts (%d) after splitting on _", skuName, len(parts)) } var tier mariadb.SkuTier @@ -391,21 +584,41 @@ func expandServerSkuName(skuName string) (*mariadb.Sku, error) { }, nil } -func expandAzureRmMariaDbStorageProfile(d *schema.ResourceData) *mariadb.StorageProfile { - storageprofiles := d.Get("storage_profile").([]interface{}) - storageprofile := storageprofiles[0].(map[string]interface{}) +func expandMariaDbStorageProfile(d *schema.ResourceData) *mariadb.StorageProfile { + storage := mariadb.StorageProfile{} + if v, ok := d.GetOk("storage_profile"); ok { + storageprofile := v.([]interface{})[0].(map[string]interface{}) - backupRetentionDays := storageprofile["backup_retention_days"].(int) - geoRedundantBackup := storageprofile["geo_redundant_backup"].(string) - storageMB := storageprofile["storage_mb"].(int) - autoGrow := storageprofile["auto_grow"].(string) + storage.BackupRetentionDays = utils.Int32(int32(storageprofile["backup_retention_days"].(int))) + storage.GeoRedundantBackup = mariadb.GeoRedundantBackup(storageprofile["geo_redundant_backup"].(string)) + storage.StorageAutogrow = mariadb.StorageAutogrow(storageprofile["auto_grow"].(string)) + storage.StorageMB = utils.Int32(int32(storageprofile["storage_mb"].(int))) + } - return &mariadb.StorageProfile{ - BackupRetentionDays: utils.Int32(int32(backupRetentionDays)), - GeoRedundantBackup: mariadb.GeoRedundantBackup(geoRedundantBackup), - StorageMB: utils.Int32(int32(storageMB)), - StorageAutogrow: mariadb.StorageAutogrow(autoGrow), + // now override whatever we may have from the block with the top level properties + if v, ok := d.GetOk("auto_grow_enabled"); ok { + storage.StorageAutogrow = mariadb.StorageAutogrowDisabled + if v.(bool) { + storage.StorageAutogrow = mariadb.StorageAutogrowEnabled + } } + + if v, ok := d.GetOk("backup_retention_days"); ok { + storage.BackupRetentionDays = utils.Int32(int32(v.(int))) + } + + if v, ok := d.GetOk("geo_redundant_backup_enabled"); ok { + storage.GeoRedundantBackup = mariadb.Disabled + if v.(bool) { + storage.GeoRedundantBackup = mariadb.Enabled + } + } + + if v, ok := d.GetOk("storage_mb"); ok { + storage.StorageMB = utils.Int32(int32(v.(int))) + } + + return &storage } func flattenMariaDbStorageProfile(storage *mariadb.StorageProfile) []interface{} { @@ -415,9 +628,7 @@ func flattenMariaDbStorageProfile(storage *mariadb.StorageProfile) []interface{} return []interface{}{} } - if storageMB := storage.StorageMB; storageMB != nil { - values["storage_mb"] = *storageMB - } + values["auto_grow"] = string(storage.StorageAutogrow) if backupRetentionDays := storage.BackupRetentionDays; backupRetentionDays != nil { values["backup_retention_days"] = *backupRetentionDays @@ -425,7 +636,9 @@ func flattenMariaDbStorageProfile(storage *mariadb.StorageProfile) []interface{} values["geo_redundant_backup"] = string(storage.GeoRedundantBackup) - values["auto_grow"] = string(storage.StorageAutogrow) + if storageMB := storage.StorageMB; storageMB != nil { + values["storage_mb"] = *storageMB + } return []interface{}{values} } diff --git a/azurerm/internal/services/mariadb/mariadb_virtual_network_rule_resource.go b/azurerm/internal/services/mariadb/mariadb_virtual_network_rule_resource.go index d59179d23a91e..8c186f711ed51 100644 --- a/azurerm/internal/services/mariadb/mariadb_virtual_network_rule_resource.go +++ b/azurerm/internal/services/mariadb/mariadb_virtual_network_rule_resource.go @@ -7,14 +7,15 @@ import ( "strings" "time" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb/validate" + "github.com/Azure/azure-sdk-for-go/services/mariadb/mgmt/2018-06-01/mariadb" "github.com/hashicorp/go-azure-helpers/response" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "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/helpers/validate" + azValidate "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" @@ -43,7 +44,7 @@ func resourceArmMariaDbVirtualNetworkRule() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.VirtualNetworkRuleName, + ValidateFunc: azValidate.VirtualNetworkRuleName, }, "resource_group_name": azure.SchemaResourceGroupName(), @@ -52,7 +53,7 @@ func resourceArmMariaDbVirtualNetworkRule() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.StringIsNotEmpty, + ValidateFunc: validate.MariaDbServerServerName, }, "subnet_id": { diff --git a/azurerm/internal/services/mariadb/parse/mariadb.go b/azurerm/internal/services/mariadb/parse/mariadb.go new file mode 100644 index 0000000000000..f13fbfb352e3a --- /dev/null +++ b/azurerm/internal/services/mariadb/parse/mariadb.go @@ -0,0 +1,33 @@ +package parse + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" +) + +type MariaDbServerServerId struct { + ResourceGroup string + Name string +} + +func MariaDbServerServerID(input string) (*MariaDbServerServerId, error) { + id, err := azure.ParseAzureResourceID(input) + if err != nil { + return nil, fmt.Errorf("unable to parse MariaDB Server ID %q: %+v", input, err) + } + + server := MariaDbServerServerId{ + ResourceGroup: id.ResourceGroup, + } + + if server.Name, err = id.PopSegment("servers"); err != nil { + return nil, err + } + + if err := id.ValidateNoEmptySegments(input); err != nil { + return nil, err + } + + return &server, nil +} diff --git a/azurerm/internal/services/mariadb/parse/mariadb_test.go b/azurerm/internal/services/mariadb/parse/mariadb_test.go new file mode 100644 index 0000000000000..a8bfac7548319 --- /dev/null +++ b/azurerm/internal/services/mariadb/parse/mariadb_test.go @@ -0,0 +1,68 @@ +package parse + +import ( + "testing" +) + +func TestValidateMariaDbServerServerID(t *testing.T) { + testData := []struct { + Name string + Input string + Expected *MariaDbServerServerId + }{ + { + 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.DBforMariaDB/servers/", + Expected: nil, + }, + { + Name: "Valid", + Input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMariaDB/servers/test-mariadb", + Expected: &MariaDbServerServerId{ + Name: "test-mariadb", + ResourceGroup: "test-rg", + }, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q", v.Name) + + actual, err := MariaDbServerServerID(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.ResourceGroup != v.Expected.ResourceGroup { + t.Fatalf("Expected %q but got %q for Resource Group", v.Expected.ResourceGroup, actual.ResourceGroup) + } + } +} diff --git a/azurerm/internal/services/mariadb/tests/mariadb_configuration_resource_test.go b/azurerm/internal/services/mariadb/tests/mariadb_configuration_resource_test.go index 7cf5c68a23a10..ac2c0ab8d3bae 100644 --- a/azurerm/internal/services/mariadb/tests/mariadb_configuration_resource_test.go +++ b/azurerm/internal/services/mariadb/tests/mariadb_configuration_resource_test.go @@ -218,19 +218,15 @@ resource "azurerm_mariadb_server" "test" { name = "acctestmariadbsvr-%d" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" - - sku = "GP_Gen5_2" - - storage_profile { - storage_mb = 51200 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } + sku_name = "GP_Gen5_2" + version = "10.2" administrator_login = "acctestun" administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" + backup_retention_days = 7 + geo_redundant_backup_enabled = false + ssl_enforcement_enabled = true + storage_mb = 51200 } `, data.RandomInteger, data.Locations.Primary, data.RandomInteger) } diff --git a/azurerm/internal/services/mariadb/tests/mariadb_server_resource_test.go b/azurerm/internal/services/mariadb/tests/mariadb_server_resource_test.go index 9dfe8fc610437..b8c76091c3285 100644 --- a/azurerm/internal/services/mariadb/tests/mariadb_server_resource_test.go +++ b/azurerm/internal/services/mariadb/tests/mariadb_server_resource_test.go @@ -3,6 +3,7 @@ package tests import ( "fmt" "testing" + "time" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" @@ -11,8 +12,9 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func TestAccAzureRMMariaDbServer_basic(t *testing.T) { +func TestAccAzureRMMariaDbServer_basicTenTwo(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + version := "10.2" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -20,12 +22,10 @@ func TestAccAzureRMMariaDbServer_basic(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_basic(data), + Config: testAccAzureRMMariaDbServer_basic(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), - resource.TestCheckResourceAttr(data.ResourceName, "version", "10.2"), - resource.TestCheckResourceAttr(data.ResourceName, "ssl_enforcement", "Enabled"), + resource.TestCheckResourceAttr(data.ResourceName, "version", version), ), }, data.ImportStep("administrator_login_password"), // not returned as sensitive @@ -33,8 +33,9 @@ func TestAccAzureRMMariaDbServer_basic(t *testing.T) { }) } -func TestAccAzureRMMariaDbServer_requiresImport(t *testing.T) { +func TestAccAzureRMMariaDbServer_basicTenTwoDeprecated(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + version := "10.2" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -42,21 +43,41 @@ func TestAccAzureRMMariaDbServer_requiresImport(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_basic(data), + Config: testAccAzureRMMariaDbServer_basicDeprecated(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "version", version), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive + }, + }) +} + +func TestAccAzureRMMariaDbServer_basicTenThree(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + version := "10.3" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMariaDbServerDestroy, + Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_requiresImport(data), - ExpectError: acceptance.RequiresImportError("azurerm_mariadb_server"), + Config: testAccAzureRMMariaDbServer_basic(data, version), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMariaDbServerExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "version", version), + ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive }, }) } -func TestAccAzureRMMariaDbServer_basicMaxStorage(t *testing.T) { +func TestAccAzureRMMariaDbServer_autogrowOnly(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + version := "10.3" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -64,12 +85,9 @@ func TestAccAzureRMMariaDbServer_basicMaxStorage(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_basicMaxStorage(data), + Config: testAccAzureRMMariaDbServer_autogrow(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), - resource.TestCheckResourceAttr(data.ResourceName, "version", "10.2"), - resource.TestCheckResourceAttr(data.ResourceName, "ssl_enforcement", "Enabled"), ), }, data.ImportStep("administrator_login_password"), // not returned as sensitive @@ -77,7 +95,26 @@ func TestAccAzureRMMariaDbServer_basicMaxStorage(t *testing.T) { }) } -func TestAccAzureRMMariaDbServer_generalPurpose(t *testing.T) { +func TestAccAzureRMMariaDbServer_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMariaDbServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMariaDbServer_basic(data, "10.3"), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMariaDbServerExists(data.ResourceName), + ), + }, + data.RequiresImportErrorStep(testAccAzureRMMariaDbServer_requiresImport), + }, + }) +} + +func TestAccAzureRMMariaDbServer_complete(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") resource.ParallelTest(t, resource.TestCase{ @@ -86,7 +123,7 @@ func TestAccAzureRMMariaDbServer_generalPurpose(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_generalPurpose(data), + Config: testAccAzureRMMariaDbServer_complete(data, "10.3"), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), ), @@ -96,8 +133,9 @@ func TestAccAzureRMMariaDbServer_generalPurpose(t *testing.T) { }) } -func TestAccAzureRMMariaDbServer_memoryOptimized(t *testing.T) { +func TestAccAzureRMMariaDbServer_update(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + version := "10.3" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -105,7 +143,21 @@ func TestAccAzureRMMariaDbServer_memoryOptimized(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_memoryOptimizedGeoRedundant(data), + Config: testAccAzureRMMariaDbServer_basic(data, version), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMariaDbServerExists(data.ResourceName), + ), + }, + data.ImportStep("administrator_login_password"), // not returned as sensitive + { + Config: testAccAzureRMMariaDbServer_complete(data, version), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMariaDbServerExists(data.ResourceName), + ), + }, + data.ImportStep("administrator_login_password"), // not returned as sensitive + { + Config: testAccAzureRMMariaDbServer_basic(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), ), @@ -115,8 +167,9 @@ func TestAccAzureRMMariaDbServer_memoryOptimized(t *testing.T) { }) } -func TestAccAzureRMMariaDbServer_updatePassword(t *testing.T) { +func TestAccAzureRMMariaDbServer_completeDeprecatedMigrate(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + version := "10.3" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -124,23 +177,26 @@ func TestAccAzureRMMariaDbServer_updatePassword(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_basic(data), + Config: testAccAzureRMMariaDbServer_completeDeprecated(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive { - Config: testAccAzureRMMariaDbServer_basicUpdatedPassword(data), + Config: testAccAzureRMMariaDbServer_complete(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive }, }) } -func TestAccAzureRMMariaDbServer_updated(t *testing.T) { +func TestAccAzureRMMariaDbServer_updateDeprecated(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + version := "10.2" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -148,25 +204,26 @@ func TestAccAzureRMMariaDbServer_updated(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_basic(data), + Config: testAccAzureRMMariaDbServer_basicDeprecated(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "B_Gen5_2"), - resource.TestCheckResourceAttr(data.ResourceName, "version", "10.2"), - resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "51200"), - resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive + { + Config: testAccAzureRMMariaDbServer_completeDeprecated(data, version), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMariaDbServerExists(data.ResourceName), + ), + }, + data.ImportStep("administrator_login_password"), // not returned as sensitive { - Config: testAccAzureRMMariaDbServer_basicUpdated(data), + Config: testAccAzureRMMariaDbServer_basicDeprecated(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku.0.name", "B_Gen5_1"), - resource.TestCheckResourceAttr(data.ResourceName, "version", "10.2"), - resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "640000"), - resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive }, }) } @@ -180,29 +237,55 @@ func TestAccAzureRMMariaDbServer_updateSKU(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_generalPurpose(data), + Config: testAccAzureRMMariaDbServer_sku(data, "GP_Gen5_32"), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMariaDbServerExists(data.ResourceName), + ), + }, + data.ImportStep("administrator_login_password"), // not returned as sensitive + { + Config: testAccAzureRMMariaDbServer_sku(data, "MO_Gen5_16"), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMMariaDbServerExists(data.ResourceName), + ), + }, + data.ImportStep("administrator_login_password"), // not returned as sensitive + }, + }) +} + +func TestAccAzureRMMariaDbServer_createReplica(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + version := "10.3" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMMariaDbServerDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMMariaDbServer_basic(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "GP_Gen5_32"), - resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "640000"), - resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive { - Config: testAccAzureRMMariaDbServer_memoryOptimized(data), + Config: testAccAzureRMMariaDbServer_createReplica(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "sku_name", "MO_Gen5_16"), - resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.storage_mb", "4096000"), - resource.TestCheckResourceAttr(data.ResourceName, "administrator_login", "acctestun"), + testCheckAzureRMMariaDbServerExists("azurerm_mariadb_server.replica"), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive }, }) } -func TestAccAzureRMMariaDbServer_storageAutogrow(t *testing.T) { +func TestAccAzureRMMariaDbServer_createPointInTimeRestore(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_mariadb_server", "test") + restoreTime := time.Now().Add(11 * time.Minute) + version := "10.3" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acceptance.PreCheck(t) }, @@ -210,19 +293,21 @@ func TestAccAzureRMMariaDbServer_storageAutogrow(t *testing.T) { CheckDestroy: testCheckAzureRMMariaDbServerDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMMariaDbServer_basic(data), + Config: testAccAzureRMMariaDbServer_basic(data, version), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.auto_grow", "Enabled"), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive { - Config: testAccAzureRMMariaDbServer_storageAutogrowUpdated(data), + PreConfig: func() { time.Sleep(restoreTime.Sub(time.Now().Add(-7 * time.Minute))) }, + Config: testAccAzureRMMariaDbServer_createPointInTimeRestore(data, version, restoreTime.Format(time.RFC3339)), Check: resource.ComposeTestCheckFunc( testCheckAzureRMMariaDbServerExists(data.ResourceName), - resource.TestCheckResourceAttr(data.ResourceName, "storage_profile.0.auto_grow", "Disabled"), + testCheckAzureRMMariaDbServerExists("azurerm_mariadb_server.restore"), ), }, + data.ImportStep("administrator_login_password"), // not returned as sensitive }, }) } @@ -284,7 +369,7 @@ func testCheckAzureRMMariaDbServerDestroy(s *terraform.State) error { return nil } -func testAccAzureRMMariaDbServer_basic(data acceptance.TestData) string { +func testAccAzureRMMariaDbServer_basic(data acceptance.TestData, version string) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -299,50 +384,18 @@ resource "azurerm_mariadb_server" "test" { name = "acctestmariadbsvr-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - - sku_name = "B_Gen5_2" - - storage_profile { - storage_mb = 51200 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } - - administrator_login = "acctestun" - administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) -} - -func testAccAzureRMMariaDbServer_requiresImport(data acceptance.TestData) string { - template := testAccAzureRMMariaDbServer_basic(data) - return fmt.Sprintf(` -%s - -resource "azurerm_mariadb_server" "import" { - name = azurerm_mariadb_server.test.name - location = azurerm_mariadb_server.test.location - resource_group_name = azurerm_mariadb_server.test.resource_group_name - - sku_name = "B_Gen5_2" - - storage_profile { - storage_mb = 51200 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } + sku_name = "B_Gen5_2" + version = "%s" administrator_login = "acctestun" administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" + ssl_enforcement_enabled = true + storage_mb = 51200 } -`, template) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) } -func testAccAzureRMMariaDbServer_basicUpdatedPassword(data acceptance.TestData) string { +func testAccAzureRMMariaDbServer_basicDeprecated(data acceptance.TestData, version string) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -357,24 +410,21 @@ resource "azurerm_mariadb_server" "test" { name = "acctestmariadbsvr-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - - sku_name = "B_Gen5_2" + sku_name = "B_Gen5_2" + version = "%s" storage_profile { - storage_mb = 51200 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" + storage_mb = 51200 } administrator_login = "acctestun" - administrator_login_password = "R3dH0TCh1l1P3pp3rs!" - version = "10.2" + administrator_login_password = "H@Sh1CoR3!" ssl_enforcement = "Enabled" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) } -func testAccAzureRMMariaDbServer_basicUpdated(data acceptance.TestData) string { +func testAccAzureRMMariaDbServer_complete(data acceptance.TestData, version string) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -389,24 +439,22 @@ resource "azurerm_mariadb_server" "test" { name = "acctestmariadbsvr-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - - sku_name = "B_Gen5_1" - - storage_profile { - storage_mb = 640000 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } + sku_name = "B_Gen5_2" + version = "%s" administrator_login = "acctestun" administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" + auto_grow_enabled = true + backup_retention_days = 14 + create_mode = "Default" + geo_redundant_backup_enabled = false + ssl_enforcement_enabled = true + storage_mb = 51200 } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) } -func testAccAzureRMMariaDbServer_basicMaxStorage(data acceptance.TestData) string { +func testAccAzureRMMariaDbServer_completeDeprecated(data acceptance.TestData, version string) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -421,24 +469,25 @@ resource "azurerm_mariadb_server" "test" { name = "acctestmariadbsvr-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - - sku_name = "B_Gen5_2" + sku_name = "B_Gen5_2" + version = "%s" storage_profile { - storage_mb = 947200 + auto_grow = "Enabled" backup_retention_days = 7 geo_redundant_backup = "Disabled" + storage_mb = 51200 } administrator_login = "acctestun" administrator_login_password = "H@Sh1CoR3!" - version = "10.2" + create_mode = "Default" ssl_enforcement = "Enabled" } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) } -func testAccAzureRMMariaDbServer_generalPurpose(data acceptance.TestData) string { +func testAccAzureRMMariaDbServer_autogrow(data acceptance.TestData, version string) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -453,56 +502,43 @@ resource "azurerm_mariadb_server" "test" { name = "acctestmariadbsvr-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - - sku_name = "GP_Gen5_32" - - storage_profile { - storage_mb = 640000 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } + sku_name = "B_Gen5_2" + version = "%s" administrator_login = "acctestun" administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" + auto_grow_enabled = true + backup_retention_days = 7 + geo_redundant_backup_enabled = false + ssl_enforcement_enabled = true + storage_mb = 51200 } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, version) } -func testAccAzureRMMariaDbServer_memoryOptimized(data acceptance.TestData) string { +func testAccAzureRMMariaDbServer_requiresImport(data acceptance.TestData) string { + template := testAccAzureRMMariaDbServer_basic(data, "10.3") return fmt.Sprintf(` -provider "azurerm" { - features {} -} - -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" -} - -resource "azurerm_mariadb_server" "test" { - name = "acctestmariadbsvr-%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - - sku_name = "MO_Gen5_16" +%s - storage_profile { - storage_mb = 4096000 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - } +resource "azurerm_mariadb_server" "import" { + name = azurerm_mariadb_server.test.name + location = azurerm_mariadb_server.test.location + resource_group_name = azurerm_mariadb_server.test.resource_group_name + sku_name = "B_Gen5_2" + version = "10.3" administrator_login = "acctestun" administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" + backup_retention_days = 7 + geo_redundant_backup_enabled = false + ssl_enforcement_enabled = true + storage_mb = 51200 } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, template) } -func testAccAzureRMMariaDbServer_memoryOptimizedGeoRedundant(data acceptance.TestData) string { +func testAccAzureRMMariaDbServer_sku(data acceptance.TestData, sku string) string { return fmt.Sprintf(` provider "azurerm" { features {} @@ -517,52 +553,50 @@ resource "azurerm_mariadb_server" "test" { name = "acctestmariadbsvr-%d" location = azurerm_resource_group.test.location resource_group_name = azurerm_resource_group.test.name - - sku_name = "MO_Gen5_16" - - storage_profile { - storage_mb = 4096000 - backup_retention_days = 7 - geo_redundant_backup = "Enabled" - } + sku_name = "%s" + version = "10.2" administrator_login = "acctestun" administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" + backup_retention_days = 7 + geo_redundant_backup_enabled = false + ssl_enforcement_enabled = true + storage_mb = 640000 } -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, sku) } -func testAccAzureRMMariaDbServer_storageAutogrowUpdated(data acceptance.TestData) string { +func testAccAzureRMMariaDbServer_createReplica(data acceptance.TestData, version string) string { return fmt.Sprintf(` -provider "azurerm" { - features {} -} +%s -resource "azurerm_resource_group" "test" { - name = "acctestRG-%d" - location = "%s" +resource "azurerm_mariadb_server" "replica" { + name = "acctestmariadbsvr-%d-replica" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "B_Gen5_2" + version = "%s" + create_mode = "Replica" + creation_source_server_id = azurerm_mariadb_server.test.id + ssl_enforcement_enabled = true +} +`, testAccAzureRMMariaDbServer_basic(data, version), data.RandomInteger, version) } -resource "azurerm_mariadb_server" "test" { - name = "acctestmariadbsvr-%d" - location = azurerm_resource_group.test.location - resource_group_name = azurerm_resource_group.test.name - - sku_name = "B_Gen5_2" - - storage_profile { - storage_mb = 51200 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - auto_grow = "Disabled" - } +func testAccAzureRMMariaDbServer_createPointInTimeRestore(data acceptance.TestData, version, restoreTime string) string { + return fmt.Sprintf(` +%s - administrator_login = "acctestun" - administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" -} -`, data.RandomInteger, data.Locations.Primary, data.RandomInteger) +resource "azurerm_mariadb_server" "restore" { + name = "acctestmariadbsvr-%d-restore" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku_name = "B_Gen5_2" + version = "%s" + create_mode = "PointInTimeRestore" + creation_source_server_id = azurerm_mariadb_server.test.id + restore_point_in_time = "%s" + ssl_enforcement_enabled = true +} +`, testAccAzureRMMariaDbServer_basic(data, version), data.RandomInteger, version, restoreTime) } diff --git a/azurerm/internal/services/mariadb/validate/mariadb.go b/azurerm/internal/services/mariadb/validate/mariadb.go new file mode 100644 index 0000000000000..a7aadae3947c6 --- /dev/null +++ b/azurerm/internal/services/mariadb/validate/mariadb.go @@ -0,0 +1,30 @@ +package validate + +import ( + "fmt" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/services/mariadb/parse" +) + +func MariaDbServerServerID(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.MariaDbServerServerID(v); err != nil { + errors = append(errors, fmt.Errorf("cannot parse %q as a MariaDB Server resource id: %v", k, err)) + } + + return warnings, errors +} + +func MariaDbServerServerName(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)) + } + + return nil, nil +} diff --git a/azurerm/internal/services/mariadb/validate/mariadb_test.go b/azurerm/internal/services/mariadb/validate/mariadb_test.go new file mode 100644 index 0000000000000..481d3320fafa4 --- /dev/null +++ b/azurerm/internal/services/mariadb/validate/mariadb_test.go @@ -0,0 +1,106 @@ +package validate + +import ( + "testing" +) + +func TestValidateMariaDbServerServerID(t *testing.T) { + testData := []struct { + input string + expected bool + }{ + { + // empty + input: "", + expected: false, + }, + { + // invalid + input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg", + expected: false, + }, + { + // valid + input: "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMariaDB/servers/test-mariadb", + expected: true, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q..", v.input) + + _, errors := MariaDbServerServerID(v.input, "name") + actual := len(errors) == 0 + if v.expected != actual { + t.Fatalf("Expected %t but got %t", v.expected, actual) + } + } +} + +func TestValidateMariaDbServerServerName(t *testing.T) { + testData := []struct { + input string + expected bool + }{ + { + // empty + input: "", + expected: false, + }, + { + // basic example + input: "ab-c", + expected: true, + }, + { + // can't contain upper case letter + input: "AbcD", + expected: false, + }, + { + // can't start with a hyphen + input: "-abc", + expected: false, + }, + { + // can't contain underscore + input: "ab_c", + expected: false, + }, + { + // can't end with hyphen + input: "abc-", + expected: false, + }, + { + // can not be shorter than 3 characters + input: "ab", + expected: false, + }, + { + // can not be shorter than 3 characters (catching bad regex) + input: "a", + expected: false, + }, + { + // 63 chars + input: "abcdefghijklmnopqrstuvwxyzabcdefabcdefghijklmnopqrstuvwxyzabcde", + expected: true, + }, + { + // 64 chars + input: "abcdefghijklmnopqrstuvwxyzabcdefabcdefghijklmnopqrstuvwxyzabcdef", + expected: false, + }, + } + + for _, v := range testData { + t.Logf("[DEBUG] Testing %q..", v.input) + + _, errors := MariaDbServerServerName(v.input, "name") + actual := len(errors) == 0 + if v.expected != actual { + t.Fatalf("Expected %t but got %t", v.expected, actual) + } + } +} diff --git a/website/docs/d/mariadb_server.html.markdown b/website/docs/d/mariadb_server.html.markdown index 6002c83c883ce..cd51308606e3e 100644 --- a/website/docs/d/mariadb_server.html.markdown +++ b/website/docs/d/mariadb_server.html.markdown @@ -47,8 +47,6 @@ The following attributes are exported: * `administrator_login` - The Administrator Login for the MariaDB Server. -* `administrator_login_password` - The password associated with the `administrator_login` for the MariaDB Server. - * `version` - The version of MariaDB being used. * `ssl_enforcement` - The SSL being enforced on connections. diff --git a/website/docs/r/mariadb_server.html.markdown b/website/docs/r/mariadb_server.html.markdown index 94baedaa439cd..dba9ef57002f4 100644 --- a/website/docs/r/mariadb_server.html.markdown +++ b/website/docs/r/mariadb_server.html.markdown @@ -13,29 +13,31 @@ Manages a MariaDB Server. ## Example Usage ```hcl +provider "azurerm" { + features {} +} + resource "azurerm_resource_group" "example" { - name = "api-rg-pro" + name = "example-resources" location = "West Europe" } resource "azurerm_mariadb_server" "example" { - name = "mariadb-server-1" + name = "example-mariadb-server" location = "${azurerm_resource_group.example.location}" resource_group_name = "${azurerm_resource_group.example.name}" - sku_name = "B_Gen5_2" - - storage_profile { - storage_mb = 5120 - backup_retention_days = 7 - geo_redundant_backup = "Disabled" - auto_grow = "Disabled" - } - administrator_login = "mariadbadmin" administrator_login_password = "H@Sh1CoR3!" - version = "10.2" - ssl_enforcement = "Enabled" + + sku_name = "B_Gen5_2" + storage_mb = 5120 + version = "10.2" + + auto_grow_enabled = true + backup_retention_days = 7 + geo_redundant_backup_enabled = false + ssl_enforcement_enabled = true } ``` @@ -51,31 +53,29 @@ The following arguments are supported: * `sku_name` - (Required) Specifies the SKU Name for this MariaDB Server. The name of the SKU, follows the `tier` + `family` + `cores` pattern (e.g. `B_Gen4_1`, `GP_Gen5_8`). For more information see the [product documentation](https://docs.microsoft.com/en-us/rest/api/mariadb/servers/create#sku). -* `storage_profile` - (Required) A `storage_profile` block as defined below. +* `version` - (Required) Specifies the version of MariaDB to use. Possible values are `10.2` and `10.3`. Changing this forces a new resource to be created. * `administrator_login` - (Required) The Administrator Login for the MariaDB Server. Changing this forces a new resource to be created. * `administrator_login_password` - (Required) The Password associated with the `administrator_login` for the MariaDB Server. -* `version` - (Required) Specifies the version of MariaDB to use. Possible values are `10.2` and `10.3`. Changing this forces a new resource to be created. - -* `ssl_enforcement` - (Required) Specifies if SSL should be enforced on connections. Possible values are `Enabled` and `Disabled`. +* `auto_grow_enabled` - (Optional) Enable/Disable auto-growing of the storage. Storage auto-grow prevents your server from running out of storage and becoming read-only. If storage auto grow is enabled, the storage automatically grows without impacting the workload. The default value if not explicitly specified is `true`. -* `tags` - (Optional) A mapping of tags to assign to the resource. +* `backup_retention_days` - (Optional) Backup retention days for the server, supported values are between `7` and `35` days. ---- +* `create_mode` - (Optional) The creation mode. Can be used to restore or replicate existing servers. Possible values are `Default`, `Replica`, `GeoRestore`, and `PointInTimeRestore`. Defaults to `Default`. -A `storage_profile` block supports the following: +* `creation_source_server_id` - (Optional) For creation modes other than `Default`, the source server ID to use. -* `storage_mb` - (Required) Max storage allowed for a server. Possible values are between `5120` MB (5GB) and `1024000`MB (1TB) for the Basic SKU and between `5120` MB (5GB) and `4096000` MB (4TB) for General Purpose/Memory Optimized SKUs. For more information see the [product documentation](https://docs.microsoft.com/en-us/rest/api/mariadb/servers/create#storageprofile). +* `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. -* `backup_retention_days` - (Optional) Backup retention days for the server, supported values are between `7` and `35` days. +* `restore_point_in_time` - (Optional) When `create_mode` is `PointInTimeRestore`, specifies the point in time to restore from `creation_source_server_id`. -* `geo_redundant_backup` - (Optional) Enable Geo-redundant or not for server backup. Valid values for this property are `Enabled` or `Disabled`. Changing this forces a new resource to be created. +* `ssl_enforcement_enabled` - (Required) Specifies if SSL should be enforced on connections. Possible values are `true` and `false`. --> **NOTE:** Geo Redundant Backups cannot be configured when using the `Basic` tier, and is only allowed during server create. +* `storage_mb` - (Required) Max storage allowed for a server. Possible values are between `5120` MB (5GB) and `1024000`MB (1TB) for the Basic SKU and between `5120` MB (5GB) and `4096000` MB (4TB) for General Purpose/Memory Optimized SKUs. For more information see the [product documentation](https://docs.microsoft.com/en-us/rest/api/mariadb/servers/create#storageprofile). -* `auto_grow` - (Optional) Defines whether autogrow is enabled or disabled for the storage. Valid values are `Enabled` or `Disabled`. +* `tags` - (Optional) A mapping of tags to assign to the resource. ## Attributes Reference