From d4b24a754925f2edf58c2645f7f34ab5812e8e16 Mon Sep 17 00:00:00 2001 From: magodo Date: Tue, 26 Nov 2024 16:00:06 +1100 Subject: [PATCH 1/4] `azurerm_private_endpoint`: Retry on "RetryableError" and "StorageAccountOperationInProgress" errors during LRO --- .../network/private_endpoint_resource.go | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/internal/services/network/private_endpoint_resource.go b/internal/services/network/private_endpoint_resource.go index 9ab1f514c560..c38f3d33686a 100644 --- a/internal/services/network/private_endpoint_resource.go +++ b/internal/services/network/private_endpoint_resource.go @@ -5,8 +5,10 @@ package network import ( "context" + "errors" "fmt" "log" + "slices" "sort" "strings" "time" @@ -25,6 +27,7 @@ import ( "github.com/hashicorp/go-azure-sdk/resource-manager/privatedns/2020-06-01/privatezones" "github.com/hashicorp/go-azure-sdk/resource-manager/redis/2024-03-01/redis" "github.com/hashicorp/go-azure-sdk/resource-manager/signalr/2023-02-01/signalr" + "github.com/hashicorp/go-azure-sdk/sdk/client/pollers" "github.com/hashicorp/terraform-provider-azurerm/helpers/azure" "github.com/hashicorp/terraform-provider-azurerm/helpers/tf" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" @@ -349,27 +352,51 @@ func resourcePrivateEndpointCreate(d *pluginsdk.ResourceData, meta interface{}) } err = pluginsdk.Retry(d.Timeout(pluginsdk.TimeoutCreate), func() *pluginsdk.RetryError { - if err = client.CreateOrUpdateThenPoll(ctx, id, parameters); err != nil { - switch { - case strings.EqualFold(err.Error(), "is missing required parameter 'group Id'"): - { + result, err := client.CreateOrUpdate(ctx, id, parameters) + if err != nil { + return &pluginsdk.RetryError{ + Err: fmt.Errorf("creating %s: %+v", id, err), + Retryable: false, + } + } + + if err := result.Poller.PollUntilDone(ctx); err != nil { + if strings.Contains(err.Error(), "PrivateLinkServiceId Invalid private link service id") { + return &pluginsdk.RetryError{ + Err: fmt.Errorf("waiting the creation of %s: %+v", id, err), + Retryable: true, + } + } + + var lroFailError pollers.PollingFailedError + if errors.As(err, &lroFailError) { + type lroErrorType struct { + Error struct { + Code string `json:"code"` + Message string `json:"message"` + } `json:"error"` + } + + var lroError lroErrorType + if err := lroFailError.HttpResponse.Unmarshal(&lroError); err != nil { return &pluginsdk.RetryError{ - Err: fmt.Errorf("creating %s due to missing 'group Id', ensure that the 'subresource_names' type is populated: %+v", id, err), + Err: fmt.Errorf("unmarshaling lro error response: %v", err), Retryable: false, } } - case strings.Contains(err.Error(), "PrivateLinkServiceId Invalid private link service id"): - { + + var retryableErrorCodes = []string{"RetryableError", "StorageAccountOperationInProgress"} + if slices.Contains(retryableErrorCodes, lroError.Error.Code) { + log.Printf("[WARN] Retry polling %q on error code: %q", id, lroError.Error.Code) return &pluginsdk.RetryError{ - Err: fmt.Errorf("creating Private Endpoint %s: %+v", id, err), Retryable: true, } } - default: - return &pluginsdk.RetryError{ - Err: fmt.Errorf("creating %s: %+v", id, err), - Retryable: false, - } + } + + return &pluginsdk.RetryError{ + Err: fmt.Errorf("waiting the creation of %s: %+v", id, err), + Retryable: false, } } From f553c286ed7a0c7fa56d25beea3e961c9b858c67 Mon Sep 17 00:00:00 2001 From: magodo Date: Wed, 23 Jul 2025 16:06:03 +1000 Subject: [PATCH 2/4] gofumpt --- internal/services/network/private_endpoint_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/network/private_endpoint_resource.go b/internal/services/network/private_endpoint_resource.go index e21fbd4da5f1..b1daab059443 100644 --- a/internal/services/network/private_endpoint_resource.go +++ b/internal/services/network/private_endpoint_resource.go @@ -389,7 +389,7 @@ func resourcePrivateEndpointCreate(d *pluginsdk.ResourceData, meta interface{}) } } - var retryableErrorCodes = []string{"RetryableError", "StorageAccountOperationInProgress"} + retryableErrorCodes := []string{"RetryableError", "StorageAccountOperationInProgress"} if slices.Contains(retryableErrorCodes, lroError.Error.Code) { log.Printf("[WARN] Retry polling %q on error code: %q", id, lroError.Error.Code) return &pluginsdk.RetryError{ From 628e5ea49de760618a4233e20854291006c4d05b Mon Sep 17 00:00:00 2001 From: magodo Date: Wed, 23 Jul 2025 16:41:58 +1000 Subject: [PATCH 3/4] remove a useless check introduced in #16315 --- internal/services/network/private_endpoint_resource.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/internal/services/network/private_endpoint_resource.go b/internal/services/network/private_endpoint_resource.go index b1daab059443..c79bd31c7998 100644 --- a/internal/services/network/private_endpoint_resource.go +++ b/internal/services/network/private_endpoint_resource.go @@ -365,13 +365,6 @@ func resourcePrivateEndpointCreate(d *pluginsdk.ResourceData, meta interface{}) } if err := result.Poller.PollUntilDone(ctx); err != nil { - if strings.Contains(err.Error(), "PrivateLinkServiceId Invalid private link service id") { - return &pluginsdk.RetryError{ - Err: fmt.Errorf("waiting the creation of %s: %+v", id, err), - Retryable: true, - } - } - var lroFailError pollers.PollingFailedError if errors.As(err, &lroFailError) { type lroErrorType struct { @@ -397,7 +390,6 @@ func resourcePrivateEndpointCreate(d *pluginsdk.ResourceData, meta interface{}) } } } - return &pluginsdk.RetryError{ Err: fmt.Errorf("waiting the creation of %s: %+v", id, err), Retryable: false, From e99c07d58243a45dcc09753f5ac9a1d943fa5906 Mon Sep 17 00:00:00 2001 From: magodo Date: Wed, 20 Aug 2025 10:43:25 +1000 Subject: [PATCH 4/4] wording --- internal/services/network/private_endpoint_resource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/services/network/private_endpoint_resource.go b/internal/services/network/private_endpoint_resource.go index c79bd31c7998..eb53e6c26c05 100644 --- a/internal/services/network/private_endpoint_resource.go +++ b/internal/services/network/private_endpoint_resource.go @@ -391,7 +391,7 @@ func resourcePrivateEndpointCreate(d *pluginsdk.ResourceData, meta interface{}) } } return &pluginsdk.RetryError{ - Err: fmt.Errorf("waiting the creation of %s: %+v", id, err), + Err: fmt.Errorf("waiting for the creation of %s: %+v", id, err), Retryable: false, } }