Skip to content

Commit

Permalink
Site Recovery - swap sdk and upgrade to 2022-10-01, support `networ…
Browse files Browse the repository at this point in the history
…k_interface.is_primary` property (hashicorp#19571)

Co-authored-by: kt <[email protected]>
  • Loading branch information
ziyeqf and katbyte authored Jan 9, 2023
1 parent 04569b6 commit 2ccc2b6
Show file tree
Hide file tree
Showing 451 changed files with 23,903 additions and 637 deletions.
79 changes: 36 additions & 43 deletions internal/services/recoveryservices/client/client.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package client

import (
"github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2018-07-10/siterecovery" // nolint: staticcheck
"github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2021-08-01/recoveryservices" // nolint: staticcheck
"github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2021-12-01/backup" // nolint: staticcheck
"github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationfabrics"
"github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationnetworkmappings"
"github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationpolicies"
"github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationprotecteditems"
"github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationprotectioncontainermappings"
"github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationprotectioncontainers"
"github.com/hashicorp/go-azure-sdk/resource-manager/recoveryservicessiterecovery/2022-10-01/replicationrecoveryplans"
"github.com/hashicorp/terraform-provider-azurerm/internal/common"
)

Expand All @@ -18,12 +24,13 @@ type Client struct {
VaultsClient *recoveryservices.VaultsClient
VaultsConfigsClient *backup.ResourceVaultConfigsClient // Not sure why this is in backup, but https://github.com/Azure/azure-sdk-for-go/issues/7279
StorageConfigsClient *backup.ResourceStorageConfigsNonCRRClient
FabricClient func(resourceGroupName string, vaultName string) siterecovery.ReplicationFabricsClient
ProtectionContainerClient func(resourceGroupName string, vaultName string) siterecovery.ReplicationProtectionContainersClient
ReplicationPoliciesClient func(resourceGroupName string, vaultName string) siterecovery.ReplicationPoliciesClient
ContainerMappingClient func(resourceGroupName string, vaultName string) siterecovery.ReplicationProtectionContainerMappingsClient
NetworkMappingClient func(resourceGroupName string, vaultName string) siterecovery.ReplicationNetworkMappingsClient
ReplicationMigrationItemsClient func(resourceGroupName string, vaultName string) siterecovery.ReplicationProtectedItemsClient
FabricClient *replicationfabrics.ReplicationFabricsClient
ProtectionContainerClient *replicationprotectioncontainers.ReplicationProtectionContainersClient
ReplicationPoliciesClient *replicationpolicies.ReplicationPoliciesClient
ContainerMappingClient *replicationprotectioncontainermappings.ReplicationProtectionContainerMappingsClient
NetworkMappingClient *replicationnetworkmappings.ReplicationNetworkMappingsClient
ReplicationProtectedItemsClient *replicationprotecteditems.ReplicationProtectedItemsClient
ReplicationRecoveryPlansClient *replicationrecoveryplans.ReplicationRecoveryPlansClient
}

func NewClient(o *common.ClientOptions) *Client {
Expand Down Expand Up @@ -57,41 +64,26 @@ func NewClient(o *common.ClientOptions) *Client {
backupProtectionContainerOperationResultsClient := backup.NewProtectionContainerOperationResultsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId)
o.ConfigureClient(&backupProtectionContainerOperationResultsClient.Client, o.ResourceManagerAuthorizer)

fabricClient := func(resourceGroupName string, vaultName string) siterecovery.ReplicationFabricsClient {
client := siterecovery.NewReplicationFabricsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, resourceGroupName, vaultName)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)
return client
}
fabricClient := replicationfabrics.NewReplicationFabricsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&fabricClient.Client, o.ResourceManagerAuthorizer)

protectionContainerClient := func(resourceGroupName string, vaultName string) siterecovery.ReplicationProtectionContainersClient {
client := siterecovery.NewReplicationProtectionContainersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, resourceGroupName, vaultName)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)
return client
}
protectionContainerClient := replicationprotectioncontainers.NewReplicationProtectionContainersClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&protectionContainerClient.Client, o.ResourceManagerAuthorizer)

