From 200262d673c207df9b825102f84f27c3f51befba Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Mon, 23 Sep 2024 15:08:05 +0800 Subject: [PATCH 1/6] New Resource: azurerm_data_protection_backup_instance_mysql_flexible_server --- ...instance_mysql_flexible_server_resource.go | 316 ++++++++++++++++++ ...nce_mysql_flexible_server_resource_test.go | 208 ++++++++++++ .../services/dataprotection/registration.go | 1 + ...stance_mysql_flexible_server.html.markdown | 116 +++++++ 4 files changed, 641 insertions(+) create mode 100644 internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go create mode 100644 internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go create mode 100644 website/docs/r/data_protection_backup_instance_mysql_flexible_server.html.markdown diff --git a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go new file mode 100644 index 000000000000..224e84d69a81 --- /dev/null +++ b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go @@ -0,0 +1,316 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package dataprotection + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-sdk/resource-manager/dataprotection/2024-04-01/backupinstances" + "github.com/hashicorp/go-azure-sdk/resource-manager/dataprotection/2024-04-01/backuppolicies" + "github.com/hashicorp/go-azure-sdk/resource-manager/mysql/2022-01-01/servers" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type BackupInstanceMySQLFlexibleServerModel struct { + Name string `tfschema:"name"` + Location string `tfschema:"location"` + VaultId string `tfschema:"vault_id"` + BackupPolicyId string `tfschema:"backup_policy_id"` + ServerId string `tfschema:"server_id"` +} + +type DataProtectionBackupInstanceMySQLFlexibleServerResource struct{} + +var _ sdk.Resource = DataProtectionBackupInstanceMySQLFlexibleServerResource{} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) ResourceType() string { + return "azurerm_data_protection_backup_instance_mysql_flexible_server" +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) ModelObject() interface{} { + return &BackupInstanceMySQLFlexibleServerModel{} +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return backupinstances.ValidateBackupInstanceID +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Arguments() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + + "location": commonschema.Location(), + + "vault_id": commonschema.ResourceIDReferenceRequiredForceNew(&backuppolicies.BackupVaultId{}), + + "backup_policy_id": commonschema.ResourceIDReferenceRequired(&backuppolicies.BackupPolicyId{}), + + "server_id": commonschema.ResourceIDReferenceRequiredForceNew(&servers.FlexibleServerId{}), + } +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Attributes() map[string]*pluginsdk.Schema { + return map[string]*pluginsdk.Schema{} +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 60 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var model BackupInstanceMySQLFlexibleServerModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + client := metadata.Client.DataProtection.BackupInstanceClient + + vaultId, err := backupinstances.ParseBackupVaultID(model.VaultId) + if err != nil { + return err + } + + id := backupinstances.NewBackupInstanceID(vaultId.SubscriptionId, vaultId.ResourceGroupName, vaultId.BackupVaultName, model.Name) + + existing, err := client.Get(ctx, id) + if err != nil { + if !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for existing %s: %+v", id, err) + } + } + + if !response.WasNotFound(existing.HttpResponse) { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + serverId, err := servers.ParseFlexibleServerID(model.ServerId) + if err != nil { + return err + } + + policyId, err := backuppolicies.ParseBackupPolicyID(model.BackupPolicyId) + if err != nil { + return err + } + + parameters := backupinstances.BackupInstanceResource{ + Properties: &backupinstances.BackupInstance{ + DataSourceInfo: backupinstances.Datasource{ + DatasourceType: pointer.To("Microsoft.DBforMySQL/flexibleServers"), + ObjectType: pointer.To("Datasource"), + ResourceID: serverId.ID(), + ResourceLocation: pointer.To(location.Normalize(model.Location)), + ResourceName: pointer.To(serverId.FlexibleServerName), + ResourceType: pointer.To("Microsoft.DBforMySQL/flexibleServers"), + ResourceUri: pointer.To(serverId.ID()), + }, + DataSourceSetInfo: &backupinstances.DatasourceSet{ + DatasourceType: pointer.To("Microsoft.DBforMySQL/flexibleServers"), + ObjectType: pointer.To("DatasourceSet"), + ResourceID: serverId.ID(), + ResourceLocation: pointer.To(location.Normalize(model.Location)), + ResourceName: pointer.To(serverId.FlexibleServerName), + ResourceType: pointer.To("Microsoft.DBforMySQL/flexibleServers"), + ResourceUri: pointer.To(serverId.ID()), + }, + FriendlyName: pointer.To(id.BackupInstanceName), + PolicyInfo: backupinstances.PolicyInfo{ + PolicyId: policyId.ID(), + }, + }, + } + + if err := client.CreateOrUpdateThenPoll(ctx, id, parameters, backupinstances.DefaultCreateOrUpdateOperationOptions()); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) + } + + // Service will continue to configure the protection after the resource is created and `provisioningState` returns `Succeeded`. At this time, service doesn't allow to change the resource until it is configured completely + deadline, ok := ctx.Deadline() + if !ok { + return fmt.Errorf("internal-error: context had no deadline") + } + + stateConf := &pluginsdk.StateChangeConf{ + Delay: 5 * time.Second, + Pending: []string{string(backupinstances.CurrentProtectionStateConfiguringProtection)}, + Target: []string{string(backupinstances.CurrentProtectionStateProtectionConfigured)}, + Refresh: dataProtectionBackupInstanceMySQLFlexibleServerStateRefreshFunc(ctx, client, id), + PollInterval: 1 * time.Minute, + Timeout: time.Until(deadline), + } + + if _, err = stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for %s to become available: %s", id, err) + } + + metadata.SetID(id) + return nil + }, + } +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DataProtection.BackupInstanceClient + + id, err := backupinstances.ParseBackupInstanceID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + return metadata.MarkAsGone(*id) + } + + return fmt.Errorf("retrieving %s: %+v", *id, err) + } + + vaultId := backupinstances.NewBackupVaultID(id.SubscriptionId, id.ResourceGroupName, id.BackupVaultName) + + state := BackupInstanceMySQLFlexibleServerModel{ + Name: id.BackupInstanceName, + VaultId: vaultId.ID(), + } + + if model := resp.Model; model != nil { + if props := model.Properties; props != nil { + state.Location = location.NormalizeNilable(props.DataSourceInfo.ResourceLocation) + + serverId, err := servers.ParseFlexibleServerID(props.DataSourceInfo.ResourceID) + if err != nil { + return err + } + state.ServerId = serverId.ID() + + backupPolicyId, err := backuppolicies.ParseBackupPolicyID(props.PolicyInfo.PolicyId) + if err != nil { + return err + } + state.BackupPolicyId = backupPolicyId.ID() + } + } + + return metadata.Encode(&state) + }, + } +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 60 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DataProtection.BackupInstanceClient + + id, err := backupinstances.ParseBackupInstanceID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + var model BackupInstanceMySQLFlexibleServerModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding: %+v", err) + } + + existing, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(existing.HttpResponse) { + return metadata.MarkAsGone(id) + } + + return fmt.Errorf("reading %s: %+v", *id, err) + } + + parameters := *existing.Model + + if metadata.ResourceData.HasChange("backup_policy_id") { + policyId, err := backuppolicies.ParseBackupPolicyID(model.BackupPolicyId) + if err != nil { + return err + } + parameters.Properties.PolicyInfo.PolicyId = policyId.ID() + } + + if err := client.CreateOrUpdateThenPoll(ctx, *id, parameters, backupinstances.DefaultCreateOrUpdateOperationOptions()); err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + + // Service will update the protection after the resource is updated and `provisioningState` returns `Succeeded`. At this time, service doesn't allow to change the resource until it is updated completely + deadline, ok := ctx.Deadline() + if !ok { + return fmt.Errorf("internal-error: context had no deadline") + } + + stateConf := &pluginsdk.StateChangeConf{ + Delay: 5 * time.Second, + Pending: []string{string(backupinstances.CurrentProtectionStateUpdatingProtection)}, + Target: []string{string(backupinstances.CurrentProtectionStateProtectionConfigured)}, + Refresh: dataProtectionBackupInstanceMySQLFlexibleServerStateRefreshFunc(ctx, client, *id), + PollInterval: 1 * time.Minute, + Timeout: time.Until(deadline), + } + + if _, err = stateConf.WaitForStateContext(ctx); err != nil { + return fmt.Errorf("waiting for %s to become available: %s", id, err) + } + + return nil + }, + } +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 60 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + client := metadata.Client.DataProtection.BackupInstanceClient + + id, err := backupinstances.ParseBackupInstanceID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + err = client.DeleteThenPoll(ctx, *id, backupinstances.DefaultDeleteOperationOptions()) + if err != nil { + return fmt.Errorf("deleting %s: %+v", *id, err) + } + + return nil + }, + } +} + +func dataProtectionBackupInstanceMySQLFlexibleServerStateRefreshFunc(ctx context.Context, client *backupinstances.BackupInstancesClient, id backupinstances.BackupInstanceId) pluginsdk.StateRefreshFunc { + return func() (interface{}, string, error) { + resp, err := client.Get(ctx, id) + if err != nil { + return nil, "", fmt.Errorf("polling for %s: %+v", id, err) + } + + if resp.Model == nil { + return nil, "", fmt.Errorf("polling for %s: `model` was nil", id) + } + + if resp.Model.Properties == nil { + return nil, "", fmt.Errorf("polling for %s: `properties` was nil", id) + } + + return resp, string(pointer.From(resp.Model.Properties.CurrentProtectionState)), nil + } +} diff --git a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go new file mode 100644 index 000000000000..c56df6c2c458 --- /dev/null +++ b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go @@ -0,0 +1,208 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package dataprotection_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-sdk/resource-manager/dataprotection/2024-04-01/backupinstances" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" + "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" + "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/utils" +) + +type DataProtectionBackupInstanceMySQLFlexibleServerResource struct{} + +func TestAccDataProtectionBackupInstanceMySQLFlexibleServer_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_instance_mysql_flexible_server", "test") + r := DataProtectionBackupInstanceMySQLFlexibleServerResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccDataProtectionBackupInstanceMySQLFlexibleServer_requiresImport(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_instance_mysql_flexible_server", "test") + r := DataProtectionBackupInstanceMySQLFlexibleServerResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.RequiresImportErrorStep(r.requiresImport), + }) +} + +func TestAccDataProtectionBackupInstanceMySQLFlexibleServer_update(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_data_protection_backup_instance_mysql_flexible_server", "test") + r := DataProtectionBackupInstanceMySQLFlexibleServerResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + { + Config: r.update(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := backupinstances.ParseBackupInstanceID(state.ID) + if err != nil { + return nil, err + } + resp, err := client.DataProtection.BackupInstanceClient.Get(ctx, *id) + if err != nil { + return nil, fmt.Errorf("reading %s: %+v", *id, err) + } + return utils.Bool(resp.Model != nil), nil +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) template(data acceptance.TestData) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctest-dataprotection-%d" + location = "%s" +} + +resource "azurerm_mysql_flexible_server" "test" { + name = "acctest-mysqlfs-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + administrator_login = "adminTerraform" + administrator_password = "QAZwsx123" + version = "8.0.21" + sku_name = "B_Standard_B1s" + zone = "1" +} + +resource "azurerm_data_protection_backup_vault" "test" { + name = "acctest-dataprotection-vault-%d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + datastore_type = "VaultStore" + redundancy = "LocallyRedundant" + soft_delete = "Off" + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_role_assignment" "test" { + scope = azurerm_resource_group.test.id + role_definition_name = "Reader" + principal_id = azurerm_data_protection_backup_vault.test.identity.0.principal_id +} + +resource "azurerm_role_assignment" "test2" { + scope = azurerm_mysql_flexible_server.test.id + role_definition_name = "MySQL Backup And Export Operator" + principal_id = azurerm_data_protection_backup_vault.test.identity.0.principal_id +} + +resource "azurerm_data_protection_backup_policy_mysql_flexible_server" "test" { + name = "acctest-dp-%d" + vault_id = azurerm_data_protection_backup_vault.test.id + backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"] + + default_retention_rule { + life_cycle { + duration = "P4M" + data_store_type = "VaultStore" + } + } + + depends_on = [azurerm_role_assignment.test, azurerm_role_assignment.test2] +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, data.RandomInteger) +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) basic(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_data_protection_backup_instance_mysql_flexible_server" "test" { + name = "acctest-dbi-%d" + location = azurerm_resource_group.test.location + vault_id = azurerm_data_protection_backup_vault.test.id + server_id = azurerm_mysql_flexible_server.test.id + backup_policy_id = azurerm_data_protection_backup_policy_mysql_flexible_server.test.id +} +`, r.template(data), data.RandomInteger) +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) requiresImport(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_data_protection_backup_instance_mysql_flexible_server" "import" { + name = azurerm_data_protection_backup_instance_mysql_flexible_server.test.name + location = azurerm_data_protection_backup_instance_mysql_flexible_server.test.location + vault_id = azurerm_data_protection_backup_instance_mysql_flexible_server.test.vault_id + server_id = azurerm_data_protection_backup_instance_mysql_flexible_server.test.server_id + backup_policy_id = azurerm_data_protection_backup_instance_mysql_flexible_server.test.backup_policy_id +} +`, r.basic(data)) +} + +func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) update(data acceptance.TestData) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +%s + +resource "azurerm_data_protection_backup_policy_mysql_flexible_server" "test2" { + name = "acctest-dp2-%d" + vault_id = azurerm_data_protection_backup_vault.test.id + backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"] + + default_retention_rule { + life_cycle { + duration = "P4M" + data_store_type = "VaultStore" + } + } + + depends_on = [azurerm_role_assignment.test, azurerm_role_assignment.test2] +} + +resource "azurerm_data_protection_backup_instance_mysql_flexible_server" "test" { + name = "acctest-dbi-%d" + location = azurerm_resource_group.test.location + vault_id = azurerm_data_protection_backup_vault.test.id + server_id = azurerm_mysql_flexible_server.test.id + backup_policy_id = azurerm_data_protection_backup_policy_mysql_flexible_server.test2.id +} +`, r.template(data), data.RandomInteger, data.RandomInteger) +} diff --git a/internal/services/dataprotection/registration.go b/internal/services/dataprotection/registration.go index b2fbd92bb26d..4020a3c11339 100644 --- a/internal/services/dataprotection/registration.go +++ b/internal/services/dataprotection/registration.go @@ -62,6 +62,7 @@ func (r Registration) Resources() []sdk.Resource { DataProtectionBackupPolicyMySQLFlexibleServerResource{}, DataProtectionBackupPolicyPostgreSQLFlexibleServerResource{}, DataProtectionBackupInstanceKubernatesClusterResource{}, + DataProtectionBackupInstanceMySQLFlexibleServerResource{}, DataProtectionBackupInstancePostgreSQLFlexibleServerResource{}, } } diff --git a/website/docs/r/data_protection_backup_instance_mysql_flexible_server.html.markdown b/website/docs/r/data_protection_backup_instance_mysql_flexible_server.html.markdown new file mode 100644 index 000000000000..60b64498160f --- /dev/null +++ b/website/docs/r/data_protection_backup_instance_mysql_flexible_server.html.markdown @@ -0,0 +1,116 @@ +--- +subcategory: "DataProtection" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_data_protection_backup_instance_mysql_flexible_server" +description: |- + Manages a Backup Instance to back up MySQL Flexible Server. +--- + +# azurerm_data_protection_backup_instance_mysql_flexible_server + +Manages a Backup Instance to back up MySQL Flexible Server. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-resources" + location = "West Europe" +} + +resource "azurerm_mysql_flexible_server" "example" { + name = "example-mysqlfs" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + administrator_login = "adminTerraform" + administrator_password = "QAZwsx123" + version = "8.0.21" + sku_name = "B_Standard_B1s" + zone = "1" +} + +resource "azurerm_data_protection_backup_vault" "example" { + name = "example-backupvault" + resource_group_name = azurerm_resource_group.example.name + location = azurerm_resource_group.example.location + datastore_type = "VaultStore" + redundancy = "LocallyRedundant" + soft_delete = "Off" + + identity { + type = "SystemAssigned" + } +} + +resource "azurerm_role_assignment" "example" { + scope = azurerm_resource_group.example.id + role_definition_name = "Reader" + principal_id = azurerm_data_protection_backup_vault.example.identity.0.principal_id +} + +resource "azurerm_role_assignment" "example2" { + scope = azurerm_mysql_flexible_server.example.id + role_definition_name = "MySQL Backup And Export Operator" + principal_id = azurerm_data_protection_backup_vault.example.identity.0.principal_id +} + +resource "azurerm_data_protection_backup_policy_mysql_flexible_server" "example" { + name = "example-dp" + vault_id = azurerm_data_protection_backup_vault.example.id + backup_repeating_time_intervals = ["R/2021-05-23T02:30:00+00:00/P1W"] + + default_retention_rule { + life_cycle { + duration = "P4M" + data_store_type = "VaultStore" + } + } + + depends_on = [azurerm_role_assignment.example, azurerm_role_assignment.example2] +} + +resource "azurerm_data_protection_backup_instance_mysql_flexible_server" "example" { + name = "example-dbi" + location = azurerm_resource_group.example.location + vault_id = azurerm_data_protection_backup_vault.example.id + server_id = azurerm_mysql_flexible_server.example.id + backup_policy_id = azurerm_data_protection_backup_policy_mysql_flexible_server.example.id +} +``` + +## Arguments Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Backup Instance for the MySQL Flexible Server. Changing this forces a new resource to be created. + +* `location` - (Required) The location of the source database. Changing this forces a new resource to be created. + +* `vault_id` - (Required) The ID of the Backup Vault within which the MySQL Flexible Server Backup Instance should exist. Changing this forces a new resource to be created. + +* `server_id` - (Required) The ID of the source server. Changing this forces a new resource to be created. + +* `backup_policy_id` - (Required) The ID of the Backup Policy. + +## Attributes Reference + +In addition to the Arguments listed above - the following Attributes are exported: + +* `id` - The ID of the Backup Instance MySQL Flexible Server. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 60 minutes) Used when creating the Backup Instance MySQL Flexible Server. +* `read` - (Defaults to 5 minutes) Used when retrieving the Backup Instance MySQL Flexible Server. +* `update` - (Defaults to 60 minutes) Used when updating the Backup Instance MySQL Flexible Server. +* `delete` - (Defaults to 60 minutes) Used when deleting the Backup Instance MySQL Flexible Server. + +## Import + +Backup Instance MySQL Flexible Servers can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_data_protection_backup_instance_mysql_flexible_server.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.DataProtection/backupVaults/vault1/backupInstances/backupInstance1 +``` From 66f37c5a841100dd6319406c8eace10fb06ae57b Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Tue, 24 Sep 2024 16:53:19 +0800 Subject: [PATCH 2/6] update pr per comments --- ...ction_backup_instance_mysql_flexible_server_resource.go | 7 +++++-- ...ion_backup_instance_mysql_flexible_server.html.markdown | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go index 224e84d69a81..f885456988a0 100644 --- a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go +++ b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go @@ -193,13 +193,13 @@ func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Read() sdk.Reso if props := model.Properties; props != nil { state.Location = location.NormalizeNilable(props.DataSourceInfo.ResourceLocation) - serverId, err := servers.ParseFlexibleServerID(props.DataSourceInfo.ResourceID) + serverId, err := servers.ParseFlexibleServerIDInsensitively(props.DataSourceInfo.ResourceID) if err != nil { return err } state.ServerId = serverId.ID() - backupPolicyId, err := backuppolicies.ParseBackupPolicyID(props.PolicyInfo.PolicyId) + backupPolicyId, err := backuppolicies.ParseBackupPolicyIDInsensitively(props.PolicyInfo.PolicyId) if err != nil { return err } @@ -236,6 +236,9 @@ func (r DataProtectionBackupInstanceMySQLFlexibleServerResource) Update() sdk.Re return fmt.Errorf("reading %s: %+v", *id, err) } + if existing.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", id) + } parameters := *existing.Model diff --git a/website/docs/r/data_protection_backup_instance_mysql_flexible_server.html.markdown b/website/docs/r/data_protection_backup_instance_mysql_flexible_server.html.markdown index 60b64498160f..9aa0cf8d055f 100644 --- a/website/docs/r/data_protection_backup_instance_mysql_flexible_server.html.markdown +++ b/website/docs/r/data_protection_backup_instance_mysql_flexible_server.html.markdown @@ -86,11 +86,11 @@ The following arguments are supported: * `location` - (Required) The location of the source database. Changing this forces a new resource to be created. -* `vault_id` - (Required) The ID of the Backup Vault within which the MySQL Flexible Server Backup Instance should exist. Changing this forces a new resource to be created. +* `backup_policy_id` - (Required) The ID of the Backup Policy. * `server_id` - (Required) The ID of the source server. Changing this forces a new resource to be created. -* `backup_policy_id` - (Required) The ID of the Backup Policy. +* `vault_id` - (Required) The ID of the Backup Vault within which the MySQL Flexible Server Backup Instance should exist. Changing this forces a new resource to be created. ## Attributes Reference From c279a47ff150b0bb5b34deaccd9501ef41f84332 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 17 Oct 2024 16:43:59 +0800 Subject: [PATCH 3/6] update zone in tc --- ...ction_backup_instance_mysql_flexible_server_resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go index c56df6c2c458..51f694dc193e 100644 --- a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go @@ -97,7 +97,7 @@ resource "azurerm_mysql_flexible_server" "test" { administrator_password = "QAZwsx123" version = "8.0.21" sku_name = "B_Standard_B1s" - zone = "1" + zone = "2" } resource "azurerm_data_protection_backup_vault" "test" { From c7dd1a17b52aefa2003b30d16c0e80b38f2831f4 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 31 Oct 2024 10:02:46 +0800 Subject: [PATCH 4/6] update mysql version --- ...protection_backup_instance_mysql_flexible_server_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go index f885456988a0..5773d3c592d7 100644 --- a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go +++ b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/location" "github.com/hashicorp/go-azure-sdk/resource-manager/dataprotection/2024-04-01/backupinstances" "github.com/hashicorp/go-azure-sdk/resource-manager/dataprotection/2024-04-01/backuppolicies" - "github.com/hashicorp/go-azure-sdk/resource-manager/mysql/2022-01-01/servers" + "github.com/hashicorp/go-azure-sdk/resource-manager/mysql/2023-12-30/servers" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" From 3116bebfcd5b7de961c15296616e106413d3dae7 Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 31 Oct 2024 11:20:52 +0800 Subject: [PATCH 5/6] merge latets change --- .github/labeler-pull-request-triage.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/labeler-pull-request-triage.yml b/.github/labeler-pull-request-triage.yml index ed1d793fc197..18d6b28fb62d 100644 --- a/.github/labeler-pull-request-triage.yml +++ b/.github/labeler-pull-request-triage.yml @@ -574,12 +574,3 @@ service/workloads: - changed-files: - any-glob-to-any-file: - internal/services/workloads/**/* - -bug: - - '- \[ ?X ?\] Bug Fix' - -enhancement: - - '- \[ ?X ?\] Enhancement' - -breaking-change: - - '- \[ ?X ?\] Breaking Change' \ No newline at end of file From 9865b301cf4fff239f4059293e64aa40dafae2ee Mon Sep 17 00:00:00 2001 From: neil-yechenwei Date: Thu, 31 Oct 2024 11:49:36 +0800 Subject: [PATCH 6/6] update tc --- ...ction_backup_instance_mysql_flexible_server_resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go index 51f694dc193e..c56df6c2c458 100644 --- a/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go +++ b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource_test.go @@ -97,7 +97,7 @@ resource "azurerm_mysql_flexible_server" "test" { administrator_password = "QAZwsx123" version = "8.0.21" sku_name = "B_Standard_B1s" - zone = "2" + zone = "1" } resource "azurerm_data_protection_backup_vault" "test" {