From 5a9b9f19da03ec1fbd5ae672cd9cf3096c3bbf5d Mon Sep 17 00:00:00 2001 From: stephybun Date: Tue, 14 May 2024 14:58:54 +0200 Subject: [PATCH] `network` - update several resources to use `hashicorp/go-azure-sdk` (#25905) * update to use hashicorp/go-azure-sdk * use NewCompositeResourceID and swap more resources over * update nat gateway data source to use hashicorp/go-azure-sdk * tflint * add exceptions to the gradually deprecated script * add TODO comment to ip group cidr resource and extend context for destroy step in local network gateway resource tests * double timeout for updating address space * use CreateOrUpdate method to circumvent broken polling behaviour * add custom poller for local network gateway * goimports --- .../network/custom_ip_prefix_resource.go | 333 +++++++++--------- .../network/custom_ip_prefix_resource_test.go | 15 +- .../local_network_gateway_poller.go | 53 +++ .../network/ip_group_cidr_resource.go | 116 +++--- .../network/ip_group_cidr_resource_test.go | 21 +- .../services/network/ip_group_data_source.go | 48 ++- .../services/network/ip_group_resource.go | 214 ++++++----- .../network/ip_group_resource_test.go | 12 +- .../services/network/ip_groups_data_source.go | 42 +-- .../local_network_gateway_data_source.go | 37 +- .../network/local_network_gateway_resource.go | 129 ++++--- .../local_network_gateway_resource_test.go | 16 +- .../network/nat_gateway_data_source.go | 69 ++-- ..._gateway_public_ip_association_resource.go | 174 ++++----- ...way_public_ip_association_resource_test.go | 11 +- ...y_public_ip_prefix_association_resource.go | 178 +++++----- ...lic_ip_prefix_association_resource_test.go | 47 +-- .../services/network/nat_gateway_resource.go | 168 ++++----- .../network/nat_gateway_resource_test.go | 12 +- .../services/network/network_subresource.go | 23 -- scripts/run-gradually-deprecated.sh | 13 +- 21 files changed, 891 insertions(+), 840 deletions(-) create mode 100644 internal/services/network/custompollers/local_network_gateway_poller.go delete mode 100644 internal/services/network/network_subresource.go diff --git a/internal/services/network/custom_ip_prefix_resource.go b/internal/services/network/custom_ip_prefix_resource.go index 9a134cb386a5..b982e8b13cb6 100644 --- a/internal/services/network/custom_ip_prefix_resource.go +++ b/internal/services/network/custom_ip_prefix_resource.go @@ -12,30 +12,30 @@ import ( "time" "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/customipprefixes" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" - "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) type CustomIpPrefixModel struct { - CIDR string `tfschema:"cidr"` - CommissioningEnabled bool `tfschema:"commissioning_enabled"` - InternetAdvertisingDisabled bool `tfschema:"internet_advertising_disabled"` - Location string `tfschema:"location"` - Name string `tfschema:"name"` - ParentCustomIPPrefixID string `tfschema:"parent_custom_ip_prefix_id"` - ROAValidityEndDate string `tfschema:"roa_validity_end_date"` - ResourceGroupName string `tfschema:"resource_group_name"` - Tags map[string]string `tfschema:"tags"` - WANValidationSignedMessage string `tfschema:"wan_validation_signed_message"` - Zones []string `tfschema:"zones"` + CIDR string `tfschema:"cidr"` + CommissioningEnabled bool `tfschema:"commissioning_enabled"` + InternetAdvertisingDisabled bool `tfschema:"internet_advertising_disabled"` + Location string `tfschema:"location"` + Name string `tfschema:"name"` + ParentCustomIPPrefixID string `tfschema:"parent_custom_ip_prefix_id"` + ROAValidityEndDate string `tfschema:"roa_validity_end_date"` + ResourceGroupName string `tfschema:"resource_group_name"` + Tags map[string]interface{} `tfschema:"tags"` + WANValidationSignedMessage string `tfschema:"wan_validation_signed_message"` + Zones []string `tfschema:"zones"` } var ( @@ -43,7 +43,7 @@ var ( ) type CustomIpPrefixResource struct { - client *network.CustomIPPrefixesClient + client *customipprefixes.CustomIPPrefixesClient } func (CustomIpPrefixResource) ResourceType() string { @@ -149,7 +149,7 @@ func (r CustomIpPrefixResource) Create() sdk.ResourceFunc { Timeout: 9 * time.Hour, Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - r.client = metadata.Client.Network.CustomIPPrefixesClient + r.client = metadata.Client.Network.Client.CustomIPPrefixes subscriptionId := metadata.Client.Account.SubscriptionId deadline, ok := ctx.Deadline() @@ -162,16 +162,16 @@ func (r CustomIpPrefixResource) Create() sdk.ResourceFunc { return fmt.Errorf("decoding: %+v", err) } - id := parse.NewCustomIpPrefixID(subscriptionId, model.ResourceGroupName, model.Name) + id := customipprefixes.NewCustomIPPrefixID(subscriptionId, model.ResourceGroupName, model.Name) - existing, err := r.client.Get(ctx, id.ResourceGroup, id.Name, "") + existing, err := r.client.Get(ctx, id, customipprefixes.DefaultGetOperationOptions()) if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { + if !response.WasNotFound(existing.HttpResponse) { return fmt.Errorf("checking for presence of existing %s: %+v", id, err) } } - if !utils.ResponseWasNotFound(existing.Response) { + if !response.WasNotFound(existing.HttpResponse) { return metadata.ResourceRequiresImport(r.ResourceType(), id) } @@ -180,16 +180,15 @@ func (r CustomIpPrefixResource) Create() sdk.ResourceFunc { return fmt.Errorf("parsing `cidr`: %+v", err) } - results, err := r.client.ListAll(ctx) + results, err := r.client.ListAll(ctx, commonids.NewSubscriptionID(subscriptionId)) if err != nil { return fmt.Errorf("listing existing %s: %+v", id, err) } - // Check for an existing CIDR - for results.NotDone() { - for _, prefix := range results.Values() { - if prefix.CustomIPPrefixPropertiesFormat != nil && prefix.CustomIPPrefixPropertiesFormat.Cidr != nil { - _, netw, err := net.ParseCIDR(*prefix.CustomIPPrefixPropertiesFormat.Cidr) + if prefixes := results.Model; prefixes != nil { + for _, prefix := range *prefixes { + if prefix.Properties != nil && prefix.Properties.Cidr != nil { + _, netw, err := net.ParseCIDR(*prefix.Properties.Cidr) if err != nil { // couldn't parse the existing custom prefix, so skip it continue @@ -199,31 +198,27 @@ func (r CustomIpPrefixResource) Create() sdk.ResourceFunc { } } } - - if err = results.NextWithContext(ctx); err != nil { - return fmt.Errorf("listing next page of %s: %+v", id, err) - } } - properties := network.CustomIPPrefix{ + payload := customipprefixes.CustomIPPrefix{ Name: &model.Name, Location: pointer.To(location.Normalize(model.Location)), - Tags: tags.FromTypedObject(model.Tags), + Tags: tags.Expand(model.Tags), ExtendedLocation: nil, - CustomIPPrefixPropertiesFormat: &network.CustomIPPrefixPropertiesFormat{ + Properties: &customipprefixes.CustomIPPrefixPropertiesFormat{ Cidr: &model.CIDR, - CommissionedState: network.CommissionedStateProvisioning, + CommissionedState: pointer.To(customipprefixes.CommissionedStateProvisioning), }, } if model.ParentCustomIPPrefixID != "" { - properties.CustomIPPrefixPropertiesFormat.CustomIPPrefixParent = &network.SubResource{ - ID: &model.ParentCustomIPPrefixID, + payload.Properties.CustomIPPrefixParent = &customipprefixes.SubResource{ + Id: &model.ParentCustomIPPrefixID, } } if model.WANValidationSignedMessage != "" { - properties.CustomIPPrefixPropertiesFormat.SignedMessage = &model.WANValidationSignedMessage + payload.Properties.SignedMessage = &model.WANValidationSignedMessage } if model.ROAValidityEndDate != "" { @@ -232,25 +227,20 @@ func (r CustomIpPrefixResource) Create() sdk.ResourceFunc { return err } authorizationMessage := fmt.Sprintf("%s|%s|%s", subscriptionId, model.CIDR, roaValidityEndDate.Format("20060102")) - properties.CustomIPPrefixPropertiesFormat.AuthorizationMessage = &authorizationMessage + payload.Properties.AuthorizationMessage = &authorizationMessage } if len(model.Zones) > 0 { - properties.Zones = &model.Zones + payload.Zones = &model.Zones } - future, err := r.client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, properties) - if err != nil { + if err := r.client.CreateOrUpdateThenPoll(ctx, id, payload); err != nil { return fmt.Errorf("creating %s: %+v", id, err) } - if err = future.WaitForCompletionRef(ctx, r.client.Client); err != nil { - return fmt.Errorf("waiting for creation of %s: %+v", id, err) - } - stateConf := &pluginsdk.StateChangeConf{ - Pending: []string{string(network.ProvisioningStateUpdating)}, - Target: []string{string(network.ProvisioningStateSucceeded)}, + Pending: []string{string(customipprefixes.ProvisioningStateUpdating)}, + Target: []string{string(customipprefixes.ProvisioningStateSucceeded)}, Refresh: r.provisioningStateRefreshFunc(ctx, id), MinTimeout: 2 * time.Minute, Timeout: time.Until(deadline), @@ -259,12 +249,12 @@ func (r CustomIpPrefixResource) Create() sdk.ResourceFunc { return fmt.Errorf("waiting for ProvisioningState of %s: %+v", id, err) } - desiredState := network.CommissionedStateProvisioned + desiredState := customipprefixes.CommissionedStateProvisioned if model.CommissioningEnabled { if model.InternetAdvertisingDisabled { - desiredState = network.CommissionedStateCommissionedNoInternetAdvertise + desiredState = customipprefixes.CommissionedStateCommissionedNoInternetAdvertise } else { - desiredState = network.CommissionedStateCommissioned + desiredState = customipprefixes.CommissionedStateCommissioned } } @@ -288,9 +278,9 @@ func (r CustomIpPrefixResource) Update() sdk.ResourceFunc { Timeout: 17 * time.Hour, Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - r.client = metadata.Client.Network.CustomIPPrefixesClient + r.client = metadata.Client.Network.Client.CustomIPPrefixes - id, err := parse.CustomIpPrefixID(metadata.ResourceData.Id()) + id, err := customipprefixes.ParseCustomIPPrefixID(metadata.ResourceData.Id()) if err != nil { return err } @@ -301,12 +291,12 @@ func (r CustomIpPrefixResource) Update() sdk.ResourceFunc { return err } - desiredState := network.CommissionedStateProvisioned + desiredState := customipprefixes.CommissionedStateProvisioned if state.CommissioningEnabled { if state.InternetAdvertisingDisabled { - desiredState = network.CommissionedStateCommissionedNoInternetAdvertise + desiredState = customipprefixes.CommissionedStateCommissionedNoInternetAdvertise } else { - desiredState = network.CommissionedStateCommissioned + desiredState = customipprefixes.CommissionedStateCommissioned } } @@ -329,56 +319,59 @@ func (r CustomIpPrefixResource) Read() sdk.ResourceFunc { Timeout: 5 * time.Minute, Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - r.client = metadata.Client.Network.CustomIPPrefixesClient + r.client = metadata.Client.Network.Client.CustomIPPrefixes - id, err := parse.CustomIpPrefixID(metadata.ResourceData.Id()) + id, err := customipprefixes.ParseCustomIPPrefixID(metadata.ResourceData.Id()) if err != nil { return err } - existing, err := r.client.Get(ctx, id.ResourceGroup, id.Name, "") + existing, err := r.client.Get(ctx, *id, customipprefixes.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(existing.Response) { + if response.WasNotFound(existing.HttpResponse) { return metadata.MarkAsGone(id) } return fmt.Errorf("retrieving %s: %+v", id, err) } - model := CustomIpPrefixModel{ - Name: id.Name, - ResourceGroupName: id.ResourceGroup, - Location: location.NormalizeNilable(existing.Location), - Tags: tags.ToTypedObject(existing.Tags), - Zones: pointer.From(existing.Zones), + state := CustomIpPrefixModel{ + Name: id.CustomIPPrefixName, + ResourceGroupName: id.ResourceGroupName, } - if props := existing.CustomIPPrefixPropertiesFormat; props != nil { - model.CIDR = pointer.From(props.Cidr) - model.InternetAdvertisingDisabled = pointer.From(props.NoInternetAdvertise) - model.WANValidationSignedMessage = pointer.From(props.SignedMessage) + if model := existing.Model; model != nil { + state.Location = location.NormalizeNilable(model.Location) + state.Tags = tags.Flatten(model.Tags) + state.Zones = pointer.From(model.Zones) - if parent := props.CustomIPPrefixParent; parent != nil { - model.ParentCustomIPPrefixID = pointer.From(parent.ID) - } + if props := model.Properties; props != nil { + state.CIDR = pointer.From(props.Cidr) + state.InternetAdvertisingDisabled = pointer.From(props.NoInternetAdvertise) + state.WANValidationSignedMessage = pointer.From(props.SignedMessage) - if props.AuthorizationMessage != nil { - authMessage := strings.Split(*props.AuthorizationMessage, "|") - if len(authMessage) == 3 { - if roaValidityEndDate, err := time.Parse("20060102", authMessage[2]); err == nil { - model.ROAValidityEndDate = roaValidityEndDate.Format("2006-01-02") + if parent := props.CustomIPPrefixParent; parent != nil { + state.ParentCustomIPPrefixID = pointer.From(parent.Id) + } + + if props.AuthorizationMessage != nil { + authMessage := strings.Split(*props.AuthorizationMessage, "|") + if len(authMessage) == 3 { + if roaValidityEndDate, err := time.Parse("20060102", authMessage[2]); err == nil { + state.ROAValidityEndDate = roaValidityEndDate.Format("2006-01-02") + } } } - } - switch props.CommissionedState { - case network.CommissionedStateCommissioning, network.CommissionedStateCommissioned, network.CommissionedStateCommissionedNoInternetAdvertise: - model.CommissioningEnabled = true - default: - model.CommissioningEnabled = false + switch pointer.From(props.CommissionedState) { + case customipprefixes.CommissionedStateCommissioning, customipprefixes.CommissionedStateCommissioned, customipprefixes.CommissionedStateCommissionedNoInternetAdvertise: + state.CommissioningEnabled = true + default: + state.CommissioningEnabled = false + } } } - return metadata.Encode(&model) + return metadata.Encode(&state) }, } } @@ -388,35 +381,30 @@ func (r CustomIpPrefixResource) Delete() sdk.ResourceFunc { Timeout: 17 * time.Hour, Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - r.client = metadata.Client.Network.CustomIPPrefixesClient + r.client = metadata.Client.Network.Client.CustomIPPrefixes - id, err := parse.CustomIpPrefixID(metadata.ResourceData.Id()) + id, err := customipprefixes.ParseCustomIPPrefixID(metadata.ResourceData.Id()) if err != nil { return err } // Must be de-provisioned before deleting - if _, err = r.updateCommissionedState(ctx, *id, network.CommissionedStateDeprovisioned); err != nil { + if _, err = r.updateCommissionedState(ctx, *id, customipprefixes.CommissionedStateDeprovisioned); err != nil { return err } - future, err := r.client.Delete(ctx, id.ResourceGroup, id.Name) - if err != nil { + if err := r.client.DeleteThenPoll(ctx, *id); err != nil { return fmt.Errorf("deleting %s: %+v", id, err) } - if err = future.WaitForCompletionRef(ctx, r.client.Client); err != nil { - return fmt.Errorf("waiting for deletion of %s: %+v", *id, err) - } - return nil }, } } -type commissionedStates []network.CommissionedState +type commissionedStates []customipprefixes.CommissionedState -func (t commissionedStates) contains(i network.CommissionedState) bool { +func (t commissionedStates) contains(i customipprefixes.CommissionedState) bool { for _, s := range t { if i == s { return true @@ -434,78 +422,81 @@ func (t commissionedStates) strings() (out []string) { // updateCommissionedState implements a state machine to coordinate transitions between different values of CommissionedState for both v4 and v6 prefixes. // The provided desiredState should be the sought after end state, and the method will work out a path to achieving that state and walk the resource to get there. -func (r CustomIpPrefixResource) updateCommissionedState(ctx context.Context, id parse.CustomIpPrefixId, desiredState network.CommissionedState) (*network.CommissionedState, error) { - existing, err := r.client.Get(ctx, id.ResourceGroup, id.Name, "") +func (r CustomIpPrefixResource) updateCommissionedState(ctx context.Context, id customipprefixes.CustomIPPrefixId, desiredState customipprefixes.CommissionedState) (*customipprefixes.CommissionedState, error) { + existing, err := r.client.Get(ctx, id, customipprefixes.DefaultGetOperationOptions()) if err != nil { return nil, fmt.Errorf("retrieving existing %s: %+v", id, err) } - if existing.CustomIPPrefixPropertiesFormat == nil { + if existing.Model == nil { + return nil, fmt.Errorf("retrieving existing %s: `model` was nil", id) + } + if existing.Model.Properties == nil { return nil, fmt.Errorf("retrieving existing %s: `properties` was nil", id) } - initialState := existing.CustomIPPrefixPropertiesFormat.CommissionedState + initialState := existing.Model.Properties.CommissionedState - log.Printf("[DEBUG] Updating CommissionedState for %s from current value %q to desired value %q..", id, initialState, desiredState) + log.Printf("[DEBUG] Updating CommissionedState for %s from current value %q to desired value %q..", id, *initialState, desiredState) // stateTree is a map of desired state, to a map of current state, to the list of transition states needed to get there - stateTree := map[network.CommissionedState]map[network.CommissionedState][]network.CommissionedState{ - network.CommissionedStateDeprovisioned: { - network.CommissionedStateProvisioned: {network.CommissionedStateDeprovisioning}, - network.CommissionedStateCommissioned: {network.CommissionedStateDecommissioning, network.CommissionedStateDeprovisioning}, - network.CommissionedStateCommissionedNoInternetAdvertise: {network.CommissionedStateDecommissioning, network.CommissionedStateDeprovisioning}, + stateTree := map[customipprefixes.CommissionedState]map[customipprefixes.CommissionedState][]customipprefixes.CommissionedState{ + customipprefixes.CommissionedStateDeprovisioned: { + customipprefixes.CommissionedStateProvisioned: {customipprefixes.CommissionedStateDeprovisioning}, + customipprefixes.CommissionedStateCommissioned: {customipprefixes.CommissionedStateDecommissioning, customipprefixes.CommissionedStateDeprovisioning}, + customipprefixes.CommissionedStateCommissionedNoInternetAdvertise: {customipprefixes.CommissionedStateDecommissioning, customipprefixes.CommissionedStateDeprovisioning}, }, - network.CommissionedStateProvisioned: { - network.CommissionedStateDeprovisioned: {network.CommissionedStateProvisioning}, - network.CommissionedStateCommissioned: {network.CommissionedStateDecommissioning}, - network.CommissionedStateCommissionedNoInternetAdvertise: {network.CommissionedStateDecommissioning}, + customipprefixes.CommissionedStateProvisioned: { + customipprefixes.CommissionedStateDeprovisioned: {customipprefixes.CommissionedStateProvisioning}, + customipprefixes.CommissionedStateCommissioned: {customipprefixes.CommissionedStateDecommissioning}, + customipprefixes.CommissionedStateCommissionedNoInternetAdvertise: {customipprefixes.CommissionedStateDecommissioning}, }, - network.CommissionedStateCommissioned: { - network.CommissionedStateDeprovisioned: {network.CommissionedStateProvisioning, network.CommissionedStateCommissioning}, - network.CommissionedStateProvisioned: {network.CommissionedStateCommissioning}, - network.CommissionedStateCommissionedNoInternetAdvertise: {network.CommissionedStateCommissioning}, + customipprefixes.CommissionedStateCommissioned: { + customipprefixes.CommissionedStateDeprovisioned: {customipprefixes.CommissionedStateProvisioning, customipprefixes.CommissionedStateCommissioning}, + customipprefixes.CommissionedStateProvisioned: {customipprefixes.CommissionedStateCommissioning}, + customipprefixes.CommissionedStateCommissionedNoInternetAdvertise: {customipprefixes.CommissionedStateCommissioning}, }, - network.CommissionedStateCommissionedNoInternetAdvertise: { - network.CommissionedStateDeprovisioned: {network.CommissionedStateProvisioning, network.CommissionedStateCommissioning}, - network.CommissionedStateProvisioned: {network.CommissionedStateCommissioning}, - network.CommissionedStateCommissioned: {network.CommissionedStateDecommissioning, network.CommissionedStateCommissioning}, + customipprefixes.CommissionedStateCommissionedNoInternetAdvertise: { + customipprefixes.CommissionedStateDeprovisioned: {customipprefixes.CommissionedStateProvisioning, customipprefixes.CommissionedStateCommissioning}, + customipprefixes.CommissionedStateProvisioned: {customipprefixes.CommissionedStateCommissioning}, + customipprefixes.CommissionedStateCommissioned: {customipprefixes.CommissionedStateDecommissioning, customipprefixes.CommissionedStateCommissioning}, }, } // transitioningStatesFor returns the known transitioning states for the desired goal state - transitioningStatesFor := func(finalState network.CommissionedState) (out commissionedStates) { + transitioningStatesFor := func(finalState customipprefixes.CommissionedState) (out commissionedStates) { switch finalState { - case network.CommissionedStateProvisioned: - out = commissionedStates{network.CommissionedStateProvisioning, network.CommissionedStateDecommissioning} - case network.CommissionedStateDeprovisioned: - out = commissionedStates{network.CommissionedStateDeprovisioning} - case network.CommissionedStateCommissioned: - out = commissionedStates{network.CommissionedStateCommissioning} + case customipprefixes.CommissionedStateProvisioned: + out = commissionedStates{customipprefixes.CommissionedStateProvisioning, customipprefixes.CommissionedStateDecommissioning} + case customipprefixes.CommissionedStateDeprovisioned: + out = commissionedStates{customipprefixes.CommissionedStateDeprovisioning} + case customipprefixes.CommissionedStateCommissioned: + out = commissionedStates{customipprefixes.CommissionedStateCommissioning} } return } // finalStatesFor returns the known final states for the current transitioning state - finalStatesFor := func(transitioningState network.CommissionedState) (out commissionedStates) { + finalStatesFor := func(transitioningState customipprefixes.CommissionedState) (out commissionedStates) { switch transitioningState { - case network.CommissionedStateProvisioning: - out = commissionedStates{network.CommissionedStateProvisioned} - case network.CommissionedStateDeprovisioning: - out = commissionedStates{network.CommissionedStateDeprovisioned} - case network.CommissionedStateCommissioning: - out = commissionedStates{network.CommissionedStateCommissioned, network.CommissionedStateCommissionedNoInternetAdvertise} - case network.CommissionedStateDecommissioning: - out = commissionedStates{network.CommissionedStateProvisioned} + case customipprefixes.CommissionedStateProvisioning: + out = commissionedStates{customipprefixes.CommissionedStateProvisioned} + case customipprefixes.CommissionedStateDeprovisioning: + out = commissionedStates{customipprefixes.CommissionedStateDeprovisioned} + case customipprefixes.CommissionedStateCommissioning: + out = commissionedStates{customipprefixes.CommissionedStateCommissioned, customipprefixes.CommissionedStateCommissionedNoInternetAdvertise} + case customipprefixes.CommissionedStateDecommissioning: + out = commissionedStates{customipprefixes.CommissionedStateProvisioned} } return } // shouldNotAdvertise determines whether to set the noInternetAdvertise flag, which can only be set at the point of transitioning to `Commissioning` - shouldNotAdvertise := func(steppingState network.CommissionedState) *bool { - if steppingState == network.CommissionedStateCommissioning { + shouldNotAdvertise := func(steppingState customipprefixes.CommissionedState) *bool { + if steppingState == customipprefixes.CommissionedStateCommissioning { switch desiredState { - case network.CommissionedStateCommissioned: + case customipprefixes.CommissionedStateCommissioned: return pointer.To(false) - case network.CommissionedStateCommissionedNoInternetAdvertise: + case customipprefixes.CommissionedStateCommissionedNoInternetAdvertise: return pointer.To(true) } } @@ -513,10 +504,10 @@ func (r CustomIpPrefixResource) updateCommissionedState(ctx context.Context, id } if plan, ok := stateTree[desiredState]; ok { - lastKnownState := pointer.To(initialState) + lastKnownState := initialState // If we're already transitioning to the desiredState, wait for this to complete - if transitioningStatesFor(desiredState).contains(initialState) { + if transitioningStatesFor(desiredState).contains(pointer.From(initialState)) { if lastKnownState, err = r.waitForCommissionedState(ctx, id, transitioningStatesFor(desiredState), commissionedStates{desiredState}); err != nil { return lastKnownState, err } @@ -578,28 +569,26 @@ func (r CustomIpPrefixResource) updateCommissionedState(ctx context.Context, id // setCommissionedState sends a PUT request to effect a transition to a different CommissionedState. The provided // desiredState should always be a contextual transition state rather than the desired end state (i.e. procedural). -func (r CustomIpPrefixResource) setCommissionedState(ctx context.Context, id parse.CustomIpPrefixId, desiredState network.CommissionedState, noInternetAdvertise *bool) error { - existing, err := r.client.Get(ctx, id.ResourceGroup, id.Name, "") +func (r CustomIpPrefixResource) setCommissionedState(ctx context.Context, id customipprefixes.CustomIPPrefixId, desiredState customipprefixes.CommissionedState, noInternetAdvertise *bool) error { + existing, err := r.client.Get(ctx, id, customipprefixes.DefaultGetOperationOptions()) if err != nil { return fmt.Errorf("retrieving existing %s: %+v", id, err) } - if existing.CustomIPPrefixPropertiesFormat == nil { + if existing.Model == nil { + return fmt.Errorf("retrieving existing %s: `model` was nil", id) + } + if existing.Model.Properties == nil { return fmt.Errorf("retrieving existing %s: `properties` was nil", id) } - existing.CustomIPPrefixPropertiesFormat.CommissionedState = desiredState - existing.CustomIPPrefixPropertiesFormat.NoInternetAdvertise = noInternetAdvertise + existing.Model.Properties.CommissionedState = pointer.To(desiredState) + existing.Model.Properties.NoInternetAdvertise = noInternetAdvertise log.Printf("[DEBUG] Updating the CommissionedState field to %q for %s..", desiredState, id) - future, err := r.client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, existing) - if err != nil { + if err := r.client.CreateOrUpdateThenPoll(ctx, id, *existing.Model); err != nil { return fmt.Errorf("updating CommissionedState to %q for %s: %+v", desiredState, id, err) } - if err := future.WaitForCompletionRef(ctx, r.client.Client); err != nil { - return fmt.Errorf("waiting for the update of CommissionedState to %q for %s: %+v", desiredState, id, err) - } - return nil } @@ -607,7 +596,7 @@ func (r CustomIpPrefixResource) setCommissionedState(ctx context.Context, id par // consecutive polls, also returning an error if a state is reached that isn't in pendingStates or targetStates. Waits // for 10 minutes before polling to account for delays in the service reporting the actual latest state, since this // method is usually called soon after setting a new CommissionedState (known service bug). -func (r CustomIpPrefixResource) waitForCommissionedState(ctx context.Context, id parse.CustomIpPrefixId, pendingStates, targetStates commissionedStates) (*network.CommissionedState, error) { +func (r CustomIpPrefixResource) waitForCommissionedState(ctx context.Context, id customipprefixes.CustomIPPrefixId, pendingStates, targetStates commissionedStates) (*customipprefixes.CommissionedState, error) { log.Printf("[DEBUG] Polling for the CommissionedState field for %s..", id) timeout, ok := ctx.Deadline() if !ok { @@ -632,40 +621,54 @@ func (r CustomIpPrefixResource) waitForCommissionedState(ctx context.Context, id return nil, fmt.Errorf("retrieving %s: response was nil", id) } - prefix, ok := result.(network.CustomIPPrefix) + prefix, ok := result.(customipprefixes.CustomIPPrefix) if !ok { return nil, fmt.Errorf("retrieving %s: response was not a valid Custom IP Prefix", id) } - if prefix.CustomIPPrefixPropertiesFormat == nil { - return &prefix.CustomIPPrefixPropertiesFormat.CommissionedState, fmt.Errorf("retrieving %s: `properties` was nil", id) + if prefix.Properties == nil { + return prefix.Properties.CommissionedState, fmt.Errorf("retrieving %s: `properties` was nil", id) } if err != nil { - return &prefix.CustomIPPrefixPropertiesFormat.CommissionedState, fmt.Errorf("waiting for CommissionedState of %s: %+v", id, err) + return prefix.Properties.CommissionedState, fmt.Errorf("waiting for CommissionedState of %s: %+v", id, err) } - return &prefix.CustomIPPrefixPropertiesFormat.CommissionedState, nil + return prefix.Properties.CommissionedState, nil } -func (r CustomIpPrefixResource) commissionedStateRefreshFunc(ctx context.Context, id parse.CustomIpPrefixId) pluginsdk.StateRefreshFunc { +func (r CustomIpPrefixResource) commissionedStateRefreshFunc(ctx context.Context, id customipprefixes.CustomIPPrefixId) pluginsdk.StateRefreshFunc { return func() (interface{}, string, error) { - res, err := r.client.Get(ctx, id.ResourceGroup, id.Name, "") + res, err := r.client.Get(ctx, id, customipprefixes.DefaultGetOperationOptions()) if err != nil { - return nil, "", fmt.Errorf("polling for %s: %+v", id.String(), err) + return nil, "", fmt.Errorf("polling for %s: %+v", id, err) } - return res, string(res.CommissionedState), nil + if res.Model == nil { + return nil, "", fmt.Errorf("polling for %s: `model` was nil", id) + } + if res.Model.Properties == nil { + return nil, "", fmt.Errorf("polling for %s: `properties` was nil", id) + } + + return res, string(pointer.From(res.Model.Properties.CommissionedState)), nil } } -func (r CustomIpPrefixResource) provisioningStateRefreshFunc(ctx context.Context, id parse.CustomIpPrefixId) pluginsdk.StateRefreshFunc { +func (r CustomIpPrefixResource) provisioningStateRefreshFunc(ctx context.Context, id customipprefixes.CustomIPPrefixId) pluginsdk.StateRefreshFunc { return func() (interface{}, string, error) { - res, err := r.client.Get(ctx, id.ResourceGroup, id.Name, "") + res, err := r.client.Get(ctx, id, customipprefixes.DefaultGetOperationOptions()) if err != nil { - return nil, "", fmt.Errorf("polling for %s: %+v", id.String(), err) + return nil, "", fmt.Errorf("polling for %s: %+v", id, err) + } + + if res.Model == nil { + return nil, "", fmt.Errorf("polling for %s: `model` was nil", id) + } + if res.Model.Properties == nil { + return nil, "", fmt.Errorf("polling for %s: `properties` was nil", id) } - return res, string(res.ProvisioningState), nil + return res, string(pointer.From(res.Model.Properties.ProvisioningState)), nil } } diff --git a/internal/services/network/custom_ip_prefix_resource_test.go b/internal/services/network/custom_ip_prefix_resource_test.go index 35429dedc1ba..0366e00678b5 100644 --- a/internal/services/network/custom_ip_prefix_resource_test.go +++ b/internal/services/network/custom_ip_prefix_resource_test.go @@ -8,12 +8,13 @@ import ( "fmt" "testing" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/customipprefixes" "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/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) type CustomIpPrefixResource struct{} @@ -125,21 +126,21 @@ func testAccCustomIpPrefix_ipv6(t *testing.T) { } func (CustomIpPrefixResource) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.CustomIpPrefixID(state.ID) + id, err := customipprefixes.ParseCustomIPPrefixID(state.ID) if err != nil { return nil, err } - resp, err := client.Network.CustomIPPrefixesClient.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := client.Network.Client.CustomIPPrefixes.Get(ctx, *id, customipprefixes.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return utils.Bool(false), nil + if response.WasNotFound(resp.HttpResponse) { + return pointer.To(false), nil } return nil, fmt.Errorf("retrieving %s: %+v", *id, err) } - return utils.Bool(true), nil + return pointer.To(true), nil } func (r CustomIpPrefixResource) ipv4Provisioned(data acceptance.TestData) string { diff --git a/internal/services/network/custompollers/local_network_gateway_poller.go b/internal/services/network/custompollers/local_network_gateway_poller.go new file mode 100644 index 000000000000..9278d861f551 --- /dev/null +++ b/internal/services/network/custompollers/local_network_gateway_poller.go @@ -0,0 +1,53 @@ +package custompollers + +import ( + "context" + "fmt" + "strings" + "time" + + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/localnetworkgateways" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" +) + +var _ pollers.PollerType = &localNetworkGatewayPoller{} + +type localNetworkGatewayPoller struct { + client *localnetworkgateways.LocalNetworkGatewaysClient + id localnetworkgateways.LocalNetworkGatewayId +} + +var ( + pollingSuccess = pollers.PollResult{ + Status: pollers.PollingStatusSucceeded, + PollInterval: 10 * time.Second, + } + pollingInProgress = pollers.PollResult{ + Status: pollers.PollingStatusInProgress, + PollInterval: 10 * time.Second, + } +) + +func NewLocalNetworkGatewayPoller(client *localnetworkgateways.LocalNetworkGatewaysClient, id localnetworkgateways.LocalNetworkGatewayId) *localNetworkGatewayPoller { + return &localNetworkGatewayPoller{ + client: client, + id: id, + } +} + +func (p localNetworkGatewayPoller) Poll(ctx context.Context) (*pollers.PollResult, error) { + resp, err := p.client.Get(ctx, p.id) + if err != nil { + return nil, fmt.Errorf("retrieving %s: %+v", p.id, err) + } + + if resp.Model != nil { + if provisioningStatus := resp.Model.Properties.ProvisioningState; provisioningStatus != nil { + if !strings.EqualFold(string(*provisioningStatus), string(pollingSuccess.Status)) { + return &pollingInProgress, nil + } + } + } + + return &pollingSuccess, nil +} diff --git a/internal/services/network/ip_group_cidr_resource.go b/internal/services/network/ip_group_cidr_resource.go index 1c33864d6f43..d41ca930da45 100644 --- a/internal/services/network/ip_group_cidr_resource.go +++ b/internal/services/network/ip_group_cidr_resource.go @@ -8,6 +8,8 @@ import ( "strings" "time" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/ipgroups" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" @@ -17,12 +19,11 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceIpGroupCidr() *pluginsdk.Resource { return &pluginsdk.Resource{ - Create: resourceIpGroupCidrCreateUpdate, + Create: resourceIpGroupCidrCreate, Read: resourceIpGroupCidrRead, Delete: resourceIpGroupCidrDelete, @@ -54,58 +55,58 @@ func resourceIpGroupCidr() *pluginsdk.Resource { } } -func resourceIpGroupCidrCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.IPGroupsClient +func resourceIpGroupCidrCreate(d *pluginsdk.ResourceData, meta interface{}) error { + client := meta.(*clients.Client).Network.Client.IPGroups subscriptionId := meta.(*clients.Client).Account.SubscriptionId - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() cidr := d.Get("cidr").(string) cidrName := strings.ReplaceAll(cidr, "/", "_") - ipGroupId, err := parse.IpGroupID(d.Get("ip_group_id").(string)) + ipGroupId, err := ipgroups.ParseIPGroupID(d.Get("ip_group_id").(string)) if err != nil { return err } - id := parse.NewIpGroupCidrID(subscriptionId, ipGroupId.ResourceGroup, ipGroupId.Name, cidrName) + id := parse.NewIpGroupCidrID(subscriptionId, ipGroupId.ResourceGroupName, ipGroupId.IpGroupName, cidrName) locks.ByID(ipGroupId.ID()) defer locks.UnlockByID(ipGroupId.ID()) - existing, err := client.Get(ctx, ipGroupId.ResourceGroup, ipGroupId.Name, "") + existing, err := client.Get(ctx, *ipGroupId, ipgroups.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(existing.Response) { + if response.WasNotFound(existing.HttpResponse) { return fmt.Errorf("checking for presence of existing %s: %s", ipGroupId, err) } } - if d.IsNewResource() { - if utils.SliceContainsValue(*existing.IPAddresses, cidr) { - return tf.ImportAsExistsError("azurerm_ip_group_cidr", id.ID()) - } + if existing.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", ipGroupId) + } + if existing.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", ipGroupId) + } + + if utils.SliceContainsValue(*existing.Model.Properties.IPAddresses, cidr) { + return tf.ImportAsExistsError("azurerm_ip_group_cidr", id.ID()) } ipAddresses := make([]string, 0) - if existing.IPAddresses != nil { - ipAddresses = *existing.IPAddresses + if existing.Model.Properties.IPAddresses != nil { + ipAddresses = *existing.Model.Properties.IPAddresses } ipAddresses = append(ipAddresses, cidr) - params := network.IPGroup{ - Name: &ipGroupId.Name, - Location: existing.Location, - Tags: existing.Tags, - IPGroupPropertiesFormat: &network.IPGroupPropertiesFormat{ + params := ipgroups.IPGroup{ + Name: &ipGroupId.IpGroupName, + Location: existing.Model.Location, + Tags: existing.Model.Tags, + Properties: &ipgroups.IPGroupPropertiesFormat{ IPAddresses: &ipAddresses, }, } - future, err := client.CreateOrUpdate(ctx, ipGroupId.ResourceGroup, ipGroupId.Name, params) - if err != nil { - return fmt.Errorf("creating/updating %s: %+v", id, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for the completion of %s: %+v", id, err) + if err := client.CreateOrUpdateThenPoll(ctx, *ipGroupId, params); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) } d.SetId(id.ID()) @@ -114,7 +115,7 @@ func resourceIpGroupCidrCreateUpdate(d *pluginsdk.ResourceData, meta interface{} } func resourceIpGroupCidrRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.IPGroupsClient + client := meta.(*clients.Client).Network.Client.IPGroups ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() @@ -122,15 +123,21 @@ func resourceIpGroupCidrRead(d *pluginsdk.ResourceData, meta interface{}) error if err != nil { return err } - ipGroupId := parse.NewIpGroupID(id.SubscriptionId, id.ResourceGroup, id.IpGroupName) + ipGroupId := ipgroups.NewIPGroupID(id.SubscriptionId, id.ResourceGroup, id.IpGroupName) cidr := strings.ReplaceAll(id.CidrName, "_", "/") - resp, err := client.Get(ctx, id.ResourceGroup, id.IpGroupName, "") + resp, err := client.Get(ctx, ipGroupId, ipgroups.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("making Read request on IP Group %q (Resource Group %q): %+v", ipGroupId.Name, ipGroupId.ResourceGroup, err) + if response.WasNotFound(resp.HttpResponse) { + return fmt.Errorf("retrieving %s: %+v", ipGroupId, err) + } + if resp.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", ipGroupId) + } + if resp.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", ipGroupId) } - if !utils.SliceContainsValue(*resp.IPAddresses, cidr) { + if !utils.SliceContainsValue(*resp.Model.Properties.IPAddresses, cidr) { d.SetId("") return nil } @@ -143,45 +150,50 @@ func resourceIpGroupCidrRead(d *pluginsdk.ResourceData, meta interface{}) error } func resourceIpGroupCidrDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.IPGroupsClient + client := meta.(*clients.Client).Network.Client.IPGroups ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - cidr := d.Get("cidr").(string) - ipGroupId, err := parse.IpGroupID(d.Get("ip_group_id").(string)) + id, err := parse.IpGroupCidrID(d.Id()) if err != nil { return err } + // TODO this resource should use a composite resource ID to remove this instance of d.Get() in the Delete + // this file can then be removed from the exceptions list in the run-gradually-deprecated.sh script + cidr := d.Get("cidr").(string) + ipGroupId := ipgroups.NewIPGroupID(id.SubscriptionId, id.ResourceGroup, id.IpGroupName) + locks.ByID(ipGroupId.ID()) defer locks.UnlockByID(ipGroupId.ID()) - existing, err := client.Get(ctx, ipGroupId.ResourceGroup, ipGroupId.Name, "") + existing, err := client.Get(ctx, ipGroupId, ipgroups.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("reading existing %s: %s", ipGroupId, err) + if response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("retrieving %s: %s", ipGroupId, err) } } + if existing.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", ipGroupId) + } + if existing.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", ipGroupId) + } - ipAddresses := *existing.IPAddresses + ipAddresses := *existing.Model.Properties.IPAddresses ipAddresses = utils.RemoveFromStringArray(ipAddresses, cidr) - params := network.IPGroup{ - Name: &ipGroupId.Name, - Location: existing.Location, - Tags: existing.Tags, - IPGroupPropertiesFormat: &network.IPGroupPropertiesFormat{ + params := ipgroups.IPGroup{ + Name: &ipGroupId.IpGroupName, + Location: existing.Model.Location, + Tags: existing.Model.Tags, + Properties: &ipgroups.IPGroupPropertiesFormat{ IPAddresses: &ipAddresses, }, } - future, err := client.CreateOrUpdate(ctx, ipGroupId.ResourceGroup, ipGroupId.Name, params) - if err != nil { - return fmt.Errorf("creating/updating %s: %+v", ipGroupId.ID(), err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("deleting IP Group CIDR %q (IP Group %q - Resource Group %q): %+v", cidr, ipGroupId.Name, ipGroupId.ResourceGroup, err) + if err := client.CreateOrUpdateThenPoll(ctx, ipGroupId, params); err != nil { + return fmt.Errorf("updating %s: %+v", ipGroupId.ID(), err) } return err diff --git a/internal/services/network/ip_group_cidr_resource_test.go b/internal/services/network/ip_group_cidr_resource_test.go index e0ccf0100f3b..272cc4cabc47 100644 --- a/internal/services/network/ip_group_cidr_resource_test.go +++ b/internal/services/network/ip_group_cidr_resource_test.go @@ -8,6 +8,8 @@ import ( "fmt" "testing" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/ipgroups" "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" @@ -79,16 +81,25 @@ func (t IPGroupCidrResource) Exists(ctx context.Context, clients *clients.Client return nil, err } - resp, err := clients.Network.IPGroupsClient.Get(ctx, id.ResourceGroup, id.IpGroupName, "") + ipGroupId := ipgroups.NewIPGroupID(id.SubscriptionId, id.ResourceGroup, id.IpGroupName) + + resp, err := clients.Network.Client.IPGroups.Get(ctx, ipGroupId, ipgroups.DefaultGetOperationOptions()) if err != nil { - return nil, fmt.Errorf("reading IP Group (%s): %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", id, err) + } + + if resp.Model == nil { + return nil, fmt.Errorf("retrieving %s: `model` was nil", ipGroupId) + } + if resp.Model.Properties == nil { + return nil, fmt.Errorf("retrieving %s: `properties` was nil", ipGroupId) } - if !utils.SliceContainsValue(*resp.IPAddresses, state.Attributes["cidr"]) { - return utils.Bool(false), nil + if !utils.SliceContainsValue(*resp.Model.Properties.IPAddresses, state.Attributes["cidr"]) { + return pointer.To(false), nil } - return utils.Bool(true), nil + return pointer.To(true), nil } func (IPGroupCidrResource) basic(data acceptance.TestData) string { diff --git a/internal/services/network/ip_group_data_source.go b/internal/services/network/ip_group_data_source.go index 12084aed7d9a..bed3f7543251 100644 --- a/internal/services/network/ip_group_data_source.go +++ b/internal/services/network/ip_group_data_source.go @@ -7,14 +7,14 @@ 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-helpers/resourcemanager/tags" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/ipgroups" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) func dataSourceIpGroup() *pluginsdk.Resource { @@ -42,45 +42,43 @@ func dataSourceIpGroup() *pluginsdk.Resource { Set: pluginsdk.HashString, }, - "tags": tags.SchemaDataSource(), + "tags": commonschema.TagsDataSource(), }, } } func dataSourceIpGroupRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.IPGroupsClient + client := meta.(*clients.Client).Network.Client.IPGroups subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id := parse.NewIpGroupID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + id := ipgroups.NewIPGroupID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) - resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := client.Get(ctx, id, ipgroups.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 %s: %+v", id, err) + return fmt.Errorf("retrieving %s: %+v", id, err) } - if resp.ID == nil || *resp.ID == "" { - return fmt.Errorf("reading request on %s: %+v", id, err) - } d.SetId(id.ID()) - d.Set("name", resp.Name) - d.Set("resource_group_name", id.ResourceGroup) - - d.Set("location", location.NormalizeNilable(resp.Location)) - - if props := resp.IPGroupPropertiesFormat; props != nil { - if props.IPAddresses == nil { - return fmt.Errorf("list of ipAddresses returned is nil") - } - if err := d.Set("cidrs", props.IPAddresses); err != nil { - return fmt.Errorf("setting `cidrs`: %+v", err) + d.Set("name", id.IpGroupName) + d.Set("resource_group_name", id.ResourceGroupName) + + if model := resp.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) + if props := model.Properties; props != nil { + if props.IPAddresses == nil { + return fmt.Errorf("list of ipAddresses returned is nil") + } + if err := d.Set("cidrs", props.IPAddresses); err != nil { + return fmt.Errorf("setting `cidrs`: %+v", err) + } } + return tags.FlattenAndSet(d, model.Tags) } - - return tags.FlattenAndSet(d, resp.Tags) + return nil } diff --git a/internal/services/network/ip_group_resource.go b/internal/services/network/ip_group_resource.go index d22855d315c7..1f924c616c92 100644 --- a/internal/services/network/ip_group_resource.go +++ b/internal/services/network/ip_group_resource.go @@ -9,21 +9,21 @@ import ( "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-helpers/resourcemanager/tags" "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/azurefirewalls" "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/firewallpolicies" - "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/ipgroups" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" "github.com/hashicorp/terraform-provider-azurerm/internal/services/firewall" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "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" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceIpGroup() *pluginsdk.Resource { @@ -34,7 +34,7 @@ func resourceIpGroup() *pluginsdk.Resource { Delete: resourceIpGroupDelete, Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := parse.IpGroupID(id) + _, err := ipgroups.ParseIPGroupID(id) return err }), @@ -82,15 +82,15 @@ func resourceIpGroup() *pluginsdk.Resource { Set: pluginsdk.HashString, }, - "tags": tags.Schema(), + "tags": commonschema.Tags(), }, } } func resourceIpGroupCreate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.IPGroupsClient + client := meta.(*clients.Client).Network.Client.IPGroups subscriptionId := meta.(*clients.Client).Account.SubscriptionId - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() for _, fw := range d.Get("firewall_ids").([]interface{}) { @@ -111,44 +111,35 @@ func resourceIpGroupCreate(d *pluginsdk.ResourceData, meta interface{}) error { defer locks.UnlockByName(id.FirewallPolicyName, firewall.AzureFirewallPolicyResourceName) } - id := parse.NewIpGroupID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + id := ipgroups.NewIPGroupID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) locks.ByID(id.ID()) defer locks.UnlockByID(id.ID()) - if d.IsNewResource() { - existing, err := client.Get(ctx, id.ResourceGroup, id.Name, "") - if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("checking for presence of existing %s: %s", id, err) - } + existing, err := client.Get(ctx, id, ipgroups.DefaultGetOperationOptions()) + if err != nil { + if !response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("checking for presence of existing %s: %s", id, err) } + } - if !utils.ResponseWasNotFound(existing.Response) { - return tf.ImportAsExistsError("azurerm_ip_group", id.ID()) - } + if !response.WasNotFound(existing.HttpResponse) { + return tf.ImportAsExistsError("azurerm_ip_group", id.ID()) } - location := azure.NormalizeLocation(d.Get("location").(string)) - t := d.Get("tags").(map[string]interface{}) ipAddresses := d.Get("cidrs").(*pluginsdk.Set).List() - sg := network.IPGroup{ - Name: &id.Name, - Location: &location, - IPGroupPropertiesFormat: &network.IPGroupPropertiesFormat{ + sg := ipgroups.IPGroup{ + Name: &id.IpGroupName, + Location: pointer.To(location.Normalize(d.Get("location").(string))), + Properties: &ipgroups.IPGroupPropertiesFormat{ IPAddresses: utils.ExpandStringSlice(ipAddresses), }, - Tags: tags.Expand(t), + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, sg) - if err != nil { - return fmt.Errorf("creating/updating %s: %+v", id, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for the completion of %s: %+v", id, err) + if err := client.CreateOrUpdateThenPoll(ctx, id, sg); err != nil { + return fmt.Errorf("creating %s: %+v", id, err) } d.SetId(id.ID()) @@ -157,66 +148,66 @@ func resourceIpGroupCreate(d *pluginsdk.ResourceData, meta interface{}) error { } func resourceIpGroupRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.IPGroupsClient + client := meta.(*clients.Client).Network.Client.IPGroups ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.IpGroupID(d.Id()) + id, err := ipgroups.ParseIPGroupID(d.Id()) if err != nil { return err } - resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := client.Get(ctx, *id, ipgroups.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 IP Group %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", id, err) } - d.Set("name", resp.Name) - d.Set("resource_group_name", id.ResourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } + d.Set("name", id.IpGroupName) + d.Set("resource_group_name", id.ResourceGroupName) - if props := resp.IPGroupPropertiesFormat; props != nil { - if props.IPAddresses == nil { - return fmt.Errorf("list of ipAddresses returned is nil") - } - if err := d.Set("cidrs", props.IPAddresses); err != nil { - return fmt.Errorf("setting `cidrs`: %+v", err) - } - } + if model := resp.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) - firewallIDs := make([]string, 0) - for _, idStr := range getIds(resp.Firewalls) { - firewallID, err := azurefirewalls.ParseAzureFirewallIDInsensitively(idStr) - if err != nil { - return fmt.Errorf("parsing Azure Firewall ID %q: %+v", idStr, err) - } - firewallIDs = append(firewallIDs, firewallID.ID()) - } - d.Set("firewall_ids", firewallIDs) + if props := model.Properties; props != nil { + if props.IPAddresses == nil { + return fmt.Errorf("list of ipAddresses returned is nil") + } + if err := d.Set("cidrs", props.IPAddresses); err != nil { + return fmt.Errorf("setting `cidrs`: %+v", err) + } - firewallPolicyIDs := make([]string, 0) - for _, idStr := range getIds(resp.FirewallPolicies) { - policyID, err := firewallpolicies.ParseFirewallPolicyIDInsensitively(idStr) - if err != nil { - return fmt.Errorf("parsing Azure Firewall Policy ID %q: %+v", idStr, err) + firewallIDs := make([]string, 0) + for _, idStr := range getIds(props.Firewalls) { + firewallID, err := azurefirewalls.ParseAzureFirewallIDInsensitively(idStr) + if err != nil { + return fmt.Errorf("parsing Azure Firewall ID %q: %+v", idStr, err) + } + firewallIDs = append(firewallIDs, firewallID.ID()) + } + d.Set("firewall_ids", firewallIDs) + + firewallPolicyIDs := make([]string, 0) + for _, idStr := range getIds(props.FirewallPolicies) { + policyID, err := firewallpolicies.ParseFirewallPolicyIDInsensitively(idStr) + if err != nil { + return fmt.Errorf("parsing Azure Firewall Policy ID %q: %+v", idStr, err) + } + firewallPolicyIDs = append(firewallPolicyIDs, policyID.ID()) + } + d.Set("firewall_policy_ids", firewallPolicyIDs) } - firewallPolicyIDs = append(firewallPolicyIDs, policyID.ID()) + return tags.FlattenAndSet(d, model.Tags) } - d.Set("firewall_policy_ids", firewallPolicyIDs) - - return tags.FlattenAndSet(d, resp.Tags) + return nil } func resourceIpGroupUpdate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.IPGroupsClient - subscriptionId := meta.(*clients.Client).Account.SubscriptionId - ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) + client := meta.(*clients.Client).Network.Client.IPGroups + ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) defer cancel() for _, fw := range d.Get("firewall_ids").([]interface{}) { @@ -237,37 +228,42 @@ func resourceIpGroupUpdate(d *pluginsdk.ResourceData, meta interface{}) error { defer locks.UnlockByName(id.FirewallPolicyName, firewall.AzureFirewallPolicyResourceName) } - id := parse.NewIpGroupID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + id, err := ipgroups.ParseIPGroupID(d.Id()) + if err != nil { + return err + } locks.ByID(id.ID()) defer locks.UnlockByID(id.ID()) - exisiting, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + existing, err := client.Get(ctx, *id, ipgroups.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(exisiting.Response) { + if response.WasNotFound(existing.HttpResponse) { d.SetId("") return nil } - return fmt.Errorf("making Read request on IP Group %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", id, err) } - if d.HasChange("cidrs") { - if exisiting.IPGroupPropertiesFormat != nil { - exisiting.IPGroupPropertiesFormat.IPAddresses = utils.ExpandStringSlice(d.Get("cidrs").(*pluginsdk.Set).List()) - } + if existing.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", id) + } + if existing.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", id) } - if d.HasChange("tags") { - exisiting.Tags = tags.Expand(d.Get("tags").(map[string]interface{})) + payload := existing.Model + + if d.HasChange("cidrs") { + payload.Properties.IPAddresses = utils.ExpandStringSlice(d.Get("cidrs").(*pluginsdk.Set).List()) } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, exisiting) - if err != nil { - return fmt.Errorf("creating/updating %s: %+v", id, err) + if d.HasChange("tags") { + payload.Tags = tags.Expand(d.Get("tags").(map[string]interface{})) } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for the completion of %s: %+v", id, err) + if err := client.CreateOrUpdateThenPoll(ctx, *id, *payload); err != nil { + return fmt.Errorf("updating %s: %+v", id, err) } d.SetId(id.ID()) @@ -275,29 +271,29 @@ func resourceIpGroupUpdate(d *pluginsdk.ResourceData, meta interface{}) error { return resourceIpGroupRead(d, meta) } -func getIds(subResource *[]network.SubResource) []string { +func getIds(subResource *[]ipgroups.SubResource) []string { if subResource == nil { return nil } ids := make([]string, 0) for _, v := range *subResource { - if v.ID == nil { + if v.Id == nil { continue } - ids = append(ids, *v.ID) + ids = append(ids, *v.Id) } return ids } func resourceIpGroupDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.IPGroupsClient + client := meta.(*clients.Client).Network.Client.IPGroups ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.IpGroupID(d.Id()) + id, err := ipgroups.ParseIPGroupID(d.Id()) if err != nil { return err } @@ -305,42 +301,42 @@ func resourceIpGroupDelete(d *pluginsdk.ResourceData, meta interface{}) error { locks.ByID(id.ID()) defer locks.UnlockByID(id.ID()) - read, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := client.Get(ctx, *id, ipgroups.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(read.Response) { - // deleted outside of TF - log.Printf("[DEBUG] IP Group %q was not found in Resource Group %q - assuming removed!", id.Name, id.ResourceGroup) + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[DEBUG] %s was not found - removing from state!", id) return nil } + return fmt.Errorf("retrieving %s : %+v", *id, err) + } - return fmt.Errorf("retrieving ip group %s : %+v", *id, err) + if resp.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", id) + } + if resp.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", id) } - for _, fw := range *read.Firewalls { - fwID, err := azurefirewalls.ParseAzureFirewallID(pointer.From(fw.ID)) + for _, fw := range *resp.Model.Properties.Firewalls { + fwID, err := azurefirewalls.ParseAzureFirewallID(pointer.From(fw.Id)) if err != nil { - return fmt.Errorf("parsing Azure Firewall ID %q: %+v", pointer.From(fw.ID), err) + return fmt.Errorf("parsing Azure Firewall ID %q: %+v", pointer.From(fw.Id), err) } locks.ByName(fwID.AzureFirewallName, firewall.AzureFirewallResourceName) defer locks.UnlockByName(fwID.AzureFirewallName, firewall.AzureFirewallResourceName) } - for _, fwpol := range *read.FirewallPolicies { - polID, err := firewallpolicies.ParseFirewallPolicyID(pointer.From(fwpol.ID)) + for _, fwpol := range *resp.Model.Properties.FirewallPolicies { + polID, err := firewallpolicies.ParseFirewallPolicyID(pointer.From(fwpol.Id)) if err != nil { - return fmt.Errorf("parsing Azure Firewall Policy ID %q: %+v", *fwpol.ID, err) + return fmt.Errorf("parsing Azure Firewall Policy ID %q: %+v", *fwpol.Id, err) } locks.ByName(polID.FirewallPolicyName, firewall.AzureFirewallPolicyResourceName) defer locks.UnlockByName(polID.FirewallPolicyName, firewall.AzureFirewallPolicyResourceName) } - future, err := client.Delete(ctx, id.ResourceGroup, id.Name) - if err != nil { - return fmt.Errorf("deleting IP Group %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("deleting IP Group %q (Resource Group %q): %+v", id.Name, id.ResourceGroup, err) + if err := client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", id, err) } return err diff --git a/internal/services/network/ip_group_resource_test.go b/internal/services/network/ip_group_resource_test.go index 93ef90d31384..ae10ed8e2702 100644 --- a/internal/services/network/ip_group_resource_test.go +++ b/internal/services/network/ip_group_resource_test.go @@ -8,12 +8,12 @@ import ( "fmt" "testing" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/ipgroups" "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/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) type IPGroupResource struct{} @@ -141,17 +141,17 @@ func TestAccIpGroup_updateWithAttachedPolicy(t *testing.T) { } func (t IPGroupResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.IpGroupID(state.ID) + id, err := ipgroups.ParseIPGroupID(state.ID) if err != nil { return nil, err } - resp, err := clients.Network.IPGroupsClient.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := clients.Network.Client.IPGroups.Get(ctx, *id, ipgroups.DefaultGetOperationOptions()) if err != nil { - return nil, fmt.Errorf("reading IP Group (%s): %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", id, err) } - return utils.Bool(resp.ID != nil), nil + return pointer.To(resp.Model != nil), nil } func (IPGroupResource) basic(data acceptance.TestData) string { diff --git a/internal/services/network/ip_groups_data_source.go b/internal/services/network/ip_groups_data_source.go index fa57da41b207..799da92c2ace 100644 --- a/internal/services/network/ip_groups_data_source.go +++ b/internal/services/network/ip_groups_data_source.go @@ -12,7 +12,6 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" ) @@ -47,67 +46,50 @@ func dataSourceIpGroups() *pluginsdk.Resource { Elem: &pluginsdk.Schema{Type: pluginsdk.TypeString}, }, - "tags": tags.SchemaDataSource(), + "tags": commonschema.TagsDataSource(), }, } } -// Find IDs and names of multiple IP Groups, filtered by name substring func dataSourceIpGroupsRead(d *pluginsdk.ResourceData, meta interface{}) error { - - // Establish a client to handle i/o operations against the API - client := meta.(*clients.Client).Network.IPGroupsClient - - // Create a context for the request and defer cancellation + client := meta.(*clients.Client).Network.Client.IPGroups + subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - // Get resource group name from data source - resourceGroupName := d.Get("resource_group_name").(string) + id := commonids.NewResourceGroupID(subscriptionId, d.Get("resource_group_name").(string)) - // Make the request to the API to download all IP groups in the resource group - allGroups, err := client.ListByResourceGroup(ctx, resourceGroupName) + resp, err := client.ListByResourceGroup(ctx, id) if err != nil { - return fmt.Errorf("error listing IP groups: %+v", err) + return fmt.Errorf("listing IP groups: %+v", err) } - // Establish lists of strings to append to, set equal to empty set to start - // If no IP groups are found, an empty set will be returned names := []string{} ids := []string{} - // Filter IDs list by substring - for _, ipGroup := range allGroups.Values() { - if ipGroup.Name != nil && strings.Contains(*ipGroup.Name, d.Get("name").(string)) { - names = append(names, *ipGroup.Name) - ids = append(ids, *ipGroup.ID) + if model := resp.Model; model != nil { + for _, group := range *model { + if group.Name != nil && strings.Contains(*group.Name, d.Get("name").(string)) { + names = append(names, *group.Name) + ids = append(ids, *group.Id) + } } } - // Sort lists of strings alphabetically slices.Sort(names) slices.Sort(ids) - // Set resource ID, required for Terraform state - // Since this is a multi-resource data source, we need to create a unique ID - // Using the ID of the resource group - subscriptionId := meta.(*clients.Client).Account.SubscriptionId - id := commonids.NewResourceGroupID(subscriptionId, resourceGroupName) d.SetId(id.ID()) - // Set names err = d.Set("names", names) if err != nil { return fmt.Errorf("error setting names: %+v", err) } - // Set IDs err = d.Set("ids", ids) if err != nil { return fmt.Errorf("error setting ids: %+v", err) } - // Return nil error return nil - } diff --git a/internal/services/network/local_network_gateway_data_source.go b/internal/services/network/local_network_gateway_data_source.go index 0ba22fe198ec..e002e9127aad 100644 --- a/internal/services/network/local_network_gateway_data_source.go +++ b/internal/services/network/local_network_gateway_data_source.go @@ -7,15 +7,14 @@ import ( "fmt" "time" + "github.com/hashicorp/go-azure-helpers/lang/response" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" - "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/localnetworkgateways" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func dataSourceLocalNetworkGateway() *pluginsdk.Resource { @@ -77,22 +76,22 @@ func dataSourceLocalNetworkGateway() *pluginsdk.Resource { }, }, - "tags": tags.SchemaDataSource(), + "tags": commonschema.TagsDataSource(), }, } } func dataSourceLocalNetworkGatewayRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.LocalNetworkGatewaysClient + client := meta.(*clients.Client).Network.Client.LocalNetworkGateways subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id := parse.NewLocalNetworkGatewayID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + id := localnetworkgateways.NewLocalNetworkGatewayID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) - resp, err := client.Get(ctx, id.ResourceGroup, id.Name) + resp, err := client.Get(ctx, id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { + if response.WasNotFound(resp.HttpResponse) { return fmt.Errorf("%s was not found", id) } @@ -101,13 +100,13 @@ func dataSourceLocalNetworkGatewayRead(d *pluginsdk.ResourceData, meta interface d.SetId(id.ID()) - d.Set("name", resp.Name) - d.Set("resource_group_name", id.ResourceGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } + d.Set("name", id.LocalNetworkGatewayName) + d.Set("resource_group_name", id.ResourceGroupName) + + if model := resp.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) - if props := resp.LocalNetworkGatewayPropertiesFormat; props != nil { + props := model.Properties d.Set("gateway_address", props.GatewayIPAddress) d.Set("gateway_fqdn", props.Fqdn) @@ -118,12 +117,14 @@ func dataSourceLocalNetworkGatewayRead(d *pluginsdk.ResourceData, meta interface if err := d.Set("bgp_settings", flattenedSettings); err != nil { return err } + + return tags.FlattenAndSet(d, model.Tags) } - return tags.FlattenAndSet(d, resp.Tags) + return nil } -func flattenLocalNetworkGatewayDataSourceBGPSettings(input *network.BgpSettings) []interface{} { +func flattenLocalNetworkGatewayDataSourceBGPSettings(input *localnetworkgateways.BgpSettings) []interface{} { output := make(map[string]interface{}) if input == nil { diff --git a/internal/services/network/local_network_gateway_resource.go b/internal/services/network/local_network_gateway_resource.go index f6026b8934bd..6d1164259a2a 100644 --- a/internal/services/network/local_network_gateway_resource.go +++ b/internal/services/network/local_network_gateway_resource.go @@ -7,17 +7,19 @@ import ( "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/terraform-provider-azurerm/helpers/azure" + "github.com/hashicorp/go-azure-helpers/resourcemanager/location" + "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/localnetworkgateways" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/tags" + "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/custompollers" "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" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceLocalNetworkGateway() *pluginsdk.Resource { @@ -27,7 +29,7 @@ func resourceLocalNetworkGateway() *pluginsdk.Resource { Update: resourceLocalNetworkGatewayCreateUpdate, Delete: resourceLocalNetworkGatewayDelete, Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := parse.LocalNetworkGatewayID(id) + _, err := localnetworkgateways.ParseLocalNetworkGatewayID(id) return err }), @@ -95,82 +97,81 @@ func resourceLocalNetworkGateway() *pluginsdk.Resource { }, }, - "tags": tags.Schema(), + "tags": commonschema.Tags(), }, } } func resourceLocalNetworkGatewayCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.LocalNetworkGatewaysClient + client := meta.(*clients.Client).Network.Client.LocalNetworkGateways subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - id := parse.NewLocalNetworkGatewayID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + id := localnetworkgateways.NewLocalNetworkGatewayID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) if d.IsNewResource() { - existing, err := client.Get(ctx, id.ResourceGroup, id.Name) + existing, err := client.Get(ctx, id) if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { + if !response.WasNotFound(existing.HttpResponse) { return fmt.Errorf("checking for presence of existing %s: %s", id, err) } } - if !utils.ResponseWasNotFound(existing.Response) { + if !response.WasNotFound(existing.HttpResponse) { return tf.ImportAsExistsError("azurerm_local_network_gateway", id.ID()) } } - location := azure.NormalizeLocation(d.Get("location").(string)) - t := d.Get("tags").(map[string]interface{}) - - gateway := network.LocalNetworkGateway{ - Name: &id.Name, - Location: &location, - LocalNetworkGatewayPropertiesFormat: &network.LocalNetworkGatewayPropertiesFormat{ - LocalNetworkAddressSpace: &network.AddressSpace{}, + gateway := localnetworkgateways.LocalNetworkGateway{ + Name: pointer.To(id.LocalNetworkGatewayName), + Location: pointer.To(location.Normalize(d.Get("location").(string))), + Properties: localnetworkgateways.LocalNetworkGatewayPropertiesFormat{ + LocalNetworkAddressSpace: &localnetworkgateways.AddressSpace{}, BgpSettings: expandLocalNetworkGatewayBGPSettings(d), }, - Tags: tags.Expand(t), + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } ipAddress := d.Get("gateway_address").(string) fqdn := d.Get("gateway_fqdn").(string) if ipAddress != "" { - gateway.LocalNetworkGatewayPropertiesFormat.GatewayIPAddress = &ipAddress + gateway.Properties.GatewayIPAddress = &ipAddress } else { - gateway.LocalNetworkGatewayPropertiesFormat.Fqdn = &fqdn + gateway.Properties.Fqdn = &fqdn } + // This custompoller can be removed once https://github.com/hashicorp/go-azure-sdk/issues/989 has been fixed + pollerType := custompollers.NewLocalNetworkGatewayPoller(client, id) + poller := pollers.NewPoller(pollerType, 10*time.Second, pollers.DefaultNumberOfDroppedConnectionsToAllow) + // There is a bug in the provider where the address space ordering doesn't change as expected. // In the UI we have to remove the current list of addresses in the address space and re-add them in the new order and we'll copy that here. if !d.IsNewResource() && d.HasChange("address_space") { // since the local network gateway cannot have both empty address prefix and empty BGP setting(confirmed with service team, it is by design), // replace the empty address prefix with the first address prefix in the "address_space" list to avoid error. if v := d.Get("address_space").([]interface{}); len(v) > 0 { - gateway.LocalNetworkGatewayPropertiesFormat.LocalNetworkAddressSpace = &network.AddressSpace{ + gateway.Properties.LocalNetworkAddressSpace = &localnetworkgateways.AddressSpace{ AddressPrefixes: &[]string{v[0].(string)}, } } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, gateway) - if err != nil { + // This can be switched back over to CreateOrUpdateThenPoll once https://github.com/hashicorp/go-azure-sdk/issues/989 has been fixed + if _, err := client.CreateOrUpdate(ctx, id, gateway); err != nil { return fmt.Errorf("removing %s: %+v", id, err) } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for completion of %s: %+v", id, err) + if err := poller.PollUntilDone(ctx); err != nil { + return err } } - gateway.LocalNetworkGatewayPropertiesFormat.LocalNetworkAddressSpace = expandLocalNetworkGatewayAddressSpaces(d) + gateway.Properties.LocalNetworkAddressSpace = expandLocalNetworkGatewayAddressSpaces(d) - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, gateway) - if err != nil { + if _, err := client.CreateOrUpdate(ctx, id, gateway); err != nil { return fmt.Errorf("creating %s: %+v", id, err) } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for completion of %s: %+v", id, err) + if err := poller.PollUntilDone(ctx); err != nil { + return err } d.SetId(id.ID()) @@ -179,32 +180,32 @@ func resourceLocalNetworkGatewayCreateUpdate(d *pluginsdk.ResourceData, meta int } func resourceLocalNetworkGatewayRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.LocalNetworkGatewaysClient + client := meta.(*clients.Client).Network.Client.LocalNetworkGateways ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - resGroup, name, err := resourceGroupAndLocalNetworkGatewayFromId(d.Id()) + id, err := localnetworkgateways.ParseLocalNetworkGatewayID(d.Id()) if err != nil { return err } - resp, err := client.Get(ctx, resGroup, name) + resp, err := client.Get(ctx, *id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { + if response.WasNotFound(resp.HttpResponse) { d.SetId("") return nil } - return fmt.Errorf("reading the state of Local Network Gateway %q (Resource Group %q): %+v", name, resGroup, err) + return fmt.Errorf("retrieving %s: %+v", id, err) } - d.Set("name", resp.Name) - d.Set("resource_group_name", resGroup) - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } + d.Set("name", id.LocalNetworkGatewayName) + d.Set("resource_group_name", id.ResourceGroupName) - if props := resp.LocalNetworkGatewayPropertiesFormat; props != nil { + if model := resp.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) + + props := model.Properties d.Set("gateway_address", props.GatewayIPAddress) d.Set("gateway_fqdn", props.Fqdn) @@ -215,43 +216,39 @@ func resourceLocalNetworkGatewayRead(d *pluginsdk.ResourceData, meta interface{} if err := d.Set("bgp_settings", flattenedSettings); err != nil { return err } - } - return tags.FlattenAndSet(d, resp.Tags) + return tags.FlattenAndSet(d, model.Tags) + } + return nil } func resourceLocalNetworkGatewayDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.LocalNetworkGatewaysClient + client := meta.(*clients.Client).Network.Client.LocalNetworkGateways ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - resGroup, name, err := resourceGroupAndLocalNetworkGatewayFromId(d.Id()) + id, err := localnetworkgateways.ParseLocalNetworkGatewayID(d.Id()) if err != nil { return err } - future, err := client.Delete(ctx, resGroup, name) - if err != nil { - return fmt.Errorf("issuing delete request for local network gateway %q (Resource Group %q): %+v", name, resGroup, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for completion of local network gateway %q (Resource Group %q): %+v", name, resGroup, err) + if err := client.DeleteThenPoll(ctx, *id); err != nil { + return fmt.Errorf("deleting %s: %+v", id, err) } return nil } func resourceGroupAndLocalNetworkGatewayFromId(localNetworkGatewayId string) (string, string, error) { - id, err := parse.LocalNetworkGatewayID(localNetworkGatewayId) + id, err := localnetworkgateways.ParseLocalNetworkGatewayID(localNetworkGatewayId) if err != nil { return "", "", err } - return id.ResourceGroup, id.Name, nil + return id.ResourceGroupName, id.LocalNetworkGatewayName, nil } -func expandLocalNetworkGatewayBGPSettings(d *pluginsdk.ResourceData) *network.BgpSettings { +func expandLocalNetworkGatewayBGPSettings(d *pluginsdk.ResourceData) *localnetworkgateways.BgpSettings { v, exists := d.GetOk("bgp_settings") if !exists { return nil @@ -260,28 +257,28 @@ func expandLocalNetworkGatewayBGPSettings(d *pluginsdk.ResourceData) *network.Bg settings := v.([]interface{}) setting := settings[0].(map[string]interface{}) - bgpSettings := network.BgpSettings{ - Asn: utils.Int64(int64(setting["asn"].(int))), - BgpPeeringAddress: utils.String(setting["bgp_peering_address"].(string)), - PeerWeight: utils.Int32(int32(setting["peer_weight"].(int))), + bgpSettings := localnetworkgateways.BgpSettings{ + Asn: pointer.To(int64(setting["asn"].(int))), + BgpPeeringAddress: pointer.To(setting["bgp_peering_address"].(string)), + PeerWeight: pointer.To(int64(setting["peer_weight"].(int))), } return &bgpSettings } -func expandLocalNetworkGatewayAddressSpaces(d *pluginsdk.ResourceData) *network.AddressSpace { +func expandLocalNetworkGatewayAddressSpaces(d *pluginsdk.ResourceData) *localnetworkgateways.AddressSpace { prefixes := make([]string, 0) for _, pref := range d.Get("address_space").([]interface{}) { prefixes = append(prefixes, pref.(string)) } - return &network.AddressSpace{ + return &localnetworkgateways.AddressSpace{ AddressPrefixes: &prefixes, } } -func flattenLocalNetworkGatewayBGPSettings(input *network.BgpSettings) []interface{} { +func flattenLocalNetworkGatewayBGPSettings(input *localnetworkgateways.BgpSettings) []interface{} { output := make(map[string]interface{}) if input == nil { diff --git a/internal/services/network/local_network_gateway_resource_test.go b/internal/services/network/local_network_gateway_resource_test.go index a82d3bb17277..de1314122dd4 100644 --- a/internal/services/network/local_network_gateway_resource_test.go +++ b/internal/services/network/local_network_gateway_resource_test.go @@ -7,7 +7,10 @@ import ( "context" "fmt" "testing" + "time" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/localnetworkgateways" "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" @@ -243,21 +246,18 @@ func (t LocalNetworkGatewayResource) Exists(ctx context.Context, clients *client } func (LocalNetworkGatewayResource) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LocalNetworkGatewayID(state.ID) + id, err := localnetworkgateways.ParseLocalNetworkGatewayID(state.ID) if err != nil { return nil, err } - future, err := client.Network.LocalNetworkGatewaysClient.Delete(ctx, id.ResourceGroup, id.Name) - if err != nil { + ctx2, cancel := context.WithTimeout(ctx, 30*time.Minute) + defer cancel() + if err := client.Network.Client.LocalNetworkGateways.DeleteThenPoll(ctx2, *id); err != nil { return nil, fmt.Errorf("deleting %s: %+v", *id, err) } - if err = future.WaitForCompletionRef(ctx, client.Network.LocalNetworkGatewaysClient.Client); err != nil { - return nil, fmt.Errorf("waiting for %s : %+v", *id, err) - } - - return utils.Bool(true), nil + return pointer.To(true), nil } func (LocalNetworkGatewayResource) basic(data acceptance.TestData) string { diff --git a/internal/services/network/nat_gateway_data_source.go b/internal/services/network/nat_gateway_data_source.go index d13c01a68199..9065740e4af1 100644 --- a/internal/services/network/nat_gateway_data_source.go +++ b/internal/services/network/nat_gateway_data_source.go @@ -7,16 +7,17 @@ import ( "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-helpers/resourcemanager/tags" "github.com/hashicorp/go-azure-helpers/resourcemanager/zones" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/natgateways" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" - "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) func dataSourceNatGateway() *pluginsdk.Resource { @@ -78,43 +79,61 @@ func dataSourceNatGateway() *pluginsdk.Resource { } func dataSourceNatGatewayRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id := parse.NewNatGatewayID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + id := natgateways.NewNatGatewayID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) - resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := client.Get(ctx, id, natgateways.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("reading %s: %+v", id, err) + return fmt.Errorf("retrieving %s: %+v", id, err) } d.SetId(id.ID()) - d.Set("name", resp.Name) - d.Set("resource_group_name", id.ResourceGroup) - if sku := resp.Sku; sku != nil { - d.Set("sku_name", resp.Sku.Name) - } - - d.Set("location", location.NormalizeNilable(resp.Location)) - d.Set("zones", zones.FlattenUntyped(resp.Zones)) + d.Set("name", id.NatGatewayName) + d.Set("resource_group_name", id.ResourceGroupName) - if props := resp.NatGatewayPropertiesFormat; props != nil { - d.Set("idle_timeout_in_minutes", props.IdleTimeoutInMinutes) - d.Set("resource_guid", props.ResourceGUID) - - if err := d.Set("public_ip_address_ids", flattenNetworkSubResourceID(props.PublicIPAddresses)); err != nil { - return fmt.Errorf("setting `public_ip_address_ids`: %+v", err) + if model := resp.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) + sku := "" + if model.Sku != nil { + sku = string(pointer.From(model.Sku.Name)) + } + d.Set("sku_name", sku) + d.Set("zones", zones.FlattenUntyped(model.Zones)) + if props := model.Properties; props != nil { + d.Set("idle_timeout_in_minutes", props.IdleTimeoutInMinutes) + d.Set("resource_guid", props.ResourceGuid) + + if err := d.Set("public_ip_address_ids", flattenNetworkSubResourceID(props.PublicIPAddresses)); err != nil { + return fmt.Errorf("setting `public_ip_address_ids`: %+v", err) + } + + if err := d.Set("public_ip_prefix_ids", flattenNetworkSubResourceID(props.PublicIPPrefixes)); err != nil { + return fmt.Errorf("setting `public_ip_prefix_ids`: %+v", err) + } } + return tags.FlattenAndSet(d, model.Tags) + } + return nil +} + +func flattenNetworkSubResourceID(input *[]natgateways.SubResource) []interface{} { + results := make([]interface{}, 0) + if input == nil { + return results + } - if err := d.Set("public_ip_prefix_ids", flattenNetworkSubResourceID(props.PublicIPPrefixes)); err != nil { - return fmt.Errorf("setting `public_ip_prefix_ids`: %+v", err) + for _, item := range *input { + if item.Id != nil { + results = append(results, *item.Id) } } - return tags.FlattenAndSet(d, resp.Tags) + return results } diff --git a/internal/services/network/nat_gateway_public_ip_association_resource.go b/internal/services/network/nat_gateway_public_ip_association_resource.go index 0e9b41abd578..e944db573803 100644 --- a/internal/services/network/nat_gateway_public_ip_association_resource.go +++ b/internal/services/network/nat_gateway_public_ip_association_resource.go @@ -9,15 +9,16 @@ import ( "strings" "time" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/natgateways" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceNATGatewayPublicIpAssociation() *pluginsdk.Resource { @@ -27,7 +28,7 @@ func resourceNATGatewayPublicIpAssociation() *pluginsdk.Resource { Delete: resourceNATGatewayPublicIpAssociationDelete, Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := parse.NatGatewayPublicIPAddressAssociationID(id) + _, err := commonids.ParseCompositeResourceID(id, &natgateways.NatGatewayId{}, &commonids.PublicIPAddressId{}) return err }), @@ -56,165 +57,166 @@ func resourceNATGatewayPublicIpAssociation() *pluginsdk.Resource { } func resourceNATGatewayPublicIpAssociationCreate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() log.Printf("[INFO] preparing arguments for NAT Gateway <-> Public IP Association creation.") - natGatewayId := d.Get("nat_gateway_id").(string) - publicIpAddressId := d.Get("public_ip_address_id").(string) - parsedNatGatewayId, err := parse.NatGatewayID(natGatewayId) + publicIpAddressId, err := commonids.ParsePublicIPAddressID(d.Get("public_ip_address_id").(string)) + if err != nil { + return err + } + natGatewayId, err := natgateways.ParseNatGatewayID(d.Get("nat_gateway_id").(string)) if err != nil { return err } - locks.ByName(parsedNatGatewayId.Name, natGatewayResourceName) - defer locks.UnlockByName(parsedNatGatewayId.Name, natGatewayResourceName) + id := commonids.NewCompositeResourceID(natGatewayId, publicIpAddressId) - natGateway, err := client.Get(ctx, parsedNatGatewayId.ResourceGroup, parsedNatGatewayId.Name, "") + locks.ByName(natGatewayId.NatGatewayName, natGatewayResourceName) + defer locks.UnlockByName(natGatewayId.NatGatewayName, natGatewayResourceName) + + natGateway, err := client.Get(ctx, *natGatewayId, natgateways.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(natGateway.Response) { - return fmt.Errorf("NAT Gateway %q (Resource Group %q) was not found.", parsedNatGatewayId.Name, parsedNatGatewayId.ResourceGroup) + if response.WasNotFound(natGateway.HttpResponse) { + return fmt.Errorf("%s was not found", natGatewayId) } - return fmt.Errorf("failed to retrieve NAT Gateway %q (Resource Group %q): %+v", parsedNatGatewayId.Name, parsedNatGatewayId.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", natGatewayId, err) + } + + if natGateway.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", natGatewayId) + } + if natGateway.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", natGatewayId) } - id := fmt.Sprintf("%s|%s", *natGateway.ID, publicIpAddressId) - publicIpAddresses := make([]network.SubResource, 0) - if natGateway.PublicIPAddresses != nil { - for _, existingPublicIPAddress := range *natGateway.PublicIPAddresses { - if existingPublicIPAddress.ID == nil { + publicIpAddresses := make([]natgateways.SubResource, 0) + if natGateway.Model.Properties.PublicIPAddresses != nil { + for _, existingPublicIPAddress := range *natGateway.Model.Properties.PublicIPAddresses { + if existingPublicIPAddress.Id == nil { continue } - if strings.EqualFold(*existingPublicIPAddress.ID, publicIpAddressId) { - return tf.ImportAsExistsError("azurerm_nat_gateway_public_ip_association", id) + if strings.EqualFold(*existingPublicIPAddress.Id, publicIpAddressId.ID()) { + return tf.ImportAsExistsError("azurerm_nat_gateway_public_ip_association", id.ID()) } publicIpAddresses = append(publicIpAddresses, existingPublicIPAddress) } } - publicIpAddresses = append(publicIpAddresses, network.SubResource{ - ID: utils.String(publicIpAddressId), + publicIpAddresses = append(publicIpAddresses, natgateways.SubResource{ + Id: pointer.To(publicIpAddressId.ID()), }) - natGateway.PublicIPAddresses = &publicIpAddresses - - future, err := client.CreateOrUpdate(ctx, parsedNatGatewayId.ResourceGroup, parsedNatGatewayId.Name, natGateway) - if err != nil { - return fmt.Errorf("failed to update Public IP Association for NAT Gateway %q (Resource Group %q): %+v", parsedNatGatewayId.Name, parsedNatGatewayId.ResourceGroup, err) - } + natGateway.Model.Properties.PublicIPAddresses = &publicIpAddresses - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("failed to wait for completion of Public IP Association for NAT Gateway %q (Resource Group %q): %+v", parsedNatGatewayId.Name, parsedNatGatewayId.ResourceGroup, err) + if err := client.CreateOrUpdateThenPoll(ctx, *natGatewayId, *natGateway.Model); err != nil { + return fmt.Errorf("updating %s: %+v", natGatewayId, err) } - d.SetId(id) + d.SetId(id.ID()) return resourceNATGatewayPublicIpAssociationRead(d, meta) } func resourceNATGatewayPublicIpAssociationRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.NatGatewayPublicIPAddressAssociationID(d.Id()) + id, err := commonids.ParseCompositeResourceID(d.Id(), &natgateways.NatGatewayId{}, &commonids.PublicIPAddressId{}) if err != nil { return err } - natGateway, err := client.Get(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, "") + natGateway, err := client.Get(ctx, *id.First, natgateways.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(natGateway.Response) { - log.Printf("[DEBUG] NAT Gateway %q (Resource Group %q) could not be found - removing from state!", id.NatGateway.Name, id.NatGateway.ResourceGroup) + if response.WasNotFound(natGateway.HttpResponse) { + log.Printf("[DEBUG] %s was not found - removing from state!", id.First) d.SetId("") return nil } - return fmt.Errorf("failed to retrieve NAT Gateway %q (Resource Group %q): %+v", id.NatGateway.Name, id.NatGateway.ResourceGroup, err) - } - - if natGateway.NatGatewayPropertiesFormat == nil { - return fmt.Errorf("`properties` was nil for NAT Gateway %q (Resource Group %q)", id.NatGateway.Name, id.NatGateway.ResourceGroup) + return fmt.Errorf("retrieving %s: %+v", id.First, err) } - props := *natGateway.NatGatewayPropertiesFormat - if props.PublicIPAddresses == nil { - log.Printf("[DEBUG] NAT Gateway %q (Resource Group %q) doesn't have any Public IP's - removing from state!", id.NatGateway.Name, id.NatGateway.ResourceGroup) - d.SetId("") - return nil - } + if model := natGateway.Model; model != nil { + if props := model.Properties; props != nil { + if props.PublicIPAddresses == nil { + log.Printf("[DEBUG] %s doesn't have any Public IP's - removing from state!", id.First) + d.SetId("") + return nil + } - publicIPAddressId := "" - for _, pip := range *props.PublicIPAddresses { - if pip.ID == nil { - continue - } + publicIPAddressId := "" + for _, pip := range *props.PublicIPAddresses { + if pip.Id == nil { + continue + } - if strings.EqualFold(*pip.ID, id.PublicIPAddressID) { - publicIPAddressId = *pip.ID - break + if strings.EqualFold(*pip.Id, id.Second.ID()) { + publicIPAddressId = *pip.Id + break + } + } + if publicIPAddressId == "" { + log.Printf("[DEBUG] Association between %s and %s was not found - removing from state", id.First, id.Second) + d.SetId("") + return nil + } } } - if publicIPAddressId == "" { - log.Printf("[DEBUG] Association between NAT Gateway %q (Resource Group %q) and Public IP Address %q was not found - removing from state", id.NatGateway.Name, id.NatGateway.ResourceGroup, id.PublicIPAddressID) - d.SetId("") - return nil - } - - d.Set("nat_gateway_id", natGateway.ID) - d.Set("public_ip_address_id", publicIPAddressId) + d.Set("nat_gateway_id", id.First.ID()) + d.Set("public_ip_address_id", id.Second.ID()) return nil } func resourceNATGatewayPublicIpAssociationDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.NatGatewayPublicIPAddressAssociationID(d.Id()) + id, err := commonids.ParseCompositeResourceID(d.Id(), &natgateways.NatGatewayId{}, &commonids.PublicIPAddressId{}) if err != nil { return err } - locks.ByName(id.NatGateway.Name, natGatewayResourceName) - defer locks.UnlockByName(id.NatGateway.Name, natGatewayResourceName) + locks.ByName(id.First.NatGatewayName, natGatewayResourceName) + defer locks.UnlockByName(id.First.NatGatewayName, natGatewayResourceName) - natGateway, err := client.Get(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, "") + natGateway, err := client.Get(ctx, *id.First, natgateways.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(natGateway.Response) { - return fmt.Errorf("NAT Gateway %q (Resource Group %q) was not found", id.NatGateway.Name, id.NatGateway.ResourceGroup) + if response.WasNotFound(natGateway.HttpResponse) { + return fmt.Errorf("%s was not found", id.First) } + return fmt.Errorf("retrieving %s: %+v", id.First, err) + } - return fmt.Errorf("retrieving NAT Gateway %q (Resource Group %q): %+v", id.NatGateway.Name, id.NatGateway.ResourceGroup, err) + if natGateway.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", id.First) } - if natGateway.NatGatewayPropertiesFormat == nil { - return fmt.Errorf("retrieving NAT Gateway %q (Resource Group %q): `properties` was nil", id.NatGateway.Name, id.NatGateway.ResourceGroup) + if natGateway.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", id.First) } - publicIpAddresses := make([]network.SubResource, 0) - if publicIPAddresses := natGateway.NatGatewayPropertiesFormat.PublicIPAddresses; publicIPAddresses != nil { + publicIpAddresses := make([]natgateways.SubResource, 0) + if publicIPAddresses := natGateway.Model.Properties.PublicIPAddresses; publicIPAddresses != nil { for _, publicIPAddress := range *publicIPAddresses { - if publicIPAddress.ID == nil { + if publicIPAddress.Id == nil { continue } - if !strings.EqualFold(*publicIPAddress.ID, id.PublicIPAddressID) { + if !strings.EqualFold(*publicIPAddress.Id, id.Second.ID()) { publicIpAddresses = append(publicIpAddresses, publicIPAddress) } } } - natGateway.NatGatewayPropertiesFormat.PublicIPAddresses = &publicIpAddresses - - future, err := client.CreateOrUpdate(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, natGateway) - if err != nil { - return fmt.Errorf("removing association between NAT Gateway %q (Resource Group %q) and Public IP Address %q: %+v", id.NatGateway.Name, id.NatGateway.ResourceGroup, id.PublicIPAddressID, err) - } + natGateway.Model.Properties.PublicIPAddresses = &publicIpAddresses - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for association between Public IP ID %q for NAT Gateway %q (Resource Group %q) to be removed: %+v", id.PublicIPAddressID, id.NatGateway.Name, id.NatGateway.ResourceGroup, err) + if err := client.CreateOrUpdateThenPoll(ctx, *id.First, *natGateway.Model); err != nil { + return fmt.Errorf("removing association between %s and %s: %+v", id.First, id.Second, err) } return nil diff --git a/internal/services/network/nat_gateway_public_ip_association_resource_test.go b/internal/services/network/nat_gateway_public_ip_association_resource_test.go index 101266911416..77e2484980f5 100644 --- a/internal/services/network/nat_gateway_public_ip_association_resource_test.go +++ b/internal/services/network/nat_gateway_public_ip_association_resource_test.go @@ -9,6 +9,9 @@ import ( "strings" "testing" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/natgateways" "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" @@ -86,17 +89,17 @@ func TestAccNatGatewayPublicIpAssociation_deleted(t *testing.T) { } func (t NatGatewayPublicAssociationResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.NatGatewayPublicIPAddressAssociationID(state.ID) + id, err := commonids.ParseCompositeResourceID(state.ID, &natgateways.NatGatewayId{}, &commonids.PublicIPAddressId{}) if err != nil { return nil, err } - resp, err := clients.Network.NatGatewayClient.Get(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, "") + resp, err := clients.Network.Client.NatGateways.Get(ctx, *id.First, natgateways.DefaultGetOperationOptions()) if err != nil { - return nil, fmt.Errorf("reading Nat Gateway Public IP Association (%s): %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", id.First, err) } - return utils.Bool(resp.ID != nil), nil + return pointer.To(resp.Model != nil), nil } func (NatGatewayPublicAssociationResource) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { diff --git a/internal/services/network/nat_gateway_public_ip_prefix_association_resource.go b/internal/services/network/nat_gateway_public_ip_prefix_association_resource.go index e1ee550448c4..786446126e94 100644 --- a/internal/services/network/nat_gateway_public_ip_prefix_association_resource.go +++ b/internal/services/network/nat_gateway_public_ip_prefix_association_resource.go @@ -9,15 +9,17 @@ import ( "strings" "time" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/natgateways" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/publicipprefixes" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceNATGatewayPublicIpPrefixAssociation() *pluginsdk.Resource { @@ -27,7 +29,7 @@ func resourceNATGatewayPublicIpPrefixAssociation() *pluginsdk.Resource { Delete: resourceNATGatewayPublicIpPrefixAssociationDelete, Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := parse.NatGatewayPublicIPPrefixAssociationID(id) + _, err := commonids.ParseCompositeResourceID(id, &natgateways.NatGatewayId{}, &publicipprefixes.PublicIPPrefixId{}) return err }), @@ -56,165 +58,167 @@ func resourceNATGatewayPublicIpPrefixAssociation() *pluginsdk.Resource { } func resourceNATGatewayPublicIpPrefixAssociationCreate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() log.Printf("[INFO] preparing arguments for NAT Gateway <-> Public IP Prefix Association creation.") - natGatewayId := d.Get("nat_gateway_id").(string) - publicIpPrefixId := d.Get("public_ip_prefix_id").(string) - parsedNatGatewayId, err := parse.NatGatewayID(natGatewayId) + + natGatewayId, err := natgateways.ParseNatGatewayID(d.Get("nat_gateway_id").(string)) if err != nil { return err } - locks.ByName(parsedNatGatewayId.Name, natGatewayResourceName) - defer locks.UnlockByName(parsedNatGatewayId.Name, natGatewayResourceName) + publicIpPrefixId, err := publicipprefixes.ParsePublicIPPrefixID(d.Get("public_ip_prefix_id").(string)) + if err != nil { + return err + } - natGateway, err := client.Get(ctx, parsedNatGatewayId.ResourceGroup, parsedNatGatewayId.Name, "") + id := commonids.NewCompositeResourceID(natGatewayId, publicIpPrefixId) + + locks.ByName(natGatewayId.NatGatewayName, natGatewayResourceName) + defer locks.UnlockByName(natGatewayId.NatGatewayName, natGatewayResourceName) + + natGateway, err := client.Get(ctx, *natGatewayId, natgateways.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(natGateway.Response) { - return fmt.Errorf("NAT Gateway %q (Resource Group %q) was not found.", parsedNatGatewayId.Name, parsedNatGatewayId.ResourceGroup) + if response.WasNotFound(natGateway.HttpResponse) { + return fmt.Errorf("%s was not found", natGatewayId) } - return fmt.Errorf("failed to retrieve NAT Gateway %q (Resource Group %q): %+v", parsedNatGatewayId.Name, parsedNatGatewayId.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", natGatewayId, err) } - id := fmt.Sprintf("%s|%s", *natGateway.ID, publicIpPrefixId) - publicIpPrefixes := make([]network.SubResource, 0) - if natGateway.PublicIPPrefixes != nil { - for _, existingPublicIPPrefix := range *natGateway.PublicIPPrefixes { - if existingPublicIPPrefix.ID == nil { + if natGateway.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", natGatewayId) + } + if natGateway.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", natGatewayId) + } + + publicIpPrefixes := make([]natgateways.SubResource, 0) + if natGateway.Model.Properties.PublicIPPrefixes != nil { + for _, existingPublicIPPrefix := range *natGateway.Model.Properties.PublicIPPrefixes { + if existingPublicIPPrefix.Id == nil { continue } - if strings.EqualFold(*existingPublicIPPrefix.ID, publicIpPrefixId) { - return tf.ImportAsExistsError("azurerm_nat_gateway_public_ip_prefix_association", id) + if strings.EqualFold(*existingPublicIPPrefix.Id, publicIpPrefixId.ID()) { + return tf.ImportAsExistsError("azurerm_nat_gateway_public_ip_prefix_association", id.ID()) } publicIpPrefixes = append(publicIpPrefixes, existingPublicIPPrefix) } } - publicIpPrefixes = append(publicIpPrefixes, network.SubResource{ - ID: utils.String(publicIpPrefixId), + publicIpPrefixes = append(publicIpPrefixes, natgateways.SubResource{ + Id: pointer.To(publicIpPrefixId.ID()), }) - natGateway.PublicIPPrefixes = &publicIpPrefixes - - future, err := client.CreateOrUpdate(ctx, parsedNatGatewayId.ResourceGroup, parsedNatGatewayId.Name, natGateway) - if err != nil { - return fmt.Errorf("failed to update Public IP Prefix Association for NAT Gateway %q (Resource Group %q): %+v", parsedNatGatewayId.Name, parsedNatGatewayId.ResourceGroup, err) - } + natGateway.Model.Properties.PublicIPPrefixes = &publicIpPrefixes - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("failed to wait for completion of Public IP Prefix Association for NAT Gateway %q (Resource Group %q): %+v", parsedNatGatewayId.Name, parsedNatGatewayId.ResourceGroup, err) + if err := client.CreateOrUpdateThenPoll(ctx, *natGatewayId, *natGateway.Model); err != nil { + return fmt.Errorf("updating %s: %+v", natGatewayId, err) } - d.SetId(id) + d.SetId(id.ID()) return resourceNATGatewayPublicIpPrefixAssociationRead(d, meta) } func resourceNATGatewayPublicIpPrefixAssociationRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.NatGatewayPublicIPPrefixAssociationID(d.Id()) + id, err := commonids.ParseCompositeResourceID(d.Id(), &natgateways.NatGatewayId{}, &publicipprefixes.PublicIPPrefixId{}) if err != nil { return err } - natGateway, err := client.Get(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, "") + natGateway, err := client.Get(ctx, *id.First, natgateways.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(natGateway.Response) { - log.Printf("[DEBUG] NAT Gateway %q (Resource Group %q) could not be found - removing from state!", id.NatGateway.Name, id.NatGateway.ResourceGroup) + if response.WasNotFound(natGateway.HttpResponse) { + log.Printf("[DEBUG] %s could not be found - removing from state!", id.First) d.SetId("") return nil } - return fmt.Errorf("failed to retrieve NAT Gateway %q (Resource Group %q): %+v", id.NatGateway.Name, id.NatGateway.ResourceGroup, err) - } - - if natGateway.NatGatewayPropertiesFormat == nil { - return fmt.Errorf("`properties` was nil for NAT Gateway %q (Resource Group %q)", id.NatGateway.Name, id.NatGateway.ResourceGroup) + return fmt.Errorf("retrieving %s: %+v", id.First, err) } - props := *natGateway.NatGatewayPropertiesFormat - if props.PublicIPPrefixes == nil { - log.Printf("[DEBUG] NAT Gateway %q (Resource Group %q) doesn't have any Public IP Prefixes - removing from state!", id.NatGateway.Name, id.NatGateway.ResourceGroup) - d.SetId("") - return nil - } + if model := natGateway.Model; model != nil { + if props := model.Properties; props != nil { + if props.PublicIPPrefixes == nil { + log.Printf("[DEBUG] %s doesn't have any Public IP Prefixes - removing from state!", id.First) + d.SetId("") + return nil + } - publicIPPrefixId := "" - for _, pipp := range *props.PublicIPPrefixes { - if pipp.ID == nil { - continue - } + publicIPPrefixId := "" + for _, pipp := range *props.PublicIPPrefixes { + if pipp.Id == nil { + continue + } - if strings.EqualFold(*pipp.ID, id.PublicIPPrefixID) { - publicIPPrefixId = *pipp.ID - break + if strings.EqualFold(*pipp.Id, id.Second.ID()) { + publicIPPrefixId = *pipp.Id + break + } + } + if publicIPPrefixId == "" { + log.Printf("[DEBUG] Association between %s and %s was not found - removing from state", id.First, id.Second) + d.SetId("") + return nil + } } } - if publicIPPrefixId == "" { - log.Printf("[DEBUG] Association between NAT Gateway %q (Resource Group %q) and Public IP Prefix %q was not found - removing from state", id.NatGateway.Name, id.NatGateway.ResourceGroup, id.PublicIPPrefixID) - d.SetId("") - return nil - } - - d.Set("nat_gateway_id", natGateway.ID) - d.Set("public_ip_prefix_id", publicIPPrefixId) + d.Set("nat_gateway_id", id.First.ID()) + d.Set("public_ip_prefix_id", id.Second.ID()) return nil } func resourceNATGatewayPublicIpPrefixAssociationDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.NatGatewayPublicIPPrefixAssociationID(d.Id()) + id, err := commonids.ParseCompositeResourceID(d.Id(), &natgateways.NatGatewayId{}, &publicipprefixes.PublicIPPrefixId{}) if err != nil { return err } - locks.ByName(id.NatGateway.Name, natGatewayResourceName) - defer locks.UnlockByName(id.NatGateway.Name, natGatewayResourceName) + locks.ByName(id.First.NatGatewayName, natGatewayResourceName) + defer locks.UnlockByName(id.First.NatGatewayName, natGatewayResourceName) - natGateway, err := client.Get(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, "") + natGateway, err := client.Get(ctx, *id.First, natgateways.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(natGateway.Response) { - return fmt.Errorf("NAT Gateway %q (Resource Group %q) was not found", id.NatGateway.Name, id.NatGateway.ResourceGroup) + if response.WasNotFound(natGateway.HttpResponse) { + return fmt.Errorf("%s was not found", id.First) } - - return fmt.Errorf("retrieving NAT Gateway %q (Resource Group %q): %+v", id.NatGateway.Name, id.NatGateway.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", id.First, err) + } + if natGateway.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", id.First) } - if natGateway.NatGatewayPropertiesFormat == nil { - return fmt.Errorf("retrieving NAT Gateway %q (Resource Group %q): `properties` was nil", id.NatGateway.Name, id.NatGateway.ResourceGroup) + if natGateway.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", id.First) } - publicIpPrefixes := make([]network.SubResource, 0) - if publicIPPrefixes := natGateway.NatGatewayPropertiesFormat.PublicIPPrefixes; publicIPPrefixes != nil { + publicIpPrefixes := make([]natgateways.SubResource, 0) + if publicIPPrefixes := natGateway.Model.Properties.PublicIPPrefixes; publicIPPrefixes != nil { for _, publicIPPrefix := range *publicIPPrefixes { - if publicIPPrefix.ID == nil { + if publicIPPrefix.Id == nil { continue } - if !strings.EqualFold(*publicIPPrefix.ID, id.PublicIPPrefixID) { + if !strings.EqualFold(*publicIPPrefix.Id, id.Second.ID()) { publicIpPrefixes = append(publicIpPrefixes, publicIPPrefix) } } } - natGateway.NatGatewayPropertiesFormat.PublicIPPrefixes = &publicIpPrefixes - - future, err := client.CreateOrUpdate(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, natGateway) - if err != nil { - return fmt.Errorf("removing association between NAT Gateway %q (Resource Group %q) and Public IP Prefix %q: %+v", id.NatGateway.Name, id.NatGateway.ResourceGroup, id.PublicIPPrefixID, err) - } + natGateway.Model.Properties.PublicIPPrefixes = &publicIpPrefixes - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for association between Public IP Prefix ID %q for NAT Gateway %q (Resource Group %q) to be removed: %+v", id.PublicIPPrefixID, id.NatGateway.Name, id.NatGateway.ResourceGroup, err) + if err := client.CreateOrUpdateThenPoll(ctx, *id.First, *natGateway.Model); err != nil { + return fmt.Errorf("removing association between %s and %s: %+v", id.First, id.Second, err) } return nil diff --git a/internal/services/network/nat_gateway_public_ip_prefix_association_resource_test.go b/internal/services/network/nat_gateway_public_ip_prefix_association_resource_test.go index 38688c04040b..20657229b0e2 100644 --- a/internal/services/network/nat_gateway_public_ip_prefix_association_resource_test.go +++ b/internal/services/network/nat_gateway_public_ip_prefix_association_resource_test.go @@ -9,13 +9,14 @@ import ( "strings" "testing" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/natgateways" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/publicipprefixes" "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/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) type NatGatewayPublicIpPrefixAssociationResource struct{} @@ -86,50 +87,52 @@ func TestAccNatGatewayPublicIpPrefixAssociation_deleted(t *testing.T) { } func (t NatGatewayPublicIpPrefixAssociationResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.NatGatewayPublicIPPrefixAssociationID(state.ID) + id, err := commonids.ParseCompositeResourceID(state.ID, &natgateways.NatGatewayId{}, &publicipprefixes.PublicIPPrefixId{}) if err != nil { return nil, err } - resp, err := clients.Network.NatGatewayClient.Get(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, "") + resp, err := clients.Network.Client.NatGateways.Get(ctx, *id.First, natgateways.DefaultGetOperationOptions()) if err != nil { - return nil, fmt.Errorf("reading Nat Gateway Public IP Prefix Association (%s): %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", id.First, err) } - return utils.Bool(resp.ID != nil), nil + return pointer.To(resp.Model != nil), nil } func (NatGatewayPublicIpPrefixAssociationResource) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.NatGatewayPublicIPPrefixAssociationID(state.ID) + id, err := commonids.ParseCompositeResourceID(state.ID, &natgateways.NatGatewayId{}, &publicipprefixes.PublicIPPrefixId{}) if err != nil { return nil, err } - resp, err := client.Network.NatGatewayClient.Get(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, "") + resp, err := client.Network.Client.NatGateways.Get(ctx, *id.First, natgateways.DefaultGetOperationOptions()) if err != nil { - return nil, fmt.Errorf("reading Nat Gateway Public IP Prefix Association (%s): %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", id.First, err) } - updatedPrefixes := make([]network.SubResource, 0) - if publicIpPrefixes := resp.PublicIPPrefixes; publicIpPrefixes != nil { + if resp.Model == nil { + return nil, fmt.Errorf("retrieving %s: `model` was nil", id.First) + } + if resp.Model.Properties == nil { + return nil, fmt.Errorf("retrieving %s: `properties` was nil", id.First) + } + + updatedPrefixes := make([]natgateways.SubResource, 0) + if publicIpPrefixes := resp.Model.Properties.PublicIPPrefixes; publicIpPrefixes != nil { for _, publicIpPrefix := range *publicIpPrefixes { - if !strings.EqualFold(*publicIpPrefix.ID, id.PublicIPPrefixID) { + if !strings.EqualFold(*publicIpPrefix.Id, id.Second.ID()) { updatedPrefixes = append(updatedPrefixes, publicIpPrefix) } } } - resp.PublicIPPrefixes = &updatedPrefixes - - future, err := client.Network.NatGatewayClient.CreateOrUpdate(ctx, id.NatGateway.ResourceGroup, id.NatGateway.Name, resp) - if err != nil { - return nil, fmt.Errorf("failed to remove Nat Gateway Public IP Prefix Association for Nat Gateway %q: %+v", id, err) - } + resp.Model.Properties.PublicIPPrefixes = &updatedPrefixes - if err = future.WaitForCompletionRef(ctx, client.Network.NatGatewayClient.Client); err != nil { - return nil, fmt.Errorf("failed to wait for removal of Nat Gateway Public IP Prefix Association for Nat Gateway %q: %+v", id, err) + if err := client.Network.Client.NatGateways.CreateOrUpdateThenPoll(ctx, *id.First, *resp.Model); err != nil { + return nil, fmt.Errorf("deleting %s from %s: %+v", id.Second, id.First, err) } - return utils.Bool(true), nil + return pointer.To(true), nil } func (r NatGatewayPublicIpPrefixAssociationResource) basic(data acceptance.TestData) string { diff --git a/internal/services/network/nat_gateway_resource.go b/internal/services/network/nat_gateway_resource.go index 86c770eeb1a3..3b23ae5df234 100644 --- a/internal/services/network/nat_gateway_resource.go +++ b/internal/services/network/nat_gateway_resource.go @@ -8,21 +8,21 @@ import ( "log" "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-helpers/resourcemanager/tags" "github.com/hashicorp/go-azure-helpers/resourcemanager/zones" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/natgateways" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/services/network/validate" - "github.com/hashicorp/terraform-provider-azurerm/internal/tags" "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" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) var natGatewayResourceName = "azurerm_nat_gateway" @@ -42,7 +42,7 @@ func resourceNatGateway() *pluginsdk.Resource { }, Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := parse.NatGatewayID(id) + _, err := natgateways.ParseNatGatewayID(id) return err }), @@ -73,9 +73,9 @@ func resourceNatGatewaySchema() map[string]*pluginsdk.Schema { "sku_name": { Type: pluginsdk.TypeString, Optional: true, - Default: string(network.NatGatewaySkuNameStandard), + Default: string(natgateways.NatGatewaySkuNameStandard), ValidateFunc: validation.StringInSlice([]string{ - string(network.NatGatewaySkuNameStandard), + string(natgateways.NatGatewaySkuNameStandard), }, false), }, @@ -86,45 +86,40 @@ func resourceNatGatewaySchema() map[string]*pluginsdk.Schema { Computed: true, }, - "tags": tags.Schema(), + "tags": commonschema.Tags(), } } func resourceNatGatewayCreate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways subscriptionId := meta.(*clients.Client).Account.SubscriptionId ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() - id := parse.NewNatGatewayID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + id := natgateways.NewNatGatewayID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) - locks.ByName(id.Name, natGatewayResourceName) - defer locks.UnlockByName(id.Name, natGatewayResourceName) + locks.ByName(id.NatGatewayName, natGatewayResourceName) + defer locks.UnlockByName(id.NatGatewayName, natGatewayResourceName) - resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := client.Get(ctx, id, natgateways.DefaultGetOperationOptions()) if err != nil { - if !utils.ResponseWasNotFound(resp.Response) { + if !response.WasNotFound(resp.HttpResponse) { return fmt.Errorf("checking for present of existing %s: %+v", id, err) } } - if resp.ID != nil && *resp.ID != "" { - return tf.ImportAsExistsError("azurerm_nat_gateway", *resp.ID) + if resp.Model != nil && resp.Model.Id != nil && *resp.Model.Id != "" { + return tf.ImportAsExistsError("azurerm_nat_gateway", id.ID()) } - location := azure.NormalizeLocation(d.Get("location").(string)) - idleTimeoutInMinutes := d.Get("idle_timeout_in_minutes").(int) - skuName := d.Get("sku_name").(string) - t := d.Get("tags").(map[string]interface{}) - - parameters := network.NatGateway{ - Location: utils.String(location), - NatGatewayPropertiesFormat: &network.NatGatewayPropertiesFormat{ - IdleTimeoutInMinutes: utils.Int32(int32(idleTimeoutInMinutes)), + parameters := natgateways.NatGateway{ + Location: pointer.To(location.Normalize(d.Get("location").(string))), + Properties: &natgateways.NatGatewayPropertiesFormat{ + IdleTimeoutInMinutes: pointer.To(int64(d.Get("idle_timeout_in_minutes").(int))), }, - Sku: &network.NatGatewaySku{ - Name: network.NatGatewaySkuName(skuName), + Sku: &natgateways.NatGatewaySku{ + Name: pointer.To(natgateways.NatGatewaySkuName(d.Get("sku_name").(string))), }, - Tags: tags.Expand(t), + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), } zones := zones.ExpandUntyped(d.Get("zones").(*schema.Set).List()) @@ -132,13 +127,9 @@ func resourceNatGatewayCreate(d *pluginsdk.ResourceData, meta interface{}) error parameters.Zones = &zones } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, parameters) - if err != nil { + if err := client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil { return fmt.Errorf("creating %s: %+v", id, err) } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for creation of %s: %+v", id, err) - } d.SetId(id.ID()) @@ -146,134 +137,125 @@ func resourceNatGatewayCreate(d *pluginsdk.ResourceData, meta interface{}) error } func resourceNatGatewayUpdate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.NatGatewayID(d.Id()) + id, err := natgateways.ParseNatGatewayID(d.Id()) if err != nil { return err } - locks.ByName(id.Name, natGatewayResourceName) - defer locks.UnlockByName(id.Name, natGatewayResourceName) + locks.ByName(id.NatGatewayName, natGatewayResourceName) + defer locks.UnlockByName(id.NatGatewayName, natGatewayResourceName) - existing, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + existing, err := client.Get(ctx, *id, natgateways.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("%s was not found!", *id) + if response.WasNotFound(existing.HttpResponse) { + return fmt.Errorf("%s was not found", *id) } return fmt.Errorf("retrieving %s: %+v", *id, err) } - if existing.NatGatewayPropertiesFormat == nil { + if existing.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", *id) + } + if existing.Model.Properties == nil { return fmt.Errorf("retrieving %s: `properties` was nil", *id) } - props := *existing.NatGatewayPropertiesFormat + props := *existing.Model.Properties // intentionally building a new object rather than reusing due to the additional read-only fields - parameters := network.NatGateway{ - Location: existing.Location, - NatGatewayPropertiesFormat: &network.NatGatewayPropertiesFormat{ + payload := natgateways.NatGateway{ + Location: existing.Model.Location, + Properties: &natgateways.NatGatewayPropertiesFormat{ IdleTimeoutInMinutes: props.IdleTimeoutInMinutes, PublicIPAddresses: props.PublicIPAddresses, // note: these can be managed via the separate resource PublicIPPrefixes: props.PublicIPPrefixes, }, - Sku: existing.Sku, - Tags: existing.Tags, - Zones: existing.Zones, + Sku: existing.Model.Sku, + Tags: existing.Model.Tags, + Zones: existing.Model.Zones, } if d.HasChange("idle_timeout_in_minutes") { timeout := d.Get("idle_timeout_in_minutes").(int) - parameters.NatGatewayPropertiesFormat.IdleTimeoutInMinutes = utils.Int32(int32(timeout)) + payload.Properties.IdleTimeoutInMinutes = pointer.To(int64(timeout)) } if d.HasChange("sku_name") { - skuName := d.Get("sku_name").(string) - parameters.Sku = &network.NatGatewaySku{ - Name: network.NatGatewaySkuName(skuName), + payload.Sku = &natgateways.NatGatewaySku{ + Name: pointer.To(natgateways.NatGatewaySkuName(d.Get("sku_name").(string))), } } if d.HasChange("tags") { - t := d.Get("tags").(map[string]interface{}) - parameters.Tags = tags.Expand(t) + payload.Tags = tags.Expand(d.Get("tags").(map[string]interface{})) } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, parameters) - if err != nil { + if err := client.CreateOrUpdateThenPoll(ctx, *id, payload); err != nil { return fmt.Errorf("updating %s: %+v", *id, err) } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of %s: %+v", *id, err) - } return resourceNatGatewayRead(d, meta) } func resourceNatGatewayRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.NatGatewayID(d.Id()) + id, err := natgateways.ParseNatGatewayID(d.Id()) if err != nil { return err } - resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := client.Get(ctx, *id, natgateways.DefaultGetOperationOptions()) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - log.Printf("[DEBUG] NAT Gateway %q does not exist - removing from state", d.Id()) + if response.WasNotFound(resp.HttpResponse) { + log.Printf("[DEBUG] %s does not exist - removing from state", id.ID()) d.SetId("") return nil } - return fmt.Errorf("reading %s: %+v", *id, err) + return fmt.Errorf("retrieving %s: %+v", *id, err) } - d.Set("name", id.Name) - d.Set("resource_group_name", id.ResourceGroup) + d.Set("name", id.NatGatewayName) + d.Set("resource_group_name", id.ResourceGroupName) - if sku := resp.Sku; sku != nil { - d.Set("sku_name", sku.Name) - } - - if location := resp.Location; location != nil { - d.Set("location", azure.NormalizeLocation(*location)) - } - - if props := resp.NatGatewayPropertiesFormat; props != nil { - d.Set("idle_timeout_in_minutes", props.IdleTimeoutInMinutes) - d.Set("resource_guid", props.ResourceGUID) + if model := resp.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) + sku := "" + if model.Sku != nil { + sku = string(pointer.From(model.Sku.Name)) + } + d.Set("sku_name", sku) + d.Set("zones", zones.FlattenUntyped(model.Zones)) + if props := model.Properties; props != nil { + d.Set("idle_timeout_in_minutes", props.IdleTimeoutInMinutes) + d.Set("resource_guid", props.ResourceGuid) + } + return tags.FlattenAndSet(d, model.Tags) } - - d.Set("zones", zones.FlattenUntyped(resp.Zones)) - - return tags.FlattenAndSet(d, resp.Tags) + return nil } func resourceNatGatewayDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).Network.NatGatewayClient + client := meta.(*clients.Client).Network.Client.NatGateways ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.NatGatewayID(d.Id()) + id, err := natgateways.ParseNatGatewayID(d.Id()) if err != nil { return err } - locks.ByName(id.Name, natGatewayResourceName) - defer locks.UnlockByName(id.Name, natGatewayResourceName) + locks.ByName(id.NatGatewayName, natGatewayResourceName) + defer locks.UnlockByName(id.NatGatewayName, natGatewayResourceName) - future, err := client.Delete(ctx, id.ResourceGroup, id.Name) - if err != nil { + if err := client.DeleteThenPoll(ctx, *id); err != nil { return fmt.Errorf("deleting %s: %+v", *id, err) } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for the deletion of %s: %+v", *id, err) - } - return nil } diff --git a/internal/services/network/nat_gateway_resource_test.go b/internal/services/network/nat_gateway_resource_test.go index d9ee09c7bfd0..b3d13f1f5a6b 100644 --- a/internal/services/network/nat_gateway_resource_test.go +++ b/internal/services/network/nat_gateway_resource_test.go @@ -8,12 +8,12 @@ import ( "fmt" "testing" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-09-01/natgateways" "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/services/network/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) type NatGatewayResource struct{} @@ -76,17 +76,17 @@ func TestAccNatGateway_update(t *testing.T) { } func (t NatGatewayResource) Exists(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.NatGatewayID(state.ID) + id, err := natgateways.ParseNatGatewayID(state.ID) if err != nil { return nil, err } - resp, err := clients.Network.NatGatewayClient.Get(ctx, id.ResourceGroup, id.Name, "") + resp, err := clients.Network.Client.NatGateways.Get(ctx, *id, natgateways.DefaultGetOperationOptions()) if err != nil { - return nil, fmt.Errorf("reading NAT Gateway (%s): %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", id, err) } - return utils.Bool(resp.ID != nil), nil + return pointer.To(resp.Model != nil), nil } // Using alt location because the resource currently in private preview and is only available in eastus2. diff --git a/internal/services/network/network_subresource.go b/internal/services/network/network_subresource.go deleted file mode 100644 index 7b772ad46d8e..000000000000 --- a/internal/services/network/network_subresource.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package network - -import ( - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" -) - -func flattenNetworkSubResourceID(input *[]network.SubResource) []interface{} { - results := make([]interface{}, 0) - if input == nil { - return results - } - - for _, item := range *input { - if item.ID != nil { - results = append(results, *item.ID) - } - } - - return results -} diff --git a/scripts/run-gradually-deprecated.sh b/scripts/run-gradually-deprecated.sh index abd0ee601107..2040e853438a 100755 --- a/scripts/run-gradually-deprecated.sh +++ b/scripts/run-gradually-deprecated.sh @@ -75,9 +75,16 @@ function runGraduallyDeprecatedFunctions { } fi - # avoid false positives - isThisScript=$(echo "$f" | grep "run-gradually-deprecated") - if [ "$isThisScript" == "" ]; + # exceptions to avoid false positives and legacy resources should have their original behaviour preserved + exceptions=("run-gradually-deprecated" "/legacy/" "network/ip_group_cidr_resource.go") + toSkip=false + for e in "${exceptions[@]}"; do + isThisException=$(echo "$f" | grep "$e") + if [ "$isThisException" != "" ] ; then + toSkip=true + fi + done + if [ "$toSkip" = false ]; then # check for d.Get inside Delete deleteFuncName=$(grep -o "Delete: .*," "$f" -m1 | grep -o " .*Delete"| tr -d " ")