replicationPoliciesClient := func(resourceGroupName string, vaultName string) siterecovery.ReplicationPoliciesClient {
client := siterecovery.NewReplicationPoliciesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, resourceGroupName, vaultName)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)
return client
}
replicationPoliciesClient := replicationpolicies.NewReplicationPoliciesClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&replicationPoliciesClient.Client, o.ResourceManagerAuthorizer)

containerMappingClient := func(resourceGroupName string, vaultName string) siterecovery.ReplicationProtectionContainerMappingsClient {
client := siterecovery.NewReplicationProtectionContainerMappingsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, resourceGroupName, vaultName)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)
return client
}
containerMappingClient := replicationprotectioncontainermappings.NewReplicationProtectionContainerMappingsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&containerMappingClient.Client, o.ResourceManagerAuthorizer)

networkMappingClient := func(resourceGroupName string, vaultName string) siterecovery.ReplicationNetworkMappingsClient {
client := siterecovery.NewReplicationNetworkMappingsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, resourceGroupName, vaultName)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)
return client
}
networkMappingClient := replicationnetworkmappings.NewReplicationNetworkMappingsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&networkMappingClient.Client, o.ResourceManagerAuthorizer)

replicationMigrationItemsClient := func(resourceGroupName string, vaultName string) siterecovery.ReplicationProtectedItemsClient {
client := siterecovery.NewReplicationProtectedItemsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId, resourceGroupName, vaultName)
o.ConfigureClient(&client.Client, o.ResourceManagerAuthorizer)
return client
}
replicationMigrationItemsClient := replicationprotecteditems.NewReplicationProtectedItemsClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&replicationMigrationItemsClient.Client, o.ResourceManagerAuthorizer)

replicationRecoveryPlanClient := replicationrecoveryplans.NewReplicationRecoveryPlansClientWithBaseURI(o.ResourceManagerEndpoint)
o.ConfigureClient(&replicationRecoveryPlanClient.Client, o.ResourceManagerAuthorizer)

return &Client{
ProtectableItemsClient: &protectableItemsClient,
Expand All @@ -104,11 +96,12 @@ func NewClient(o *common.ClientOptions) *Client {
VaultsClient: &vaultsClient,
VaultsConfigsClient: &vaultConfigsClient,
StorageConfigsClient: &storageConfigsClient,
FabricClient: fabricClient,
ProtectionContainerClient: protectionContainerClient,
ReplicationPoliciesClient: replicationPoliciesClient,
ContainerMappingClient: containerMappingClient,
NetworkMappingClient: networkMappingClient,
ReplicationMigrationItemsClient: replicationMigrationItemsClient,
FabricClient: &fabricClient,
ProtectionContainerClient: &protectionContainerClient,
ReplicationPoliciesClient: &replicationPoliciesClient,
ContainerMappingClient: &containerMappingClient,
NetworkMappingClient: &networkMappingClient,
ReplicationProtectedItemsClient: &replicationMigrationItemsClient,
ReplicationRecoveryPlansClient: &replicationRecoveryPlanClient,
}
}
28 changes: 28 additions & 0 deletions internal/services/recoveryservices/helpers.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,38 @@
package recoveryservices

import (
"net/http"
"strings"

"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/hashicorp/go-azure-helpers/lang/response"
)

// This code is a workaround for this bug https://github.com/Azure/azure-sdk-for-go/issues/2824
func handleAzureSdkForGoBug2824(id string) string {
return strings.Replace(id, "/Subscriptions/", "/subscriptions/", 1)
}

