diff --git a/internal/clients/client.go b/internal/clients/client.go index df89e72b17b6..87b9fd383d84 100644 --- a/internal/clients/client.go +++ b/internal/clients/client.go @@ -472,7 +472,9 @@ func (client *Client) Build(ctx context.Context, o *common.ClientOptions) error if client.LogAnalytics, err = loganalytics.NewClient(o); err != nil { return fmt.Errorf("building clients for LogAnalytics: %+v", err) } - client.LoadBalancers = loadbalancers.NewClient(o) + if client.LoadBalancers, err = loadbalancers.NewClient(o); err != nil { + return fmt.Errorf("building clients for LoadBalancers: %+v", err) + } if client.Logic, err = logic.NewClient(o); err != nil { return fmt.Errorf("building clients for Logic: %+v", err) } diff --git a/internal/services/databricks/databricks_workspace_resource.go b/internal/services/databricks/databricks_workspace_resource.go index cbec8c159033..bb7ae00cefc5 100644 --- a/internal/services/databricks/databricks_workspace_resource.go +++ b/internal/services/databricks/databricks_workspace_resource.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/go-azure-helpers/resourcemanager/tags" "github.com/hashicorp/go-azure-sdk/resource-manager/databricks/2023-02-01/workspaces" mlworkspace "github.com/hashicorp/go-azure-sdk/resource-manager/machinelearningservices/2023-10-01/workspaces" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" @@ -24,8 +25,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/services/databricks/validate" keyVaultParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/parse" keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate" - loadBalancerParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" - loadBalancerValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" resourcesParse "github.com/hashicorp/terraform-provider-azurerm/internal/services/resource/parse" storageValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/storage/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" @@ -160,7 +159,7 @@ func resourceDatabricksWorkspace() *pluginsdk.Resource { Type: pluginsdk.TypeString, Optional: true, ForceNew: true, - ValidateFunc: loadBalancerValidate.LoadBalancerBackendAddressPoolID, + ValidateFunc: loadbalancers.ValidateLoadBalancerBackendAddressPoolID, }, "custom_parameters": { @@ -386,13 +385,13 @@ func resourceDatabricksWorkspaceCreateUpdate(d *pluginsdk.ResourceData, meta int expandedTags := tags.Expand(d.Get("tags").(map[string]interface{})) if backendPool != "" { - backendPoolId, err := loadBalancerParse.LoadBalancerBackendAddressPoolID(backendPool) + backendPoolId, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(backendPool) if err != nil { return err } // Generate the load balancer ID from the Backend Address Pool Id... - lbId := loadBalancerParse.NewLoadBalancerID(backendPoolId.SubscriptionId, backendPoolId.ResourceGroup, backendPoolId.LoadBalancerName) + lbId := loadbalancers.NewLoadBalancerID(backendPoolId.SubscriptionId, backendPoolId.ResourceGroupName, backendPoolId.LoadBalancerName) backendPoolName = backendPoolId.BackendAddressPoolName loadBalancerId = lbId.ID() @@ -404,12 +403,13 @@ func resourceDatabricksWorkspaceCreateUpdate(d *pluginsdk.ResourceData, meta int defer locks.UnlockByID(lbId.ID()) // check to make sure the load balancer exists as referred to by the Backend Address Pool... - lb, err := lbClient.Get(ctx, lbId.ResourceGroup, lbId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: backendPoolId.SubscriptionId, ResourceGroupName: backendPoolId.ResourceGroupName, LoadBalancerName: backendPoolId.LoadBalancerName} + lb, err := lbClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(lb.Response) { - return fmt.Errorf("load balancer %q for Backend Address Pool %q was not found", lbId, backendPoolId) + if response.WasNotFound(lb.HttpResponse) { + return fmt.Errorf("%s was not found", lbId) } - return fmt.Errorf("failed to retrieve Load Balancer %q for Backend Address Pool %q: %+v", lbId, backendPoolId, err) + return fmt.Errorf("retrieving %s: %+v", lbId, err) } } @@ -829,10 +829,10 @@ func flattenWorkspaceCustomParameters(input *workspaces.WorkspaceCustomParameter parameters["virtual_network_id"] = v.Value } - lbId, err := loadBalancerParse.LoadBalancerIDInsensitively(loadBalancerId) + lbId, err := loadbalancers.ParseLoadBalancerIDInsensitively(loadBalancerId) if err == nil { - backendId := loadBalancerParse.NewLoadBalancerBackendAddressPoolID(lbId.SubscriptionId, lbId.ResourceGroup, lbId.Name, backendName) + backendId := loadbalancers.NewLoadBalancerBackendAddressPoolID(lbId.SubscriptionId, lbId.ResourceGroupName, lbId.LoadBalancerName, backendName) backendAddressPoolId = backendId.ID() } diff --git a/internal/services/loadbalancer/backend_address_pool_address_resource.go b/internal/services/loadbalancer/backend_address_pool_address_resource.go index 1f37cdf650dc..0980db339d47 100644 --- a/internal/services/loadbalancer/backend_address_pool_address_resource.go +++ b/internal/services/loadbalancer/backend_address_pool_address_resource.go @@ -8,15 +8,15 @@ import ( "fmt" "time" + "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-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) var ( @@ -77,7 +77,7 @@ func (r BackendAddressPoolAddressResource) Arguments() map[string]*pluginsdk.Sch Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.LoadBalancerBackendAddressPoolID, + ValidateFunc: loadbalancers.ValidateLoadBalancerBackendAddressPoolID, }, "virtual_network_id": { @@ -100,7 +100,7 @@ func (r BackendAddressPoolAddressResource) Arguments() map[string]*pluginsdk.Sch Type: pluginsdk.TypeString, Optional: true, ConflictsWith: []string{"virtual_network_id"}, - ValidateFunc: validate.LoadBalancerFrontendIpConfigurationID, + ValidateFunc: loadbalancers.ValidateFrontendIPConfigurationID, Description: "For global load balancer, user needs to specify the `backend_address_ip_configuration_id` of the added regional load balancers", }, } @@ -123,7 +123,7 @@ func (r BackendAddressPoolAddressResource) ResourceType() string { func (r BackendAddressPoolAddressResource) Create() sdk.ResourceFunc { return sdk.ResourceFunc{ Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - client := metadata.Client.LoadBalancers.LoadBalancerBackendAddressPoolsClient + lbClient := metadata.Client.LoadBalancers.LoadBalancersClient subscriptionId := metadata.Client.Account.SubscriptionId var model BackendAddressPoolAddressModel @@ -131,7 +131,7 @@ func (r BackendAddressPoolAddressResource) Create() sdk.ResourceFunc { return fmt.Errorf("decoding: %+v", err) } - poolId, err := parse.LoadBalancerBackendAddressPoolID(model.BackendAddressPoolId) + poolId, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(model.BackendAddressPoolId) if err != nil { return err } @@ -140,80 +140,92 @@ func (r BackendAddressPoolAddressResource) Create() sdk.ResourceFunc { defer locks.UnlockByName(poolId.BackendAddressPoolName, backendAddressPoolResourceName) // Backend Addresses can not be created for Basic sku, so we have to check - lb, err := metadata.Client.LoadBalancers.LoadBalancersClient.Get(ctx, poolId.ResourceGroup, poolId.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: subscriptionId, ResourceGroupName: poolId.ResourceGroupName, LoadBalancerName: poolId.LoadBalancerName} + lb, err := metadata.Client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return fmt.Errorf("retrieving Load Balancer %q (Resource Group %q): %+v", poolId.LoadBalancerName, poolId.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", plbId, err) } + isBasicSku := true - if lb.Sku != nil && lb.Sku.Name != network.LoadBalancerSkuNameBasic { - isBasicSku = false - } - if isBasicSku { - return fmt.Errorf("Backend Addresses are not supported on Basic SKU Load Balancers") - } - if lb.Sku != nil && lb.Sku.Tier == network.LoadBalancerSkuTierGlobal { - if model.FrontendIPConfiguration == "" { - return fmt.Errorf("Please set a Regional Backend Address Pool Addresses for the Global load balancer") + if lb := lb.Model; lb != nil { + if lb.Sku != nil && pointer.From(lb.Sku.Name) != loadbalancers.LoadBalancerSkuNameBasic { + isBasicSku = false + } + if isBasicSku { + return fmt.Errorf("Backend Addresses are not supported on Basic SKU Load Balancers") + } + if lb.Sku != nil && pointer.From(lb.Sku.Tier) == loadbalancers.LoadBalancerSkuTierGlobal { + if model.FrontendIPConfiguration == "" { + return fmt.Errorf("Please set a Regional Backend Address Pool Addresses for the Global load balancer") + } } - } - id := parse.NewBackendAddressPoolAddressID(subscriptionId, poolId.ResourceGroup, poolId.LoadBalancerName, poolId.BackendAddressPoolName, model.Name) - pool, err := client.Get(ctx, poolId.ResourceGroup, poolId.LoadBalancerName, poolId.BackendAddressPoolName) - if err != nil { - return fmt.Errorf("retrieving %s: %+v", *poolId, err) - } - if pool.BackendAddressPoolPropertiesFormat == nil { - return fmt.Errorf("retrieving %s: `properties` was nil", *poolId) - } + id := parse.NewBackendAddressPoolAddressID(subscriptionId, poolId.ResourceGroupName, poolId.LoadBalancerName, poolId.BackendAddressPoolName, model.Name) + pool, err := lbClient.LoadBalancerBackendAddressPoolsGet(ctx, *poolId) + if err != nil { + return fmt.Errorf("retrieving %s: %+v", *poolId, err) + } - addresses := make([]network.LoadBalancerBackendAddress, 0) - if pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses != nil { - addresses = *pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses - } + if pool.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", *poolId) + } - metadata.Logger.Infof("checking for existing %s..", id) - for _, address := range addresses { - if address.Name == nil { - continue + if pool.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", *poolId) } - if *address.Name == id.AddressName { - return metadata.ResourceRequiresImport(r.ResourceType(), id) + addresses := make([]loadbalancers.LoadBalancerBackendAddress, 0) + if pool.Model.Properties.LoadBalancerBackendAddresses != nil { + addresses = *pool.Model.Properties.LoadBalancerBackendAddresses + } + + metadata.Logger.Infof("checking for existing %s..", id) + for _, address := range addresses { + if address.Name == nil { + continue + } + + if *address.Name == model.Name { + return metadata.ResourceRequiresImport(r.ResourceType(), id) + } } - } - if lb.Sku.Tier == network.LoadBalancerSkuTierGlobal { - addresses = append(addresses, network.LoadBalancerBackendAddress{ - Name: utils.String(id.AddressName), - LoadBalancerBackendAddressPropertiesFormat: &network.LoadBalancerBackendAddressPropertiesFormat{ - LoadBalancerFrontendIPConfiguration: &network.SubResource{ - ID: utils.String(model.FrontendIPConfiguration), + if pointer.From(lb.Sku.Tier) == loadbalancers.LoadBalancerSkuTierGlobal { + addresses = append(addresses, loadbalancers.LoadBalancerBackendAddress{ + Name: pointer.To(model.Name), + Properties: &loadbalancers.LoadBalancerBackendAddressPropertiesFormat{ + LoadBalancerFrontendIPConfiguration: &loadbalancers.SubResource{ + Id: pointer.To(model.FrontendIPConfiguration), + }, }, - }, - }) - } else { - addresses = append(addresses, network.LoadBalancerBackendAddress{ - LoadBalancerBackendAddressPropertiesFormat: &network.LoadBalancerBackendAddressPropertiesFormat{ - IPAddress: utils.String(model.IPAddress), - VirtualNetwork: &network.SubResource{ - ID: utils.String(model.VirtualNetworkId), + }) + } else { + addresses = append(addresses, loadbalancers.LoadBalancerBackendAddress{ + Properties: &loadbalancers.LoadBalancerBackendAddressPropertiesFormat{ + IPAddress: pointer.To(model.IPAddress), + VirtualNetwork: &loadbalancers.SubResource{ + Id: pointer.To(model.VirtualNetworkId), + }, }, + Name: pointer.To(model.Name), + }) + } + + backendAddressPool := loadbalancers.BackendAddressPool{ + Properties: &loadbalancers.BackendAddressPoolPropertiesFormat{ + LoadBalancerBackendAddresses: &addresses, }, - Name: utils.String(id.AddressName), - }) - } - pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses = &addresses + } + metadata.Logger.Infof("adding %s..", id) + err = lbClient.LoadBalancerBackendAddressPoolsCreateOrUpdateThenPoll(ctx, *poolId, backendAddressPool) + if err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + metadata.Logger.Infof("waiting for update %s..", id) - metadata.Logger.Infof("adding %s..", id) - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName, pool) - if err != nil { - return fmt.Errorf("updating %s: %+v", id, err) - } - metadata.Logger.Infof("waiting for update %s..", id) - if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of %s: %+v", id, err) + metadata.SetID(id) } - metadata.SetID(id) + return nil }, Timeout: 30 * time.Minute, @@ -223,84 +235,91 @@ func (r BackendAddressPoolAddressResource) Create() sdk.ResourceFunc { func (r BackendAddressPoolAddressResource) Read() sdk.ResourceFunc { return sdk.ResourceFunc{ Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - client := metadata.Client.LoadBalancers.LoadBalancerBackendAddressPoolsClient lbClient := metadata.Client.LoadBalancers.LoadBalancersClient + id, err := parse.BackendAddressPoolAddressID(metadata.ResourceData.Id()) if err != nil { return err } - pool, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + poolId := loadbalancers.NewLoadBalancerBackendAddressPoolID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + pool, err := lbClient.LoadBalancerBackendAddressPoolsGet(ctx, poolId) if err != nil { - return fmt.Errorf("retrieving %s: %+v", *id, err) + return fmt.Errorf("retrieving %s: %+v", poolId, err) } - if pool.BackendAddressPoolPropertiesFormat == nil { - return fmt.Errorf("retrieving %s: `properties` was nil", *id) + if pool.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", poolId) + } + if pool.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", poolId) } - lb, err := lbClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroup, LoadBalancerName: id.LoadBalancerName} + lb, err := lbClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return fmt.Errorf("retrieving Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) + return fmt.Errorf("checking for presence of existing %s: %+v", plbId, err) } - var backendAddress *network.LoadBalancerBackendAddress - if pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses != nil { - for _, address := range *pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses { - if address.Name == nil { - continue - } + var backendAddress *loadbalancers.LoadBalancerBackendAddress + if model := pool.Model; model != nil { + if pool := model.Properties; pool != nil { + for _, address := range *pool.LoadBalancerBackendAddresses { + if address.Name == nil { + continue + } - if *address.Name == id.AddressName { - backendAddress = &address - break + if *address.Name == id.AddressName { + backendAddress = &address + break + } } } } + if backendAddress == nil { return metadata.MarkAsGone(id) } - backendAddressPoolId := parse.NewLoadBalancerBackendAddressPoolID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) model := BackendAddressPoolAddressModel{ Name: id.AddressName, - BackendAddressPoolId: backendAddressPoolId.ID(), + BackendAddressPoolId: poolId.ID(), } - if props := backendAddress.LoadBalancerBackendAddressPropertiesFormat; props != nil { - if lb.Sku.Tier == network.LoadBalancerSkuTierGlobal { - if props.LoadBalancerFrontendIPConfiguration != nil && props.LoadBalancerFrontendIPConfiguration.ID != nil { - model.FrontendIPConfiguration = *props.LoadBalancerFrontendIPConfiguration.ID + if props := backendAddress.Properties; props != nil { + if lb.Model != nil && pointer.From(lb.Model.Sku.Tier) == loadbalancers.LoadBalancerSkuTierGlobal { + if props.LoadBalancerFrontendIPConfiguration != nil && props.LoadBalancerFrontendIPConfiguration.Id != nil { + model.FrontendIPConfiguration = *props.LoadBalancerFrontendIPConfiguration.Id } } else { if props.IPAddress != nil { model.IPAddress = *props.IPAddress } - if props.VirtualNetwork != nil && props.VirtualNetwork.ID != nil { - model.VirtualNetworkId = *props.VirtualNetwork.ID + if props.VirtualNetwork != nil && props.VirtualNetwork.Id != nil { + model.VirtualNetworkId = *props.VirtualNetwork.Id } } - } - - var inboundNATRulePortMappingList []inboundNATRulePortMapping - if rules := backendAddress.LoadBalancerBackendAddressPropertiesFormat.InboundNatRulesPortMapping; rules != nil { - for _, rule := range *rules { - rulePortMapping := inboundNATRulePortMapping{} - - if rule.InboundNatRuleName != nil { - rulePortMapping.Name = *rule.InboundNatRuleName - } - if rule.FrontendPort != nil { - rulePortMapping.FrontendPort = *rule.FrontendPort - } - - if rule.BackendPort != nil { - rulePortMapping.BackendPort = *rule.BackendPort + var inboundNATRulePortMappingList []inboundNATRulePortMapping + if rules := props.InboundNatRulesPortMapping; rules != nil { + for _, rule := range *rules { + rulePortMapping := inboundNATRulePortMapping{} + + if rule.InboundNatRuleName != nil { + rulePortMapping.Name = *rule.InboundNatRuleName + } + if rule.FrontendPort != nil { + rulePortMapping.FrontendPort = int32(*rule.FrontendPort) + } + + if rule.BackendPort != nil { + rulePortMapping.BackendPort = int32(*rule.BackendPort) + } + inboundNATRulePortMappingList = append(inboundNATRulePortMappingList, rulePortMapping) } - inboundNATRulePortMappingList = append(inboundNATRulePortMappingList, rulePortMapping) + model.PortMapping = inboundNATRulePortMappingList } - model.PortMapping = inboundNATRulePortMappingList } + return metadata.Encode(&model) }, Timeout: 5 * time.Minute, @@ -310,7 +329,6 @@ func (r BackendAddressPoolAddressResource) Read() sdk.ResourceFunc { func (r BackendAddressPoolAddressResource) Delete() sdk.ResourceFunc { return sdk.ResourceFunc{ Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - client := metadata.Client.LoadBalancers.LoadBalancerBackendAddressPoolsClient lbClient := metadata.Client.LoadBalancers.LoadBalancersClient id, err := parse.BackendAddressPoolAddressID(metadata.ResourceData.Id()) if err != nil { @@ -320,18 +338,23 @@ func (r BackendAddressPoolAddressResource) Delete() sdk.ResourceFunc { locks.ByName(id.BackendAddressPoolName, backendAddressPoolResourceName) defer locks.UnlockByName(id.BackendAddressPoolName, backendAddressPoolResourceName) - pool, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + poolId := loadbalancers.NewLoadBalancerBackendAddressPoolID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + pool, err := lbClient.LoadBalancerBackendAddressPoolsGet(ctx, poolId) if err != nil { - return fmt.Errorf("retrieving %s: %+v", *id, err) + return fmt.Errorf("retrieving %s: %+v", poolId, err) } - if pool.BackendAddressPoolPropertiesFormat == nil { - return fmt.Errorf("retrieving %s: `properties` was nil", *id) + if pool.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", poolId) + } + + if pool.Model.Properties == nil { + return fmt.Errorf("retrieving %s: `properties` was nil", poolId) } timeout, _ := ctx.Deadline() lbStatus := &pluginsdk.StateChangeConf{ - Pending: []string{string(network.ProvisioningStateUpdating)}, - Target: []string{string(network.ProvisioningStateSucceeded)}, + Pending: []string{string(loadbalancers.ProvisioningStateUpdating)}, + Target: []string{string(loadbalancers.ProvisioningStateSucceeded)}, MinTimeout: 5 * time.Second, Refresh: loadbalacnerProvisioningStatusRefreshFunc(ctx, lbClient, *id), ContinuousTargetOccurence: 10, @@ -342,12 +365,12 @@ func (r BackendAddressPoolAddressResource) Delete() sdk.ResourceFunc { return fmt.Errorf("waiting for parent resource loadbalancer status to be ready error: %+v", err) } - addresses := make([]network.LoadBalancerBackendAddress, 0) - if pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses != nil { - addresses = *pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses + addresses := make([]loadbalancers.LoadBalancerBackendAddress, 0) + if pool.Model.Properties.LoadBalancerBackendAddresses != nil { + addresses = *pool.Model.Properties.LoadBalancerBackendAddresses } - newAddresses := make([]network.LoadBalancerBackendAddress, 0) + newAddresses := make([]loadbalancers.LoadBalancerBackendAddress, 0) for _, address := range addresses { if address.Name == nil { continue @@ -357,16 +380,19 @@ func (r BackendAddressPoolAddressResource) Delete() sdk.ResourceFunc { newAddresses = append(newAddresses, address) } } - pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses = &newAddresses metadata.Logger.Infof("removing %s..", *id) - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName, pool) + backendAddress := loadbalancers.BackendAddressPool{ + Properties: &loadbalancers.BackendAddressPoolPropertiesFormat{ + LoadBalancerBackendAddresses: &newAddresses, + }, + } + + err = lbClient.LoadBalancerBackendAddressPoolsCreateOrUpdateThenPoll(ctx, poolId, backendAddress) if err != nil { return fmt.Errorf("removing %s: %+v", *id, err) } - if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for removal of %s: %+v", *id, err) - } + return nil }, Timeout: 30 * time.Minute, @@ -380,7 +406,6 @@ func (r BackendAddressPoolAddressResource) IDValidationFunc() pluginsdk.SchemaVa func (r BackendAddressPoolAddressResource) Update() sdk.ResourceFunc { return sdk.ResourceFunc{ Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - client := metadata.Client.LoadBalancers.LoadBalancerBackendAddressPoolsClient lbClient := metadata.Client.LoadBalancers.LoadBalancersClient id, err := parse.BackendAddressPoolAddressID(metadata.ResourceData.Id()) if err != nil { @@ -395,22 +420,27 @@ func (r BackendAddressPoolAddressResource) Update() sdk.ResourceFunc { return fmt.Errorf("decoding: %+v", err) } - pool, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + poolId := loadbalancers.NewLoadBalancerBackendAddressPoolID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + pool, err := lbClient.LoadBalancerBackendAddressPoolsGet(ctx, poolId) if err != nil { return fmt.Errorf("retrieving %s: %+v", *id, err) } - if pool.BackendAddressPoolPropertiesFormat == nil { + if pool.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", *id) + } + if pool.Model.Properties == nil { return fmt.Errorf("retrieving %s: `properties` was nil", *id) } - lb, err := lbClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroup, LoadBalancerName: id.LoadBalancerName} + lb, err := lbClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return fmt.Errorf("retrieving Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) + return fmt.Errorf("retrieving %s: %+v", plbId, err) } - addresses := make([]network.LoadBalancerBackendAddress, 0) - if pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses != nil { - addresses = *pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses + addresses := make([]loadbalancers.LoadBalancerBackendAddress, 0) + if backendAddress := pool.Model.Properties.LoadBalancerBackendAddresses; backendAddress != nil { + addresses = *backendAddress } index := -1 for i, address := range addresses { @@ -427,32 +457,37 @@ func (r BackendAddressPoolAddressResource) Update() sdk.ResourceFunc { return fmt.Errorf("%s was not found", *id) } - if lb.Sku.Tier == network.LoadBalancerSkuTierGlobal { - addresses[index] = network.LoadBalancerBackendAddress{ - Name: utils.String(model.Name), - LoadBalancerBackendAddressPropertiesFormat: &network.LoadBalancerBackendAddressPropertiesFormat{ - LoadBalancerFrontendIPConfiguration: &network.SubResource{ - ID: utils.String(model.FrontendIPConfiguration), + if lb.Model != nil && pointer.From(lb.Model.Sku.Tier) == loadbalancers.LoadBalancerSkuTierGlobal { + addresses[index] = loadbalancers.LoadBalancerBackendAddress{ + Name: pointer.To(model.Name), + Properties: &loadbalancers.LoadBalancerBackendAddressPropertiesFormat{ + LoadBalancerFrontendIPConfiguration: &loadbalancers.SubResource{ + Id: pointer.To(model.FrontendIPConfiguration), }, }, } } else { - addresses[index] = network.LoadBalancerBackendAddress{ - LoadBalancerBackendAddressPropertiesFormat: &network.LoadBalancerBackendAddressPropertiesFormat{ - IPAddress: utils.String(model.IPAddress), - VirtualNetwork: &network.SubResource{ - ID: utils.String(model.VirtualNetworkId), + addresses[index] = loadbalancers.LoadBalancerBackendAddress{ + Properties: &loadbalancers.LoadBalancerBackendAddressPropertiesFormat{ + IPAddress: pointer.To(model.IPAddress), + VirtualNetwork: &loadbalancers.SubResource{ + Id: pointer.To(model.VirtualNetworkId), }, }, - Name: utils.String(id.AddressName), + Name: pointer.To(id.AddressName), } } - pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses = &addresses + + backendAddressPool := loadbalancers.BackendAddressPool{ + Properties: &loadbalancers.BackendAddressPoolPropertiesFormat{ + LoadBalancerBackendAddresses: &addresses, + }, + } timeout, _ := ctx.Deadline() lbStatus := &pluginsdk.StateChangeConf{ - Pending: []string{string(network.ProvisioningStateUpdating)}, - Target: []string{string(network.ProvisioningStateSucceeded)}, + Pending: []string{string(loadbalancers.ProvisioningStateUpdating)}, + Target: []string{string(loadbalancers.ProvisioningStateSucceeded)}, MinTimeout: 5 * time.Minute, PollInterval: 10 * time.Second, Refresh: loadbalacnerProvisioningStatusRefreshFunc(ctx, lbClient, *id), @@ -464,25 +499,28 @@ func (r BackendAddressPoolAddressResource) Update() sdk.ResourceFunc { return fmt.Errorf("waiting for parent resource loadbalancer status to be ready error: %+v", err) } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName, pool) + err = lbClient.LoadBalancerBackendAddressPoolsCreateOrUpdateThenPoll(ctx, poolId, backendAddressPool) if 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 nil }, Timeout: 30 * time.Minute, } } -func loadbalacnerProvisioningStatusRefreshFunc(ctx context.Context, client *network.LoadBalancersClient, id parse.BackendAddressPoolAddressId) pluginsdk.StateRefreshFunc { +func loadbalacnerProvisioningStatusRefreshFunc(ctx context.Context, client *loadbalancers.LoadBalancersClient, id parse.BackendAddressPoolAddressId) pluginsdk.StateRefreshFunc { return func() (interface{}, string, error) { - lbClient, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroup, LoadBalancerName: id.LoadBalancerName} + lbClient, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { return nil, "", fmt.Errorf("retrieving load balancer error: %+v", err) } - return lbClient, string(lbClient.ProvisioningState), nil + if model := lbClient.Model; model != nil { + if props := model.Properties; props != nil { + return lbClient, string(pointer.From(props.ProvisioningState)), nil + } + } + return lbClient, "", nil } } diff --git a/internal/services/loadbalancer/backend_address_pool_address_resource_test.go b/internal/services/loadbalancer/backend_address_pool_address_resource_test.go index 42ca150027ab..fa89e7bcade7 100644 --- a/internal/services/loadbalancer/backend_address_pool_address_resource_test.go +++ b/internal/services/loadbalancer/backend_address_pool_address_resource_test.go @@ -8,14 +8,14 @@ import ( "fmt" "testing" + "github.com/hashicorp/go-azure-helpers/lang/pointer" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/types" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/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" ) var _ types.TestResourceVerifyingRemoved = BackendAddressPoolAddressResourceTests{} @@ -130,26 +130,31 @@ func (BackendAddressPoolAddressResourceTests) Exists(ctx context.Context, client return nil, err } - pool, err := client.LoadBalancers.LoadBalancerBackendAddressPoolsClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + poolId := loadbalancers.NewLoadBalancerBackendAddressPoolID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + pool, err := client.LoadBalancers.LoadBalancersClient.LoadBalancerBackendAddressPoolsGet(ctx, poolId) if err != nil { return nil, fmt.Errorf("retrieving %s: %+v", *id, err) } - if pool.BackendAddressPoolPropertiesFormat == nil { + if pool.Model == nil { + return nil, fmt.Errorf("retrieving %s: `model` was nil", *id) + } + + if pool.Model.Properties == nil { return nil, fmt.Errorf("retrieving %s: `properties` was nil", *id) } - if pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses != nil { - for _, address := range *pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses { + if backendAddress := pool.Model.Properties.LoadBalancerBackendAddresses; backendAddress != nil { + for _, address := range *backendAddress { if address.Name == nil { continue } if *address.Name == id.AddressName { - return utils.Bool(true), nil + return pointer.To(true), nil } } } - return utils.Bool(false), nil + return pointer.To(false), nil } func (BackendAddressPoolAddressResourceTests) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { @@ -158,19 +163,23 @@ func (BackendAddressPoolAddressResourceTests) Destroy(ctx context.Context, clien return nil, err } - pool, err := client.LoadBalancers.LoadBalancerBackendAddressPoolsClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + poolId := loadbalancers.NewLoadBalancerBackendAddressPoolID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + pool, err := client.LoadBalancers.LoadBalancersClient.LoadBalancerBackendAddressPoolsGet(ctx, poolId) if err != nil { return nil, fmt.Errorf("retrieving %s: %+v", *id, err) } - if pool.BackendAddressPoolPropertiesFormat == nil { + if pool.Model == nil { + return nil, fmt.Errorf("retrieving %s: `model` was nil", *id) + } + if pool.Model.Properties == nil { return nil, fmt.Errorf("retrieving %s: `properties` was nil", *id) } - addresses := make([]network.LoadBalancerBackendAddress, 0) - if pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses != nil { - addresses = *pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses + addresses := make([]loadbalancers.LoadBalancerBackendAddress, 0) + if pool.Model.Properties.LoadBalancerBackendAddresses != nil { + addresses = *pool.Model.Properties.LoadBalancerBackendAddresses } - newAddresses := make([]network.LoadBalancerBackendAddress, 0) + newAddresses := make([]loadbalancers.LoadBalancerBackendAddress, 0) for _, address := range addresses { if address.Name == nil { continue @@ -180,39 +189,43 @@ func (BackendAddressPoolAddressResourceTests) Destroy(ctx context.Context, clien newAddresses = append(newAddresses, address) } } - pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses = &newAddresses - future, err := client.LoadBalancers.LoadBalancerBackendAddressPoolsClient.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName, pool) + backendAddressPool := loadbalancers.BackendAddressPool{ + Properties: &loadbalancers.BackendAddressPoolPropertiesFormat{ + LoadBalancerBackendAddresses: &newAddresses, + }, + } + err = client.LoadBalancers.LoadBalancersClient.LoadBalancerBackendAddressPoolsCreateOrUpdateThenPoll(ctx, poolId, backendAddressPool) if err != nil { return nil, fmt.Errorf("updating %s: %+v", *id, err) } - if err := future.WaitForCompletionRef(ctx, client.LoadBalancers.LoadBalancerBackendAddressPoolsClient.Client); err != nil { - return nil, fmt.Errorf("waiting for update of %s: %+v", *id, err) - } - return utils.Bool(true), nil + + return pointer.To(true), nil } // nolint unused - for future use func (BackendAddressPoolAddressResourceTests) backendAddressPoolHasAddresses(expected int) acceptance.ClientCheckFunc { return func(ctx context.Context, clients *clients.Client, state *pluginsdk.InstanceState) error { - id, err := parse.LoadBalancerBackendAddressPoolID(state.ID) + id, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(state.ID) if err != nil { return err } - client := clients.LoadBalancers.LoadBalancerBackendAddressPoolsClient - pool, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + pool, err := clients.LoadBalancers.LoadBalancersClient.LoadBalancerBackendAddressPoolsGet(ctx, *id) if err != nil { return err } - if pool.BackendAddressPoolPropertiesFormat == nil { + if pool.Model == nil { + return fmt.Errorf("`model` is nil") + } + if pool.Model.Properties == nil { return fmt.Errorf("`properties` is nil") } - if pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses == nil { + if pool.Model.Properties.LoadBalancerBackendAddresses == nil { return fmt.Errorf("`properties.loadBalancerBackendAddresses` is nil") } - actual := len(*pool.BackendAddressPoolPropertiesFormat.LoadBalancerBackendAddresses) + actual := len(*pool.Model.Properties.LoadBalancerBackendAddresses) if actual != expected { return fmt.Errorf("expected %d but got %d addresses", expected, actual) } diff --git a/internal/services/loadbalancer/backend_address_pool_data_source.go b/internal/services/loadbalancer/backend_address_pool_data_source.go index 35aca69239ec..302752033359 100644 --- a/internal/services/loadbalancer/backend_address_pool_data_source.go +++ b/internal/services/loadbalancer/backend_address_pool_data_source.go @@ -7,14 +7,13 @@ import ( "fmt" "time" + "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-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func dataSourceArmLoadBalancerBackendAddressPool() *pluginsdk.Resource { @@ -34,7 +33,7 @@ func dataSourceArmLoadBalancerBackendAddressPool() *pluginsdk.Resource { "loadbalancer_id": { Type: pluginsdk.TypeString, Required: true, - ValidateFunc: validate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "backend_address": { @@ -122,90 +121,92 @@ func dataSourceArmLoadBalancerBackendAddressPool() *pluginsdk.Resource { } func dataSourceArmLoadBalancerBackendAddressPoolRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).LoadBalancers.LoadBalancerBackendAddressPoolsClient + lbClient := meta.(*clients.Client).LoadBalancers.LoadBalancersClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() name := d.Get("name").(string) - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return err } - id := parse.NewLoadBalancerBackendAddressPoolID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, name) + id := loadbalancers.NewLoadBalancerBackendAddressPoolID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, name) - resp, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + resp, err := lbClient.LoadBalancerBackendAddressPoolsGet(ctx, id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Load Balancer Backend Address Pool %q was not found", id) + if response.WasNotFound(resp.HttpResponse) { + return fmt.Errorf("%s was not found", id) } - return fmt.Errorf("failed to retrieve Load Balancer Backend Address Pool %q: %+v", id, err) + return fmt.Errorf("retrieving %s: %+v", id, err) } d.SetId(id.ID()) - if props := resp.BackendAddressPoolPropertiesFormat; props != nil { - if err := d.Set("backend_address", flattenArmLoadBalancerBackendAddresses(props.LoadBalancerBackendAddresses)); err != nil { - return fmt.Errorf("setting `backend_address`: %v", err) - } + if model := resp.Model; model != nil { + if props := model.Properties; props != nil { + if err := d.Set("backend_address", flattenArmLoadBalancerBackendAddresses(props.LoadBalancerBackendAddresses)); err != nil { + return fmt.Errorf("setting `backend_address`: %v", err) + } - var backendIPConfigurations []interface{} - if beipConfigs := props.BackendIPConfigurations; beipConfigs != nil { - for _, config := range *beipConfigs { - ipConfig := make(map[string]interface{}) - if id := config.ID; id != nil { - ipConfig["id"] = *id - backendIPConfigurations = append(backendIPConfigurations, ipConfig) + var backendIPConfigurations []interface{} + if beipConfigs := props.BackendIPConfigurations; beipConfigs != nil { + for _, config := range *beipConfigs { + ipConfig := make(map[string]interface{}) + if id := config.Id; id != nil { + ipConfig["id"] = pointer.From(id) + backendIPConfigurations = append(backendIPConfigurations, ipConfig) + } } } - } - if err := d.Set("backend_ip_configurations", backendIPConfigurations); err != nil { - return fmt.Errorf("setting `backend_ip_configurations`: %v", err) - } + if err := d.Set("backend_ip_configurations", backendIPConfigurations); err != nil { + return fmt.Errorf("setting `backend_ip_configurations`: %v", err) + } - var loadBalancingRules []string - if rules := props.LoadBalancingRules; rules != nil { - for _, rule := range *rules { - if rule.ID == nil { - continue + var loadBalancingRules []string + if rules := props.LoadBalancingRules; rules != nil { + for _, rule := range *rules { + if rule.Id == nil { + continue + } + loadBalancingRules = append(loadBalancingRules, pointer.From(rule.Id)) } - loadBalancingRules = append(loadBalancingRules, *rule.ID) } - } - if err := d.Set("load_balancing_rules", loadBalancingRules); err != nil { - return fmt.Errorf("setting `load_balancing_rules`: %v", err) - } + if err := d.Set("load_balancing_rules", loadBalancingRules); err != nil { + return fmt.Errorf("setting `load_balancing_rules`: %v", err) + } - var outboundRules []string - if rules := props.OutboundRules; rules != nil { - for _, rule := range *rules { - if rule.ID == nil { - continue + var outboundRules []string + if rules := props.OutboundRules; rules != nil { + for _, rule := range *rules { + if rule.Id == nil { + continue + } + outboundRules = append(outboundRules, pointer.From(rule.Id)) } - outboundRules = append(outboundRules, *rule.ID) } - } - if err := d.Set("outbound_rules", outboundRules); err != nil { - return fmt.Errorf("setting `outbound_rules`: %v", err) - } + if err := d.Set("outbound_rules", outboundRules); err != nil { + return fmt.Errorf("setting `outbound_rules`: %v", err) + } - var inboundNATRules []string - if rules := props.InboundNatRules; rules != nil { - for _, rule := range *rules { - if rule.ID == nil { - continue + var inboundNATRules []string + if rules := props.InboundNatRules; rules != nil { + for _, rule := range *rules { + if rule.Id == nil { + continue + } + inboundNATRules = append(inboundNATRules, pointer.From(rule.Id)) } - inboundNATRules = append(inboundNATRules, *rule.ID) } - } - if err := d.Set("inbound_nat_rules", inboundNATRules); err != nil { - return fmt.Errorf("setting `inbound_nat_rules`: %v", err) + if err := d.Set("inbound_nat_rules", inboundNATRules); err != nil { + return fmt.Errorf("setting `inbound_nat_rules`: %v", err) + } } } return nil } -func flattenArmLoadBalancerBackendAddresses(input *[]network.LoadBalancerBackendAddress) []interface{} { +func flattenArmLoadBalancerBackendAddresses(input *[]loadbalancers.LoadBalancerBackendAddress) []interface{} { if input == nil { return []interface{}{} } @@ -223,12 +224,12 @@ func flattenArmLoadBalancerBackendAddresses(input *[]network.LoadBalancerBackend vnetId string ) var inboundNATRulePortMappingList []interface{} - if prop := e.LoadBalancerBackendAddressPropertiesFormat; prop != nil { - if prop.IPAddress != nil { - ipAddress = *prop.IPAddress - } - if prop.VirtualNetwork != nil && prop.VirtualNetwork.ID != nil { - vnetId = *prop.VirtualNetwork.ID + if prop := e.Properties; prop != nil { + + ipAddress = pointer.From(prop.IPAddress) + + if prop.VirtualNetwork != nil { + vnetId = pointer.From(prop.VirtualNetwork.Id) } if prop.InboundNatRulesPortMapping != nil { rules := prop.InboundNatRulesPortMapping @@ -236,7 +237,7 @@ func flattenArmLoadBalancerBackendAddresses(input *[]network.LoadBalancerBackend rulePortMapping := make(map[string]interface{}) if rule.InboundNatRuleName != nil { - rulePortMapping["inbound_nat_rule_name"] = *rule.InboundNatRuleName + rulePortMapping["inbound_nat_rule_name"] = pointer.From(rule.InboundNatRuleName) } if rule.FrontendPort != nil { rulePortMapping["frontendPort"] = *rule.FrontendPort diff --git a/internal/services/loadbalancer/backend_address_pool_resource.go b/internal/services/loadbalancer/backend_address_pool_resource.go index 3dec3a05a04c..2ef0c4f9cacc 100644 --- a/internal/services/loadbalancer/backend_address_pool_resource.go +++ b/internal/services/loadbalancer/backend_address_pool_resource.go @@ -8,17 +8,16 @@ 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/commonids" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-06-01/loadbalancers" "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/loadbalancer/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) var backendAddressPoolResourceName = "azurerm_lb_backend_address_pool" @@ -30,13 +29,13 @@ func resourceArmLoadBalancerBackendAddressPool() *pluginsdk.Resource { Read: resourceArmLoadBalancerBackendAddressPoolRead, Delete: resourceArmLoadBalancerBackendAddressPoolDelete, - Importer: loadBalancerSubResourceImporter(func(input string) (*parse.LoadBalancerId, error) { - id, err := parse.LoadBalancerBackendAddressPoolID(input) + Importer: loadBalancerSubResourceImporter(func(input string) (*loadbalancers.LoadBalancerId, error) { + id, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(input) if err != nil { return nil, err } - lbId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + lbId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) return &lbId, nil }), @@ -59,7 +58,7 @@ func resourceArmLoadBalancerBackendAddressPool() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "tunnel_interface": { @@ -77,9 +76,9 @@ func resourceArmLoadBalancerBackendAddressPool() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.GatewayLoadBalancerTunnelInterfaceTypeNone), - string(network.GatewayLoadBalancerTunnelInterfaceTypeInternal), - string(network.GatewayLoadBalancerTunnelInterfaceTypeExternal), + string(loadbalancers.GatewayLoadBalancerTunnelInterfaceTypeNone), + string(loadbalancers.GatewayLoadBalancerTunnelInterfaceTypeInternal), + string(loadbalancers.GatewayLoadBalancerTunnelInterfaceTypeExternal), }, false, ), @@ -89,9 +88,9 @@ func resourceArmLoadBalancerBackendAddressPool() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.GatewayLoadBalancerTunnelProtocolNone), - string(network.GatewayLoadBalancerTunnelProtocolNative), - string(network.GatewayLoadBalancerTunnelProtocolVXLAN), + string(loadbalancers.GatewayLoadBalancerTunnelProtocolNone), + string(loadbalancers.GatewayLoadBalancerTunnelProtocolNative), + string(loadbalancers.GatewayLoadBalancerTunnelProtocolVXLAN), }, false, ), @@ -147,28 +146,27 @@ func resourceArmLoadBalancerBackendAddressPool() *pluginsdk.Resource { } func resourceArmLoadBalancerBackendAddressPoolCreateUpdate(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).LoadBalancers.LoadBalancerBackendAddressPoolsClient lbClient := meta.(*clients.Client).LoadBalancers.LoadBalancersClient ctx, cancel := timeouts.ForCreate(meta.(*clients.Client).StopContext, d) defer cancel() - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return fmt.Errorf("parsing Load Balancer Name and Group: %+v", err) } name := d.Get("name").(string) - id := parse.NewLoadBalancerBackendAddressPoolID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, name) + id := loadbalancers.NewLoadBalancerBackendAddressPoolID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, name) if d.IsNewResource() { - existing, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + existing, err := lbClient.LoadBalancerBackendAddressPoolsGet(ctx, id) if err != nil { - if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("checking for presence of existing Load Balancer Backend Address Pool %q: %+v", id, err) + 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 tf.ImportAsExistsError("azurerm_lb_backend_address_pool", id.ID()) } } @@ -179,15 +177,16 @@ func resourceArmLoadBalancerBackendAddressPoolCreateUpdate(d *pluginsdk.Resource locks.ByID(loadBalancerId.ID()) defer locks.UnlockByID(loadBalancerId.ID()) - lb, err := lbClient.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: loadBalancerId.SubscriptionId, ResourceGroupName: loadBalancerId.ResourceGroupName, LoadBalancerName: loadBalancerId.LoadBalancerName} + lb, err := lbClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(lb.Response) { - return fmt.Errorf("Load Balancer %q for Backend Address Pool %q was not found", loadBalancerId, id) + if response.WasNotFound(lb.HttpResponse) { + return fmt.Errorf("%s was not found", *loadBalancerId) } - return fmt.Errorf("failed to retrieve Load Balancer %q for Backend Address Pool %q: %+v", loadBalancerId, id, err) + return fmt.Errorf("retrieving %s: %+v", *loadBalancerId, err) } - param := network.BackendAddressPool{ + param := loadbalancers.BackendAddressPool{ Name: &id.BackendAddressPoolName, } @@ -197,172 +196,167 @@ func resourceArmLoadBalancerBackendAddressPoolCreateUpdate(d *pluginsdk.Resource // - Standard sku: interact with BAP endpoint for CUD // Particularly, the BAP endpoint can be used for R for bot cases. // See: https://github.com/Azure/azure-rest-api-specs/issues/11234 for details. - sku := lb.Sku + if lb.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", *loadBalancerId) + } + sku := lb.Model.Sku if sku == nil { - return fmt.Errorf("nil or empty `sku` for Load Balancer %q for Backend Address Pool %q was not found", loadBalancerId, id) + return fmt.Errorf("nil or empty `sku` for Load Balancer %q for Backend Address Pool %q was not found", *loadBalancerId, id) } - if len(d.Get("tunnel_interface").([]interface{})) != 0 && sku.Name != network.LoadBalancerSkuNameGateway { + if len(d.Get("tunnel_interface").([]interface{})) != 0 && *sku.Name != loadbalancers.LoadBalancerSkuNameGateway { return fmt.Errorf("only the Gateway (sku) Load Balancer allows IP based Backend Address Pool configuration,"+ - "whilst %q is of sku %s", id, sku.Name) + "whilst %q is of sku %s", id, *sku.Name) } - if len(d.Get("tunnel_interface").([]interface{})) == 0 && sku.Name == network.LoadBalancerSkuNameGateway { - return fmt.Errorf("`tunnel_interface` is required for %q when sku is set to %s", id, sku.Name) + if len(d.Get("tunnel_interface").([]interface{})) == 0 && *sku.Name == loadbalancers.LoadBalancerSkuNameGateway { + return fmt.Errorf("`tunnel_interface` is required for %q when sku is set to %s", id, *sku.Name) } if v, ok := d.GetOk("virtual_network_id"); ok { - param.BackendAddressPoolPropertiesFormat = &network.BackendAddressPoolPropertiesFormat{ - VirtualNetwork: &network.SubResource{ - ID: utils.String(v.(string)), + param.Properties = &loadbalancers.BackendAddressPoolPropertiesFormat{ + VirtualNetwork: &loadbalancers.SubResource{ + Id: pointer.To(v.(string)), }} } - switch sku.Name { - case network.LoadBalancerSkuNameBasic: - if !d.IsNewResource() && d.HasChange("virtual_network_id") { - return fmt.Errorf("updating the virtual_network_id of Backend Address Pool %q is not allowed for basic (sku) Load Balancer", id) - } + if properties := lb.Model.Properties; properties != nil { + switch *sku.Name { + case loadbalancers.LoadBalancerSkuNameBasic: + if !d.IsNewResource() && d.HasChange("virtual_network_id") { + return fmt.Errorf("updating the virtual_network_id of Backend Address Pool %q is not allowed for basic (sku) Load Balancer", id) + } - // Insert this BAP and update the LB since the dedicated BAP endpoint doesn't work for the Basic sku. - backendAddressPools := append(*lb.LoadBalancerPropertiesFormat.BackendAddressPools, param) - _, existingPoolIndex, exists := FindLoadBalancerBackEndAddressPoolByName(&lb, id.BackendAddressPoolName) - if exists { - // this pool is being updated/reapplied remove the old copy from the slice - backendAddressPools = append(backendAddressPools[:existingPoolIndex], backendAddressPools[existingPoolIndex+1:]...) - } + // Insert this BAP and update the LB since the dedicated BAP endpoint doesn't work for the Basic sku. + backendAddressPools := append(*properties.BackendAddressPools, param) + _, existingPoolIndex, exists := FindLoadBalancerBackEndAddressPoolByName(lb.Model, id.BackendAddressPoolName) + if exists { + // this pool is being updated/reapplied remove the old copy from the slice + backendAddressPools = append(backendAddressPools[:existingPoolIndex], backendAddressPools[existingPoolIndex+1:]...) + } - lb.LoadBalancerPropertiesFormat.BackendAddressPools = &backendAddressPools + properties.BackendAddressPools = &backendAddressPools - future, err := lbClient.CreateOrUpdate(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, lb) - if err != nil { - return fmt.Errorf("updating Load Balancer %q for Backend Address Pool %q: %+v", loadBalancerId, id, err) - } - - if err = future.WaitForCompletionRef(ctx, lbClient.Client); err != nil { - return fmt.Errorf("waiting for update of Load Balancer %q for Backend Address Pool %q: %+v", loadBalancerId, id, err) - } - case network.LoadBalancerSkuNameStandard: - if param.BackendAddressPoolPropertiesFormat == nil { - param.BackendAddressPoolPropertiesFormat = &network.BackendAddressPoolPropertiesFormat{ - // NOTE: Backend Addresses are managed using `azurerm_lb_backend_pool_address` + err := lbClient.CreateOrUpdateThenPoll(ctx, plbId, *lb.Model) + if err != nil { + return fmt.Errorf("updating %s: %+v", *loadBalancerId, err) + } + case loadbalancers.LoadBalancerSkuNameStandard: + if param.Properties == nil { + param.Properties = &loadbalancers.BackendAddressPoolPropertiesFormat{ + // NOTE: Backend Addresses are managed using `azurerm_lb_backend_pool_address` + } } - } - - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName, param) - if err != nil { - return fmt.Errorf("creating/updating Load Balancer Backend Address Pool %q: %+v", id, err) - } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for Creating/Updating of Load Balancer Backend Address Pool %q: %+v", id, err) - } - case network.LoadBalancerSkuNameGateway: - if param.BackendAddressPoolPropertiesFormat == nil { - param.BackendAddressPoolPropertiesFormat = &network.BackendAddressPoolPropertiesFormat{} - } - param.BackendAddressPoolPropertiesFormat.TunnelInterfaces = expandGatewayLoadBalancerTunnelInterfaces(d.Get("tunnel_interface").([]interface{})) + err := lbClient.LoadBalancerBackendAddressPoolsCreateOrUpdateThenPoll(ctx, id, param) + if err != nil { + return fmt.Errorf("creating/updating Load Balancer Backend Address Pool %q: %+v", id, err) + } + case loadbalancers.LoadBalancerSkuNameGateway: + if param.Properties == nil { + param.Properties = &loadbalancers.BackendAddressPoolPropertiesFormat{} + } + param.Properties.TunnelInterfaces = expandGatewayLoadBalancerTunnelInterfaces(d.Get("tunnel_interface").([]interface{})) - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName, param) - if err != nil { - return fmt.Errorf("creating/updating %q: %+v", id, err) + err := lbClient.LoadBalancerBackendAddressPoolsCreateOrUpdateThenPoll(ctx, id, param) + if err != nil { + return fmt.Errorf("creating/updating %q: %+v", id, err) + } } - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for Creating/Updating of %q: %+v", id, err) - } + d.SetId(id.ID()) } - d.SetId(id.ID()) - return resourceArmLoadBalancerBackendAddressPoolRead(d, meta) } func resourceArmLoadBalancerBackendAddressPoolRead(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).LoadBalancers.LoadBalancerBackendAddressPoolsClient + lbClient := meta.(*clients.Client).LoadBalancers.LoadBalancersClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerBackendAddressPoolID(d.Id()) + id, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(d.Id()) if err != nil { return err } - lbId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + lbId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) - resp, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + resp, err := lbClient.LoadBalancerBackendAddressPoolsGet(ctx, *id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { + if response.WasNotFound(resp.HttpResponse) { d.SetId("") - log.Printf("[INFO] Load Balancer Backend Address Pool %q not found - removing from state", id) + log.Printf("[INFO] %s was not found - removing from state", *id) return nil } - return fmt.Errorf("failed to retrieve Load Balancer Backend Address Pool %q: %+v", id, err) + return fmt.Errorf("retrieving %s: %+v", *id, err) } d.Set("name", id.BackendAddressPoolName) d.Set("loadbalancer_id", lbId.ID()) - if props := resp.BackendAddressPoolPropertiesFormat; props != nil { - if err := d.Set("tunnel_interface", flattenGatewayLoadBalancerTunnelInterfaces(props.TunnelInterfaces)); err != nil { - return fmt.Errorf("setting `tunnel_interface`: %v", err) - } + if model := resp.Model; model != nil { + if properties := model.Properties; properties != nil { + if err := d.Set("tunnel_interface", flattenGatewayLoadBalancerTunnelInterfaces(properties.TunnelInterfaces)); err != nil { + return fmt.Errorf("setting `tunnel_interface`: %v", err) + } - var backendIPConfigurations []string - if configs := props.BackendIPConfigurations; configs != nil { - for _, backendConfig := range *configs { - if backendConfig.ID == nil { - continue + var backendIPConfigurations []string + if configs := properties.BackendIPConfigurations; configs != nil { + for _, backendConfig := range *configs { + if backendConfig.Id == nil { + continue + } + backendIPConfigurations = append(backendIPConfigurations, *backendConfig.Id) } - backendIPConfigurations = append(backendIPConfigurations, *backendConfig.ID) } - } - if err := d.Set("backend_ip_configurations", backendIPConfigurations); err != nil { - return fmt.Errorf("setting `backend_ip_configurations`: %v", err) - } - - network := "" - if vnet := props.VirtualNetwork; vnet != nil && vnet.ID != nil { - network = *vnet.ID - } - d.Set("virtual_network_id", network) + if err := d.Set("backend_ip_configurations", backendIPConfigurations); err != nil { + return fmt.Errorf("setting `backend_ip_configurations`: %v", err) + } - var loadBalancingRules []string - if rules := props.LoadBalancingRules; rules != nil { - for _, rule := range *rules { - if rule.ID == nil { - continue + network := "" + if vnet := properties.VirtualNetwork; vnet != nil && vnet.Id != nil { + network = *vnet.Id + } + d.Set("virtual_network_id", network) + + var loadBalancingRules []string + if rules := properties.LoadBalancingRules; rules != nil { + for _, rule := range *rules { + if rule.Id == nil { + continue + } + loadBalancingRules = append(loadBalancingRules, *rule.Id) } - loadBalancingRules = append(loadBalancingRules, *rule.ID) } - } - if err := d.Set("load_balancing_rules", loadBalancingRules); err != nil { - return fmt.Errorf("setting `load_balancing_rules`: %v", err) - } + if err := d.Set("load_balancing_rules", loadBalancingRules); err != nil { + return fmt.Errorf("setting `load_balancing_rules`: %v", err) + } - var outboundRules []string - if rules := props.OutboundRules; rules != nil { - for _, rule := range *rules { - if rule.ID == nil { - continue + var outboundRules []string + if rules := properties.OutboundRules; rules != nil { + for _, rule := range *rules { + if rule.Id == nil { + continue + } + outboundRules = append(outboundRules, *rule.Id) } - outboundRules = append(outboundRules, *rule.ID) } - } - if err := d.Set("outbound_rules", outboundRules); err != nil { - return fmt.Errorf("setting `outbound_rules`: %v", err) - } + if err := d.Set("outbound_rules", outboundRules); err != nil { + return fmt.Errorf("setting `outbound_rules`: %v", err) + } - var inboundNATRules []string - if rules := props.InboundNatRules; rules != nil { - for _, rule := range *rules { - if rule.ID == nil { - continue + var inboundNATRules []string + if rules := properties.InboundNatRules; rules != nil { + for _, rule := range *rules { + if rule.Id == nil { + continue + } + inboundNATRules = append(inboundNATRules, *rule.Id) } - inboundNATRules = append(inboundNATRules, *rule.ID) } - } - if err := d.Set("inbound_nat_rules", inboundNATRules); err != nil { - return fmt.Errorf("setting `inbound_nat_rules`: %v", err) + if err := d.Set("inbound_nat_rules", inboundNATRules); err != nil { + return fmt.Errorf("setting `inbound_nat_rules`: %v", err) + } } } @@ -370,17 +364,16 @@ func resourceArmLoadBalancerBackendAddressPoolRead(d *pluginsdk.ResourceData, me } func resourceArmLoadBalancerBackendAddressPoolDelete(d *pluginsdk.ResourceData, meta interface{}) error { - client := meta.(*clients.Client).LoadBalancers.LoadBalancerBackendAddressPoolsClient lbClient := meta.(*clients.Client).LoadBalancers.LoadBalancersClient ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerBackendAddressPoolID(d.Id()) + id, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(d.Id()) if err != nil { return err } - loadBalancerId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + loadBalancerId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) loadBalancerID := loadBalancerId.ID() locks.ByID(loadBalancerID) defer locks.UnlockByID(loadBalancerID) @@ -388,73 +381,73 @@ func resourceArmLoadBalancerBackendAddressPoolDelete(d *pluginsdk.ResourceData, locks.ByName(id.BackendAddressPoolName, backendAddressPoolResourceName) defer locks.UnlockByName(id.BackendAddressPoolName, backendAddressPoolResourceName) - lb, err := lbClient.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := lbClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(lb.Response) { + if response.WasNotFound(lb.HttpResponse) { d.SetId("") return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Backend Address Pool %q: %+v", loadBalancerId.Name, loadBalancerId.ResourceGroup, id.BackendAddressPoolName, err) + return fmt.Errorf("retrieving %s: %+v", loadBalancerId, err) } - sku := lb.Sku + if lb.Model == nil { + return fmt.Errorf("retrieving %s: `model` was nil", plbId) + } + sku := lb.Model.Sku if sku == nil { return fmt.Errorf("nil or empty `sku` for Load Balancer %q for Backend Address Pool %q was not found", loadBalancerId, id) } - if sku.Name == network.LoadBalancerSkuNameBasic { - _, index, exists := FindLoadBalancerBackEndAddressPoolByName(&lb, id.BackendAddressPoolName) + if *sku.Name == loadbalancers.LoadBalancerSkuNameBasic { + _, index, exists := FindLoadBalancerBackEndAddressPoolByName(lb.Model, id.BackendAddressPoolName) if !exists { return nil } - backEndPools := *lb.LoadBalancerPropertiesFormat.BackendAddressPools + if lb.Model.Properties == nil { + return fmt.Errorf("retrieving %s: properties was nil", *id) + } + + backEndPools := *lb.Model.Properties.BackendAddressPools backEndPools = append(backEndPools[:index], backEndPools[index+1:]...) - lb.LoadBalancerPropertiesFormat.BackendAddressPools = &backEndPools + lb.Model.Properties.BackendAddressPools = &backEndPools - future, err := lbClient.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, lb) + err := lbClient.CreateOrUpdateThenPoll(ctx, plbId, *lb.Model) if err != nil { - return fmt.Errorf("updating Load Balancer %q (resource group %q) to remove Backend Address Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.BackendAddressPoolName, err) - } - - if err = future.WaitForCompletionRef(ctx, lbClient.Client); err != nil { - return fmt.Errorf("waiting for update of Load Balancer %q (resource group %q) for Backend Address Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.BackendAddressPoolName, err) + return fmt.Errorf("updating %s: %+v", loadBalancerId, err) } } else { - future, err := client.Delete(ctx, id.ResourceGroup, id.LoadBalancerName, id.BackendAddressPoolName) + err := lbClient.LoadBalancerBackendAddressPoolsDeleteThenPoll(ctx, *id) if err != nil { - return fmt.Errorf("deleting Load Balancer Backend Address Pool %q: %+v", id, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for deleting of Load Balancer Backend Address Pool %q: %+v", id, err) + return fmt.Errorf("deleting %s: %+v", *id, err) } } return nil } -func expandGatewayLoadBalancerTunnelInterfaces(input []interface{}) *[]network.GatewayLoadBalancerTunnelInterface { +func expandGatewayLoadBalancerTunnelInterfaces(input []interface{}) *[]loadbalancers.GatewayLoadBalancerTunnelInterface { if len(input) == 0 { return nil } - result := make([]network.GatewayLoadBalancerTunnelInterface, 0) + result := make([]loadbalancers.GatewayLoadBalancerTunnelInterface, 0) for _, e := range input { e := e.(map[string]interface{}) - result = append(result, network.GatewayLoadBalancerTunnelInterface{ - Identifier: utils.Int32(int32(e["identifier"].(int))), - Type: network.GatewayLoadBalancerTunnelInterfaceType(e["type"].(string)), - Protocol: network.GatewayLoadBalancerTunnelProtocol(e["protocol"].(string)), - Port: utils.Int32(int32(e["port"].(int))), + result = append(result, loadbalancers.GatewayLoadBalancerTunnelInterface{ + Identifier: pointer.To(int64(e["identifier"].(int))), + Type: pointer.To(loadbalancers.GatewayLoadBalancerTunnelInterfaceType(e["type"].(string))), + Protocol: pointer.To(loadbalancers.GatewayLoadBalancerTunnelProtocol(e["protocol"].(string))), + Port: pointer.To(int64(e["port"].(int))), }) } return &result } -func flattenGatewayLoadBalancerTunnelInterfaces(input *[]network.GatewayLoadBalancerTunnelInterface) []interface{} { +func flattenGatewayLoadBalancerTunnelInterfaces(input *[]loadbalancers.GatewayLoadBalancerTunnelInterface) []interface{} { if input == nil { return []interface{}{} } @@ -467,9 +460,9 @@ func flattenGatewayLoadBalancerTunnelInterfaces(input *[]network.GatewayLoadBala identifier = int(*e.Identifier) } - t := string(e.Type) + t := string(pointer.From(e.Type)) - protocol := string(e.Protocol) + protocol := string(pointer.From(e.Protocol)) var port int if e.Port != nil { diff --git a/internal/services/loadbalancer/backend_address_pool_resource_test.go b/internal/services/loadbalancer/backend_address_pool_resource_test.go index 7de96c8432d4..a5c336d8e27b 100644 --- a/internal/services/loadbalancer/backend_address_pool_resource_test.go +++ b/internal/services/loadbalancer/backend_address_pool_resource_test.go @@ -8,13 +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-06-01/loadbalancers" "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/loadbalancer/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 LoadBalancerBackendAddressPool struct{} @@ -164,72 +164,76 @@ func TestAccBackendAddressPool_GatewaySkuUpdate(t *testing.T) { } func (r LoadBalancerBackendAddressPool) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancerBackendAddressPoolID(state.ID) + id, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(state.ID) if err != nil { return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(lb.Response) { - return nil, fmt.Errorf("Load Balancer %q (resource group %q) not found for Backend Address Pool %q", id.LoadBalancerName, id.ResourceGroup, id.BackendAddressPoolName) + if response.WasNotFound(lb.HttpResponse) { + return nil, fmt.Errorf("%s was not found", plbId) } - return nil, fmt.Errorf("failed reading Load Balancer %q (resource group %q) for Backend Address Pool %q", id.LoadBalancerName, id.ResourceGroup, id.BackendAddressPoolName) - } - props := lb.LoadBalancerPropertiesFormat - if props == nil || props.BackendAddressPools == nil || len(*props.BackendAddressPools) == 0 { - return nil, fmt.Errorf("Backend Pool %q not found in Load Balancer %q (resource group %q)", id.BackendAddressPoolName, id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) } + if model := lb.Model; model != nil { + props := model.Properties + if props == nil || props.BackendAddressPools == nil || len(*props.BackendAddressPools) == 0 { + return nil, fmt.Errorf("Backend Pool %q not found in Load Balancer %q (resource group %q)", id.BackendAddressPoolName, id.LoadBalancerName, id.ResourceGroupName) + } - found := false - for _, v := range *props.BackendAddressPools { - if v.Name != nil && *v.Name == id.BackendAddressPoolName { - found = true + found := false + for _, v := range *props.BackendAddressPools { + if v.Name != nil && *v.Name == id.BackendAddressPoolName { + found = true + } + } + if !found { + return nil, fmt.Errorf("Backend Pool %q not found in Load Balancer %q (resource group %q)", id.BackendAddressPoolName, id.LoadBalancerName, id.ResourceGroupName) } } - if !found { - return nil, fmt.Errorf("Backend Pool %q not found in Load Balancer %q (resource group %q)", id.BackendAddressPoolName, id.LoadBalancerName, id.ResourceGroup) - } - return utils.Bool(true), nil + + return pointer.To(true), nil } func (r LoadBalancerBackendAddressPool) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancerBackendAddressPoolID(state.ID) + id, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(state.ID) if err != nil { return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return nil, fmt.Errorf("retrieving Load Balancer %q (Resource Group %q)", id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("retrieving Load Balancer %q (Resource Group %q)", id.LoadBalancerName, id.ResourceGroupName) + } + if lb.Model == nil { + return nil, fmt.Errorf("`model` was nil") } - if lb.LoadBalancerPropertiesFormat == nil { + if lb.Model.Properties == nil { return nil, fmt.Errorf("`properties` was nil") } - if lb.LoadBalancerPropertiesFormat.BackendAddressPools == nil { + if lb.Model.Properties.BackendAddressPools == nil { return nil, fmt.Errorf("`properties.BackendAddressPools` was nil") } - backendAddressPools := make([]network.BackendAddressPool, 0) - for _, backendAddressPool := range *lb.LoadBalancerPropertiesFormat.BackendAddressPools { + backendAddressPools := make([]loadbalancers.BackendAddressPool, 0) + for _, backendAddressPool := range *lb.Model.Properties.BackendAddressPools { if backendAddressPool.Name == nil || *backendAddressPool.Name == id.BackendAddressPoolName { continue } backendAddressPools = append(backendAddressPools, backendAddressPool) } - lb.LoadBalancerPropertiesFormat.BackendAddressPools = &backendAddressPools + lb.Model.Properties.BackendAddressPools = &backendAddressPools - future, err := client.LoadBalancers.LoadBalancersClient.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, lb) + err = client.LoadBalancers.LoadBalancersClient.CreateOrUpdateThenPoll(ctx, plbId, *lb.Model) if err != nil { - return nil, fmt.Errorf("updating Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) + return nil, fmt.Errorf("updating Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroupName, err) } - if err := future.WaitForCompletionRef(ctx, client.LoadBalancers.LoadBalancersClient.Client); err != nil { - return nil, fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) - } - - return utils.Bool(true), nil + return pointer.To(true), nil } func (r LoadBalancerBackendAddressPool) basicSkuBasic(data acceptance.TestData) string { @@ -395,6 +399,10 @@ locals { location = %q } +provider "azurerm" { + features {} +} + resource "azurerm_resource_group" "test" { name = "acctestRG-${local.number}" location = local.location diff --git a/internal/services/loadbalancer/client/client.go b/internal/services/loadbalancer/client/client.go index 54b718d7615b..7c764419ed9b 100644 --- a/internal/services/loadbalancer/client/client.go +++ b/internal/services/loadbalancer/client/client.go @@ -4,29 +4,24 @@ package client import ( + "fmt" + + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/internal/common" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) type Client struct { - LoadBalancersClient *network.LoadBalancersClient - LoadBalancerBackendAddressPoolsClient *network.LoadBalancerBackendAddressPoolsClient - LoadBalancingRulesClient *network.LoadBalancerLoadBalancingRulesClient + LoadBalancersClient *loadbalancers.LoadBalancersClient } -func NewClient(o *common.ClientOptions) *Client { - loadBalancersClient := network.NewLoadBalancersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&loadBalancersClient.Client, o.ResourceManagerAuthorizer) - - loadBalancerBackendAddressPoolsClient := network.NewLoadBalancerBackendAddressPoolsClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&loadBalancerBackendAddressPoolsClient.Client, o.ResourceManagerAuthorizer) - - loadBalancingRulesClient := network.NewLoadBalancerLoadBalancingRulesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) - o.ConfigureClient(&loadBalancingRulesClient.Client, o.ResourceManagerAuthorizer) +func NewClient(o *common.ClientOptions) (*Client, error) { + loadBalancersClient, err := loadbalancers.NewLoadBalancersClientWithBaseURI(o.Environment.ResourceManager) + if err != nil { + return nil, fmt.Errorf("building loadBalancers client: %+v", err) + } + o.Configure(loadBalancersClient.Client, o.Authorizers.ResourceManager) return &Client{ - LoadBalancersClient: &loadBalancersClient, - LoadBalancerBackendAddressPoolsClient: &loadBalancerBackendAddressPoolsClient, - LoadBalancingRulesClient: &loadBalancingRulesClient, - } + LoadBalancersClient: loadBalancersClient, + }, nil } diff --git a/internal/services/loadbalancer/loadbalancer.go b/internal/services/loadbalancer/loadbalancer.go index f825feaee187..31cf5e90f015 100644 --- a/internal/services/loadbalancer/loadbalancer.go +++ b/internal/services/loadbalancer/loadbalancer.go @@ -6,20 +6,19 @@ package loadbalancer import ( "context" + "github.com/hashicorp/go-azure-sdk/resource-manager/network/2023-06-01/loadbalancers" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) // TODO: refactor this -func FindLoadBalancerBackEndAddressPoolByName(lb *network.LoadBalancer, name string) (*network.BackendAddressPool, int, bool) { - if lb == nil || lb.LoadBalancerPropertiesFormat == nil || lb.LoadBalancerPropertiesFormat.BackendAddressPools == nil { +func FindLoadBalancerBackEndAddressPoolByName(lb *loadbalancers.LoadBalancer, name string) (*loadbalancers.BackendAddressPool, int, bool) { + if lb == nil || lb.Properties == nil || lb.Properties.BackendAddressPools == nil { return nil, -1, false } - for i, apc := range *lb.LoadBalancerPropertiesFormat.BackendAddressPools { + for i, apc := range *lb.Properties.BackendAddressPools { if apc.Name != nil && *apc.Name == name { return &apc, i, true } @@ -28,12 +27,12 @@ func FindLoadBalancerBackEndAddressPoolByName(lb *network.LoadBalancer, name str return nil, -1, false } -func FindLoadBalancerFrontEndIpConfigurationByName(lb *network.LoadBalancer, name string) (*network.FrontendIPConfiguration, bool) { - if lb == nil || lb.LoadBalancerPropertiesFormat == nil || lb.LoadBalancerPropertiesFormat.FrontendIPConfigurations == nil { +func FindLoadBalancerFrontEndIpConfigurationByName(lb *loadbalancers.LoadBalancer, name string) (*loadbalancers.FrontendIPConfiguration, bool) { + if lb == nil || lb.Properties == nil || lb.Properties.FrontendIPConfigurations == nil { return nil, false } - for _, feip := range *lb.LoadBalancerPropertiesFormat.FrontendIPConfigurations { + for _, feip := range *lb.Properties.FrontendIPConfigurations { if feip.Name != nil && *feip.Name == name { return &feip, true } @@ -42,12 +41,12 @@ func FindLoadBalancerFrontEndIpConfigurationByName(lb *network.LoadBalancer, nam return nil, false } -func FindLoadBalancerRuleByName(lb *network.LoadBalancer, name string) (*network.LoadBalancingRule, int, bool) { - if lb == nil || lb.LoadBalancerPropertiesFormat == nil || lb.LoadBalancerPropertiesFormat.LoadBalancingRules == nil { +func FindLoadBalancerRuleByName(lb *loadbalancers.LoadBalancer, name string) (*loadbalancers.LoadBalancingRule, int, bool) { + if lb == nil || lb.Properties == nil || lb.Properties.LoadBalancingRules == nil { return nil, -1, false } - for i, lbr := range *lb.LoadBalancerPropertiesFormat.LoadBalancingRules { + for i, lbr := range *lb.Properties.LoadBalancingRules { if lbr.Name != nil && *lbr.Name == name { return &lbr, i, true } @@ -56,12 +55,12 @@ func FindLoadBalancerRuleByName(lb *network.LoadBalancer, name string) (*network return nil, -1, false } -func FindLoadBalancerOutboundRuleByName(lb *network.LoadBalancer, name string) (*network.OutboundRule, int, bool) { - if lb == nil || lb.LoadBalancerPropertiesFormat == nil || lb.LoadBalancerPropertiesFormat.OutboundRules == nil { +func FindLoadBalancerOutboundRuleByName(lb *loadbalancers.LoadBalancer, name string) (*loadbalancers.OutboundRule, int, bool) { + if lb == nil || lb.Properties == nil || lb.Properties.OutboundRules == nil { return nil, -1, false } - for i, or := range *lb.LoadBalancerPropertiesFormat.OutboundRules { + for i, or := range *lb.Properties.OutboundRules { if or.Name != nil && *or.Name == name { return &or, i, true } @@ -70,12 +69,12 @@ func FindLoadBalancerOutboundRuleByName(lb *network.LoadBalancer, name string) ( return nil, -1, false } -func FindLoadBalancerNatRuleByName(lb *network.LoadBalancer, name string) (*network.InboundNatRule, int, bool) { - if lb == nil || lb.LoadBalancerPropertiesFormat == nil || lb.LoadBalancerPropertiesFormat.InboundNatRules == nil { +func FindLoadBalancerNatRuleByName(lb *loadbalancers.LoadBalancer, name string) (*loadbalancers.InboundNatRule, int, bool) { + if lb == nil || lb.Properties == nil || lb.Properties.InboundNatRules == nil { return nil, -1, false } - for i, nr := range *lb.LoadBalancerPropertiesFormat.InboundNatRules { + for i, nr := range *lb.Properties.InboundNatRules { if nr.Name != nil && *nr.Name == name { return &nr, i, true } @@ -84,12 +83,12 @@ func FindLoadBalancerNatRuleByName(lb *network.LoadBalancer, name string) (*netw return nil, -1, false } -func FindLoadBalancerNatPoolByName(lb *network.LoadBalancer, name string) (*network.InboundNatPool, int, bool) { - if lb == nil || lb.LoadBalancerPropertiesFormat == nil || lb.LoadBalancerPropertiesFormat.InboundNatPools == nil { +func FindLoadBalancerNatPoolByName(lb *loadbalancers.LoadBalancer, name string) (*loadbalancers.InboundNatPool, int, bool) { + if lb == nil || lb.Properties == nil || lb.Properties.InboundNatPools == nil { return nil, -1, false } - for i, np := range *lb.LoadBalancerPropertiesFormat.InboundNatPools { + for i, np := range *lb.Properties.InboundNatPools { if np.Name != nil && *np.Name == name { return &np, i, true } @@ -98,12 +97,12 @@ func FindLoadBalancerNatPoolByName(lb *network.LoadBalancer, name string) (*netw return nil, -1, false } -func FindLoadBalancerProbeByName(lb *network.LoadBalancer, name string) (*network.Probe, int, bool) { - if lb == nil || lb.LoadBalancerPropertiesFormat == nil || lb.LoadBalancerPropertiesFormat.Probes == nil { +func FindLoadBalancerProbeByName(lb *loadbalancers.LoadBalancer, name string) (*loadbalancers.Probe, int, bool) { + if lb == nil || lb.Properties == nil || lb.Properties.Probes == nil { return nil, -1, false } - for i, p := range *lb.LoadBalancerPropertiesFormat.Probes { + for i, p := range *lb.Properties.Probes { if p.Name != nil && *p.Name == name { return &p, i, true } @@ -112,7 +111,7 @@ func FindLoadBalancerProbeByName(lb *network.LoadBalancer, name string) (*networ return nil, -1, false } -func loadBalancerSubResourceImporter(parser func(input string) (*parse.LoadBalancerId, error)) *schema.ResourceImporter { +func loadBalancerSubResourceImporter(parser func(input string) (*loadbalancers.LoadBalancerId, error)) *schema.ResourceImporter { return pluginsdk.ImporterValidatingResourceIdThen(func(id string) error { _, err := parser(id) return err diff --git a/internal/services/loadbalancer/loadbalancer_data_source.go b/internal/services/loadbalancer/loadbalancer_data_source.go index f7be1ea3d639..f40c1e5e93be 100644 --- a/internal/services/loadbalancer/loadbalancer_data_source.go +++ b/internal/services/loadbalancer/loadbalancer_data_source.go @@ -7,17 +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-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/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 dataSourceArmLoadBalancer() *pluginsdk.Resource { @@ -113,10 +113,11 @@ func dataSourceArmLoadBalancerRead(d *pluginsdk.ResourceData, meta interface{}) ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id := parse.NewLoadBalancerID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) - resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + id := loadbalancers.NewLoadBalancerID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: subscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + resp, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { + if response.WasNotFound(resp.HttpResponse) { return fmt.Errorf("%s was not found", id) } @@ -124,43 +125,48 @@ func dataSourceArmLoadBalancerRead(d *pluginsdk.ResourceData, meta interface{}) } d.SetId(id.ID()) - d.Set("location", location.NormalizeNilable(resp.Location)) - if sku := resp.Sku; sku != nil { - d.Set("sku", string(sku.Name)) - } - - privateIpAddress := "" - privateIpAddresses := make([]string, 0) - frontendIpConfigurations := make([]interface{}, 0) - if props := resp.LoadBalancerPropertiesFormat; props != nil { - if feipConfigs := props.FrontendIPConfigurations; feipConfigs != nil { - frontendIpConfigurations = flattenLoadBalancerDataSourceFrontendIpConfiguration(feipConfigs) + if model := resp.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) + if sku := model.Sku; sku != nil { + d.Set("sku", string(pointer.From(sku.Name))) + } - for _, config := range *feipConfigs { - if feipProps := config.FrontendIPConfigurationPropertiesFormat; feipProps != nil { - if ip := feipProps.PrivateIPAddress; ip != nil { - if privateIpAddress == "" { - privateIpAddress = *feipProps.PrivateIPAddress + privateIpAddress := "" + privateIpAddresses := make([]string, 0) + frontendIpConfigurations := make([]interface{}, 0) + + if props := model.Properties; props != nil { + if feipConfigs := props.FrontendIPConfigurations; feipConfigs != nil { + frontendIpConfigurations = flattenLoadBalancerDataSourceFrontendIpConfiguration(feipConfigs) + for _, config := range *feipConfigs { + if feipProps := config.Properties; feipProps != nil { + if ip := feipProps.PrivateIPAddress; ip != nil { + if privateIpAddress == "" { + privateIpAddress = pointer.From(ip) + } + + privateIpAddresses = append(privateIpAddresses, pointer.From(ip)) } - - privateIpAddresses = append(privateIpAddresses, *feipProps.PrivateIPAddress) } } } } - } - if err := d.Set("frontend_ip_configuration", frontendIpConfigurations); err != nil { - return fmt.Errorf("flattening `frontend_ip_configuration`: %+v", err) + if err := d.Set("frontend_ip_configuration", frontendIpConfigurations); err != nil { + return fmt.Errorf("flattening `frontend_ip_configuration`: %+v", err) + } + d.Set("private_ip_address", privateIpAddress) + d.Set("private_ip_addresses", privateIpAddresses) + + return tags.FlattenAndSet(d, model.Tags) } - d.Set("private_ip_address", privateIpAddress) - d.Set("private_ip_addresses", privateIpAddresses) - return tags.FlattenAndSet(d, resp.Tags) + return nil + } -func flattenLoadBalancerDataSourceFrontendIpConfiguration(ipConfigs *[]network.FrontendIPConfiguration) []interface{} { +func flattenLoadBalancerDataSourceFrontendIpConfiguration(ipConfigs *[]loadbalancers.FrontendIPConfiguration) []interface{} { result := make([]interface{}, 0) if ipConfigs == nil { return result @@ -173,8 +179,8 @@ func flattenLoadBalancerDataSourceFrontendIpConfiguration(ipConfigs *[]network.F } id := "" - if config.ID != nil { - id = *config.ID + if config.Id != nil { + id = *config.Id } privateIpAddress := "" @@ -182,23 +188,18 @@ func flattenLoadBalancerDataSourceFrontendIpConfiguration(ipConfigs *[]network.F privateIpAddressVersion := "" publicIpAddressId := "" subnetId := "" - if props := config.FrontendIPConfigurationPropertiesFormat; props != nil { - privateIpAddressAllocation = string(props.PrivateIPAllocationMethod) + if props := config.Properties; props != nil { + privateIpAddressAllocation = string(pointer.From(props.PrivateIPAllocationMethod)) - if subnet := props.Subnet; subnet != nil && subnet.ID != nil { - subnetId = *subnet.ID + if subnet := props.Subnet; subnet != nil { + subnetId = pointer.From(subnet.Id) } - if pip := props.PrivateIPAddress; pip != nil { - privateIpAddress = *pip - } - - if props.PrivateIPAddressVersion != "" { - privateIpAddressVersion = string(props.PrivateIPAddressVersion) - } + privateIpAddress = pointer.From(props.PrivateIPAddress) + privateIpAddressVersion = string(pointer.From(props.PrivateIPAddressVersion)) - if pip := props.PublicIPAddress; pip != nil && pip.ID != nil { - publicIpAddressId = *pip.ID + if pip := props.PublicIPAddress; pip != nil { + publicIpAddressId = pointer.From(pip.Id) } } diff --git a/internal/services/loadbalancer/loadbalancer_nat_pool_resource_test.go b/internal/services/loadbalancer/loadbalancer_nat_pool_resource_test.go index 82e3bcd17c3f..b2ef3c2e0b39 100644 --- a/internal/services/loadbalancer/loadbalancer_nat_pool_resource_test.go +++ b/internal/services/loadbalancer/loadbalancer_nat_pool_resource_test.go @@ -8,13 +8,14 @@ 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-06-01/loadbalancers" "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/loadbalancer/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 LoadBalancerNatPool struct{} @@ -140,20 +141,21 @@ func (r LoadBalancerNatPool) Exists(ctx context.Context, client *clients.Client, return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroup, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(lb.Response) { - return nil, fmt.Errorf("Load Balancer %q (resource group %q) not found for Nat Pool %q", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName) + if response.WasNotFound(lb.HttpResponse) { + return nil, fmt.Errorf("%s was not found", plbId) } - return nil, fmt.Errorf("failed reading Load Balancer %q (resource group %q) for Nat Pool %q", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) } - props := lb.LoadBalancerPropertiesFormat - if props == nil || props.InboundNatPools == nil || len(*props.InboundNatPools) == 0 { + model := lb.Model + if model == nil || model.Properties == nil || model.Properties.InboundNatPools == nil || len(*model.Properties.InboundNatPools) == 0 { return nil, fmt.Errorf("Nat Pool %q not found in Load Balancer %q (resource group %q)", id.InboundNatPoolName, id.LoadBalancerName, id.ResourceGroup) } found := false - for _, v := range *props.InboundNatPools { + for _, v := range *model.Properties.InboundNatPools { if v.Name != nil && *v.Name == id.InboundNatPoolName { found = true } @@ -162,7 +164,7 @@ func (r LoadBalancerNatPool) Exists(ctx context.Context, client *clients.Client, return nil, fmt.Errorf("Nat Pool %q not found in Load Balancer %q (resource group %q)", id.InboundNatPoolName, id.LoadBalancerName, id.ResourceGroup) } - return utils.Bool(found), nil + return pointer.To(found), nil } func (r LoadBalancerNatPool) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { @@ -171,37 +173,36 @@ func (r LoadBalancerNatPool) Destroy(ctx context.Context, client *clients.Client return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroup, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return nil, fmt.Errorf("retrieving Load Balancer %q (Resource Group %q)", id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) } - if lb.LoadBalancerPropertiesFormat == nil { + if lb.Model == nil { + return nil, fmt.Errorf("`model` was nil") + } + if lb.Model.Properties == nil { return nil, fmt.Errorf("`properties` was nil") } - if lb.LoadBalancerPropertiesFormat.InboundNatPools == nil { + if lb.Model.Properties.InboundNatPools == nil { return nil, fmt.Errorf("`properties.InboundNatPools` was nil") } - inboundNatPools := make([]network.InboundNatPool, 0) - for _, inboundNatPool := range *lb.LoadBalancerPropertiesFormat.InboundNatPools { + inboundNatPools := make([]loadbalancers.InboundNatPool, 0) + for _, inboundNatPool := range *lb.Model.Properties.InboundNatPools { if inboundNatPool.Name == nil || *inboundNatPool.Name == id.InboundNatPoolName { continue } inboundNatPools = append(inboundNatPools, inboundNatPool) } - lb.LoadBalancerPropertiesFormat.InboundNatPools = &inboundNatPools + lb.Model.Properties.InboundNatPools = &inboundNatPools - future, err := client.LoadBalancers.LoadBalancersClient.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, lb) + err = client.LoadBalancers.LoadBalancersClient.CreateOrUpdateThenPoll(ctx, plbId, *lb.Model) if err != nil { return nil, fmt.Errorf("updating Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) } - - if err := future.WaitForCompletionRef(ctx, client.LoadBalancers.LoadBalancersClient.Client); err != nil { - return nil, fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) - } - - return utils.Bool(true), nil + return pointer.To(true), nil } func (r LoadBalancerNatPool) basic(data acceptance.TestData, sku string) string { diff --git a/internal/services/loadbalancer/loadbalancer_nat_rule_resource_test.go b/internal/services/loadbalancer/loadbalancer_nat_rule_resource_test.go index 8c618c2b738c..833aaf83b10d 100644 --- a/internal/services/loadbalancer/loadbalancer_nat_rule_resource_test.go +++ b/internal/services/loadbalancer/loadbalancer_nat_rule_resource_test.go @@ -8,13 +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-06-01/loadbalancers" "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/loadbalancer/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 LoadBalancerNatRule struct{} @@ -205,72 +205,73 @@ func TestAccAzureRMLoadBalancerNatRule_zeroPortNumber(t *testing.T) { } func (r LoadBalancerNatRule) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancerInboundNatRuleID(state.ID) + id, err := loadbalancers.ParseInboundNatRuleID(state.ID) if err != nil { return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(lb.Response) { - return nil, fmt.Errorf("Load Balancer %q (resource group %q) not found for Nat Rule %q", id.LoadBalancerName, id.ResourceGroup, id.InboundNatRuleName) + if response.WasNotFound(lb.HttpResponse) { + return nil, fmt.Errorf("%s was not found", plbId) } - return nil, fmt.Errorf("failed reading Load Balancer %q (resource group %q) for Nat Rule %q", id.LoadBalancerName, id.ResourceGroup, id.InboundNatRuleName) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) } - props := lb.LoadBalancerPropertiesFormat - if props == nil || props.InboundNatRules == nil || len(*props.InboundNatRules) == 0 { - return nil, fmt.Errorf("Nat Rule %q not found in Load Balancer %q (resource group %q)", id.InboundNatRuleName, id.LoadBalancerName, id.ResourceGroup) + props := lb.Model + if props == nil || props.Properties == nil || len(*props.Properties.InboundNatRules) == 0 { + return nil, fmt.Errorf("Nat Rule %q not found in Load Balancer %q (resource group %q)", id.InboundNatRuleName, id.LoadBalancerName, id.ResourceGroupName) } found := false - for _, v := range *props.InboundNatRules { + for _, v := range *props.Properties.InboundNatRules { if v.Name != nil && *v.Name == id.InboundNatRuleName { found = true } } if !found { - return nil, fmt.Errorf("Nat Rule %q not found in Load Balancer %q (resource group %q)", id.InboundNatRuleName, id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("Nat Rule %q not found in Load Balancer %q (resource group %q)", id.InboundNatRuleName, id.LoadBalancerName, id.ResourceGroupName) } - return utils.Bool(found), nil + return pointer.To(found), nil } func (r LoadBalancerNatRule) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancerInboundNatRuleID(state.ID) + id, err := loadbalancers.ParseInboundNatRuleID(state.ID) if err != nil { return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return nil, fmt.Errorf("retrieving Load Balancer %q (Resource Group %q)", id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) } - if lb.LoadBalancerPropertiesFormat == nil { + if lb.Model == nil { + return nil, fmt.Errorf("`model` was nil") + } + if lb.Model.Properties == nil { return nil, fmt.Errorf("`properties` was nil") } - if lb.LoadBalancerPropertiesFormat.InboundNatRules == nil { + if lb.Model.Properties.InboundNatRules == nil { return nil, fmt.Errorf("`properties.InboundNatRules` was nil") } - inboundNatRules := make([]network.InboundNatRule, 0) - for _, inboundNatRule := range *lb.LoadBalancerPropertiesFormat.InboundNatRules { + inboundNatRules := make([]loadbalancers.InboundNatRule, 0) + for _, inboundNatRule := range *lb.Model.Properties.InboundNatRules { if inboundNatRule.Name == nil || *inboundNatRule.Name == id.InboundNatRuleName { continue } inboundNatRules = append(inboundNatRules, inboundNatRule) } - lb.LoadBalancerPropertiesFormat.InboundNatRules = &inboundNatRules + lb.Model.Properties.InboundNatRules = &inboundNatRules - future, err := client.LoadBalancers.LoadBalancersClient.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, lb) + err = client.LoadBalancers.LoadBalancersClient.CreateOrUpdateThenPoll(ctx, plbId, *lb.Model) if err != nil { - return nil, fmt.Errorf("updating Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) - } - - if err := future.WaitForCompletionRef(ctx, client.LoadBalancers.LoadBalancersClient.Client); err != nil { - return nil, fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) + return nil, fmt.Errorf("updating %s: %+v", *id, err) } - return utils.Bool(true), nil + return pointer.To(true), nil } func (r LoadBalancerNatRule) template(data acceptance.TestData, sku string) string { diff --git a/internal/services/loadbalancer/loadbalancer_outbound_rule_resource_test.go b/internal/services/loadbalancer/loadbalancer_outbound_rule_resource_test.go index b6998172b4a5..30cfd51d5075 100644 --- a/internal/services/loadbalancer/loadbalancer_outbound_rule_resource_test.go +++ b/internal/services/loadbalancer/loadbalancer_outbound_rule_resource_test.go @@ -8,13 +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-06-01/loadbalancers" "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/loadbalancer/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 LoadBalancerOutboundRule struct{} @@ -126,72 +126,72 @@ func TestAccAzureRMLoadBalancerOutboundRule_allocatedOutboundPorts(t *testing.T) } func (r LoadBalancerOutboundRule) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancerOutboundRuleID(state.ID) + id, err := loadbalancers.ParseOutboundRuleID(state.ID) if err != nil { return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(lb.Response) { - return nil, fmt.Errorf("Load Balancer %q (resource group %q) not found for Outbound Rule %q", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName) + if response.WasNotFound(lb.HttpResponse) { + return nil, fmt.Errorf("%s was not found", plbId) } - return nil, fmt.Errorf("failed reading Load Balancer %q (resource group %q) for Outbound Rule %q", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) } - props := lb.LoadBalancerPropertiesFormat - if props == nil || props.OutboundRules == nil || len(*props.OutboundRules) == 0 { - return nil, fmt.Errorf("Outbound Rule %q not found in Load Balancer %q (resource group %q)", id.OutboundRuleName, id.LoadBalancerName, id.ResourceGroup) + props := lb.Model + if props == nil || props.Properties == nil || len(*props.Properties.OutboundRules) == 0 { + return nil, fmt.Errorf("Outbound Rule %q not found in Load Balancer %q (resource group %q)", id.OutboundRuleName, id.LoadBalancerName, id.ResourceGroupName) } found := false - for _, v := range *props.OutboundRules { + for _, v := range *props.Properties.OutboundRules { if v.Name != nil && *v.Name == id.OutboundRuleName { found = true } } if !found { - return nil, fmt.Errorf("Outbound Rule %q not found in Load Balancer %q (resource group %q)", id.OutboundRuleName, id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("Outbound Rule %q not found in Load Balancer %q (resource group %q)", id.OutboundRuleName, id.LoadBalancerName, id.ResourceGroupName) } - return utils.Bool(found), nil + return pointer.To(found), nil } func (r LoadBalancerOutboundRule) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancerOutboundRuleID(state.ID) + id, err := loadbalancers.ParseOutboundRuleID(state.ID) if err != nil { return nil, err } - - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return nil, fmt.Errorf("retrieving Load Balancer %q (Resource Group %q)", id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) + } + if lb.Model == nil { + return nil, fmt.Errorf("`model` was nil") } - if lb.LoadBalancerPropertiesFormat == nil { + if lb.Model.Properties == nil { return nil, fmt.Errorf("`properties` was nil") } - if lb.LoadBalancerPropertiesFormat.OutboundRules == nil { + if lb.Model.Properties.OutboundRules == nil { return nil, fmt.Errorf("`properties.OutboundRules` was nil") } - outboundRules := make([]network.OutboundRule, 0) - for _, outboundRule := range *lb.LoadBalancerPropertiesFormat.OutboundRules { + outboundRules := make([]loadbalancers.OutboundRule, 0) + for _, outboundRule := range *lb.Model.Properties.OutboundRules { if outboundRule.Name == nil || *outboundRule.Name == id.OutboundRuleName { continue } outboundRules = append(outboundRules, outboundRule) } - lb.LoadBalancerPropertiesFormat.OutboundRules = &outboundRules + lb.Model.Properties.OutboundRules = &outboundRules - future, err := client.LoadBalancers.LoadBalancersClient.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, lb) + err = client.LoadBalancers.LoadBalancersClient.CreateOrUpdateThenPoll(ctx, plbId, *lb.Model) if err != nil { - return nil, fmt.Errorf("updating Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) - } - - if err := future.WaitForCompletionRef(ctx, client.LoadBalancers.LoadBalancersClient.Client); err != nil { - return nil, fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) + return nil, fmt.Errorf("updating %s: %+v", *id, err) } - return utils.Bool(true), nil + return pointer.To(true), nil } func (r LoadBalancerOutboundRule) basic(data acceptance.TestData) string { diff --git a/internal/services/loadbalancer/loadbalancer_probe_resource_test.go b/internal/services/loadbalancer/loadbalancer_probe_resource_test.go index d34baee2d247..ff5e3a32491e 100644 --- a/internal/services/loadbalancer/loadbalancer_probe_resource_test.go +++ b/internal/services/loadbalancer/loadbalancer_probe_resource_test.go @@ -8,13 +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-06-01/loadbalancers" "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/loadbalancer/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 LoadBalancerProbe struct{} @@ -128,72 +128,73 @@ func TestAccAzureRMLoadBalancerProbe_updateProtocol(t *testing.T) { } func (r LoadBalancerProbe) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancerProbeID(state.ID) + id, err := loadbalancers.ParseProbeID(state.ID) if err != nil { return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(lb.Response) { - return nil, fmt.Errorf("Load Balancer %q (resource group %q) not found for Probe %q", id.LoadBalancerName, id.ResourceGroup, id.ProbeName) + if response.WasNotFound(lb.HttpResponse) { + return nil, fmt.Errorf("%s was not found", plbId) } - return nil, fmt.Errorf("failed reading Load Balancer %q (resource group %q) for Probe %q", id.LoadBalancerName, id.ResourceGroup, id.ProbeName) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) } - props := lb.LoadBalancerPropertiesFormat - if props == nil || props.Probes == nil || len(*props.Probes) == 0 { - return nil, fmt.Errorf("Probe %q not found in Load Balancer %q (resource group %q)", id.ProbeName, id.LoadBalancerName, id.ResourceGroup) + props := lb.Model + if props == nil || props.Properties.Probes == nil || len(*props.Properties.Probes) == 0 { + return nil, fmt.Errorf("Probe %q not found in Load Balancer %q (resource group %q)", id.ProbeName, id.LoadBalancerName, id.ResourceGroupName) } found := false - for _, v := range *props.Probes { + for _, v := range *props.Properties.Probes { if v.Name != nil && *v.Name == id.ProbeName { found = true } } if !found { - return nil, fmt.Errorf("Probe %q not found in Load Balancer %q (resource group %q)", id.ProbeName, id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("Probe %q not found in Load Balancer %q (resource group %q)", id.ProbeName, id.LoadBalancerName, id.ResourceGroupName) } - return utils.Bool(found), nil + return pointer.To(found), nil } func (r LoadBalancerProbe) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancerProbeID(state.ID) + id, err := loadbalancers.ParseProbeID(state.ID) if err != nil { return nil, err } - lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + lb, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return nil, fmt.Errorf("retrieving Load Balancer %q (Resource Group %q)", id.LoadBalancerName, id.ResourceGroup) + return nil, fmt.Errorf("retrieving Load Balancer %q (Resource Group %q)", id.LoadBalancerName, id.ResourceGroupName) } - if lb.LoadBalancerPropertiesFormat == nil { + if lb.Model == nil { + return nil, fmt.Errorf("`model` was nil") + } + if lb.Model.Properties == nil { return nil, fmt.Errorf("`properties` was nil") } - if lb.LoadBalancerPropertiesFormat.Probes == nil { + if lb.Model.Properties.Probes == nil { return nil, fmt.Errorf("`properties.Probes` was nil") } - probes := make([]network.Probe, 0) - for _, probe := range *lb.LoadBalancerPropertiesFormat.Probes { + probes := make([]loadbalancers.Probe, 0) + for _, probe := range *lb.Model.Properties.Probes { if probe.Name == nil || *probe.Name == id.ProbeName { continue } probes = append(probes, probe) } - lb.LoadBalancerPropertiesFormat.Probes = &probes + lb.Model.Properties.Probes = &probes - future, err := client.LoadBalancers.LoadBalancersClient.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, lb) + err = client.LoadBalancers.LoadBalancersClient.CreateOrUpdateThenPoll(ctx, plbId, *lb.Model) if err != nil { - return nil, fmt.Errorf("updating Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) - } - - if err := future.WaitForCompletionRef(ctx, client.LoadBalancers.LoadBalancersClient.Client); err != nil { - return nil, fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) + return nil, fmt.Errorf("updating %s: %+v", *id, err) } - return utils.Bool(true), nil + return pointer.To(true), nil } func (r LoadBalancerProbe) basic(data acceptance.TestData) string { diff --git a/internal/services/loadbalancer/loadbalancer_resource.go b/internal/services/loadbalancer/loadbalancer_resource.go index 6ee2c825e8af..0b56225df848 100644 --- a/internal/services/loadbalancer/loadbalancer_resource.go +++ b/internal/services/loadbalancer/loadbalancer_resource.go @@ -12,25 +12,24 @@ 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-helpers/resourcemanager/commonschema" "github.com/hashicorp/go-azure-helpers/resourcemanager/edgezones" "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-06-01/loadbalancers" "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/services/loadbalancer/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" networkValidate "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/suppress" "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 resourceArmLoadBalancer() *pluginsdk.Resource { @@ -41,7 +40,7 @@ func resourceArmLoadBalancer() *pluginsdk.Resource { Delete: resourceArmLoadBalancerDelete, Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := parse.LoadBalancerID(id) + _, err := loadbalancers.ParseLoadBalancerID(id) return err }), @@ -88,57 +87,53 @@ func resourceArmLoadBalancerCreateUpdate(d *pluginsdk.ResourceData, meta interfa log.Printf("[INFO] preparing arguments for Azure ARM Load Balancer creation.") - id := parse.NewLoadBalancerID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + id := loadbalancers.NewLoadBalancerID(subscriptionId, d.Get("resource_group_name").(string), d.Get("name").(string)) + plbId := loadbalancers.ProviderLoadBalancerId(id) if d.IsNewResource() { - existing, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + existing, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) 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 tf.ImportAsExistsError("azurerm_lb", id.ID()) } } - if strings.EqualFold(d.Get("sku_tier").(string), string(network.LoadBalancerSkuTierGlobal)) { - if !strings.EqualFold(d.Get("sku").(string), string(network.LoadBalancerSkuNameStandard)) { + if strings.EqualFold(d.Get("sku_tier").(string), string(loadbalancers.LoadBalancerSkuTierGlobal)) { + if !strings.EqualFold(d.Get("sku").(string), string(loadbalancers.LoadBalancerSkuNameStandard)) { return fmt.Errorf("global load balancing is only supported for standard SKU load balancers") } } location := azure.NormalizeLocation(d.Get("location").(string)) - sku := network.LoadBalancerSku{ - Name: network.LoadBalancerSkuName(d.Get("sku").(string)), - Tier: network.LoadBalancerSkuTier(d.Get("sku_tier").(string)), + sku := loadbalancers.LoadBalancerSku{ + Name: pointer.To(loadbalancers.LoadBalancerSkuName(d.Get("sku").(string))), + Tier: pointer.To(loadbalancers.LoadBalancerSkuTier(d.Get("sku_tier").(string))), } - t := d.Get("tags").(map[string]interface{}) - expandedTags := tags.Expand(t) - properties := network.LoadBalancerPropertiesFormat{} + properties := loadbalancers.LoadBalancerPropertiesFormat{} if _, ok := d.GetOk("frontend_ip_configuration"); ok { properties.FrontendIPConfigurations = expandAzureRmLoadBalancerFrontendIpConfigurations(d) } - loadBalancer := network.LoadBalancer{ - Name: utils.String(id.Name), - ExtendedLocation: expandEdgeZone(d.Get("edge_zone").(string)), - Location: utils.String(location), - Tags: expandedTags, - Sku: &sku, - LoadBalancerPropertiesFormat: &properties, + loadBalancer := loadbalancers.LoadBalancer{ + Name: pointer.To(id.LoadBalancerName), + ExtendedLocation: expandEdgeZone(d.Get("edge_zone").(string)), + Location: pointer.To(location), + Tags: tags.Expand(d.Get("tags").(map[string]interface{})), + Sku: pointer.To(sku), + Properties: pointer.To(properties), } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.Name, loadBalancer) + err := client.CreateOrUpdateThenPoll(ctx, plbId, loadBalancer) 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 creation/update of %s: %+v", id, err) - } d.SetId(id.ID()) @@ -150,14 +145,15 @@ func resourceArmLoadBalancerRead(d *pluginsdk.ResourceData, meta interface{}) er ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerID(d.Id()) + id, err := loadbalancers.ParseLoadBalancerID(d.Id()) if err != nil { return err } - resp, err := client.Get(ctx, id.ResourceGroup, id.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + resp, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { + if response.WasNotFound(resp.HttpResponse) { log.Printf("[INFO] %s was not found - removing from state", *id) d.SetId("") return nil @@ -165,42 +161,45 @@ func resourceArmLoadBalancerRead(d *pluginsdk.ResourceData, meta interface{}) er return fmt.Errorf("retrieving %s: %+v", *id, err) } - d.Set("name", id.Name) - d.Set("resource_group_name", id.ResourceGroup) - d.Set("location", location.NormalizeNilable(resp.Location)) - d.Set("edge_zone", flattenEdgeZone(resp.ExtendedLocation)) + d.Set("name", id.LoadBalancerName) + d.Set("resource_group_name", id.ResourceGroupName) - if sku := resp.Sku; sku != nil { - d.Set("sku", string(sku.Name)) - d.Set("sku_tier", string(sku.Tier)) - } + if model := resp.Model; model != nil { + d.Set("location", location.NormalizeNilable(model.Location)) + d.Set("edge_zone", flattenEdgeZone(model.ExtendedLocation)) + if sku := model.Sku; sku != nil { + d.Set("sku", string(pointer.From(sku.Name))) + d.Set("sku_tier", string(pointer.From(sku.Tier))) + } - if props := resp.LoadBalancerPropertiesFormat; props != nil { - if feipConfigs := props.FrontendIPConfigurations; feipConfigs != nil { - if err := d.Set("frontend_ip_configuration", flattenLoadBalancerFrontendIpConfiguration(feipConfigs)); err != nil { - return fmt.Errorf("flattening `frontend_ip_configuration`: %+v", err) - } + if props := model.Properties; props != nil { + if feipConfigs := props.FrontendIPConfigurations; feipConfigs != nil { + if err := d.Set("frontend_ip_configuration", flattenLoadBalancerFrontendIpConfiguration(feipConfigs)); err != nil { + return fmt.Errorf("flattening `frontend_ip_configuration`: %+v", err) + } - privateIpAddress := "" - privateIpAddresses := make([]string, 0) - for _, config := range *feipConfigs { - if feipProps := config.FrontendIPConfigurationPropertiesFormat; feipProps != nil { - if ip := feipProps.PrivateIPAddress; ip != nil { - if privateIpAddress == "" { - privateIpAddress = *feipProps.PrivateIPAddress - } + privateIpAddress := "" + privateIpAddresses := make([]string, 0) + for _, config := range *feipConfigs { + if feipProps := config.Properties; feipProps != nil { + if ip := feipProps.PrivateIPAddress; ip != nil { + if privateIpAddress == "" { + privateIpAddress = pointer.From(feipProps.PrivateIPAddress) + } - privateIpAddresses = append(privateIpAddresses, *feipProps.PrivateIPAddress) + privateIpAddresses = append(privateIpAddresses, *feipProps.PrivateIPAddress) + } } } - } - d.Set("private_ip_address", privateIpAddress) - d.Set("private_ip_addresses", privateIpAddresses) + d.Set("private_ip_address", privateIpAddress) + d.Set("private_ip_addresses", privateIpAddresses) + } } - } - return tags.FlattenAndSet(d, resp.Tags) + return tags.FlattenAndSet(d, model.Tags) + } + return nil } func resourceArmLoadBalancerDelete(d *pluginsdk.ResourceData, meta interface{}) error { @@ -208,70 +207,69 @@ func resourceArmLoadBalancerDelete(d *pluginsdk.ResourceData, meta interface{}) ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerID(d.Id()) + id, err := loadbalancers.ParseLoadBalancerID(d.Id()) if err != nil { return err } - future, err := client.Delete(ctx, id.ResourceGroup, id.Name) + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + + err = client.DeleteThenPoll(ctx, plbId) if 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 } -func expandAzureRmLoadBalancerFrontendIpConfigurations(d *pluginsdk.ResourceData) *[]network.FrontendIPConfiguration { +func expandAzureRmLoadBalancerFrontendIpConfigurations(d *pluginsdk.ResourceData) *[]loadbalancers.FrontendIPConfiguration { configs := d.Get("frontend_ip_configuration").([]interface{}) - frontEndConfigs := make([]network.FrontendIPConfiguration, 0, len(configs)) + frontEndConfigs := make([]loadbalancers.FrontendIPConfiguration, 0, len(configs)) for _, configRaw := range configs { data := configRaw.(map[string]interface{}) - privateIpAllocationMethod := data["private_ip_address_allocation"].(string) - properties := network.FrontendIPConfigurationPropertiesFormat{ - PrivateIPAllocationMethod: network.IPAllocationMethod(privateIpAllocationMethod), + properties := loadbalancers.FrontendIPConfigurationPropertiesFormat{} + + if v := data["private_ip_address_allocation"].(string); v != "" { + properties.PrivateIPAllocationMethod = pointer.To(loadbalancers.IPAllocationMethod(v)) } if v := data["gateway_load_balancer_frontend_ip_configuration_id"].(string); v != "" { - properties.GatewayLoadBalancer = &network.SubResource{ - ID: utils.String(v), + properties.GatewayLoadBalancer = &loadbalancers.SubResource{ + Id: pointer.To(v), } } if v := data["private_ip_address"].(string); v != "" { - properties.PrivateIPAddress = &v + properties.PrivateIPAddress = pointer.To(v) } if v := data["public_ip_address_id"].(string); v != "" { - properties.PublicIPAddress = &network.PublicIPAddress{ - ID: &v, + properties.PublicIPAddress = &loadbalancers.PublicIPAddress{ + Id: pointer.To(v), } } if v := data["public_ip_prefix_id"].(string); v != "" { - properties.PublicIPPrefix = &network.SubResource{ - ID: &v, + properties.PublicIPPrefix = &loadbalancers.SubResource{ + Id: pointer.To(v), } } if v := data["subnet_id"].(string); v != "" { - properties.PrivateIPAddressVersion = network.IPVersionIPv4 + properties.PrivateIPAddressVersion = pointer.To(loadbalancers.IPVersionIPvFour) if v := data["private_ip_address_version"].(string); v != "" { - properties.PrivateIPAddressVersion = network.IPVersion(v) + properties.PrivateIPAddressVersion = pointer.To(loadbalancers.IPVersion(v)) } - properties.Subnet = &network.Subnet{ - ID: &v, + properties.Subnet = &loadbalancers.Subnet{ + Id: pointer.To(v), } } - frontEndConfig := network.FrontendIPConfiguration{ - Name: utils.String(data["name"].(string)), - FrontendIPConfigurationPropertiesFormat: &properties, + frontEndConfig := loadbalancers.FrontendIPConfiguration{ + Name: pointer.To(data["name"].(string)), + Properties: pointer.To(properties), } zones := zones.ExpandUntyped(data["zones"].(*pluginsdk.Set).List()) @@ -285,7 +283,7 @@ func expandAzureRmLoadBalancerFrontendIpConfigurations(d *pluginsdk.ResourceData return &frontEndConfigs } -func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]network.FrontendIPConfiguration) []interface{} { +func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]loadbalancers.FrontendIPConfiguration) []interface{} { result := make([]interface{}, 0) if ipConfigs == nil { return result @@ -298,8 +296,8 @@ func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]network.FrontendIPC } id := "" - if config.ID != nil { - id = *config.ID + if config.Id != nil { + id = *config.Id } var inboundNatRules []interface{} @@ -313,52 +311,46 @@ func flattenLoadBalancerFrontendIpConfiguration(ipConfigs *[]network.FrontendIPC subnetId := "" privateIpAddress := "" - if props := config.FrontendIPConfigurationPropertiesFormat; props != nil { - privateIPAllocationMethod = string(props.PrivateIPAllocationMethod) + if props := config.Properties; props != nil { + privateIPAllocationMethod = string(pointer.From(props.PrivateIPAllocationMethod)) - if props.GatewayLoadBalancer != nil && props.GatewayLoadBalancer.ID != nil { - gatewayLoadBalancerId = *props.GatewayLoadBalancer.ID + if props.GatewayLoadBalancer != nil { + gatewayLoadBalancerId = pointer.From(props.GatewayLoadBalancer.Id) } if subnet := props.Subnet; subnet != nil { - subnetId = *subnet.ID - } - - if pip := props.PrivateIPAddress; pip != nil { - privateIpAddress = *pip - } - - if props.PrivateIPAddressVersion != "" { - privateIpAddressVersion = string(props.PrivateIPAddressVersion) + subnetId = pointer.From(subnet.Id) } + privateIpAddress = pointer.From(props.PrivateIPAddress) + privateIpAddressVersion = string(pointer.From(props.PrivateIPAddressVersion)) if pip := props.PublicIPAddress; pip != nil { - publicIpAddressId = *pip.ID + publicIpAddressId = pointer.From(pip.Id) } if pip := props.PublicIPPrefix; pip != nil { - publicIpPrefixId = *pip.ID + publicIpPrefixId = pointer.From(pip.Id) } if rules := props.LoadBalancingRules; rules != nil { for _, rule := range *rules { - if rule.ID == nil { + if rule.Id == nil { continue } - loadBalancingRules = append(loadBalancingRules, *rule.ID) + loadBalancingRules = append(loadBalancingRules, pointer.From(rule.Id)) } } if rules := props.InboundNatRules; rules != nil { for _, rule := range *rules { - inboundNatRules = append(inboundNatRules, *rule.ID) + inboundNatRules = append(inboundNatRules, pointer.From(rule.Id)) } } if rules := props.OutboundRules; rules != nil { for _, rule := range *rules { - outboundRules = append(outboundRules, *rule.ID) + outboundRules = append(outboundRules, pointer.From(rule.Id)) } } } @@ -401,23 +393,23 @@ func resourceArmLoadBalancerSchema() map[string]*pluginsdk.Schema { "sku": { Type: pluginsdk.TypeString, Optional: true, - Default: string(network.LoadBalancerSkuNameBasic), + Default: string(loadbalancers.LoadBalancerSkuNameBasic), ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.LoadBalancerSkuNameBasic), - string(network.LoadBalancerSkuNameStandard), - string(network.LoadBalancerSkuNameGateway), + string(loadbalancers.LoadBalancerSkuNameBasic), + string(loadbalancers.LoadBalancerSkuNameStandard), + string(loadbalancers.LoadBalancerSkuNameGateway), }, false), }, "sku_tier": { Type: pluginsdk.TypeString, Optional: true, - Default: string(network.LoadBalancerSkuTierRegional), + Default: string(loadbalancers.LoadBalancerSkuTierRegional), ForceNew: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.LoadBalancerSkuTierRegional), - string(network.LoadBalancerSkuTierGlobal), + string(loadbalancers.LoadBalancerSkuTierRegional), + string(loadbalancers.LoadBalancerSkuTierGlobal), }, false), }, @@ -455,8 +447,8 @@ func resourceArmLoadBalancerSchema() map[string]*pluginsdk.Schema { Optional: true, Computed: true, // TODO: why is this computed? ValidateFunc: validation.StringInSlice([]string{ - string(network.IPVersionIPv4), - string(network.IPVersionIPv6), + string(loadbalancers.IPVersionIPvFour), + string(loadbalancers.IPVersionIPvSix), }, false), }, @@ -479,8 +471,8 @@ func resourceArmLoadBalancerSchema() map[string]*pluginsdk.Schema { Optional: true, Computed: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.IPAllocationMethodDynamic), - string(network.IPAllocationMethodStatic), + string(loadbalancers.IPAllocationMethodDynamic), + string(loadbalancers.IPAllocationMethodStatic), }, true), DiffSuppressFunc: suppress.CaseDifference, }, @@ -489,7 +481,7 @@ func resourceArmLoadBalancerSchema() map[string]*pluginsdk.Schema { Type: pluginsdk.TypeString, Optional: true, Computed: true, - ValidateFunc: validate.LoadBalancerFrontendIpConfigurationID, + ValidateFunc: loadbalancers.ValidateFrontendIPConfigurationID, }, "load_balancer_rules": { @@ -544,25 +536,24 @@ func resourceArmLoadBalancerSchema() map[string]*pluginsdk.Schema { }, }, - "tags": tags.Schema(), + "tags": commonschema.Tags(), } } -func expandEdgeZone(input string) *network.ExtendedLocation { +func expandEdgeZone(input string) *edgezones.Model { normalized := edgezones.Normalize(input) if normalized == "" { return nil } - return &network.ExtendedLocation{ - Name: utils.String(normalized), - Type: network.ExtendedLocationTypesEdgeZone, + return &edgezones.Model{ + Name: normalized, } } -func flattenEdgeZone(input *network.ExtendedLocation) string { - if input == nil || input.Type != network.ExtendedLocationTypesEdgeZone || input.Name == nil { +func flattenEdgeZone(input *edgezones.Model) string { + if input == nil || input.Name == "" { return "" } - return edgezones.NormalizeNilable(input.Name) + return edgezones.NormalizeNilable(&input.Name) } diff --git a/internal/services/loadbalancer/loadbalancer_resource_test.go b/internal/services/loadbalancer/loadbalancer_resource_test.go index 58cca69e1b95..9eea89b3476a 100644 --- a/internal/services/loadbalancer/loadbalancer_resource_test.go +++ b/internal/services/loadbalancer/loadbalancer_resource_test.go @@ -6,14 +6,15 @@ package loadbalancer_test import ( "context" "fmt" - "net/http" "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-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) type LoadBalancer struct{} @@ -249,19 +250,17 @@ func TestAccAzureRMLoadBalancer_edgeZone(t *testing.T) { } func (r LoadBalancer) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - loadBalancerName := state.Attributes["name"] - resourceGroup := state.Attributes["resource_group_name"] - - resp, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, resourceGroup, loadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: client.Account.SubscriptionId, ResourceGroupName: state.Attributes["resource_group_name"], LoadBalancerName: state.Attributes["name"]} + resp, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if resp.StatusCode == http.StatusNotFound { - return nil, fmt.Errorf("Bad: Load Balancer %q (resource group: %q) does not exist", loadBalancerName, resourceGroup) + if response.WasNotFound(resp.HttpResponse) { + return nil, fmt.Errorf("%s was not found", plbId) } - return nil, fmt.Errorf("Bad: Get on loadBalancerClient: %+v", err) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) } - return utils.Bool(resp.ID != nil), nil + return pointer.To(resp.Model != nil && resp.Model.Id != nil), nil } func (r LoadBalancer) basic(data acceptance.TestData) string { diff --git a/internal/services/loadbalancer/loadbalancer_rule_resource_test.go b/internal/services/loadbalancer/loadbalancer_rule_resource_test.go index 792569c1b493..af547f08ef26 100644 --- a/internal/services/loadbalancer/loadbalancer_rule_resource_test.go +++ b/internal/services/loadbalancer/loadbalancer_rule_resource_test.go @@ -8,13 +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-06-01/loadbalancers" "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/loadbalancer/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 LoadBalancerRule struct{} @@ -213,59 +213,58 @@ func TestAccAzureRMLoadBalancerRule_gatewayLBRuleMultiple(t *testing.T) { } func (r LoadBalancerRule) Exists(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancingRuleID(state.ID) + id, err := loadbalancers.ParseLoadBalancingRuleID(state.ID) if err != nil { return nil, err } - rule, err := client.LoadBalancers.LoadBalancingRulesClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, id.Name) + rule, err := client.LoadBalancers.LoadBalancersClient.LoadBalancerLoadBalancingRulesGet(ctx, *id) if err != nil { - if utils.ResponseWasNotFound(rule.Response) { - return utils.Bool(false), nil + if response.WasNotFound(rule.HttpResponse) { + return pointer.To(false), nil } - return nil, fmt.Errorf("retrieving %s: %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", *id, err) } - return utils.Bool(rule.ID != nil), nil + return pointer.To(rule.Model != nil && rule.Model.Id != nil), nil } func (r LoadBalancerRule) Destroy(ctx context.Context, client *clients.Client, state *pluginsdk.InstanceState) (*bool, error) { - id, err := parse.LoadBalancingRuleID(state.ID) + id, err := loadbalancers.ParseLoadBalancingRuleID(state.ID) if err != nil { return nil, err } - - loadBalancer, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.LoadBalancers.LoadBalancersClient.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - return nil, fmt.Errorf("retrieving %s: %+v", id, err) + return nil, fmt.Errorf("retrieving %s: %+v", plbId, err) + } + if loadBalancer.Model == nil { + return nil, fmt.Errorf(`model was nil`) } - if loadBalancer.LoadBalancerPropertiesFormat == nil { + if loadBalancer.Model.Properties == nil { return nil, fmt.Errorf(`properties was nil`) } - if loadBalancer.LoadBalancerPropertiesFormat.LoadBalancingRules == nil { + if loadBalancer.Model.Properties.LoadBalancingRules == nil { return nil, fmt.Errorf(`properties.LoadBalancingRules was nil`) } - rules := make([]network.LoadBalancingRule, 0) - for _, v := range *loadBalancer.LoadBalancerPropertiesFormat.LoadBalancingRules { - if v.Name == nil || *v.Name == id.Name { + rules := make([]loadbalancers.LoadBalancingRule, 0) + for _, v := range *loadBalancer.Model.Properties.LoadBalancingRules { + if v.Name == nil || *v.Name == id.LoadBalancingRuleName { continue } rules = append(rules, v) } - loadBalancer.LoadBalancerPropertiesFormat.LoadBalancingRules = &rules + loadBalancer.Model.Properties.LoadBalancingRules = &rules - future, err := client.LoadBalancers.LoadBalancersClient.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, loadBalancer) + err = client.LoadBalancers.LoadBalancersClient.CreateOrUpdateThenPoll(ctx, plbId, *loadBalancer.Model) if err != nil { - return nil, fmt.Errorf("updating Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) - } - - if err := future.WaitForCompletionRef(ctx, client.LoadBalancers.LoadBalancersClient.Client); err != nil { - return nil, fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) + return nil, fmt.Errorf("updating %s: %+v", *id, err) } - return utils.Bool(true), nil + return pointer.To(true), nil } func (r LoadBalancerRule) template(data acceptance.TestData, sku string) string { diff --git a/internal/services/loadbalancer/nat_pool_resource.go b/internal/services/loadbalancer/nat_pool_resource.go index 8104ed5e004f..4cb209027500 100644 --- a/internal/services/loadbalancer/nat_pool_resource.go +++ b/internal/services/loadbalancer/nat_pool_resource.go @@ -8,18 +8,19 @@ 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-sdk/resource-manager/network/2023-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" - loadBalancerValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceArmLoadBalancerNatPool() *pluginsdk.Resource { @@ -29,13 +30,13 @@ func resourceArmLoadBalancerNatPool() *pluginsdk.Resource { Update: resourceArmLoadBalancerNatPoolCreateUpdate, Delete: resourceArmLoadBalancerNatPoolDelete, - Importer: loadBalancerSubResourceImporter(func(input string) (*parse.LoadBalancerId, error) { + Importer: loadBalancerSubResourceImporter(func(input string) (*loadbalancers.LoadBalancerId, error) { id, err := parse.LoadBalancerInboundNatPoolID(input) if err != nil { return nil, err } - lbId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + lbId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) return &lbId, nil }), @@ -60,16 +61,16 @@ func resourceArmLoadBalancerNatPool() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: loadBalancerValidate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "protocol": { Type: pluginsdk.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.TransportProtocolAll), - string(network.TransportProtocolTCP), - string(network.TransportProtocolUDP), + string(loadbalancers.TransportProtocolAll), + string(loadbalancers.TransportProtocolTcp), + string(loadbalancers.TransportProtocolUdp), }, false), }, @@ -128,54 +129,57 @@ func resourceArmLoadBalancerNatPoolCreateUpdate(d *pluginsdk.ResourceData, meta ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return fmt.Errorf("parsing Load Balancer Name and Group: %+v", err) } - id := parse.NewLoadBalancerInboundNatPoolID(subscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, d.Get("name").(string)) + id := parse.NewLoadBalancerInboundNatPoolID(subscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, d.Get("name").(string)) loadBalancerID := loadBalancerId.ID() locks.ByID(loadBalancerID) defer locks.UnlockByID(loadBalancerID) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroup, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Nat Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName, err) + return fmt.Errorf("retrieving %s: %+v", *loadBalancerId, err) } - newNatPool, err := expandAzureRmLoadBalancerNatPool(d, &loadBalancer) - if err != nil { - return fmt.Errorf("expanding NAT Pool: %+v", err) - } - - natPools := append(*loadBalancer.LoadBalancerPropertiesFormat.InboundNatPools, *newNatPool) - existingNatPool, existingNatPoolIndex, exists := FindLoadBalancerNatPoolByName(&loadBalancer, id.InboundNatPoolName) - if exists { - if id.InboundNatPoolName == *existingNatPool.Name { - if d.IsNewResource() { - return tf.ImportAsExistsError("azurerm_lb_nat_pool", *existingNatPool.ID) - } + if model := loadBalancer.Model; model != nil { + newNatPool, err := expandAzureRmLoadBalancerNatPool(d, model) + if err != nil { + return fmt.Errorf("expanding NAT Pool: %+v", err) + } - // this pool is being updated/reapplied remove old copy from the slice - natPools = append(natPools[:existingNatPoolIndex], natPools[existingNatPoolIndex+1:]...) + natPools := make([]loadbalancers.InboundNatPool, 0) + if props := model.Properties; props != nil { + natPools = append(*props.InboundNatPools, *newNatPool) } - } - loadBalancer.LoadBalancerPropertiesFormat.InboundNatPools = &natPools + existingNatPool, existingNatPoolIndex, exists := FindLoadBalancerNatPoolByName(model, id.InboundNatPoolName) + if exists { + if id.InboundNatPoolName == *existingNatPool.Name { + if d.IsNewResource() { + return tf.ImportAsExistsError("azurerm_lb_nat_pool", *existingNatPool.Id) + } - future, err := client.CreateOrUpdate(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, loadBalancer) - if err != nil { - return fmt.Errorf("updating Load Balancer %q (Resource Group %q) for Nat Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName, err) - } + // this pool is being updated/reapplied remove old copy from the slice + natPools = append(natPools[:existingNatPoolIndex], natPools[existingNatPoolIndex+1:]...) + } + } + + model.Properties.InboundNatPools = &natPools - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for the update of Load Balancer %q (Resource Group %q) for Nat Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName, err) + err = client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("creating/updating %s : %+v", id, err) + } } d.SetId(id.ID()) @@ -193,62 +197,51 @@ func resourceArmLoadBalancerNatPoolRead(d *pluginsdk.ResourceData, meta interfac return err } - loadBalancer, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroup, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Nat Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName, err) - } - - config, _, exists := FindLoadBalancerNatPoolByName(&loadBalancer, id.InboundNatPoolName) - if !exists { - d.SetId("") - log.Printf("[INFO] Load Balancer Nat Pool %q not found. Removing from state", id.InboundNatPoolName) - return nil + return fmt.Errorf("retrieving %s: %+v", plbId, err) } - d.Set("name", config.Name) - d.Set("resource_group_name", id.ResourceGroup) - - if props := config.InboundNatPoolPropertiesFormat; props != nil { - backendPort := 0 - if props.BackendPort != nil { - backendPort = int(*props.BackendPort) + if model := loadBalancer.Model; model != nil { + config, _, exists := FindLoadBalancerNatPoolByName(model, id.InboundNatPoolName) + if !exists { + d.SetId("") + log.Printf("[INFO] Load Balancer Nat Pool %q not found. Removing from state", id.InboundNatPoolName) + return nil } - d.Set("backend_port", backendPort) - d.Set("floating_ip_enabled", props.EnableFloatingIP) - d.Set("tcp_reset_enabled", props.EnableTCPReset) - - frontendIPConfigName := "" - frontendIPConfigID := "" - if props.FrontendIPConfiguration != nil && props.FrontendIPConfiguration.ID != nil { - feid, err := parse.LoadBalancerFrontendIpConfigurationIDInsensitively(*props.FrontendIPConfiguration.ID) - if err != nil { - return err - } - frontendIPConfigName = feid.FrontendIPConfigurationName - frontendIPConfigID = feid.ID() - } - d.Set("frontend_ip_configuration_id", frontendIPConfigID) - d.Set("frontend_ip_configuration_name", frontendIPConfigName) + d.Set("name", config.Name) + d.Set("resource_group_name", id.ResourceGroup) - frontendPortRangeEnd := 0 - if props.FrontendPortRangeEnd != nil { - frontendPortRangeEnd = int(*props.FrontendPortRangeEnd) - } - d.Set("frontend_port_end", frontendPortRangeEnd) + if props := config.Properties; props != nil { + d.Set("backend_port", props.BackendPort) + d.Set("floating_ip_enabled", pointer.From(props.EnableFloatingIP)) + d.Set("tcp_reset_enabled", pointer.From(props.EnableTcpReset)) + + frontendIPConfigName := "" + frontendIPConfigID := "" + if props.FrontendIPConfiguration != nil && props.FrontendIPConfiguration.Id != nil { + feid, err := loadbalancers.ParseFrontendIPConfigurationIDInsensitively(*props.FrontendIPConfiguration.Id) + if err != nil { + return err + } - frontendPortRangeStart := 0 - if props.FrontendPortRangeStart != nil { - frontendPortRangeStart = int(*props.FrontendPortRangeStart) + frontendIPConfigName = feid.FrontendIPConfigurationName + frontendIPConfigID = feid.ID() + } + d.Set("frontend_ip_configuration_id", frontendIPConfigID) + d.Set("frontend_ip_configuration_name", frontendIPConfigName) + d.Set("frontend_port_end", props.FrontendPortRangeEnd) + d.Set("frontend_port_start", props.FrontendPortRangeStart) + d.Set("idle_timeout_in_minutes", int(*props.IdleTimeoutInMinutes)) + d.Set("protocol", string(props.Protocol)) } - d.Set("frontend_port_start", frontendPortRangeStart) - d.Set("idle_timeout_in_minutes", int(*props.IdleTimeoutInMinutes)) - d.Set("protocol", string(props.Protocol)) } return nil @@ -264,47 +257,47 @@ func resourceArmLoadBalancerNatPoolDelete(d *pluginsdk.ResourceData, meta interf return err } - loadBalancerId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + loadBalancerId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) loadBalancerID := loadBalancerId.ID() locks.ByID(loadBalancerID) defer locks.UnlockByID(loadBalancerID) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroup, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for deletion of Nat Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName, err) - } - - _, index, exists := FindLoadBalancerNatPoolByName(&loadBalancer, id.InboundNatPoolName) - if !exists { - return nil + return fmt.Errorf("retrieving %s: %+v", loadBalancerId, err) } - natPools := *loadBalancer.LoadBalancerPropertiesFormat.InboundNatPools - natPools = append(natPools[:index], natPools[index+1:]...) - loadBalancer.LoadBalancerPropertiesFormat.InboundNatPools = &natPools + if model := loadBalancer.Model; model != nil { + _, index, exists := FindLoadBalancerNatPoolByName(model, id.InboundNatPoolName) + if !exists { + return nil + } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, loadBalancer) - if err != nil { - return fmt.Errorf("updating Load Balancer %q (Resource Group %q) for Nat Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName, err) - } + if props := model.Properties; props != nil { + natPools := *props.InboundNatPools + natPools = append(natPools[:index], natPools[index+1:]...) + props.InboundNatPools = &natPools - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of the Load Balancer %q (Resource Group %q) for Nat Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName, err) + err := client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("updating Load Balancer %q (Resource Group %q) for Nat Pool %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatPoolName, err) + } + } } - return nil } -func expandAzureRmLoadBalancerNatPool(d *pluginsdk.ResourceData, lb *network.LoadBalancer) (*network.InboundNatPool, error) { - properties := network.InboundNatPoolPropertiesFormat{ - Protocol: network.TransportProtocol(d.Get("protocol").(string)), - FrontendPortRangeStart: utils.Int32(int32(d.Get("frontend_port_start").(int))), - FrontendPortRangeEnd: utils.Int32(int32(d.Get("frontend_port_end").(int))), - BackendPort: utils.Int32(int32(d.Get("backend_port").(int))), +func expandAzureRmLoadBalancerNatPool(d *pluginsdk.ResourceData, lb *loadbalancers.LoadBalancer) (*loadbalancers.InboundNatPool, error) { + properties := loadbalancers.InboundNatPoolPropertiesFormat{ + Protocol: loadbalancers.TransportProtocol(d.Get("protocol").(string)), + FrontendPortRangeStart: int64(d.Get("frontend_port_start").(int)), + FrontendPortRangeEnd: int64(d.Get("frontend_port_end").(int)), + BackendPort: int64(d.Get("backend_port").(int)), } if v, ok := d.GetOk("floating_ip_enabled"); ok { @@ -312,10 +305,10 @@ func expandAzureRmLoadBalancerNatPool(d *pluginsdk.ResourceData, lb *network.Loa } if v, ok := d.GetOk("tcp_reset_enabled"); ok { - properties.EnableTCPReset = utils.Bool(v.(bool)) + properties.EnableTcpReset = utils.Bool(v.(bool)) } - properties.IdleTimeoutInMinutes = utils.Int32(int32(d.Get("idle_timeout_in_minutes").(int))) + properties.IdleTimeoutInMinutes = pointer.To(int64(d.Get("idle_timeout_in_minutes").(int))) if v := d.Get("frontend_ip_configuration_name").(string); v != "" { rule, exists := FindLoadBalancerFrontEndIpConfigurationByName(lb, v) @@ -323,13 +316,13 @@ func expandAzureRmLoadBalancerNatPool(d *pluginsdk.ResourceData, lb *network.Loa return nil, fmt.Errorf("[ERROR] Cannot find FrontEnd IP Configuration with the name %s", v) } - properties.FrontendIPConfiguration = &network.SubResource{ - ID: rule.ID, + properties.FrontendIPConfiguration = &loadbalancers.SubResource{ + Id: rule.Id, } } - return &network.InboundNatPool{ - Name: utils.String(d.Get("name").(string)), - InboundNatPoolPropertiesFormat: &properties, + return &loadbalancers.InboundNatPool{ + Name: pointer.To(d.Get("name").(string)), + Properties: &properties, }, nil } diff --git a/internal/services/loadbalancer/nat_rule_resource.go b/internal/services/loadbalancer/nat_rule_resource.go index 9bcae5826649..f5e73025471b 100644 --- a/internal/services/loadbalancer/nat_rule_resource.go +++ b/internal/services/loadbalancer/nat_rule_resource.go @@ -8,18 +8,17 @@ 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-sdk/resource-manager/network/2023-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" - loadBalancerValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceArmLoadBalancerNatRule() *pluginsdk.Resource { @@ -29,13 +28,13 @@ func resourceArmLoadBalancerNatRule() *pluginsdk.Resource { Update: resourceArmLoadBalancerNatRuleCreateUpdate, Delete: resourceArmLoadBalancerNatRuleDelete, - Importer: loadBalancerSubResourceImporter(func(input string) (*parse.LoadBalancerId, error) { - id, err := parse.LoadBalancerInboundNatRuleID(input) + Importer: loadBalancerSubResourceImporter(func(input string) (*loadbalancers.LoadBalancerId, error) { + id, err := loadbalancers.ParseInboundNatRuleID(input) if err != nil { return nil, err } - lbId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + lbId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) return &lbId, nil }), @@ -60,16 +59,16 @@ func resourceArmLoadBalancerNatRule() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: loadBalancerValidate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "protocol": { Type: pluginsdk.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.TransportProtocolAll), - string(network.TransportProtocolTCP), - string(network.TransportProtocolUDP), + string(loadbalancers.TransportProtocolAll), + string(loadbalancers.TransportProtocolTcp), + string(loadbalancers.TransportProtocolUdp), }, false), }, @@ -108,7 +107,7 @@ func resourceArmLoadBalancerNatRule() *pluginsdk.Resource { "backend_address_pool_id": { Type: pluginsdk.TypeString, Optional: true, - ValidateFunc: loadBalancerValidate.LoadBalancerBackendAddressPoolID, + ValidateFunc: loadbalancers.ValidateLoadBalancerBackendAddressPoolID, ConflictsWith: []string{"frontend_port"}, RequiredWith: []string{"frontend_port_start", "frontend_port_end"}, }, @@ -155,56 +154,57 @@ func resourceArmLoadBalancerNatRuleCreateUpdate(d *pluginsdk.ResourceData, meta ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return fmt.Errorf("retrieving Load Balancer Name and Group: %+v", err) } - id := parse.NewLoadBalancerInboundNatRuleID(subscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, d.Get("name").(string)) + id := loadbalancers.NewInboundNatRuleID(subscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, d.Get("name").(string)) loadBalancerIdRaw := loadBalancerId.ID() locks.ByID(loadBalancerIdRaw) defer locks.UnlockByID(loadBalancerIdRaw) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Nat Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatRuleName, err) + return fmt.Errorf("retrieving %s: %+v", *loadBalancerId, err) } - newNatRule, err := expandAzureRmLoadBalancerNatRule(d, &loadBalancer, *loadBalancerId) - if err != nil { - return fmt.Errorf("expanding NAT Rule: %+v", err) - } + if model := loadBalancer.Model; model != nil { + newNatRule, err := expandAzureRmLoadBalancerNatRule(d, model, *loadBalancerId) + if err != nil { + return fmt.Errorf("expanding NAT Rule: %+v", err) + } - natRules := append(*loadBalancer.LoadBalancerPropertiesFormat.InboundNatRules, *newNatRule) + natRules := make([]loadbalancers.InboundNatRule, 0) + if props := model.Properties; props != nil { + natRules = append(*props.InboundNatRules, *newNatRule) - existingNatRule, existingNatRuleIndex, exists := FindLoadBalancerNatRuleByName(&loadBalancer, id.InboundNatRuleName) - if exists { - if id.InboundNatRuleName == *existingNatRule.Name { - if d.IsNewResource() { - return tf.ImportAsExistsError("azurerm_lb_nat_rule", *existingNatRule.ID) - } + existingNatRule, existingNatRuleIndex, exists := FindLoadBalancerNatRuleByName(model, id.InboundNatRuleName) + if exists { + if id.InboundNatRuleName == *existingNatRule.Name { + if d.IsNewResource() { + return tf.ImportAsExistsError("azurerm_lb_nat_rule", *existingNatRule.Id) + } - // this nat rule is being updated/reapplied remove old copy from the slice - natRules = append(natRules[:existingNatRuleIndex], natRules[existingNatRuleIndex+1:]...) - } - } + // this nat rule is being updated/reapplied remove old copy from the slice + natRules = append(natRules[:existingNatRuleIndex], natRules[existingNatRuleIndex+1:]...) + } + } - loadBalancer.LoadBalancerPropertiesFormat.InboundNatRules = &natRules + props.InboundNatRules = &natRules - future, err := client.CreateOrUpdate(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, loadBalancer) - if err != nil { - return fmt.Errorf("updating Load Balancer %q (Resource Group %q) for Nat Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatRuleName, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q) for Nat Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatRuleName, err) + err := client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + } } - d.SetId(id.ID()) return resourceArmLoadBalancerNatRuleRead(d, meta) @@ -215,85 +215,67 @@ func resourceArmLoadBalancerNatRuleRead(d *pluginsdk.ResourceData, meta interfac ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerInboundNatRuleID(d.Id()) + id, err := loadbalancers.ParseInboundNatRuleID(d.Id()) if err != nil { return err } - loadBalancer, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Nat Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.InboundNatRuleName, err) + return fmt.Errorf("retrieving %s: %+v", plbId, err) } - config, _, exists := FindLoadBalancerNatRuleByName(&loadBalancer, id.InboundNatRuleName) - if !exists { - d.SetId("") - log.Printf("[INFO] Load Balancer Nat Rule %q not found. Removing from state", id.InboundNatRuleName) - return nil - } - - d.Set("name", config.Name) - d.Set("resource_group_name", id.ResourceGroup) - - if props := config.InboundNatRulePropertiesFormat; props != nil { - backendIPConfigId := "" - if props.BackendIPConfiguration != nil && props.BackendIPConfiguration.ID != nil { - backendIPConfigId = *props.BackendIPConfiguration.ID - } - d.Set("backend_ip_configuration_id", backendIPConfigId) - - backendPort := 0 - if props.BackendPort != nil { - backendPort = int(*props.BackendPort) - } - d.Set("backend_port", backendPort) - d.Set("enable_floating_ip", props.EnableFloatingIP) - d.Set("enable_tcp_reset", props.EnableTCPReset) - - frontendIPConfigName := "" - frontendIPConfigID := "" - if props.FrontendIPConfiguration != nil && props.FrontendIPConfiguration.ID != nil { - feid, err := parse.LoadBalancerFrontendIpConfigurationIDInsensitively(*props.FrontendIPConfiguration.ID) - if err != nil { - return err - } - - frontendIPConfigName = feid.FrontendIPConfigurationName - frontendIPConfigID = feid.ID() - } - d.Set("frontend_ip_configuration_name", frontendIPConfigName) - d.Set("frontend_ip_configuration_id", frontendIPConfigID) - - if props.BackendAddressPool != nil && props.BackendAddressPool.ID != nil { - d.Set("backend_address_pool_id", props.BackendAddressPool.ID) + if model := loadBalancer.Model; model != nil { + config, _, exists := FindLoadBalancerNatRuleByName(model, id.InboundNatRuleName) + if !exists { + d.SetId("") + log.Printf("[INFO] Load Balancer Nat Rule %q not found. Removing from state", id.InboundNatRuleName) + return nil } - frontendPort := 0 - if props.FrontendPort != nil { - frontendPort = int(*props.FrontendPort) - d.Set("frontend_port", frontendPort) - } + d.Set("name", config.Name) + d.Set("resource_group_name", id.ResourceGroupName) - if props.FrontendPortRangeStart != nil { - d.Set("frontend_port_start", int(*props.FrontendPortRangeStart)) - } - if props.FrontendPortRangeEnd != nil { - d.Set("frontend_port_end", int(*props.FrontendPortRangeEnd)) - } + if props := config.Properties; props != nil { + backendIPConfigId := "" + if props.BackendIPConfiguration != nil && props.BackendIPConfiguration.Id != nil { + backendIPConfigId = *props.BackendIPConfiguration.Id + } + d.Set("backend_ip_configuration_id", backendIPConfigId) + d.Set("backend_port", pointer.From(props.BackendPort)) + d.Set("enable_floating_ip", pointer.From(props.EnableFloatingIP)) + d.Set("enable_tcp_reset", pointer.From(props.EnableTcpReset)) + + frontendIPConfigName := "" + frontendIPConfigID := "" + if props.FrontendIPConfiguration != nil && props.FrontendIPConfiguration.Id != nil { + feid, err := loadbalancers.ParseFrontendIPConfigurationIDInsensitively(*props.FrontendIPConfiguration.Id) + if err != nil { + return err + } + + frontendIPConfigName = feid.FrontendIPConfigurationName + frontendIPConfigID = feid.ID() + } + d.Set("frontend_ip_configuration_name", frontendIPConfigName) + d.Set("frontend_ip_configuration_id", frontendIPConfigID) - idleTimeoutInMinutes := 0 - if props.IdleTimeoutInMinutes != nil { - idleTimeoutInMinutes = int(*props.IdleTimeoutInMinutes) + if props.BackendAddressPool != nil { + d.Set("backend_address_pool_id", pointer.From(props.BackendAddressPool.Id)) + } + d.Set("frontend_port", pointer.From(props.FrontendPort)) + d.Set("frontend_port_start", int(pointer.From(props.FrontendPortRangeStart))) + d.Set("frontend_port_end", int(pointer.From(props.FrontendPortRangeEnd))) + d.Set("idle_timeout_in_minutes", int(pointer.From(props.IdleTimeoutInMinutes))) + d.Set("protocol", string(pointer.From(props.Protocol))) } - d.Set("idle_timeout_in_minutes", idleTimeoutInMinutes) - d.Set("protocol", string(props.Protocol)) } - return nil } @@ -302,50 +284,50 @@ func resourceArmLoadBalancerNatRuleDelete(d *pluginsdk.ResourceData, meta interf ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerInboundNatRuleID(d.Id()) + id, err := loadbalancers.ParseInboundNatRuleID(d.Id()) if err != nil { return err } - loadBalancerId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + loadBalancerId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) loadBalancerID := loadBalancerId.ID() locks.ByID(loadBalancerID) defer locks.UnlockByID(loadBalancerID) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Nat Rule %q: %+v", loadBalancerId.Name, loadBalancerId.ResourceGroup, id.InboundNatRuleName, err) - } - _, index, exists := FindLoadBalancerNatRuleByName(&loadBalancer, id.InboundNatRuleName) - if !exists { - return nil + return fmt.Errorf("retrieving %s: %+v", loadBalancerId, err) } + if model := loadBalancer.Model; model != nil { + _, index, exists := FindLoadBalancerNatRuleByName(model, id.InboundNatRuleName) + if !exists { + return nil + } - natRules := *loadBalancer.LoadBalancerPropertiesFormat.InboundNatRules - natRules = append(natRules[:index], natRules[index+1:]...) - loadBalancer.LoadBalancerPropertiesFormat.InboundNatRules = &natRules + if props := model.Properties; props != nil { + natRules := *props.InboundNatRules + natRules = append(natRules[:index], natRules[index+1:]...) + props.InboundNatRules = &natRules - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, loadBalancer) - if err != nil { - return fmt.Errorf("Creating/Updating Load Balancer %q (Resource Group %q) %+v", id.LoadBalancerName, id.ResourceGroup, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for the completion of Load Balancer updates for %q (Resource Group %q) %+v", id.LoadBalancerName, id.ResourceGroup, err) + err := client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("Creating/Updating %s: %+v", *id, err) + } + } } - return nil } -func expandAzureRmLoadBalancerNatRule(d *pluginsdk.ResourceData, lb *network.LoadBalancer, loadBalancerId parse.LoadBalancerId) (*network.InboundNatRule, error) { - properties := network.InboundNatRulePropertiesFormat{ - Protocol: network.TransportProtocol(d.Get("protocol").(string)), - BackendPort: utils.Int32(int32(d.Get("backend_port").(int))), - EnableTCPReset: utils.Bool(d.Get("enable_tcp_reset").(bool)), +func expandAzureRmLoadBalancerNatRule(d *pluginsdk.ResourceData, lb *loadbalancers.LoadBalancer, loadBalancerId loadbalancers.LoadBalancerId) (*loadbalancers.InboundNatRule, error) { + properties := loadbalancers.InboundNatRulePropertiesFormat{ + Protocol: pointer.To(loadbalancers.TransportProtocol(d.Get("protocol").(string))), + BackendPort: pointer.To(int64(d.Get("backend_port").(int))), + EnableTcpReset: pointer.To(d.Get("enable_tcp_reset").(bool)), } backendAddressPoolSet, frontendPort := false, false @@ -357,26 +339,26 @@ func expandAzureRmLoadBalancerNatRule(d *pluginsdk.ResourceData, lb *network.Loa } if backendAddressPoolSet { - properties.FrontendPortRangeStart = utils.Int32(int32(d.Get("frontend_port_start").(int))) - properties.FrontendPortRangeEnd = utils.Int32(int32(d.Get("frontend_port_end").(int))) - properties.BackendAddressPool = &network.SubResource{ - ID: utils.String(d.Get("backend_address_pool_id").(string)), + properties.FrontendPortRangeStart = pointer.To(int64(d.Get("frontend_port_start").(int))) + properties.FrontendPortRangeEnd = pointer.To(int64(d.Get("frontend_port_end").(int))) + properties.BackendAddressPool = &loadbalancers.SubResource{ + Id: pointer.To(d.Get("backend_address_pool_id").(string)), } } else { if frontendPort { - properties.FrontendPort = utils.Int32(int32(d.Get("frontend_port").(int))) + properties.FrontendPort = pointer.To(int64(d.Get("frontend_port").(int))) } else { - properties.FrontendPortRangeStart = utils.Int32(int32(d.Get("frontend_port_start").(int))) - properties.FrontendPortRangeEnd = utils.Int32(int32(d.Get("frontend_port_end").(int))) + properties.FrontendPortRangeStart = pointer.To(int64(d.Get("frontend_port_start").(int))) + properties.FrontendPortRangeEnd = pointer.To(int64(d.Get("frontend_port_end").(int))) } } if v, ok := d.GetOk("enable_floating_ip"); ok { - properties.EnableFloatingIP = utils.Bool(v.(bool)) + properties.EnableFloatingIP = pointer.To(v.(bool)) } if v, ok := d.GetOk("idle_timeout_in_minutes"); ok { - properties.IdleTimeoutInMinutes = utils.Int32(int32(v.(int))) + properties.IdleTimeoutInMinutes = pointer.To(int64(v.(int))) } if v := d.Get("frontend_ip_configuration_name").(string); v != "" { @@ -384,15 +366,15 @@ func expandAzureRmLoadBalancerNatRule(d *pluginsdk.ResourceData, lb *network.Loa return nil, fmt.Errorf("[ERROR] Cannot find FrontEnd IP Configuration with the name %s", v) } - id := parse.NewLoadBalancerFrontendIpConfigurationID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, v).ID() - properties.FrontendIPConfiguration = &network.SubResource{ - ID: utils.String(id), + id := loadbalancers.NewFrontendIPConfigurationID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, v).ID() + properties.FrontendIPConfiguration = &loadbalancers.SubResource{ + Id: pointer.To(id), } } - natRule := network.InboundNatRule{ - Name: utils.String(d.Get("name").(string)), - InboundNatRulePropertiesFormat: &properties, + natRule := loadbalancers.InboundNatRule{ + Name: pointer.To(d.Get("name").(string)), + Properties: &properties, } return &natRule, nil diff --git a/internal/services/loadbalancer/outbound_rule_data_source.go b/internal/services/loadbalancer/outbound_rule_data_source.go index 8beaf6a47eaa..973394e19359 100644 --- a/internal/services/loadbalancer/outbound_rule_data_source.go +++ b/internal/services/loadbalancer/outbound_rule_data_source.go @@ -7,13 +7,13 @@ import ( "fmt" "time" + "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-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" ) func dataSourceArmLoadBalancerOutboundRule() *pluginsdk.Resource { @@ -34,7 +34,7 @@ func dataSourceArmLoadBalancerOutboundRule() *pluginsdk.Resource { "loadbalancer_id": { Type: pluginsdk.TypeString, Required: true, - ValidateFunc: validate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "frontend_ip_configuration": { @@ -89,71 +89,66 @@ func dataSourceArmLoadBalancerOutboundRuleRead(d *pluginsdk.ResourceData, meta i defer cancel() name := d.Get("name").(string) - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return err } - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: loadBalancerId.SubscriptionId, ResourceGroupName: loadBalancerId.ResourceGroupName, LoadBalancerName: loadBalancerId.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { - return fmt.Errorf("parent %s was not found", *loadBalancerId) + if response.WasNotFound(loadBalancer.HttpResponse) { + return fmt.Errorf("%s was not found", *loadBalancerId) } - return fmt.Errorf("retrieving parent %s: %+v", *loadBalancerId, err) + return fmt.Errorf("retrieving %s: %+v", *loadBalancerId, err) } - id := parse.NewLoadBalancerOutboundRuleID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, name) - config, _, exists := FindLoadBalancerOutboundRuleByName(&loadBalancer, id.OutboundRuleName) - if !exists { - return fmt.Errorf("%s was not found", id) - } + id := loadbalancers.NewOutboundRuleID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, name) - d.SetId(id.ID()) - if props := config.OutboundRulePropertiesFormat; props != nil { - allocatedOutboundPorts := 0 - if props.AllocatedOutboundPorts != nil { - allocatedOutboundPorts = int(*props.AllocatedOutboundPorts) + if model := loadBalancer.Model; model != nil { + config, _, exists := FindLoadBalancerOutboundRuleByName(model, id.OutboundRuleName) + if !exists { + return fmt.Errorf("%s was not found", id) } - d.Set("allocated_outbound_ports", allocatedOutboundPorts) - backendAddressPoolId := "" - if props.BackendAddressPool != nil && props.BackendAddressPool.ID != nil { - bapid, err := parse.LoadBalancerBackendAddressPoolID(*props.BackendAddressPool.ID) - if err != nil { - return err - } + d.SetId(id.ID()) - backendAddressPoolId = bapid.ID() - } - d.Set("backend_address_pool_id", backendAddressPoolId) - d.Set("tcp_reset_enabled", props.EnableTCPReset) - - frontendIpConfigurations := make([]interface{}, 0) - if configs := props.FrontendIPConfigurations; configs != nil { - for _, feConfig := range *configs { - if feConfig.ID == nil { - continue - } - feid, err := parse.LoadBalancerFrontendIpConfigurationID(*feConfig.ID) + if props := config.Properties; props != nil { + d.Set("allocated_outbound_ports", int(pointer.From(props.AllocatedOutboundPorts))) + + backendAddressPoolId := "" + if props.BackendAddressPool.Id != nil { + bapid, err := loadbalancers.ParseLoadBalancerBackendAddressPoolID(*props.BackendAddressPool.Id) if err != nil { return err } - frontendIpConfigurations = append(frontendIpConfigurations, map[string]interface{}{ - "id": feid.ID(), - "name": feid.FrontendIPConfigurationName, - }) + backendAddressPoolId = bapid.ID() } + d.Set("backend_address_pool_id", backendAddressPoolId) + d.Set("tcp_reset_enabled", pointer.From(props.EnableTcpReset)) + + frontendIpConfigurations := make([]interface{}, 0) + if configs := props.FrontendIPConfigurations; configs != nil { + for _, feConfig := range configs { + if feConfig.Id == nil { + continue + } + feid, err := loadbalancers.ParseFrontendIPConfigurationID(*feConfig.Id) + if err != nil { + return err + } + + frontendIpConfigurations = append(frontendIpConfigurations, map[string]interface{}{ + "id": feid.ID(), + "name": feid.FrontendIPConfigurationName, + }) + } + } + d.Set("frontend_ip_configuration", frontendIpConfigurations) + d.Set("idle_timeout_in_minutes", int(pointer.From(props.IdleTimeoutInMinutes))) + d.Set("protocol", string(props.Protocol)) } - d.Set("frontend_ip_configuration", frontendIpConfigurations) - - idleTimeoutInMinutes := 0 - if props.IdleTimeoutInMinutes != nil { - idleTimeoutInMinutes = int(*props.IdleTimeoutInMinutes) - } - d.Set("idle_timeout_in_minutes", idleTimeoutInMinutes) - d.Set("protocol", string(props.Protocol)) } - return nil } diff --git a/internal/services/loadbalancer/outbound_rule_resource.go b/internal/services/loadbalancer/outbound_rule_resource.go index 9e757198ea96..c6e1b301e2e2 100644 --- a/internal/services/loadbalancer/outbound_rule_resource.go +++ b/internal/services/loadbalancer/outbound_rule_resource.go @@ -8,16 +8,15 @@ import ( "log" "time" + "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-06-01/loadbalancers" "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/loadbalancer/parse" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceArmLoadBalancerOutboundRule() *pluginsdk.Resource { @@ -27,13 +26,13 @@ func resourceArmLoadBalancerOutboundRule() *pluginsdk.Resource { Update: resourceArmLoadBalancerOutboundRuleCreateUpdate, Delete: resourceArmLoadBalancerOutboundRuleDelete, - Importer: loadBalancerSubResourceImporter(func(input string) (*parse.LoadBalancerId, error) { - id, err := parse.LoadBalancerOutboundRuleID(input) + Importer: loadBalancerSubResourceImporter(func(input string) (*loadbalancers.LoadBalancerId, error) { + id, err := loadbalancers.ParseOutboundRuleID(input) if err != nil { return nil, err } - lbId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + lbId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) return &lbId, nil }), @@ -56,7 +55,7 @@ func resourceArmLoadBalancerOutboundRule() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: validate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "frontend_ip_configuration": { @@ -88,9 +87,9 @@ func resourceArmLoadBalancerOutboundRule() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ValidateFunc: validation.StringInSlice([]string{ - string(network.TransportProtocolAll), - string(network.TransportProtocolTCP), - string(network.TransportProtocolUDP), + string(loadbalancers.TransportProtocolAll), + string(loadbalancers.TransportProtocolTcp), + string(loadbalancers.TransportProtocolUdp), }, false), }, @@ -123,59 +122,60 @@ func resourceArmLoadBalancerOutboundRuleCreateUpdate(d *pluginsdk.ResourceData, ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return err } loadBalancerIDRaw := loadBalancerId.ID() - id := parse.NewLoadBalancerOutboundRuleID(subscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, d.Get("name").(string)) + id := loadbalancers.NewOutboundRuleID(subscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, d.Get("name").(string)) locks.ByID(loadBalancerIDRaw) defer locks.UnlockByID(loadBalancerIDRaw) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Outbound Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName, err) + return fmt.Errorf("retrieving %s: %+v", *loadBalancerId, err) } - newOutboundRule, err := expandAzureRmLoadBalancerOutboundRule(d, &loadBalancer) - if err != nil { - return fmt.Errorf("expanding Load Balancer Outbound Rule: %+v", err) - } - - outboundRules := make([]network.OutboundRule, 0) + if model := loadBalancer.Model; model != nil { + newOutboundRule, err := expandAzureRmLoadBalancerOutboundRule(d, model) + if err != nil { + return fmt.Errorf("expanding Load Balancer Outbound Rule: %+v", err) + } - if loadBalancer.LoadBalancerPropertiesFormat.OutboundRules != nil { - outboundRules = *loadBalancer.LoadBalancerPropertiesFormat.OutboundRules - } + outboundRules := make([]loadbalancers.OutboundRule, 0) - existingOutboundRule, existingOutboundRuleIndex, exists := FindLoadBalancerOutboundRuleByName(&loadBalancer, id.OutboundRuleName) - if exists { - if id.OutboundRuleName == *existingOutboundRule.Name { - if d.IsNewResource() { - return tf.ImportAsExistsError("azurerm_lb_outbound_rule", *existingOutboundRule.ID) + if props := model.Properties; props != nil { + if props.OutboundRules != nil { + outboundRules = pointer.From(props.OutboundRules) } - // this outbound rule is being updated/reapplied remove old copy from the slice - outboundRules = append(outboundRules[:existingOutboundRuleIndex], outboundRules[existingOutboundRuleIndex+1:]...) - } - } + existingOutboundRule, existingOutboundRuleIndex, exists := FindLoadBalancerOutboundRuleByName(model, id.OutboundRuleName) + if exists { + if id.OutboundRuleName == *existingOutboundRule.Name { + if d.IsNewResource() { + return tf.ImportAsExistsError("azurerm_lb_outbound_rule", *existingOutboundRule.Id) + } - outboundRules = append(outboundRules, *newOutboundRule) + // this outbound rule is being updated/reapplied remove old copy from the slice + outboundRules = append(outboundRules[:existingOutboundRuleIndex], outboundRules[existingOutboundRuleIndex+1:]...) + } + } - loadBalancer.LoadBalancerPropertiesFormat.OutboundRules = &outboundRules + outboundRules = append(outboundRules, *newOutboundRule) - future, err := client.CreateOrUpdate(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, loadBalancer) - if err != nil { - return fmt.Errorf("updating LoadBalancer %q (resource group %q) for Outbound Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName, err) - } + props.OutboundRules = &outboundRules - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of Load Balancer %q (resource group %q) for Outbound Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName, err) + err := client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("creating/updating %s: %+v", id, err) + } + } } d.SetId(id.ID()) @@ -188,74 +188,72 @@ func resourceArmLoadBalancerOutboundRuleRead(d *pluginsdk.ResourceData, meta int ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerOutboundRuleID(d.Id()) + id, err := loadbalancers.ParseOutboundRuleID(d.Id()) if err != nil { return err } - loadBalancer, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Outbound Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName, err) - } - - config, _, exists := FindLoadBalancerOutboundRuleByName(&loadBalancer, id.OutboundRuleName) - if !exists { - d.SetId("") - log.Printf("[INFO] Load Balancer Outbound Rule %q not found. Removing from state", id.OutboundRuleName) - return nil + return fmt.Errorf("retrieving %s: %+v", plbId, err) } - d.Set("name", config.Name) - - if props := config.OutboundRulePropertiesFormat; props != nil { - allocatedOutboundPorts := 0 - if props.AllocatedOutboundPorts != nil { - allocatedOutboundPorts = int(*props.AllocatedOutboundPorts) + if model := loadBalancer.Model; model != nil { + config, _, exists := FindLoadBalancerOutboundRuleByName(model, id.OutboundRuleName) + if !exists { + d.SetId("") + log.Printf("[INFO] Load Balancer Outbound Rule %q not found. Removing from state", id.OutboundRuleName) + return nil } - d.Set("allocated_outbound_ports", allocatedOutboundPorts) - backendAddressPoolId := "" - if props.BackendAddressPool != nil && props.BackendAddressPool.ID != nil { - bapid, err := parse.LoadBalancerBackendAddressPoolIDInsensitively(*props.BackendAddressPool.ID) - if err != nil { - return err + d.Set("name", config.Name) + + if props := config.Properties; props != nil { + allocatedOutboundPorts := 0 + if props.AllocatedOutboundPorts != nil { + allocatedOutboundPorts = int(*props.AllocatedOutboundPorts) } + d.Set("allocated_outbound_ports", allocatedOutboundPorts) - backendAddressPoolId = bapid.ID() - } - d.Set("backend_address_pool_id", backendAddressPoolId) - d.Set("enable_tcp_reset", props.EnableTCPReset) - - frontendIpConfigurations := make([]interface{}, 0) - if configs := props.FrontendIPConfigurations; configs != nil { - for _, feConfig := range *configs { - if feConfig.ID == nil { - continue - } - feid, err := parse.LoadBalancerFrontendIpConfigurationIDInsensitively(*feConfig.ID) + backendAddressPoolId := "" + if props.BackendAddressPool.Id != nil { + bapid, err := loadbalancers.ParseLoadBalancerBackendAddressPoolIDInsensitively(*props.BackendAddressPool.Id) if err != nil { return err } - frontendIpConfigurations = append(frontendIpConfigurations, map[string]interface{}{ - "id": feid.ID(), - "name": feid.FrontendIPConfigurationName, - }) + backendAddressPoolId = bapid.ID() } + d.Set("backend_address_pool_id", backendAddressPoolId) + d.Set("enable_tcp_reset", props.EnableTcpReset) + + frontendIpConfigurations := make([]interface{}, 0) + if configs := props.FrontendIPConfigurations; configs != nil { + for _, feConfig := range configs { + if feConfig.Id == nil { + continue + } + feid, err := loadbalancers.ParseFrontendIPConfigurationIDInsensitively(*feConfig.Id) + if err != nil { + return err + } + + frontendIpConfigurations = append(frontendIpConfigurations, map[string]interface{}{ + "id": feid.ID(), + "name": feid.FrontendIPConfigurationName, + }) + } + } + d.Set("frontend_ip_configuration", frontendIpConfigurations) + d.Set("idle_timeout_in_minutes", int(pointer.From(props.IdleTimeoutInMinutes))) + d.Set("protocol", string(props.Protocol)) } - d.Set("frontend_ip_configuration", frontendIpConfigurations) - - idleTimeoutInMinutes := 0 - if props.IdleTimeoutInMinutes != nil { - idleTimeoutInMinutes = int(*props.IdleTimeoutInMinutes) - } - d.Set("idle_timeout_in_minutes", idleTimeoutInMinutes) - d.Set("protocol", string(props.Protocol)) } return nil @@ -266,54 +264,54 @@ func resourceArmLoadBalancerOutboundRuleDelete(d *pluginsdk.ResourceData, meta i ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerOutboundRuleID(d.Id()) + id, err := loadbalancers.ParseOutboundRuleID(d.Id()) if err != nil { return err } - loadBalancerId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + loadBalancerId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) loadBalancerID := loadBalancerId.ID() locks.ByID(loadBalancerID) defer locks.UnlockByID(loadBalancerID) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Outbound Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName, err) - } - - _, index, exists := FindLoadBalancerOutboundRuleByName(&loadBalancer, id.OutboundRuleName) - if !exists { - return nil + return fmt.Errorf("retrieving %s: %+v", loadBalancerId, err) } - outboundRules := *loadBalancer.LoadBalancerPropertiesFormat.OutboundRules - outboundRules = append(outboundRules[:index], outboundRules[index+1:]...) - loadBalancer.LoadBalancerPropertiesFormat.OutboundRules = &outboundRules + if model := loadBalancer.Model; model != nil { + _, index, exists := FindLoadBalancerOutboundRuleByName(model, id.OutboundRuleName) + if !exists { + return nil + } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, loadBalancer) - if err != nil { - return fmt.Errorf("updating Load Balancer %q (Resource Group %q) for Outbound Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName, err) - } + if props := model.Properties; props != nil { + outboundRules := *props.OutboundRules + outboundRules = append(outboundRules[:index], outboundRules[index+1:]...) + props.OutboundRules = &outboundRules - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q) for Outbound Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.OutboundRuleName, err) + err := client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("updating %s: %+v", *id, err) + } + } } - return nil } -func expandAzureRmLoadBalancerOutboundRule(d *pluginsdk.ResourceData, lb *network.LoadBalancer) (*network.OutboundRule, error) { - properties := network.OutboundRulePropertiesFormat{ - Protocol: network.LoadBalancerOutboundRuleProtocol(d.Get("protocol").(string)), - AllocatedOutboundPorts: utils.Int32(int32(d.Get("allocated_outbound_ports").(int))), +func expandAzureRmLoadBalancerOutboundRule(d *pluginsdk.ResourceData, lb *loadbalancers.LoadBalancer) (*loadbalancers.OutboundRule, error) { + properties := loadbalancers.OutboundRulePropertiesFormat{ + Protocol: loadbalancers.LoadBalancerOutboundRuleProtocol(d.Get("protocol").(string)), + AllocatedOutboundPorts: pointer.To(int64(d.Get("allocated_outbound_ports").(int))), } feConfigs := d.Get("frontend_ip_configuration").([]interface{}) - feConfigSubResources := make([]network.SubResource, 0) + feConfigSubResources := make([]loadbalancers.SubResource, 0) for _, raw := range feConfigs { v := raw.(map[string]interface{}) @@ -322,31 +320,31 @@ func expandAzureRmLoadBalancerOutboundRule(d *pluginsdk.ResourceData, lb *networ return nil, fmt.Errorf("[ERROR] Cannot find FrontEnd IP Configuration with the name %s", v["name"]) } - feConfigSubResource := network.SubResource{ - ID: rule.ID, + feConfigSubResource := loadbalancers.SubResource{ + Id: rule.Id, } feConfigSubResources = append(feConfigSubResources, feConfigSubResource) } - properties.FrontendIPConfigurations = &feConfigSubResources + properties.FrontendIPConfigurations = feConfigSubResources if v := d.Get("backend_address_pool_id").(string); v != "" { - properties.BackendAddressPool = &network.SubResource{ - ID: &v, + properties.BackendAddressPool = loadbalancers.SubResource{ + Id: &v, } } if v, ok := d.GetOk("idle_timeout_in_minutes"); ok { - properties.IdleTimeoutInMinutes = utils.Int32(int32(v.(int))) + properties.IdleTimeoutInMinutes = pointer.To(int64(v.(int))) } if v, ok := d.GetOk("enable_tcp_reset"); ok { - properties.EnableTCPReset = utils.Bool(v.(bool)) + properties.EnableTcpReset = pointer.To(v.(bool)) } - return &network.OutboundRule{ - Name: utils.String(d.Get("name").(string)), - OutboundRulePropertiesFormat: &properties, + return &loadbalancers.OutboundRule{ + Name: pointer.To(d.Get("name").(string)), + Properties: &properties, }, nil } diff --git a/internal/services/loadbalancer/parse/load_balancer_outbound_rule.go b/internal/services/loadbalancer/parse/load_balancer_outbound_rule.go deleted file mode 100644 index 5b9c96949a98..000000000000 --- a/internal/services/loadbalancer/parse/load_balancer_outbound_rule.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package parse - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "fmt" - "strings" - - "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" -) - -type LoadBalancerOutboundRuleId struct { - SubscriptionId string - ResourceGroup string - LoadBalancerName string - OutboundRuleName string -} - -func NewLoadBalancerOutboundRuleID(subscriptionId, resourceGroup, loadBalancerName, outboundRuleName string) LoadBalancerOutboundRuleId { - return LoadBalancerOutboundRuleId{ - SubscriptionId: subscriptionId, - ResourceGroup: resourceGroup, - LoadBalancerName: loadBalancerName, - OutboundRuleName: outboundRuleName, - } -} - -func (id LoadBalancerOutboundRuleId) String() string { - segments := []string{ - fmt.Sprintf("Outbound Rule Name %q", id.OutboundRuleName), - fmt.Sprintf("Load Balancer Name %q", id.LoadBalancerName), - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Load Balancer Outbound Rule", segmentsStr) -} - -func (id LoadBalancerOutboundRuleId) ID() string { - fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/loadBalancers/%s/outboundRules/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.OutboundRuleName) -} - -// LoadBalancerOutboundRuleID parses a LoadBalancerOutboundRule ID into an LoadBalancerOutboundRuleId struct -func LoadBalancerOutboundRuleID(input string) (*LoadBalancerOutboundRuleId, error) { - id, err := resourceids.ParseAzureResourceID(input) - if err != nil { - return nil, fmt.Errorf("parsing %q as an LoadBalancerOutboundRule ID: %+v", input, err) - } - - resourceId := LoadBalancerOutboundRuleId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, - } - - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } - - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") - } - - if resourceId.LoadBalancerName, err = id.PopSegment("loadBalancers"); err != nil { - return nil, err - } - if resourceId.OutboundRuleName, err = id.PopSegment("outboundRules"); err != nil { - return nil, err - } - - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err - } - - return &resourceId, nil -} diff --git a/internal/services/loadbalancer/parse/load_balancer_outbound_rule_test.go b/internal/services/loadbalancer/parse/load_balancer_outbound_rule_test.go deleted file mode 100644 index fb58638b7588..000000000000 --- a/internal/services/loadbalancer/parse/load_balancer_outbound_rule_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package parse - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "testing" - - "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" -) - -var _ resourceids.Id = LoadBalancerOutboundRuleId{} - -func TestLoadBalancerOutboundRuleIDFormatter(t *testing.T) { - actual := NewLoadBalancerOutboundRuleID("12345678-1234-9876-4563-123456789012", "resGroup1", "loadBalancer1", "rule1").ID() - expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/outboundRules/rule1" - if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) - } -} - -func TestLoadBalancerOutboundRuleID(t *testing.T) { - testData := []struct { - Input string - Error bool - Expected *LoadBalancerOutboundRuleId - }{ - - { - // empty - Input: "", - Error: true, - }, - - { - // missing SubscriptionId - Input: "/", - Error: true, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Error: true, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Error: true, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Error: true, - }, - - { - // missing LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Error: true, - }, - - { - // missing value for LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Error: true, - }, - - { - // missing OutboundRuleName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/", - Error: true, - }, - - { - // missing value for OutboundRuleName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/outboundRules/", - Error: true, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/outboundRules/rule1", - Expected: &LoadBalancerOutboundRuleId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "resGroup1", - LoadBalancerName: "loadBalancer1", - OutboundRuleName: "rule1", - }, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/LOADBALANCERS/LOADBALANCER1/OUTBOUNDRULES/RULE1", - Error: true, - }, - } - - for _, v := range testData { - t.Logf("[DEBUG] Testing %q", v.Input) - - actual, err := LoadBalancerOutboundRuleID(v.Input) - if err != nil { - if v.Error { - continue - } - - t.Fatalf("Expect a value but got an error: %s", err) - } - if v.Error { - t.Fatal("Expect an error but didn't get one") - } - - if actual.SubscriptionId != v.Expected.SubscriptionId { - t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) - } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) - } - if actual.LoadBalancerName != v.Expected.LoadBalancerName { - t.Fatalf("Expected %q but got %q for LoadBalancerName", v.Expected.LoadBalancerName, actual.LoadBalancerName) - } - if actual.OutboundRuleName != v.Expected.OutboundRuleName { - t.Fatalf("Expected %q but got %q for OutboundRuleName", v.Expected.OutboundRuleName, actual.OutboundRuleName) - } - } -} diff --git a/internal/services/loadbalancer/parse/load_balancer_probe.go b/internal/services/loadbalancer/parse/load_balancer_probe.go deleted file mode 100644 index 6f76badcd173..000000000000 --- a/internal/services/loadbalancer/parse/load_balancer_probe.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package parse - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "fmt" - "strings" - - "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" -) - -type LoadBalancerProbeId struct { - SubscriptionId string - ResourceGroup string - LoadBalancerName string - ProbeName string -} - -func NewLoadBalancerProbeID(subscriptionId, resourceGroup, loadBalancerName, probeName string) LoadBalancerProbeId { - return LoadBalancerProbeId{ - SubscriptionId: subscriptionId, - ResourceGroup: resourceGroup, - LoadBalancerName: loadBalancerName, - ProbeName: probeName, - } -} - -func (id LoadBalancerProbeId) String() string { - segments := []string{ - fmt.Sprintf("Probe Name %q", id.ProbeName), - fmt.Sprintf("Load Balancer Name %q", id.LoadBalancerName), - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Load Balancer Probe", segmentsStr) -} - -func (id LoadBalancerProbeId) ID() string { - fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/loadBalancers/%s/probes/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.ProbeName) -} - -// LoadBalancerProbeID parses a LoadBalancerProbe ID into an LoadBalancerProbeId struct -func LoadBalancerProbeID(input string) (*LoadBalancerProbeId, error) { - id, err := resourceids.ParseAzureResourceID(input) - if err != nil { - return nil, fmt.Errorf("parsing %q as an LoadBalancerProbe ID: %+v", input, err) - } - - resourceId := LoadBalancerProbeId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, - } - - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } - - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") - } - - if resourceId.LoadBalancerName, err = id.PopSegment("loadBalancers"); err != nil { - return nil, err - } - if resourceId.ProbeName, err = id.PopSegment("probes"); err != nil { - return nil, err - } - - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err - } - - return &resourceId, nil -} diff --git a/internal/services/loadbalancer/parse/load_balancer_probe_test.go b/internal/services/loadbalancer/parse/load_balancer_probe_test.go deleted file mode 100644 index db671b8d865f..000000000000 --- a/internal/services/loadbalancer/parse/load_balancer_probe_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package parse - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "testing" - - "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" -) - -var _ resourceids.Id = LoadBalancerProbeId{} - -func TestLoadBalancerProbeIDFormatter(t *testing.T) { - actual := NewLoadBalancerProbeID("12345678-1234-9876-4563-123456789012", "resGroup1", "loadBalancer1", "probe1").ID() - expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/probes/probe1" - if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) - } -} - -func TestLoadBalancerProbeID(t *testing.T) { - testData := []struct { - Input string - Error bool - Expected *LoadBalancerProbeId - }{ - - { - // empty - Input: "", - Error: true, - }, - - { - // missing SubscriptionId - Input: "/", - Error: true, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Error: true, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Error: true, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Error: true, - }, - - { - // missing LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Error: true, - }, - - { - // missing value for LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Error: true, - }, - - { - // missing ProbeName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/", - Error: true, - }, - - { - // missing value for ProbeName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/probes/", - Error: true, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/probes/probe1", - Expected: &LoadBalancerProbeId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "resGroup1", - LoadBalancerName: "loadBalancer1", - ProbeName: "probe1", - }, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/LOADBALANCERS/LOADBALANCER1/PROBES/PROBE1", - Error: true, - }, - } - - for _, v := range testData { - t.Logf("[DEBUG] Testing %q", v.Input) - - actual, err := LoadBalancerProbeID(v.Input) - if err != nil { - if v.Error { - continue - } - - t.Fatalf("Expect a value but got an error: %s", err) - } - if v.Error { - t.Fatal("Expect an error but didn't get one") - } - - if actual.SubscriptionId != v.Expected.SubscriptionId { - t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) - } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) - } - if actual.LoadBalancerName != v.Expected.LoadBalancerName { - t.Fatalf("Expected %q but got %q for LoadBalancerName", v.Expected.LoadBalancerName, actual.LoadBalancerName) - } - if actual.ProbeName != v.Expected.ProbeName { - t.Fatalf("Expected %q but got %q for ProbeName", v.Expected.ProbeName, actual.ProbeName) - } - } -} diff --git a/internal/services/loadbalancer/parse/load_balancer_test.go b/internal/services/loadbalancer/parse/load_balancer_test.go deleted file mode 100644 index be3636c47641..000000000000 --- a/internal/services/loadbalancer/parse/load_balancer_test.go +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package parse - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "testing" - - "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" -) - -var _ resourceids.Id = LoadBalancerId{} - -func TestLoadBalancerIDFormatter(t *testing.T) { - actual := NewLoadBalancerID("12345678-1234-9876-4563-123456789012", "resGroup1", "loadBalancer1").ID() - expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1" - if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) - } -} - -func TestLoadBalancerID(t *testing.T) { - testData := []struct { - Input string - Error bool - Expected *LoadBalancerId - }{ - - { - // empty - Input: "", - Error: true, - }, - - { - // missing SubscriptionId - Input: "/", - Error: true, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Error: true, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Error: true, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Error: true, - }, - - { - // missing Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Error: true, - }, - - { - // missing value for Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Error: true, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1", - Expected: &LoadBalancerId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "resGroup1", - Name: "loadBalancer1", - }, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/LOADBALANCERS/LOADBALANCER1", - Error: true, - }, - } - - for _, v := range testData { - t.Logf("[DEBUG] Testing %q", v.Input) - - actual, err := LoadBalancerID(v.Input) - if err != nil { - if v.Error { - continue - } - - t.Fatalf("Expect a value but got an error: %s", err) - } - if v.Error { - t.Fatal("Expect an error but didn't get one") - } - - if actual.SubscriptionId != v.Expected.SubscriptionId { - t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) - } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) - } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) - } - } -} - -func TestLoadBalancerIDInsensitively(t *testing.T) { - testData := []struct { - Input string - Error bool - Expected *LoadBalancerId - }{ - - { - // empty - Input: "", - Error: true, - }, - - { - // missing SubscriptionId - Input: "/", - Error: true, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Error: true, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Error: true, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Error: true, - }, - - { - // missing Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Error: true, - }, - - { - // missing value for Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Error: true, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1", - Expected: &LoadBalancerId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "resGroup1", - Name: "loadBalancer1", - }, - }, - - { - // lower-cased segment names - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadbalancers/loadBalancer1", - Expected: &LoadBalancerId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "resGroup1", - Name: "loadBalancer1", - }, - }, - - { - // upper-cased segment names - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/LOADBALANCERS/loadBalancer1", - Expected: &LoadBalancerId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "resGroup1", - Name: "loadBalancer1", - }, - }, - - { - // mixed-cased segment names - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/LoAdBaLaNcErS/loadBalancer1", - Expected: &LoadBalancerId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "resGroup1", - Name: "loadBalancer1", - }, - }, - } - - for _, v := range testData { - t.Logf("[DEBUG] Testing %q", v.Input) - - actual, err := LoadBalancerIDInsensitively(v.Input) - if err != nil { - if v.Error { - continue - } - - t.Fatalf("Expect a value but got an error: %s", err) - } - if v.Error { - t.Fatal("Expect an error but didn't get one") - } - - if actual.SubscriptionId != v.Expected.SubscriptionId { - t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) - } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) - } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) - } - } -} diff --git a/internal/services/loadbalancer/parse/load_balancing_rule.go b/internal/services/loadbalancer/parse/load_balancing_rule.go deleted file mode 100644 index 6b66a6b5c1b9..000000000000 --- a/internal/services/loadbalancer/parse/load_balancing_rule.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package parse - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "fmt" - "strings" - - "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" -) - -type LoadBalancingRuleId struct { - SubscriptionId string - ResourceGroup string - LoadBalancerName string - Name string -} - -func NewLoadBalancingRuleID(subscriptionId, resourceGroup, loadBalancerName, name string) LoadBalancingRuleId { - return LoadBalancingRuleId{ - SubscriptionId: subscriptionId, - ResourceGroup: resourceGroup, - LoadBalancerName: loadBalancerName, - Name: name, - } -} - -func (id LoadBalancingRuleId) String() string { - segments := []string{ - fmt.Sprintf("Name %q", id.Name), - fmt.Sprintf("Load Balancer Name %q", id.LoadBalancerName), - fmt.Sprintf("Resource Group %q", id.ResourceGroup), - } - segmentsStr := strings.Join(segments, " / ") - return fmt.Sprintf("%s: (%s)", "Load Balancing Rule", segmentsStr) -} - -func (id LoadBalancingRuleId) ID() string { - fmtString := "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/loadBalancers/%s/loadBalancingRules/%s" - return fmt.Sprintf(fmtString, id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName, id.Name) -} - -// LoadBalancingRuleID parses a LoadBalancingRule ID into an LoadBalancingRuleId struct -func LoadBalancingRuleID(input string) (*LoadBalancingRuleId, error) { - id, err := resourceids.ParseAzureResourceID(input) - if err != nil { - return nil, fmt.Errorf("parsing %q as an LoadBalancingRule ID: %+v", input, err) - } - - resourceId := LoadBalancingRuleId{ - SubscriptionId: id.SubscriptionID, - ResourceGroup: id.ResourceGroup, - } - - if resourceId.SubscriptionId == "" { - return nil, fmt.Errorf("ID was missing the 'subscriptions' element") - } - - if resourceId.ResourceGroup == "" { - return nil, fmt.Errorf("ID was missing the 'resourceGroups' element") - } - - if resourceId.LoadBalancerName, err = id.PopSegment("loadBalancers"); err != nil { - return nil, err - } - if resourceId.Name, err = id.PopSegment("loadBalancingRules"); err != nil { - return nil, err - } - - if err := id.ValidateNoEmptySegments(input); err != nil { - return nil, err - } - - return &resourceId, nil -} diff --git a/internal/services/loadbalancer/parse/load_balancing_rule_test.go b/internal/services/loadbalancer/parse/load_balancing_rule_test.go deleted file mode 100644 index 57175fe8fff7..000000000000 --- a/internal/services/loadbalancer/parse/load_balancing_rule_test.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package parse - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "testing" - - "github.com/hashicorp/go-azure-helpers/resourcemanager/resourceids" -) - -var _ resourceids.Id = LoadBalancingRuleId{} - -func TestLoadBalancingRuleIDFormatter(t *testing.T) { - actual := NewLoadBalancingRuleID("12345678-1234-9876-4563-123456789012", "resGroup1", "loadBalancer1", "rule1").ID() - expected := "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/loadBalancingRules/rule1" - if actual != expected { - t.Fatalf("Expected %q but got %q", expected, actual) - } -} - -func TestLoadBalancingRuleID(t *testing.T) { - testData := []struct { - Input string - Error bool - Expected *LoadBalancingRuleId - }{ - - { - // empty - Input: "", - Error: true, - }, - - { - // missing SubscriptionId - Input: "/", - Error: true, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Error: true, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Error: true, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Error: true, - }, - - { - // missing LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Error: true, - }, - - { - // missing value for LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Error: true, - }, - - { - // missing Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/", - Error: true, - }, - - { - // missing value for Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/loadBalancingRules/", - Error: true, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/loadBalancingRules/rule1", - Expected: &LoadBalancingRuleId{ - SubscriptionId: "12345678-1234-9876-4563-123456789012", - ResourceGroup: "resGroup1", - LoadBalancerName: "loadBalancer1", - Name: "rule1", - }, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/LOADBALANCERS/LOADBALANCER1/LOADBALANCINGRULES/RULE1", - Error: true, - }, - } - - for _, v := range testData { - t.Logf("[DEBUG] Testing %q", v.Input) - - actual, err := LoadBalancingRuleID(v.Input) - if err != nil { - if v.Error { - continue - } - - t.Fatalf("Expect a value but got an error: %s", err) - } - if v.Error { - t.Fatal("Expect an error but didn't get one") - } - - if actual.SubscriptionId != v.Expected.SubscriptionId { - t.Fatalf("Expected %q but got %q for SubscriptionId", v.Expected.SubscriptionId, actual.SubscriptionId) - } - if actual.ResourceGroup != v.Expected.ResourceGroup { - t.Fatalf("Expected %q but got %q for ResourceGroup", v.Expected.ResourceGroup, actual.ResourceGroup) - } - if actual.LoadBalancerName != v.Expected.LoadBalancerName { - t.Fatalf("Expected %q but got %q for LoadBalancerName", v.Expected.LoadBalancerName, actual.LoadBalancerName) - } - if actual.Name != v.Expected.Name { - t.Fatalf("Expected %q but got %q for Name", v.Expected.Name, actual.Name) - } - } -} diff --git a/internal/services/loadbalancer/probe_resource.go b/internal/services/loadbalancer/probe_resource.go index 002d05dabeba..ea0a79b9a686 100644 --- a/internal/services/loadbalancer/probe_resource.go +++ b/internal/services/loadbalancer/probe_resource.go @@ -8,17 +8,16 @@ import ( "log" "time" + "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-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" - loadBalancerValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" "github.com/hashicorp/terraform-provider-azurerm/internal/timeouts" - "github.com/hashicorp/terraform-provider-azurerm/utils" - "github.com/tombuildsstuff/kermit/sdk/network/2022-07-01/network" ) func resourceArmLoadBalancerProbe() *pluginsdk.Resource { @@ -28,13 +27,13 @@ func resourceArmLoadBalancerProbe() *pluginsdk.Resource { Update: resourceArmLoadBalancerProbeCreateUpdate, Delete: resourceArmLoadBalancerProbeDelete, - Importer: loadBalancerSubResourceImporter(func(input string) (*parse.LoadBalancerId, error) { - id, err := parse.LoadBalancerProbeID(input) + Importer: loadBalancerSubResourceImporter(func(input string) (*loadbalancers.LoadBalancerId, error) { + id, err := loadbalancers.ParseProbeID(input) if err != nil { return nil, err } - lbId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + lbId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) return &lbId, nil }), @@ -57,17 +56,17 @@ func resourceArmLoadBalancerProbe() *pluginsdk.Resource { Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: loadBalancerValidate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "protocol": { Type: pluginsdk.TypeString, - Computed: true, Optional: true, + Default: string(loadbalancers.ProbeProtocolTcp), ValidateFunc: validation.StringInSlice([]string{ - string(network.ProbeProtocolHTTP), - string(network.ProbeProtocolHTTPS), - string(network.ProbeProtocolTCP), + string(loadbalancers.ProbeProtocolHTTP), + string(loadbalancers.ProbeProtocolHTTPS), + string(loadbalancers.ProbeProtocolTcp), }, false), }, @@ -121,49 +120,49 @@ func resourceArmLoadBalancerProbeCreateUpdate(d *pluginsdk.ResourceData, meta in ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return err } loadBalancerIDRaw := loadBalancerId.ID() - id := parse.NewLoadBalancerProbeID(subscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, d.Get("name").(string)) + id := loadbalancers.NewProbeID(subscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, d.Get("name").(string)) locks.ByID(loadBalancerIDRaw) defer locks.UnlockByID(loadBalancerIDRaw) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing Proe %q from state", id.LoadBalancerName, id.ProbeName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Probe %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.ProbeName, err) + return fmt.Errorf("retrieving %s: %+v", *loadBalancerId, err) } - newProbe := expandAzureRmLoadBalancerProbe(d) - probes := append(*loadBalancer.LoadBalancerPropertiesFormat.Probes, *newProbe) - - existingProbe, existingProbeIndex, exists := FindLoadBalancerProbeByName(&loadBalancer, id.ProbeName) - if exists { - if id.ProbeName == *existingProbe.Name { - if d.IsNewResource() { - return tf.ImportAsExistsError("azurerm_lb_probe", *existingProbe.ID) + if model := loadBalancer.Model; model != nil { + if props := model.Properties; props != nil { + newProbe := expandAzureRmLoadBalancerProbe(d) + probes := append(*props.Probes, *newProbe) + existingProbe, existingProbeIndex, exists := FindLoadBalancerProbeByName(model, id.ProbeName) + if exists { + if id.ProbeName == *existingProbe.Name { + if d.IsNewResource() { + return tf.ImportAsExistsError("azurerm_lb_probe", *existingProbe.Id) + } + + // this probe is being updated/reapplied remove old copy from the slice + probes = append(probes[:existingProbeIndex], probes[existingProbeIndex+1:]...) + } } - // this probe is being updated/reapplied remove old copy from the slice - probes = append(probes[:existingProbeIndex], probes[existingProbeIndex+1:]...) - } - } - - loadBalancer.LoadBalancerPropertiesFormat.Probes = &probes - - future, err := client.CreateOrUpdate(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, loadBalancer) - if err != nil { - return fmt.Errorf("updating Load Balancer %q (Resource Group %q) for Probe %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.ProbeName, err) - } + props.Probes = &probes - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q) for Probe %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.ProbeName, err) + err := client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("updating %s: %+v", id, err) + } + } } d.SetId(id.ID()) @@ -176,71 +175,54 @@ func resourceArmLoadBalancerProbeRead(d *pluginsdk.ResourceData, meta interface{ ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerProbeID(d.Id()) + id, err := loadbalancers.ParseProbeID(d.Id()) if err != nil { return err } - loadBalancer, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Probe %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.ProbeName, err) - } - - config, _, exists := FindLoadBalancerProbeByName(&loadBalancer, id.ProbeName) - if !exists { - d.SetId("") - log.Printf("[INFO] Load Balancer Probe %q not found. Removing from state", id.ProbeName) - return nil + return fmt.Errorf("retrieving %s: %+v", plbId, err) } - d.Set("name", config.Name) - - if props := config.ProbePropertiesFormat; props != nil { - intervalInSeconds := 0 - if props.IntervalInSeconds != nil { - intervalInSeconds = int(*props.IntervalInSeconds) - } - d.Set("interval_in_seconds", intervalInSeconds) - - numberOfProbes := 0 - if props.NumberOfProbes != nil { - numberOfProbes = int(*props.NumberOfProbes) - } - d.Set("number_of_probes", numberOfProbes) - - port := 0 - if props.Port != nil { - port = int(*props.Port) + if model := loadBalancer.Model; model != nil { + config, _, exists := FindLoadBalancerProbeByName(model, id.ProbeName) + if !exists { + d.SetId("") + log.Printf("[INFO] Load Balancer Probe %q not found. Removing from state", id.ProbeName) + return nil } - d.Set("port", port) - d.Set("protocol", string(props.Protocol)) - d.Set("request_path", props.RequestPath) - var threshold int - if v := props.ProbeThreshold; v != nil { - threshold = int(*v) - } - d.Set("probe_threshold", threshold) - - // TODO: parse/make these consistent - var loadBalancerRules []string - if rules := props.LoadBalancingRules; rules != nil { - for _, ruleConfig := range *rules { - if id := ruleConfig.ID; id != nil { - loadBalancerRules = append(loadBalancerRules, *id) + d.Set("name", config.Name) + + if props := config.Properties; props != nil { + d.Set("interval_in_seconds", int(pointer.From(props.IntervalInSeconds))) + d.Set("number_of_probes", int(pointer.From(props.NumberOfProbes))) + d.Set("port", int(props.Port)) + d.Set("protocol", string(props.Protocol)) + d.Set("request_path", pointer.From(props.RequestPath)) + d.Set("probe_threshold", int(pointer.From(props.ProbeThreshold))) + + // TODO: parse/make these consistent + var loadBalancerRules []string + if rules := props.LoadBalancingRules; rules != nil { + for _, ruleConfig := range *rules { + if id := ruleConfig.Id; id != nil { + loadBalancerRules = append(loadBalancerRules, *id) + } } } - } - if err := d.Set("load_balancer_rules", loadBalancerRules); err != nil { - return fmt.Errorf("setting `load_balancer_rules` (Load Balancer %q Probe %q): %+v", id.LoadBalancerName, id.ProbeName, err) + if err := d.Set("load_balancer_rules", loadBalancerRules); err != nil { + return fmt.Errorf("setting `load_balancer_rules` (Load Balancer %q Probe %q): %+v", id.LoadBalancerName, id.ProbeName, err) + } } } - return nil } @@ -249,67 +231,66 @@ func resourceArmLoadBalancerProbeDelete(d *pluginsdk.ResourceData, meta interfac ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancerProbeID(d.Id()) + id, err := loadbalancers.ParseProbeID(d.Id()) if err != nil { return err } - loadBalancerId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + loadBalancerId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) loadBalancerID := loadBalancerId.ID() locks.ByID(loadBalancerID) defer locks.UnlockByID(loadBalancerID) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Probe %q: %+v", loadBalancerId.Name, loadBalancerId.ResourceGroup, id.ProbeName, err) - } - - _, index, exists := FindLoadBalancerProbeByName(&loadBalancer, id.ProbeName) - if !exists { - return nil + return fmt.Errorf("retrieving %s: %+v", loadBalancerId, err) } + if model := loadBalancer.Model; model != nil { + _, index, exists := FindLoadBalancerProbeByName(model, id.ProbeName) + if !exists { + return nil + } - probes := *loadBalancer.LoadBalancerPropertiesFormat.Probes - probes = append(probes[:index], probes[index+1:]...) - loadBalancer.LoadBalancerPropertiesFormat.Probes = &probes - - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, loadBalancer) - if err != nil { - return fmt.Errorf("updating Load Balancer %q (Resource Group %q) for deletion of Probe %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.ProbeName, err) - } + if props := model.Properties; props != nil { + probes := *props.Probes + probes = append(probes[:index], probes[index+1:]...) + props.Probes = &probes - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of Load Balancer %q (Resource Group %q) for deletion of Probe %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.ProbeName, err) + err := client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("updating Load Balancer %q (Resource Group %q) for deletion of Probe %q: %+v", id.LoadBalancerName, id.ResourceGroupName, id.ProbeName, err) + } + } } - return nil } -func expandAzureRmLoadBalancerProbe(d *pluginsdk.ResourceData) *network.Probe { - properties := network.ProbePropertiesFormat{ - NumberOfProbes: utils.Int32(int32(d.Get("number_of_probes").(int))), - IntervalInSeconds: utils.Int32(int32(d.Get("interval_in_seconds").(int))), - Port: utils.Int32(int32(d.Get("port").(int))), +func expandAzureRmLoadBalancerProbe(d *pluginsdk.ResourceData) *loadbalancers.Probe { + properties := loadbalancers.ProbePropertiesFormat{ + NumberOfProbes: pointer.To(int64(d.Get("number_of_probes").(int))), + IntervalInSeconds: pointer.To(int64(d.Get("interval_in_seconds").(int))), + Port: int64(d.Get("port").(int)), } if v, ok := d.GetOk("protocol"); ok { - properties.Protocol = network.ProbeProtocol(v.(string)) + properties.Protocol = loadbalancers.ProbeProtocol(v.(string)) } if v, ok := d.GetOk("request_path"); ok { - properties.RequestPath = utils.String(v.(string)) + properties.RequestPath = pointer.To(v.(string)) } if v, ok := d.GetOk("probe_threshold"); ok { - properties.ProbeThreshold = utils.Int32(int32(v.(int))) + properties.ProbeThreshold = pointer.To(int64(v.(int))) } - return &network.Probe{ - Name: utils.String(d.Get("name").(string)), - ProbePropertiesFormat: &properties, + return &loadbalancers.Probe{ + Name: pointer.To(d.Get("name").(string)), + Properties: &properties, } } diff --git a/internal/services/loadbalancer/rule_data_source.go b/internal/services/loadbalancer/rule_data_source.go index 3d6141283ab5..81dafc4a94bb 100644 --- a/internal/services/loadbalancer/rule_data_source.go +++ b/internal/services/loadbalancer/rule_data_source.go @@ -7,12 +7,13 @@ import ( "fmt" "time" + "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-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/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" ) func dataSourceArmLoadBalancerRule() *pluginsdk.Resource { @@ -33,7 +34,7 @@ func dataSourceArmLoadBalancerRule() *pluginsdk.Resource { "loadbalancer_id": { Type: pluginsdk.TypeString, Required: true, - ValidateFunc: validate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "frontend_ip_configuration_name": { @@ -98,28 +99,28 @@ func dataSourceArmLoadBalancerRule() *pluginsdk.Resource { func dataSourceArmLoadBalancerRuleRead(d *pluginsdk.ResourceData, meta interface{}) error { client := meta.(*clients.Client).LoadBalancers.LoadBalancersClient - lbRuleClient := meta.(*clients.Client).LoadBalancers.LoadBalancingRulesClient ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() name := d.Get("name").(string) - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return err } - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: loadBalancerId.SubscriptionId, ResourceGroupName: loadBalancerId.ResourceGroupName, LoadBalancerName: loadBalancerId.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { - return fmt.Errorf("parent %s was not found", *loadBalancerId) + if response.WasNotFound(loadBalancer.HttpResponse) { + return fmt.Errorf("%s was not found", *loadBalancerId) } - return fmt.Errorf("retrieving parent %s: %+v", *loadBalancerId, err) + return fmt.Errorf("retrieving %s: %+v", *loadBalancerId, err) } - id := parse.NewLoadBalancingRuleID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, name) - resp, err := lbRuleClient.Get(ctx, id.ResourceGroup, *loadBalancer.Name, name) + id := loadbalancers.NewLoadBalancingRuleID(loadBalancerId.SubscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, name) + resp, err := client.LoadBalancerLoadBalancingRulesGet(ctx, id) if err != nil { - if utils.ResponseWasNotFound(resp.Response) { + if response.WasNotFound(resp.HttpResponse) { return fmt.Errorf("%s was not found", id) } @@ -127,49 +128,50 @@ func dataSourceArmLoadBalancerRuleRead(d *pluginsdk.ResourceData, meta interface } d.SetId(id.ID()) - if props := resp.LoadBalancingRulePropertiesFormat; props != nil { - frontendIPConfigurationName, err := parse.LoadBalancerFrontendIpConfigurationID(*props.FrontendIPConfiguration.ID) - if err != nil { - return err - } + if model := resp.Model; model != nil { + if props := model.Properties; props != nil { + frontendIPConfigurationName, err := loadbalancers.ParseFrontendIPConfigurationID(*props.FrontendIPConfiguration.Id) + if err != nil { + return err + } - d.Set("frontend_ip_configuration_name", frontendIPConfigurationName.FrontendIPConfigurationName) - d.Set("protocol", props.Protocol) - d.Set("frontend_port", props.FrontendPort) - d.Set("backend_port", props.BackendPort) + d.Set("frontend_ip_configuration_name", frontendIPConfigurationName.FrontendIPConfigurationName) + d.Set("protocol", string(props.Protocol)) + d.Set("frontend_port", props.FrontendPort) + d.Set("backend_port", pointer.From(props.BackendPort)) - if props.BackendAddressPool != nil { - if err := d.Set("backend_address_pool_id", props.BackendAddressPool.ID); err != nil { - return fmt.Errorf("setting `backend_address_pool_id`: %+v", err) + if props.BackendAddressPool != nil { + if err := d.Set("backend_address_pool_id", pointer.From(props.BackendAddressPool.Id)); err != nil { + return fmt.Errorf("setting `backend_address_pool_id`: %+v", err) + } } - } - if props.Probe != nil { - if err := d.Set("probe_id", props.Probe.ID); err != nil { - return fmt.Errorf("setting `probe_id`: %+v", err) + if props.Probe != nil { + if err := d.Set("probe_id", pointer.From(props.Probe.Id)); err != nil { + return fmt.Errorf("setting `probe_id`: %+v", err) + } } - } - if err := d.Set("enable_floating_ip", props.EnableFloatingIP); err != nil { - return fmt.Errorf("setting `enable_floating_ip`: %+v", err) - } + if err := d.Set("enable_floating_ip", pointer.From(props.EnableFloatingIP)); err != nil { + return fmt.Errorf("setting `enable_floating_ip`: %+v", err) + } - if err := d.Set("enable_tcp_reset", props.EnableTCPReset); err != nil { - return fmt.Errorf("setting `enable_tcp_reset`: %+v", err) - } + if err := d.Set("enable_tcp_reset", pointer.From(props.EnableTcpReset)); err != nil { + return fmt.Errorf("setting `enable_tcp_reset`: %+v", err) + } - if err := d.Set("disable_outbound_snat", props.DisableOutboundSnat); err != nil { - return fmt.Errorf("setting `disable_outbound_snat`: %+v", err) - } + if err := d.Set("disable_outbound_snat", pointer.From(props.DisableOutboundSnat)); err != nil { + return fmt.Errorf("setting `disable_outbound_snat`: %+v", err) + } - if err := d.Set("idle_timeout_in_minutes", props.IdleTimeoutInMinutes); err != nil { - return fmt.Errorf("setting `idle_timeout_in_minutes`: %+v", err) - } + if err := d.Set("idle_timeout_in_minutes", int(pointer.From(props.IdleTimeoutInMinutes))); err != nil { + return fmt.Errorf("setting `idle_timeout_in_minutes`: %+v", err) + } - if err := d.Set("load_distribution", props.LoadDistribution); err != nil { - return fmt.Errorf("setting `load_distribution`: %+v", err) + if err := d.Set("load_distribution", string(pointer.From(props.LoadDistribution))); err != nil { + return fmt.Errorf("setting `load_distribution`: %+v", err) + } } } - return nil } diff --git a/internal/services/loadbalancer/rule_resource.go b/internal/services/loadbalancer/rule_resource.go index 0cf346687a9b..74365aa9721e 100644 --- a/internal/services/loadbalancer/rule_resource.go +++ b/internal/services/loadbalancer/rule_resource.go @@ -8,18 +8,18 @@ import ( "log" "time" + "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-06-01/loadbalancers" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/helpers/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" "github.com/hashicorp/terraform-provider-azurerm/internal/locks" - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" loadBalancerValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/suppress" "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 resourceArmLoadBalancerRule() *pluginsdk.Resource { @@ -29,13 +29,13 @@ func resourceArmLoadBalancerRule() *pluginsdk.Resource { Update: resourceArmLoadBalancerRuleCreateUpdate, Delete: resourceArmLoadBalancerRuleDelete, - Importer: loadBalancerSubResourceImporter(func(input string) (*parse.LoadBalancerId, error) { - id, err := parse.LoadBalancingRuleID(input) + Importer: loadBalancerSubResourceImporter(func(input string) (*loadbalancers.LoadBalancerId, error) { + id, err := loadbalancers.ParseLoadBalancingRuleID(input) if err != nil { return nil, err } - lbId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + lbId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) return &lbId, nil }), @@ -56,43 +56,47 @@ func resourceArmLoadBalancerRuleCreateUpdate(d *pluginsdk.ResourceData, meta int ctx, cancel := timeouts.ForCreateUpdate(meta.(*clients.Client).StopContext, d) defer cancel() - loadBalancerId, err := parse.LoadBalancerID(d.Get("loadbalancer_id").(string)) + loadBalancerId, err := loadbalancers.ParseLoadBalancerID(d.Get("loadbalancer_id").(string)) if err != nil { return err } - id := parse.NewLoadBalancingRuleID(subscriptionId, loadBalancerId.ResourceGroup, loadBalancerId.Name, d.Get("name").(string)) + id := loadbalancers.NewLoadBalancingRuleID(subscriptionId, loadBalancerId.ResourceGroupName, loadBalancerId.LoadBalancerName, d.Get("name").(string)) loadBalancerID := loadBalancerId.ID() locks.ByID(loadBalancerID) defer locks.UnlockByID(loadBalancerID) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.Name, err) + return fmt.Errorf("retrieving %s: %+v", *loadBalancerId, err) } - if loadBalancer.LoadBalancerPropertiesFormat == nil { + if loadBalancer.Model == nil { + return fmt.Errorf("retrieving Load Balancer %s: `model` was nil", id) + } + if loadBalancer.Model.Properties == nil { return fmt.Errorf("retrieving Load Balancer %s: `properties` was nil", id) } - newLbRule, err := expandAzureRmLoadBalancerRule(d, &loadBalancer) + newLbRule, err := expandAzureRmLoadBalancerRule(d, loadBalancer.Model) if err != nil { return fmt.Errorf("expanding Load Balancer Rule: %+v", err) } - lbRules := append(*loadBalancer.LoadBalancerPropertiesFormat.LoadBalancingRules, *newLbRule) + lbRules := append(*loadBalancer.Model.Properties.LoadBalancingRules, *newLbRule) - existingRule, existingRuleIndex, exists := FindLoadBalancerRuleByName(&loadBalancer, id.Name) + existingRule, existingRuleIndex, exists := FindLoadBalancerRuleByName(loadBalancer.Model, id.LoadBalancingRuleName) if exists { - if id.Name == *existingRule.Name { + if id.LoadBalancingRuleName == *existingRule.Name { if d.IsNewResource() { - return tf.ImportAsExistsError("azurerm_lb_rule", *existingRule.ID) + return tf.ImportAsExistsError("azurerm_lb_rule", *existingRule.Id) } // this rule is being updated/reapplied remove old copy from the slice @@ -100,15 +104,11 @@ func resourceArmLoadBalancerRuleCreateUpdate(d *pluginsdk.ResourceData, meta int } } - loadBalancer.LoadBalancerPropertiesFormat.LoadBalancingRules = &lbRules + loadBalancer.Model.Properties.LoadBalancingRules = &lbRules - future, err := client.CreateOrUpdate(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, loadBalancer) + err = client.CreateOrUpdateThenPoll(ctx, plbId, *loadBalancer.Model) if err != nil { - return fmt.Errorf("updating Loadbalancer %q (resource group %q) for Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.Name, err) - } - - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for update of Load Balancer %q (resource group %q) for Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.Name, err) + return fmt.Errorf("updating %s: %+v", id, err) } d.SetId(id.ID()) @@ -121,110 +121,92 @@ func resourceArmLoadBalancerRuleRead(d *pluginsdk.ResourceData, meta interface{} ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancingRuleID(d.Id()) + id, err := loadbalancers.ParseLoadBalancingRuleID(d.Id()) if err != nil { return err } - loadBalancer, err := client.Get(ctx, id.ResourceGroup, id.LoadBalancerName, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") log.Printf("[INFO] Load Balancer %q not found. Removing from state", id.LoadBalancerName) return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.Name, err) - } - - config, _, exists := FindLoadBalancerRuleByName(&loadBalancer, id.Name) - if !exists { - d.SetId("") - log.Printf("[INFO] Load Balancer Rule %q not found. Removing from state", id.Name) - return nil + return fmt.Errorf("retrieving %s: %+v", plbId, err) } - d.Set("name", config.Name) + if model := loadBalancer.Model; model != nil { + config, _, exists := FindLoadBalancerRuleByName(model, id.LoadBalancingRuleName) + if !exists { + d.SetId("") + log.Printf("[INFO] Load Balancer Rule %q not found. Removing from state", id.LoadBalancerName) + return nil + } - if props := config.LoadBalancingRulePropertiesFormat; props != nil { - d.Set("disable_outbound_snat", props.DisableOutboundSnat) - d.Set("enable_floating_ip", props.EnableFloatingIP) - d.Set("enable_tcp_reset", props.EnableTCPReset) - d.Set("protocol", string(props.Protocol)) + d.Set("name", config.Name) - backendPort := 0 - if props.BackendPort != nil { - backendPort = int(*props.BackendPort) - } - d.Set("backend_port", backendPort) + if props := config.Properties; props != nil { + d.Set("disable_outbound_snat", pointer.From(props.DisableOutboundSnat)) + d.Set("enable_floating_ip", pointer.From(props.EnableFloatingIP)) + d.Set("enable_tcp_reset", pointer.From(props.EnableTcpReset)) + d.Set("protocol", string(props.Protocol)) + d.Set("backend_port", int(pointer.From(props.BackendPort))) - // The backendAddressPools is designed for Gateway LB, while the backendAddressPool is designed for other skus. - // Thought currently the API returns both, but for the sake of stability, we do use different fields here depending on the LB sku. - var isGateway bool - if loadBalancer.Sku != nil && loadBalancer.Sku.Name == network.LoadBalancerSkuNameGateway { - isGateway = true - } - var ( - backendAddressPoolId string - backendAddressPoolIds []interface{} - ) - if isGateway { - // The gateway LB rule can have up to 2 backend address pools. - // In case there is only one BAP, we set it to both "backendAddressPoolId" and "backendAddressPoolIds". - // Otherwise, we leave the "backendAddressPoolId" as empty. - if props.BackendAddressPools != nil { - for _, p := range *props.BackendAddressPools { - if p.ID != nil { - backendAddressPoolIds = append(backendAddressPoolIds, *p.ID) + // The backendAddressPools is designed for Gateway LB, while the backendAddressPool is designed for other skus. + // Thought currently the API returns both, but for the sake of stability, we do use different fields here depending on the LB sku. + var isGateway bool + if model.Sku != nil && pointer.From(model.Sku.Name) == loadbalancers.LoadBalancerSkuNameGateway { + isGateway = true + } + var ( + backendAddressPoolId string + backendAddressPoolIds []interface{} + ) + if isGateway { + // The gateway LB rule can have up to 2 backend address pools. + // In case there is only one BAP, we set it to both "backendAddressPoolId" and "backendAddressPoolIds". + // Otherwise, we leave the "backendAddressPoolId" as empty. + if props.BackendAddressPools != nil { + for _, p := range *props.BackendAddressPools { + if p.Id != nil { + backendAddressPoolIds = append(backendAddressPoolIds, *p.Id) + } } } + } else { + if props.BackendAddressPool != nil && props.BackendAddressPool.Id != nil { + backendAddressPoolId = *props.BackendAddressPool.Id + backendAddressPoolIds = []interface{}{backendAddressPoolId} + } } - } else { - if props.BackendAddressPool != nil && props.BackendAddressPool.ID != nil { - backendAddressPoolId = *props.BackendAddressPool.ID - backendAddressPoolIds = []interface{}{backendAddressPoolId} - } - } - d.Set("backend_address_pool_ids", backendAddressPoolIds) + d.Set("backend_address_pool_ids", backendAddressPoolIds) + + frontendIPConfigName := "" + frontendIPConfigID := "" + if props.FrontendIPConfiguration != nil && props.FrontendIPConfiguration.Id != nil { + feid, err := loadbalancers.ParseFrontendIPConfigurationIDInsensitively(*props.FrontendIPConfiguration.Id) + if err != nil { + return err + } - frontendIPConfigName := "" - frontendIPConfigID := "" - if props.FrontendIPConfiguration != nil && props.FrontendIPConfiguration.ID != nil { - feid, err := parse.LoadBalancerFrontendIpConfigurationIDInsensitively(*props.FrontendIPConfiguration.ID) - if err != nil { - return err + frontendIPConfigName = feid.FrontendIPConfigurationName + frontendIPConfigID = feid.ID() } - - frontendIPConfigName = feid.FrontendIPConfigurationName - frontendIPConfigID = feid.ID() - } - d.Set("frontend_ip_configuration_name", frontendIPConfigName) - d.Set("frontend_ip_configuration_id", frontendIPConfigID) - - frontendPort := 0 - if props.FrontendPort != nil { - frontendPort = int(*props.FrontendPort) - } - d.Set("frontend_port", frontendPort) - - idleTimeoutInMinutes := 0 - if props.IdleTimeoutInMinutes != nil { - idleTimeoutInMinutes = int(*props.IdleTimeoutInMinutes) - } - d.Set("idle_timeout_in_minutes", idleTimeoutInMinutes) - - loadDistribution := "" - if props.LoadDistribution != "" { - loadDistribution = string(props.LoadDistribution) - } - d.Set("load_distribution", loadDistribution) - - probeId := "" - if props.Probe != nil && props.Probe.ID != nil { - probeId = *props.Probe.ID + d.Set("frontend_ip_configuration_name", frontendIPConfigName) + d.Set("frontend_ip_configuration_id", frontendIPConfigID) + d.Set("frontend_port", int(props.FrontendPort)) + d.Set("idle_timeout_in_minutes", int(pointer.From(props.IdleTimeoutInMinutes))) + d.Set("load_distribution", string(pointer.From(props.LoadDistribution))) + + probeId := "" + if props.Probe != nil { + probeId = pointer.From(props.Probe.Id) + } + d.Set("probe_id", probeId) } - d.Set("probe_id", probeId) } - return nil } @@ -233,64 +215,65 @@ func resourceArmLoadBalancerRuleDelete(d *pluginsdk.ResourceData, meta interface ctx, cancel := timeouts.ForDelete(meta.(*clients.Client).StopContext, d) defer cancel() - id, err := parse.LoadBalancingRuleID(d.Id()) + id, err := loadbalancers.ParseLoadBalancingRuleID(d.Id()) if err != nil { return err } - loadBalancerId := parse.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroup, id.LoadBalancerName) + loadBalancerId := loadbalancers.NewLoadBalancerID(id.SubscriptionId, id.ResourceGroupName, id.LoadBalancerName) loadBalancerIDRaw := loadBalancerId.ID() locks.ByID(loadBalancerIDRaw) defer locks.UnlockByID(loadBalancerIDRaw) - loadBalancer, err := client.Get(ctx, loadBalancerId.ResourceGroup, loadBalancerId.Name, "") + plbId := loadbalancers.ProviderLoadBalancerId{SubscriptionId: id.SubscriptionId, ResourceGroupName: id.ResourceGroupName, LoadBalancerName: id.LoadBalancerName} + loadBalancer, err := client.Get(ctx, plbId, loadbalancers.GetOperationOptions{}) if err != nil { - if utils.ResponseWasNotFound(loadBalancer.Response) { + if response.WasNotFound(loadBalancer.HttpResponse) { d.SetId("") return nil } - return fmt.Errorf("failed to retrieve Load Balancer %q (resource group %q) for Rule %q: %+v", id.LoadBalancerName, id.ResourceGroup, id.Name, err) + return fmt.Errorf("retrieving %s: %+v", loadBalancerId, err) } - if loadBalancer.LoadBalancerPropertiesFormat != nil && loadBalancer.LoadBalancerPropertiesFormat.LoadBalancingRules != nil { - _, index, exists := FindLoadBalancerRuleByName(&loadBalancer, d.Get("name").(string)) - if !exists { - return nil - } - - lbRules := *loadBalancer.LoadBalancerPropertiesFormat.LoadBalancingRules - lbRules = append(lbRules[:index], lbRules[index+1:]...) - loadBalancer.LoadBalancerPropertiesFormat.LoadBalancingRules = &lbRules + if model := loadBalancer.Model; model != nil { + if props := model.Properties; props != nil { + if props.LoadBalancingRules != nil { + _, index, exists := FindLoadBalancerRuleByName(model, d.Get("name").(string)) + if !exists { + return nil + } - future, err := client.CreateOrUpdate(ctx, id.ResourceGroup, id.LoadBalancerName, loadBalancer) - if err != nil { - return fmt.Errorf("Creating/Updating Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) - } + lbRules := *props.LoadBalancingRules + lbRules = append(lbRules[:index], lbRules[index+1:]...) + props.LoadBalancingRules = &lbRules - if err = future.WaitForCompletionRef(ctx, client.Client); err != nil { - return fmt.Errorf("waiting for completion of Load Balancer %q (Resource Group %q): %+v", id.LoadBalancerName, id.ResourceGroup, err) + err := client.CreateOrUpdateThenPoll(ctx, plbId, *model) + if err != nil { + return fmt.Errorf("Creating/Updating %s: %+v", id, err) + } + } } } return nil } -func expandAzureRmLoadBalancerRule(d *pluginsdk.ResourceData, lb *network.LoadBalancer) (*network.LoadBalancingRule, error) { - properties := network.LoadBalancingRulePropertiesFormat{ - Protocol: network.TransportProtocol(d.Get("protocol").(string)), - FrontendPort: utils.Int32(int32(d.Get("frontend_port").(int))), - BackendPort: utils.Int32(int32(d.Get("backend_port").(int))), - EnableFloatingIP: utils.Bool(d.Get("enable_floating_ip").(bool)), - EnableTCPReset: utils.Bool(d.Get("enable_tcp_reset").(bool)), - DisableOutboundSnat: utils.Bool(d.Get("disable_outbound_snat").(bool)), +func expandAzureRmLoadBalancerRule(d *pluginsdk.ResourceData, lb *loadbalancers.LoadBalancer) (*loadbalancers.LoadBalancingRule, error) { + properties := loadbalancers.LoadBalancingRulePropertiesFormat{ + Protocol: loadbalancers.TransportProtocol(d.Get("protocol").(string)), + FrontendPort: int64(d.Get("frontend_port").(int)), + BackendPort: pointer.To(int64(d.Get("backend_port").(int))), + EnableFloatingIP: pointer.To(d.Get("enable_floating_ip").(bool)), + EnableTcpReset: pointer.To(d.Get("enable_tcp_reset").(bool)), + DisableOutboundSnat: pointer.To(d.Get("disable_outbound_snat").(bool)), } if v, ok := d.GetOk("idle_timeout_in_minutes"); ok { - properties.IdleTimeoutInMinutes = utils.Int32(int32(v.(int))) + properties.IdleTimeoutInMinutes = pointer.To(int64(v.(int))) } if v := d.Get("load_distribution").(string); v != "" { - properties.LoadDistribution = network.LoadDistribution(v) + properties.LoadDistribution = pointer.To(loadbalancers.LoadDistribution(v)) } // TODO: ensure these ID's are consistent @@ -300,23 +283,23 @@ func expandAzureRmLoadBalancerRule(d *pluginsdk.ResourceData, lb *network.LoadBa return nil, fmt.Errorf("[ERROR] Cannot find FrontEnd IP Configuration with the name %s", v) } - properties.FrontendIPConfiguration = &network.SubResource{ - ID: rule.ID, + properties.FrontendIPConfiguration = &loadbalancers.SubResource{ + Id: rule.Id, } } var isGateway bool - if lb != nil && lb.Sku != nil && lb.Sku.Name == network.LoadBalancerSkuNameGateway { + if lb != nil && lb.Sku != nil && pointer.From(lb.Sku.Name) == loadbalancers.LoadBalancerSkuNameGateway { isGateway = true } if l := d.Get("backend_address_pool_ids").([]interface{}); len(l) != 0 { if isGateway { - var baps []network.SubResource + var baps []loadbalancers.SubResource for _, p := range l { p := p.(string) - baps = append(baps, network.SubResource{ - ID: &p, + baps = append(baps, loadbalancers.SubResource{ + Id: &p, }) } properties.BackendAddressPools = &baps @@ -324,21 +307,21 @@ func expandAzureRmLoadBalancerRule(d *pluginsdk.ResourceData, lb *network.LoadBa if len(l) > 1 { return nil, fmt.Errorf(`only Gateway SKU Load Balancer can have more than one "backend_address_pool_ids"`) } - properties.BackendAddressPool = &network.SubResource{ - ID: utils.String(l[0].(string)), + properties.BackendAddressPool = &loadbalancers.SubResource{ + Id: pointer.To(l[0].(string)), } } } if v := d.Get("probe_id").(string); v != "" { - properties.Probe = &network.SubResource{ - ID: &v, + properties.Probe = &loadbalancers.SubResource{ + Id: &v, } } - return &network.LoadBalancingRule{ - Name: utils.String(d.Get("name").(string)), - LoadBalancingRulePropertiesFormat: &properties, + return &loadbalancers.LoadBalancingRule{ + Name: pointer.To(d.Get("name").(string)), + Properties: &properties, }, nil } @@ -355,7 +338,7 @@ func resourceArmLoadBalancerRuleSchema() map[string]*pluginsdk.Schema { Type: pluginsdk.TypeString, Required: true, ForceNew: true, - ValidateFunc: loadBalancerValidate.LoadBalancerID, + ValidateFunc: loadbalancers.ValidateLoadBalancerID, }, "frontend_ip_configuration_name": { @@ -376,7 +359,7 @@ func resourceArmLoadBalancerRuleSchema() map[string]*pluginsdk.Schema { MaxItems: 2, // Only Gateway SKU LB can have 2 backend address pools Elem: &pluginsdk.Schema{ Type: pluginsdk.TypeString, - ValidateFunc: loadBalancerValidate.LoadBalancerBackendAddressPoolID, + ValidateFunc: loadbalancers.ValidateLoadBalancerBackendAddressPoolID, }, }, @@ -385,9 +368,9 @@ func resourceArmLoadBalancerRuleSchema() map[string]*pluginsdk.Schema { Required: true, DiffSuppressFunc: suppress.CaseDifference, ValidateFunc: validation.StringInSlice([]string{ - string(network.TransportProtocolAll), - string(network.TransportProtocolTCP), - string(network.TransportProtocolUDP), + string(loadbalancers.TransportProtocolAll), + string(loadbalancers.TransportProtocolTcp), + string(loadbalancers.TransportProtocolUdp), }, false), }, diff --git a/internal/services/loadbalancer/validate/load_balancer_id_test.go b/internal/services/loadbalancer/validate/load_balancer_id_test.go deleted file mode 100644 index 402862a0219f..000000000000 --- a/internal/services/loadbalancer/validate/load_balancer_id_test.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package validate - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import "testing" - -func TestLoadBalancerID(t *testing.T) { - cases := []struct { - Input string - Valid bool - }{ - - { - // empty - Input: "", - Valid: false, - }, - - { - // missing SubscriptionId - Input: "/", - Valid: false, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Valid: false, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Valid: false, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Valid: false, - }, - - { - // missing Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Valid: false, - }, - - { - // missing value for Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Valid: false, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1", - Valid: true, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/LOADBALANCERS/LOADBALANCER1", - Valid: false, - }, - } - for _, tc := range cases { - t.Logf("[DEBUG] Testing Value %s", tc.Input) - _, errors := LoadBalancerID(tc.Input, "test") - valid := len(errors) == 0 - - if tc.Valid != valid { - t.Fatalf("Expected %t but got %t", tc.Valid, valid) - } - } -} diff --git a/internal/services/loadbalancer/validate/load_balancer_outbound_rule_id.go b/internal/services/loadbalancer/validate/load_balancer_outbound_rule_id.go deleted file mode 100644 index 4cb659dae49f..000000000000 --- a/internal/services/loadbalancer/validate/load_balancer_outbound_rule_id.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package validate - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "fmt" - - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" -) - -func LoadBalancerOutboundRuleID(input interface{}, key string) (warnings []string, errors []error) { - v, ok := input.(string) - if !ok { - errors = append(errors, fmt.Errorf("expected %q to be a string", key)) - return - } - - if _, err := parse.LoadBalancerOutboundRuleID(v); err != nil { - errors = append(errors, err) - } - - return -} diff --git a/internal/services/loadbalancer/validate/load_balancer_outbound_rule_id_test.go b/internal/services/loadbalancer/validate/load_balancer_outbound_rule_id_test.go deleted file mode 100644 index 648001936d6f..000000000000 --- a/internal/services/loadbalancer/validate/load_balancer_outbound_rule_id_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package validate - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import "testing" - -func TestLoadBalancerOutboundRuleID(t *testing.T) { - cases := []struct { - Input string - Valid bool - }{ - - { - // empty - Input: "", - Valid: false, - }, - - { - // missing SubscriptionId - Input: "/", - Valid: false, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Valid: false, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Valid: false, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Valid: false, - }, - - { - // missing LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Valid: false, - }, - - { - // missing value for LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Valid: false, - }, - - { - // missing OutboundRuleName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/", - Valid: false, - }, - - { - // missing value for OutboundRuleName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/outboundRules/", - Valid: false, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/outboundRules/rule1", - Valid: true, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/LOADBALANCERS/LOADBALANCER1/OUTBOUNDRULES/RULE1", - Valid: false, - }, - } - for _, tc := range cases { - t.Logf("[DEBUG] Testing Value %s", tc.Input) - _, errors := LoadBalancerOutboundRuleID(tc.Input, "test") - valid := len(errors) == 0 - - if tc.Valid != valid { - t.Fatalf("Expected %t but got %t", tc.Valid, valid) - } - } -} diff --git a/internal/services/loadbalancer/validate/load_balancer_probe_id.go b/internal/services/loadbalancer/validate/load_balancer_probe_id.go deleted file mode 100644 index 845a83aa2723..000000000000 --- a/internal/services/loadbalancer/validate/load_balancer_probe_id.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package validate - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "fmt" - - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" -) - -func LoadBalancerProbeID(input interface{}, key string) (warnings []string, errors []error) { - v, ok := input.(string) - if !ok { - errors = append(errors, fmt.Errorf("expected %q to be a string", key)) - return - } - - if _, err := parse.LoadBalancerProbeID(v); err != nil { - errors = append(errors, err) - } - - return -} diff --git a/internal/services/loadbalancer/validate/load_balancer_probe_id_test.go b/internal/services/loadbalancer/validate/load_balancer_probe_id_test.go deleted file mode 100644 index bde8c63da89e..000000000000 --- a/internal/services/loadbalancer/validate/load_balancer_probe_id_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package validate - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import "testing" - -func TestLoadBalancerProbeID(t *testing.T) { - cases := []struct { - Input string - Valid bool - }{ - - { - // empty - Input: "", - Valid: false, - }, - - { - // missing SubscriptionId - Input: "/", - Valid: false, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Valid: false, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Valid: false, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Valid: false, - }, - - { - // missing LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Valid: false, - }, - - { - // missing value for LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Valid: false, - }, - - { - // missing ProbeName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/", - Valid: false, - }, - - { - // missing value for ProbeName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/probes/", - Valid: false, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/probes/probe1", - Valid: true, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/LOADBALANCERS/LOADBALANCER1/PROBES/PROBE1", - Valid: false, - }, - } - for _, tc := range cases { - t.Logf("[DEBUG] Testing Value %s", tc.Input) - _, errors := LoadBalancerProbeID(tc.Input, "test") - valid := len(errors) == 0 - - if tc.Valid != valid { - t.Fatalf("Expected %t but got %t", tc.Valid, valid) - } - } -} diff --git a/internal/services/loadbalancer/validate/load_balancing_rule_id.go b/internal/services/loadbalancer/validate/load_balancing_rule_id.go deleted file mode 100644 index 486e69c01462..000000000000 --- a/internal/services/loadbalancer/validate/load_balancing_rule_id.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package validate - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import ( - "fmt" - - "github.com/hashicorp/terraform-provider-azurerm/internal/services/loadbalancer/parse" -) - -func LoadBalancingRuleID(input interface{}, key string) (warnings []string, errors []error) { - v, ok := input.(string) - if !ok { - errors = append(errors, fmt.Errorf("expected %q to be a string", key)) - return - } - - if _, err := parse.LoadBalancingRuleID(v); err != nil { - errors = append(errors, err) - } - - return -} diff --git a/internal/services/loadbalancer/validate/load_balancing_rule_id_test.go b/internal/services/loadbalancer/validate/load_balancing_rule_id_test.go deleted file mode 100644 index 43828b4a741e..000000000000 --- a/internal/services/loadbalancer/validate/load_balancing_rule_id_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package validate - -// NOTE: this file is generated via 'go:generate' - manual changes will be overwritten - -import "testing" - -func TestLoadBalancingRuleID(t *testing.T) { - cases := []struct { - Input string - Valid bool - }{ - - { - // empty - Input: "", - Valid: false, - }, - - { - // missing SubscriptionId - Input: "/", - Valid: false, - }, - - { - // missing value for SubscriptionId - Input: "/subscriptions/", - Valid: false, - }, - - { - // missing ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/", - Valid: false, - }, - - { - // missing value for ResourceGroup - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/", - Valid: false, - }, - - { - // missing LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/", - Valid: false, - }, - - { - // missing value for LoadBalancerName - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/", - Valid: false, - }, - - { - // missing Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/", - Valid: false, - }, - - { - // missing value for Name - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/loadBalancingRules/", - Valid: false, - }, - - { - // valid - Input: "/subscriptions/12345678-1234-9876-4563-123456789012/resourceGroups/resGroup1/providers/Microsoft.Network/loadBalancers/loadBalancer1/loadBalancingRules/rule1", - Valid: true, - }, - - { - // upper-cased - Input: "/SUBSCRIPTIONS/12345678-1234-9876-4563-123456789012/RESOURCEGROUPS/RESGROUP1/PROVIDERS/MICROSOFT.NETWORK/LOADBALANCERS/LOADBALANCER1/LOADBALANCINGRULES/RULE1", - Valid: false, - }, - } - for _, tc := range cases { - t.Logf("[DEBUG] Testing Value %s", tc.Input) - _, errors := LoadBalancingRuleID(tc.Input, "test") - valid := len(errors) == 0 - - if tc.Valid != valid { - t.Fatalf("Expected %t but got %t", tc.Valid, valid) - } - } -} diff --git a/website/docs/r/lb_probe.html.markdown b/website/docs/r/lb_probe.html.markdown index 4f009c70e0b8..53ac71c17dfd 100644 --- a/website/docs/r/lb_probe.html.markdown +++ b/website/docs/r/lb_probe.html.markdown @@ -51,7 +51,7 @@ The following arguments are supported: * `name` - (Required) Specifies the name of the Probe. Changing this forces a new resource to be created. * `loadbalancer_id` - (Required) The ID of the LoadBalancer in which to create the NAT Rule. Changing this forces a new resource to be created. -* `protocol` - (Optional) Specifies the protocol of the end point. Possible values are `Http`, `Https` or `Tcp`. If TCP is specified, a received ACK is required for the probe to be successful. If HTTP is specified, a 200 OK response from the specified URI is required for the probe to be successful. +* `protocol` - (Optional) Specifies the protocol of the end point. Possible values are `Http`, `Https` or `Tcp`. If TCP is specified, a received ACK is required for the probe to be successful. If HTTP is specified, a 200 OK response from the specified URI is required for the probe to be successful. Defaults to `Tcp`. * `port` - (Required) Port on which the Probe queries the backend endpoint. Possible values range from 1 to 65535, inclusive. * `probe_threshold` - (Optional) The number of consecutive successful or failed probes that allow or deny traffic to this endpoint. Possible values range from `1` to `100`. The default value is `1`. * `request_path` - (Optional) The URI used for requesting health status from the backend endpoint. Required if protocol is set to `Http` or `Https`. Otherwise, it is not allowed.