From 0a49cbb9439e57dd744adc211e6c74df3712e28e Mon Sep 17 00:00:00 2001 From: ziyeqf Date: Tue, 14 Feb 2023 17:10:14 +0800 Subject: [PATCH 1/5] New Resource:`azurerm_site_recovery_replication_policy_hyperv` --- .../services/recoveryservices/registration.go | 1 + ...very_replication_policy_hyperv_resource.go | 245 ++++++++++++++++++ ...replication_policy_hyperv_resource_test.go | 99 +++++++ ...ry_replication_policy_hyperv.html.markdown | 75 ++++++ 4 files changed, 420 insertions(+) create mode 100644 internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go create mode 100644 internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource_test.go create mode 100644 website/docs/r/site_recovery_replication_policy_hyperv.html.markdown diff --git a/internal/services/recoveryservices/registration.go b/internal/services/recoveryservices/registration.go index 32c86fee4a75..f8ac526d3b5d 100644 --- a/internal/services/recoveryservices/registration.go +++ b/internal/services/recoveryservices/registration.go @@ -26,6 +26,7 @@ func (r Registration) Resources() []sdk.Resource { return []sdk.Resource{ BackupProtectionPolicyVMWorkloadResource{}, SiteRecoveryReplicationRecoveryPlanResource{}, + ReplicationPolicyHyperVResource{}, } } diff --git a/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go b/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go new file mode 100644 index 000000000000..32826fccefa5 --- /dev/null +++ b/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go @@ -0,0 +1,245 @@ +package recoveryservices + +import ( + "context" + "fmt" + "time" + + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationpolicies" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/recoveryservices/validate" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" + "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" +) + +type ReplicationPolicyHyperVModel struct { + Name string `tfschema:"name"` + ResourceGroupName string `tfschema:"resource_group_name"` + RecoveryVaultName string `tfschema:"recovery_vault_name"` + RecoveryPointRetentionInHours int64 `tfschema:"recovery_point_retention_in_hours"` + ApplicationConsistentSnapshotFrequencyInHours int64 `tfschema:"application_consistent_snapshot_frequency_in_hours"` + CopyFrequency int64 `tfschema:"replication_interval_in_seconds"` +} + +type ReplicationPolicyHyperVResource struct{} + +var _ sdk.ResourceWithUpdate = ReplicationPolicyHyperVResource{} + +func (r ReplicationPolicyHyperVResource) Arguments() map[string]*schema.Schema { + return map[string]*schema.Schema{ + "name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + "resource_group_name": commonschema.ResourceGroupName(), + + "recovery_vault_name": { + Type: pluginsdk.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.RecoveryServicesVaultName, + }, + "recovery_point_retention_in_hours": { + Type: pluginsdk.TypeInt, + Required: true, + ForceNew: false, + ValidateFunc: validation.IntBetween(0, 24), + }, + "application_consistent_snapshot_frequency_in_hours": { + Type: pluginsdk.TypeInt, + Required: true, + ForceNew: false, + ValidateFunc: validation.IntBetween(0, 12), + }, + "replication_interval_in_seconds": { + Type: pluginsdk.TypeInt, + Required: true, + ForceNew: false, + ValidateFunc: validation.IntInSlice([]int{30, 300}), + }, + } +} + +func (r ReplicationPolicyHyperVResource) Attributes() map[string]*schema.Schema { + return map[string]*schema.Schema{} +} + +func (r ReplicationPolicyHyperVResource) ModelObject() interface{} { + return &ReplicationPolicyHyperVModel{} +} + +func (r ReplicationPolicyHyperVResource) ResourceType() string { + return "azurerm_site_recovery_replication_policy_hyperv" +} + +func (r ReplicationPolicyHyperVResource) Create() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var plan ReplicationPolicyHyperVModel + if err := metadata.Decode(&plan); err != nil { + return fmt.Errorf("decoding %+v", err) + } + + subscriptionId := metadata.Client.Account.SubscriptionId + client := metadata.Client.RecoveryServices.ReplicationPoliciesClient + + id := replicationpolicies.NewReplicationPolicyID(subscriptionId, plan.ResourceGroupName, plan.RecoveryVaultName, plan.Name) + + existing, err := client.Get(ctx, id) + if err != nil { + // NOTE: Bad Request due to https://github.com/Azure/azure-rest-api-specs/issues/12759 + if !response.WasNotFound(existing.HttpResponse) && !wasBadRequestWithNotExist(existing.HttpResponse, err) { + return fmt.Errorf("checking presence %s: %+v", plan.Name, err) + } + } + + if existing.Model != nil && existing.Model.Id != nil && *existing.Model.Id != "" { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } + + parameters := replicationpolicies.CreatePolicyInput{ + Properties: &replicationpolicies.CreatePolicyInputProperties{ + ProviderSpecificInput: &replicationpolicies.HyperVReplicaAzurePolicyInput{ + RecoveryPointHistoryDuration: &plan.RecoveryPointRetentionInHours, + ApplicationConsistentSnapshotFrequencyInHours: &plan.ApplicationConsistentSnapshotFrequencyInHours, + ReplicationInterval: &plan.CopyFrequency, + }, + }, + } + err = client.CreateThenPoll(ctx, id, parameters) + if err != nil { + return fmt.Errorf("creating site recovery replication policy %s: %+v", id, err) + } + + metadata.SetID(id) + + return nil + }, + } +} + +func (r ReplicationPolicyHyperVResource) Read() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 5 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + id, err := replicationpolicies.ParseReplicationPolicyID(metadata.ResourceData.Id()) + if err != nil { + return fmt.Errorf("parsing %s: %+v", metadata.ResourceData.Id(), err) + } + + client := metadata.Client.RecoveryServices.ReplicationPoliciesClient + + resp, err := client.Get(ctx, *id) + if err != nil { + if response.WasNotFound(resp.HttpResponse) { + metadata.MarkAsGone(id) + return nil + } + return fmt.Errorf("reading %s : %+v", id.String(), err) + } + + state := ReplicationPolicyHyperVModel{ + Name: id.ReplicationPolicyName, + ResourceGroupName: id.ResourceGroupName, + RecoveryVaultName: id.VaultName, + } + + if model := resp.Model; model != nil { + if detail, isA2A := expandH2APolicyDetail(resp.Model); isA2A { + if detail.ApplicationConsistentSnapshotFrequencyInHours != nil { + state.ApplicationConsistentSnapshotFrequencyInHours = *detail.ApplicationConsistentSnapshotFrequencyInHours + } + if detail.ReplicationInterval != nil { + state.CopyFrequency = *detail.ReplicationInterval + } + if detail.RecoveryPointHistoryDurationInHours != nil { + state.RecoveryPointRetentionInHours = *detail.RecoveryPointHistoryDurationInHours + } + + } + } + return metadata.Encode(&state) + }, + } +} + +func (r ReplicationPolicyHyperVResource) Update() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var model ReplicationPolicyHyperVModel + if err := metadata.Decode(&model); err != nil { + return fmt.Errorf("decoding %+v", err) + } + + id, err := replicationpolicies.ParseReplicationPolicyID(metadata.ResourceData.Id()) + if err != nil { + return fmt.Errorf("parsing %s: %+v", metadata.ResourceData.Id(), err) + } + + client := metadata.Client.RecoveryServices.ReplicationPoliciesClient + + parameters := replicationpolicies.UpdatePolicyInput{ + Properties: &replicationpolicies.UpdatePolicyInputProperties{ + ReplicationProviderSettings: &replicationpolicies.HyperVReplicaAzurePolicyInput{ + RecoveryPointHistoryDuration: &model.RecoveryPointRetentionInHours, + ApplicationConsistentSnapshotFrequencyInHours: &model.ApplicationConsistentSnapshotFrequencyInHours, + ReplicationInterval: &model.CopyFrequency, + }, + }, + } + + err = client.UpdateThenPoll(ctx, *id, parameters) + if err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + + return nil + }, + } +} + +func (r ReplicationPolicyHyperVResource) Delete() sdk.ResourceFunc { + return sdk.ResourceFunc{ + Timeout: 30 * time.Minute, + Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + id, err := replicationpolicies.ParseReplicationPolicyID(metadata.ResourceData.Id()) + if err != nil { + return err + } + + client := metadata.Client.RecoveryServices.ReplicationPoliciesClient + + err = client.DeleteThenPoll(ctx, *id) + if err != nil { + return fmt.Errorf("deleting %s : %+v", id, err) + } + + return nil + }, + } +} + +func (r ReplicationPolicyHyperVResource) IDValidationFunc() pluginsdk.SchemaValidateFunc { + return replicationpolicies.ValidateReplicationPolicyID +} + +func expandH2APolicyDetail(input *replicationpolicies.Policy) (out *replicationpolicies.HyperVReplicaAzurePolicyDetails, isA2A bool) { + if input.Properties == nil { + return nil, false + } + if input.Properties.ProviderSpecificDetails == nil { + return nil, false + } + detail, isA2A := input.Properties.ProviderSpecificDetails.(replicationpolicies.HyperVReplicaAzurePolicyDetails) + if isA2A { + out = &detail + } + return +} diff --git a/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource_test.go b/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource_test.go new file mode 100644 index 000000000000..b5b2b81f2b46 --- /dev/null +++ b/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource_test.go @@ -0,0 +1,99 @@ +package recoveryservices_test + +import ( + "context" + "fmt" + "testing" + + "github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationpolicies" + "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 SiteRecoveryReplicationPolicyHyperVResource struct{} + +func TestAccSiteRecoveryReplicationPolicyHyperV_basic(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_site_recovery_replication_policy_hyperv", "test") + r := SiteRecoveryReplicationPolicyHyperVResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data, 2, 1, 300), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + +func TestAccSiteRecoveryReplicationPolicyHyperV_noSnapshots(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_site_recovery_replication_policy_hyperv", "test") + r := SiteRecoveryReplicationPolicyHyperVResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.basic(data, 2, 0, 30), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + check.That(data.ResourceName).Key("recovery_point_retention_in_hours").HasValue("2"), + check.That(data.ResourceName).Key("application_consistent_snapshot_frequency_in_hours").HasValue("0"), + check.That(data.ResourceName).Key("replication_interval_in_seconds").HasValue("30"), + ), + }, + data.ImportStep(), + }) +} + +func (SiteRecoveryReplicationPolicyHyperVResource) basic(data acceptance.TestData, retentionInHours int, snapshotFrequencyInHours int, replicationInterval int) string { + return fmt.Sprintf(` +provider "azurerm" { + features {} +} + +resource "azurerm_resource_group" "test" { + name = "acctestRG-recovery-%d" + location = "%s" +} + +resource "azurerm_recovery_services_vault" "test" { + name = "acctest-vault-%d" + location = azurerm_resource_group.test.location + resource_group_name = azurerm_resource_group.test.name + sku = "Standard" + + soft_delete_enabled = false +} + +resource "azurerm_site_recovery_replication_policy_hyperv" "test" { + resource_group_name = azurerm_resource_group.test.name + recovery_vault_name = azurerm_recovery_services_vault.test.name + name = "acctest-policy-%d" + recovery_point_retention_in_hours = %d + application_consistent_snapshot_frequency_in_hours = %d + replication_interval_in_seconds = %d +} +`, data.RandomInteger, data.Locations.Primary, data.RandomInteger, data.RandomInteger, retentionInHours, snapshotFrequencyInHours, replicationInterval) +} + +func (t SiteRecoveryReplicationPolicyHyperVResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { + id, err := replicationpolicies.ParseReplicationPolicyID(state.ID) + if err != nil { + return nil, err + } + + resp, err := clients.RecoveryServices.ReplicationPoliciesClient.Get(ctx, *id) + if err != nil { + return nil, fmt.Errorf("reading site recovery replication policy (%s): %+v", id.String(), err) + } + + model := resp.Model + if model == nil { + return nil, fmt.Errorf("reading site recovery replication policy (%s): model is nil", id.String()) + } + + return utils.Bool(model.Id != nil), nil +} diff --git a/website/docs/r/site_recovery_replication_policy_hyperv.html.markdown b/website/docs/r/site_recovery_replication_policy_hyperv.html.markdown new file mode 100644 index 000000000000..c8a0b1119173 --- /dev/null +++ b/website/docs/r/site_recovery_replication_policy_hyperv.html.markdown @@ -0,0 +1,75 @@ +--- +subcategory: "Recovery Services" +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_site_recovery_replication_policy_hyperv" +description: |- + Manages an Azure Site Recovery replication policy for HyperV on Azure. +--- + +# azurerm_site_recovery_replication_policy_hyperv + +Manages a Azure Site Recovery replication policy fir HyperV within a recovery vault. Replication policies define the frequency at which recovery points are created and how long they are stored. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example-rg" + location = "East US" +} + +resource "azurerm_recovery_services_vault" "vault" { + name = "example-recovery-vault" + location = azurerm_resource_group.example.location + resource_group_name = azurerm_resource_group.example.name + sku = "Standard" +} + +resource "azurerm_site_recovery_replication_policy_hyperv" "policy" { + name = "policy" + resource_group_name = azurerm_resource_group.example.name + recovery_vault_name = azurerm_recovery_services_vault.vault.name + recovery_point_retention_in_hours = 2 + application_consistent_snapshot_frequency_in_hours = 1 + replication_interval_in_seconds = 300 +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the replication policy. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) Name of the resource group where the vault that should be updated is located. Changing this forces a new resource to be created. + +* `recovery_vault_name` - (Required) The name of the vault that should be updated. Changing this forces a new resource to be created. + +* `recovery_point_retention_in_hours` - (Required) The duration in hours for which the recovery points need to be stored. + +* `application_consistent_snapshot_frequency_in_hours` - (Required) Specifies the frequency(in hours) at which to create application consistent recovery points. + +* `replication_interval_in_seconds` - (Required) Specifies how frequently data should be synchronized between source and target locations. Possible values are `30` and `300`. + +## Attributes Reference + +In addition to the arguments above, the following attributes are exported: + +* `id` - The ID of the Site Recovery Replication Policy. + +## Timeouts + +The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/language/resources/syntax#operation-timeouts) for certain actions: + +* `create` - (Defaults to 30 minutes) Used when creating the Site Recovery Replication Policy. +* `update` - (Defaults to 30 minutes) Used when updating the Site Recovery Replication Policy. +* `read` - (Defaults to 5 minutes) Used when retrieving the Site Recovery Replication Policy. +* `delete` - (Defaults to 30 minutes) Used when deleting the Site Recovery Replication Policy. + +## Import + +Site Recovery Replication Policies can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_site_recovery_replication_policy.mypolicy /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resource-group-name/providers/Microsoft.RecoveryServices/vaults/recovery-vault-name/replicationPolicies/policy-name +``` From 6770a56fc69337ef1ebb473453adb84fcfe9bdd8 Mon Sep 17 00:00:00 2001 From: ziyeqf Date: Tue, 14 Feb 2023 17:38:23 +0800 Subject: [PATCH 2/5] golint --- .../site_recovery_replication_policy_hyperv_resource.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go b/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go index 32826fccefa5..a0a4a3f4c148 100644 --- a/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go +++ b/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go @@ -138,8 +138,7 @@ func (r ReplicationPolicyHyperVResource) Read() sdk.ResourceFunc { resp, err := client.Get(ctx, *id) if err != nil { if response.WasNotFound(resp.HttpResponse) { - metadata.MarkAsGone(id) - return nil + return metadata.MarkAsGone(id) } return fmt.Errorf("reading %s : %+v", id.String(), err) } From 0e4c8746c6a444b7f85e34775854e8bbc1f7fda6 Mon Sep 17 00:00:00 2001 From: ziyeqf Date: Wed, 15 Feb 2023 09:47:16 +0800 Subject: [PATCH 3/5] update per comments --- ...ery_hyperv_replication_policy_resource.go} | 48 +++++++++---------- ...yperv_replication_policy_resource_test.go} | 15 ++---- ...ry_replication_policy_hyperv.html.markdown | 10 ++-- 3 files changed, 33 insertions(+), 40 deletions(-) rename internal/services/recoveryservices/{site_recovery_replication_policy_hyperv_resource.go => site_recovery_hyperv_replication_policy_resource.go} (81%) rename internal/services/recoveryservices/{site_recovery_replication_policy_hyperv_resource_test.go => site_recovery_hyperv_replication_policy_resource_test.go} (85%) diff --git a/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go b/internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource.go similarity index 81% rename from internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go rename to internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource.go index a0a4a3f4c148..e21f77619278 100644 --- a/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource.go +++ b/internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource.go @@ -6,19 +6,17 @@ import ( "time" "github.com/hashicorp/go-azure-helpers/lang/response" - "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" + "github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservices/2022-10-01/vaults" "github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationpolicies" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/recoveryservices/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" ) type ReplicationPolicyHyperVModel struct { Name string `tfschema:"name"` - ResourceGroupName string `tfschema:"resource_group_name"` - RecoveryVaultName string `tfschema:"recovery_vault_name"` + RecoveryVaultId string `tfschema:"recovery_vault_id"` RecoveryPointRetentionInHours int64 `tfschema:"recovery_point_retention_in_hours"` ApplicationConsistentSnapshotFrequencyInHours int64 `tfschema:"application_consistent_snapshot_frequency_in_hours"` CopyFrequency int64 `tfschema:"replication_interval_in_seconds"` @@ -36,30 +34,25 @@ func (r ReplicationPolicyHyperVResource) Arguments() map[string]*schema.Schema { ForceNew: true, ValidateFunc: validation.StringIsNotEmpty, }, - "resource_group_name": commonschema.ResourceGroupName(), - - "recovery_vault_name": { + "recovery_vault_id": { Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.RecoveryServicesVaultName, + ValidateFunc: vaults.ValidateVaultID, }, "recovery_point_retention_in_hours": { Type: pluginsdk.TypeInt, Required: true, - ForceNew: false, ValidateFunc: validation.IntBetween(0, 24), }, "application_consistent_snapshot_frequency_in_hours": { Type: pluginsdk.TypeInt, Required: true, - ForceNew: false, ValidateFunc: validation.IntBetween(0, 12), }, "replication_interval_in_seconds": { Type: pluginsdk.TypeInt, Required: true, - ForceNew: false, ValidateFunc: validation.IntInSlice([]int{30, 300}), }, } @@ -74,7 +67,7 @@ func (r ReplicationPolicyHyperVResource) ModelObject() interface{} { } func (r ReplicationPolicyHyperVResource) ResourceType() string { - return "azurerm_site_recovery_replication_policy_hyperv" + return "azurerm_site_recovery_hyperv_replication_policy" } func (r ReplicationPolicyHyperVResource) Create() sdk.ResourceFunc { @@ -86,10 +79,14 @@ func (r ReplicationPolicyHyperVResource) Create() sdk.ResourceFunc { return fmt.Errorf("decoding %+v", err) } - subscriptionId := metadata.Client.Account.SubscriptionId client := metadata.Client.RecoveryServices.ReplicationPoliciesClient - id := replicationpolicies.NewReplicationPolicyID(subscriptionId, plan.ResourceGroupName, plan.RecoveryVaultName, plan.Name) + parsedVaultId, err := vaults.ParseVaultID(plan.RecoveryVaultId) + if err != nil { + return fmt.Errorf("parsing %s: %+v", plan.RecoveryVaultId, err) + } + + id := replicationpolicies.NewReplicationPolicyID(parsedVaultId.SubscriptionId, parsedVaultId.ResourceGroupName, parsedVaultId.VaultName, plan.Name) existing, err := client.Get(ctx, id) if err != nil { @@ -99,7 +96,7 @@ func (r ReplicationPolicyHyperVResource) Create() sdk.ResourceFunc { } } - if existing.Model != nil && existing.Model.Id != nil && *existing.Model.Id != "" { + if existing.Model != nil { return metadata.ResourceRequiresImport(r.ResourceType(), id) } @@ -114,7 +111,7 @@ func (r ReplicationPolicyHyperVResource) Create() sdk.ResourceFunc { } err = client.CreateThenPoll(ctx, id, parameters) if err != nil { - return fmt.Errorf("creating site recovery replication policy %s: %+v", id, err) + return fmt.Errorf("creating %s: %+v", id, err) } metadata.SetID(id) @@ -130,7 +127,7 @@ func (r ReplicationPolicyHyperVResource) Read() sdk.ResourceFunc { Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { id, err := replicationpolicies.ParseReplicationPolicyID(metadata.ResourceData.Id()) if err != nil { - return fmt.Errorf("parsing %s: %+v", metadata.ResourceData.Id(), err) + return err } client := metadata.Client.RecoveryServices.ReplicationPoliciesClient @@ -140,17 +137,18 @@ func (r ReplicationPolicyHyperVResource) Read() sdk.ResourceFunc { if response.WasNotFound(resp.HttpResponse) { return metadata.MarkAsGone(id) } - return fmt.Errorf("reading %s : %+v", id.String(), err) + return fmt.Errorf("retrieving %s : %+v", *id, err) } + vaultId := vaults.NewVaultID(id.SubscriptionId, id.ResourceGroupName, id.VaultName) + state := ReplicationPolicyHyperVModel{ - Name: id.ReplicationPolicyName, - ResourceGroupName: id.ResourceGroupName, - RecoveryVaultName: id.VaultName, + Name: id.ReplicationPolicyName, + RecoveryVaultId: vaultId.ID(), } if model := resp.Model; model != nil { - if detail, isA2A := expandH2APolicyDetail(resp.Model); isA2A { + if detail, isA2A := expandHyperVToAzurePolicyDetail(resp.Model); isA2A { if detail.ApplicationConsistentSnapshotFrequencyInHours != nil { state.ApplicationConsistentSnapshotFrequencyInHours = *detail.ApplicationConsistentSnapshotFrequencyInHours } @@ -179,7 +177,7 @@ func (r ReplicationPolicyHyperVResource) Update() sdk.ResourceFunc { id, err := replicationpolicies.ParseReplicationPolicyID(metadata.ResourceData.Id()) if err != nil { - return fmt.Errorf("parsing %s: %+v", metadata.ResourceData.Id(), err) + return err } client := metadata.Client.RecoveryServices.ReplicationPoliciesClient @@ -217,7 +215,7 @@ func (r ReplicationPolicyHyperVResource) Delete() sdk.ResourceFunc { err = client.DeleteThenPoll(ctx, *id) if err != nil { - return fmt.Errorf("deleting %s : %+v", id, err) + return fmt.Errorf("deleting %s : %+v", id, err) } return nil @@ -229,7 +227,7 @@ func (r ReplicationPolicyHyperVResource) IDValidationFunc() pluginsdk.SchemaVali return replicationpolicies.ValidateReplicationPolicyID } -func expandH2APolicyDetail(input *replicationpolicies.Policy) (out *replicationpolicies.HyperVReplicaAzurePolicyDetails, isA2A bool) { +func expandHyperVToAzurePolicyDetail(input *replicationpolicies.Policy) (out *replicationpolicies.HyperVReplicaAzurePolicyDetails, isA2A bool) { if input.Properties == nil { return nil, false } diff --git a/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource_test.go b/internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource_test.go similarity index 85% rename from internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource_test.go rename to internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource_test.go index b5b2b81f2b46..2837ba213adc 100644 --- a/internal/services/recoveryservices/site_recovery_replication_policy_hyperv_resource_test.go +++ b/internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource_test.go @@ -16,7 +16,7 @@ import ( type SiteRecoveryReplicationPolicyHyperVResource struct{} func TestAccSiteRecoveryReplicationPolicyHyperV_basic(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_site_recovery_replication_policy_hyperv", "test") + data := acceptance.BuildTestData(t, "azurerm_site_recovery_hyperv_replication_policy", "test") r := SiteRecoveryReplicationPolicyHyperVResource{} data.ResourceTest(t, r, []acceptance.TestStep{ @@ -31,7 +31,7 @@ func TestAccSiteRecoveryReplicationPolicyHyperV_basic(t *testing.T) { } func TestAccSiteRecoveryReplicationPolicyHyperV_noSnapshots(t *testing.T) { - data := acceptance.BuildTestData(t, "azurerm_site_recovery_replication_policy_hyperv", "test") + data := acceptance.BuildTestData(t, "azurerm_site_recovery_hyperv_replication_policy", "test") r := SiteRecoveryReplicationPolicyHyperVResource{} data.ResourceTest(t, r, []acceptance.TestStep{ @@ -68,7 +68,7 @@ resource "azurerm_recovery_services_vault" "test" { soft_delete_enabled = false } -resource "azurerm_site_recovery_replication_policy_hyperv" "test" { +resource "azurerm_site_recovery_hyperv_replication_policy" "test" { resource_group_name = azurerm_resource_group.test.name recovery_vault_name = azurerm_recovery_services_vault.test.name name = "acctest-policy-%d" @@ -87,13 +87,8 @@ func (t SiteRecoveryReplicationPolicyHyperVResource) Exists(ctx context.Context, resp, err := clients.RecoveryServices.ReplicationPoliciesClient.Get(ctx, *id) if err != nil { - return nil, fmt.Errorf("reading site recovery replication policy (%s): %+v", id.String(), err) + return nil, fmt.Errorf("retrieving %s: %+v", *id, err) } - model := resp.Model - if model == nil { - return nil, fmt.Errorf("reading site recovery replication policy (%s): model is nil", id.String()) - } - - return utils.Bool(model.Id != nil), nil + return utils.Bool(resp.Model != nil), nil } diff --git a/website/docs/r/site_recovery_replication_policy_hyperv.html.markdown b/website/docs/r/site_recovery_replication_policy_hyperv.html.markdown index c8a0b1119173..c434ce54295f 100644 --- a/website/docs/r/site_recovery_replication_policy_hyperv.html.markdown +++ b/website/docs/r/site_recovery_replication_policy_hyperv.html.markdown @@ -1,14 +1,14 @@ --- subcategory: "Recovery Services" layout: "azurerm" -page_title: "Azure Resource Manager: azurerm_site_recovery_replication_policy_hyperv" +page_title: "Azure Resource Manager: azurerm_site_recovery_hyperv_replication_policy" description: |- Manages an Azure Site Recovery replication policy for HyperV on Azure. --- -# azurerm_site_recovery_replication_policy_hyperv +# azurerm_site_recovery_hyperv_replication_policy -Manages a Azure Site Recovery replication policy fir HyperV within a recovery vault. Replication policies define the frequency at which recovery points are created and how long they are stored. +Manages a Azure Site Recovery replication policy for HyperV within a Recovery Vault. Replication policies define the frequency at which recovery points are created and how long they are stored. ## Example Usage @@ -25,7 +25,7 @@ resource "azurerm_recovery_services_vault" "vault" { sku = "Standard" } -resource "azurerm_site_recovery_replication_policy_hyperv" "policy" { +resource "azurerm_site_recovery_hyperv_replication_policy" "policy" { name = "policy" resource_group_name = azurerm_resource_group.example.name recovery_vault_name = azurerm_recovery_services_vault.vault.name @@ -47,7 +47,7 @@ The following arguments are supported: * `recovery_point_retention_in_hours` - (Required) The duration in hours for which the recovery points need to be stored. -* `application_consistent_snapshot_frequency_in_hours` - (Required) Specifies the frequency(in hours) at which to create application consistent recovery points. +* `application_consistent_snapshot_frequency_in_hours` - (Required) Specifies the frequency at which to create application consistent recovery points. * `replication_interval_in_seconds` - (Required) Specifies how frequently data should be synchronized between source and target locations. Possible values are `30` and `300`. From c196151e78ad3934329964030ba86dd3e814cc96 Mon Sep 17 00:00:00 2001 From: ziyeqf Date: Fri, 17 Feb 2023 11:01:25 +0800 Subject: [PATCH 4/5] update test case --- .../site_recovery_hyperv_replication_policy_resource_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource_test.go b/internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource_test.go index 2837ba213adc..812dd8f104fa 100644 --- a/internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource_test.go +++ b/internal/services/recoveryservices/site_recovery_hyperv_replication_policy_resource_test.go @@ -69,8 +69,7 @@ resource "azurerm_recovery_services_vault" "test" { } resource "azurerm_site_recovery_hyperv_replication_policy" "test" { - resource_group_name = azurerm_resource_group.test.name - recovery_vault_name = azurerm_recovery_services_vault.test.name + recovery_vault_id = azurerm_recovery_services_vault.test.id name = "acctest-policy-%d" recovery_point_retention_in_hours = %d application_consistent_snapshot_frequency_in_hours = %d From 7c9663bba26442c7a687521b8b936b1145029232 Mon Sep 17 00:00:00 2001 From: ziyeqf Date: Fri, 17 Feb 2023 11:21:30 +0800 Subject: [PATCH 5/5] fix a fmt error in test file --- .../recoveryservices/recovery_services_vault_resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/recoveryservices/recovery_services_vault_resource_test.go b/internal/services/recoveryservices/recovery_services_vault_resource_test.go index 43dc24e46dfc..688633e5d72e 100644 --- a/internal/services/recoveryservices/recovery_services_vault_resource_test.go +++ b/internal/services/recoveryservices/recovery_services_vault_resource_test.go @@ -550,7 +550,7 @@ resource "azurerm_recovery_services_vault" "test" { resource_group_name = azurerm_resource_group.test.name sku = "Standard" - cross_region_restore_enabled = %v + cross_region_restore_enabled = %t soft_delete_enabled = false }