func wasBadRequestWithNotExist(resp *http.Response, err error) bool {
e, ok := err.(autorest.DetailedError)
if !ok {
return false
}

r, ok := e.Original.(*azure.RequestError)
if !ok {
return false
}

if r.ServiceError == nil || len(r.ServiceError.Details) == 0 {
return false
}

sc, ok := r.ServiceError.Details[0]["code"]
if !ok {
return false
}

return response.WasBadRequest(resp) && sc == "SubscriptionIdNotRegisteredWithSrs"
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import (
"fmt"
"time"

"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/recoveryservicessiterecovery/2022-10-01/replicationfabrics"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
"github.com/hashicorp/terraform-provider-azurerm/internal/services/recoveryservices/parse"
"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"
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

func dataSourceSiteRecoveryFabric() *pluginsdk.Resource {
Expand Down Expand Up @@ -43,30 +43,33 @@ func dataSourceSiteRecoveryFabric() *pluginsdk.Resource {

func dataSourceSiteRecoveryFabricRead(d *pluginsdk.ResourceData, meta interface{}) error {
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
id := parse.NewReplicationFabricID(subscriptionId, d.Get("resource_group_name").(string), d.Get("recovery_vault_name").(string), d.Get("name").(string))
id := replicationfabrics.NewReplicationFabricID(subscriptionId, d.Get("resource_group_name").(string), d.Get("recovery_vault_name").(string), d.Get("name").(string))

client := meta.(*clients.Client).RecoveryServices.FabricClient(id.ResourceGroup, id.VaultName)
client := meta.(*clients.Client).RecoveryServices.FabricClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

resp, err := client.Get(ctx, id.Name)
resp, err := client.Get(ctx, id, replicationfabrics.DefaultGetOperationOptions())
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
if response.WasNotFound(resp.HttpResponse) {
return fmt.Errorf("%s was not found", id)
}
return fmt.Errorf("making read request on site recovery fabric %s: %+v", id.String(), err)
}

model := resp.Model
if model == nil {
return fmt.Errorf("making read request on site recovery fabric %s: model is nil", id.String())
}

d.SetId(id.ID())
d.Set("name", id.Name)
d.Set("resource_group_name", id.ResourceGroup)
d.Set("recovery_vault_name", id.VaultName)
d.Set("name", id.FabricName)
d.Set("resource_group_name", id.ResourceGroupName)
d.Set("recovery_vault_name", id.ResourceName)

normalizedLocation := ""
if props := resp.Properties; props != nil {
if azureDetails, isAzureDetails := props.CustomDetails.AsAzureFabricSpecificDetails(); isAzureDetails {
normalizedLocation = location.NormalizeNilable(azureDetails.Location)
}
if l := model.Location; l != nil {
normalizedLocation = location.NormalizeNilable(l)
}
d.Set("location", normalizedLocation)

Expand Down
75 changes: 35 additions & 40 deletions internal/services/recoveryservices/site_recovery_fabric_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"fmt"
"time"

"github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/2018-07-10/siterecovery" // nolint: staticcheck
"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/recoveryservicessiterecovery/2022-10-01/replicationfabrics"
"github.com/hashicorp/terraform-provider-azurerm/helpers/azure"
"github.com/hashicorp/terraform-provider-azurerm/helpers/tf"
"github.com/hashicorp/terraform-provider-azurerm/internal/clients"
Expand All @@ -14,7 +16,6 @@ import (
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
"github.com/hashicorp/terraform-provider-azurerm/internal/timeouts"
"github.com/hashicorp/terraform-provider-azurerm/utils"
)

func resourceSiteRecoveryFabric() *pluginsdk.Resource {
Expand Down Expand Up @@ -56,105 +57,99 @@ func resourceSiteRecoveryFabric() *pluginsdk.Resource {
}

func resourceSiteRecoveryFabricCreate(d *pluginsdk.ResourceData, meta interface{}) error {
subscriptionId := meta.(*clients.Client).Account.SubscriptionId
resGroup := d.Get("resource_group_name").(string)
vaultName := d.Get("recovery_vault_name").(string)
location := azure.NormalizeLocation(d.Get("location").(string))
name := d.Get("name").(string)

client := meta.(*clients.Client).RecoveryServices.FabricClient(resGroup, vaultName)
client := meta.(*clients.Client).RecoveryServices.FabricClient
ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d)
defer cancel()

id := replicationfabrics.NewReplicationFabricID(subscriptionId, resGroup, vaultName, name)

if d.IsNewResource() {
existing, err := client.Get(ctx, name)
existing, err := client.Get(ctx, id, replicationfabrics.DefaultGetOperationOptions())
if err != nil {
// NOTE: Bad Request due to https://github.com/Azure/azure-rest-api-specs/issues/12759
if !utils.ResponseWasNotFound(existing.Response) && !utils.ResponseWasBadRequestWithServiceCode(existing.Response, err, "SubscriptionIdNotRegisteredWithSrs") {
if !response.WasNotFound(existing.HttpResponse) && !wasBadRequestWithNotExist(existing.HttpResponse, err) {
return fmt.Errorf("checking for presence of existing site recovery fabric %s (vault %s): %+v", name, vaultName, err)
}
}

if existing.ID != nil && *existing.ID != "" {
return tf.ImportAsExistsError("azurerm_site_recovery_fabric", handleAzureSdkForGoBug2824(*existing.ID))
if model := existing.Model; model != nil && model.Id != nil && *model.Id != "" {
return tf.ImportAsExistsError("azurerm_site_recovery_fabric", handleAzureSdkForGoBug2824(*model.Id))
}
}

parameters := siterecovery.FabricCreationInput{
Properties: &siterecovery.FabricCreationInputProperties{
CustomDetails: siterecovery.AzureFabricCreationInput{
InstanceType: "Azure",
Location: &location,
parameters := replicationfabrics.FabricCreationInput{
Properties: &replicationfabrics.FabricCreationInputProperties{
CustomDetails: replicationfabrics.AzureFabricCreationInput{
Location: &location,
},
},
}

future, err := client.Create(ctx, name, parameters)
err := client.CreateThenPoll(ctx, id, parameters)
if err != nil {
return fmt.Errorf("creating site recovery fabric %s (vault %s): %+v", name, vaultName, err)
}
if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("creating site recovery fabric %s (vault %s): %+v", name, vaultName, err)
}

resp, err := client.Get(ctx, name)
if err != nil {
return fmt.Errorf("retrieving site recovery fabric %s (vault %s): %+v", name, vaultName, err)
}

d.SetId(handleAzureSdkForGoBug2824(*resp.ID))
d.SetId(id.ID())

return resourceSiteRecoveryFabricRead(d, meta)
}

func resourceSiteRecoveryFabricRead(d *pluginsdk.ResourceData, meta interface{}) error {
id, err := parse.ReplicationFabricID(d.Id())
id, err := replicationfabrics.ParseReplicationFabricID(d.Id())
if err != nil {
return err
}

fabricClient := meta.(*clients.Client).RecoveryServices.FabricClient(id.ResourceGroup, id.VaultName)
fabricClient := meta.(*clients.Client).RecoveryServices.FabricClient
client := fabricClient
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d)
defer cancel()

resp, err := client.Get(ctx, id.Name)
resp, err := client.Get(ctx, *id, replicationfabrics.DefaultGetOperationOptions())
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
if response.WasNotFound(resp.HttpResponse) {
d.SetId("")
return nil
}
return fmt.Errorf("making read request on site recovery fabric %s: %+v", id.String(), err)
}

d.Set("name", resp.Name)
d.Set("resource_group_name", id.ResourceGroup)
if props := resp.Properties; props != nil {
if azureDetails, isAzureDetails := props.CustomDetails.AsAzureFabricSpecificDetails(); isAzureDetails {
d.Set("location", azureDetails.Location)
}
model := resp.Model
if model == nil {
return fmt.Errorf("making read request on site recovery fabric %s: model is nil", id.String())
}

d.Set("name", model.Name)
d.Set("resource_group_name", id.ResourceGroupName)
if model.Properties.CustomDetails != nil {
loc := *model.Properties.CustomDetails.(replicationfabrics.AzureFabricSpecificDetails).Location
d.Set("location", location.Normalize(loc))
}
d.Set("recovery_vault_name", id.VaultName)
d.Set("recovery_vault_name", id.ResourceName)
return nil
}

func resourceSiteRecoveryFabricDelete(d *pluginsdk.ResourceData, meta interface{}) error {
id, err := parse.ReplicationFabricID(d.Id())
id, err := replicationfabrics.ParseReplicationFabricID(d.Id())
if err != nil {
return err
}

client := meta.(*clients.Client).RecoveryServices.FabricClient(id.ResourceGroup, id.VaultName)
client := meta.(*clients.Client).RecoveryServices.FabricClient
ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d)
defer cancel()

future, err := client.Delete(ctx, id.Name)
err = client.DeleteThenPoll(ctx, *id)
if err != nil {
return fmt.Errorf("deleting site recovery fabric %s : %+v", id.String(), err)
}

if err = future.WaitForCompletionRef(ctx, client.Client); err != nil {
return fmt.Errorf("waiting for deletion of site recovery fabric %s : %+v", id.String(), err)
}

return nil
}
Loading

0 comments on commit 2ccc2b6

Please sign in to comment.