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..5773d3c592d7 --- /dev/null +++ b/internal/services/dataprotection/data_protection_backup_instance_mysql_flexible_server_resource.go @@ -0,0 +1,319 @@ +// 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/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" +) + +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.ParseFlexibleServerIDInsensitively(props.DataSourceInfo.ResourceID) + if err != nil { + return err + } + state.ServerId = serverId.ID() + + backupPolicyId, err := backuppolicies.ParseBackupPolicyIDInsensitively(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) + } + if existing.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", id) + } + + 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..9aa0cf8d055f --- /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. + +* `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. + +* `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 + +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 +```