Skip to content

Commit

Permalink
resource/pingone_language_update: Add retry condition for language …
Browse files Browse the repository at this point in the history
…enabled race condition (#884)

* `resource/pingone_language_update`: Add retry condition for language enabled race condition

* changelog

* add retry for failed language enabled update
  • Loading branch information
patrickcping committed Jul 8, 2024
1 parent a98bbdf commit ff10442
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 13 deletions.
3 changes: 3 additions & 0 deletions .changelog/884.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
`resource/pingone_language_update`: Fixed "The language must be enabled before it is set as the default" error when setting a language as enabled and the environment default.
```
114 changes: 101 additions & 13 deletions internal/service/base/resource_language_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ import (
"context"
"fmt"
"net/http"
"regexp"
"time"

"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/patrickcping/pingone-go-sdk-v2/management"
"github.com/patrickcping/pingone-go-sdk-v2/pingone/model"
client "github.com/pingidentity/terraform-provider-pingone/internal/client"
"github.com/pingidentity/terraform-provider-pingone/internal/framework"
"github.com/pingidentity/terraform-provider-pingone/internal/sdk"
Expand Down Expand Up @@ -290,27 +295,90 @@ func updateLanguageEnabledDefaultSequence(ctx context.Context, apiClient *manage
errorFunction = sdk.CustomErrorResourceNotFoundWarning
}

response, d := sdk.ParseResponse(
ctx,
var response interface{}

func() (any, *http.Response, error) {
fO, fR, fErr := apiClient.LanguagesApi.UpdateLanguage(ctx, environmentID, languageID).Language(language).Execute()
return framework.CheckEnvironmentExistsOnPermissionsError(ctx, apiClient, environmentID, fO, fR, fErr)
stateConf := &retry.StateChangeConf{
Pending: []string{
"false",
},
"UpdateLanguage-UpdateSequence1",
errorFunction,
nil,
)
diags = append(diags, d...)
if diags.HasError() {
Target: []string{
"true",
"err",
},
Refresh: func() (interface{}, string, error) {

// Run the API call
responseCreate, d := sdk.ParseResponse(
ctx,

func() (any, *http.Response, error) {
fO, fR, fErr := apiClient.LanguagesApi.UpdateLanguage(ctx, environmentID, languageID).Language(language).Execute()
return framework.CheckEnvironmentExistsOnPermissionsError(ctx, apiClient, environmentID, fO, fR, fErr)
},
"UpdateLanguage-UpdateSequence1",
errorFunction,
nil,
)
diags = append(diags, d...)
if diags.HasError() {
return nil, "err", fmt.Errorf("Error reading language")
}

if responseCreate == nil {
return nil, "err", fmt.Errorf("Language not found")
}

// Run the API call
response, d = sdk.ParseResponse(
ctx,

func() (any, *http.Response, error) {
fO, fR, fErr := apiClient.LanguagesApi.ReadOneLanguage(ctx, environmentID, languageID).Execute()
return framework.CheckEnvironmentExistsOnPermissionsError(ctx, apiClient, environmentID, fO, fR, fErr)
},
"ReadOneLanguage-UpdateSequence1",
errorFunction,
nil,
)
diags = append(diags, d...)
if diags.HasError() {
return nil, "err", fmt.Errorf("Error reading language")
}

if response == nil {
return nil, "err", fmt.Errorf("Language not found")
}

if response.(*management.Language).GetEnabled() != enabled {
return nil, "false", nil
}

return response, "true", nil
},
Timeout: 5 * time.Minute,
Delay: 1 * time.Second,
MinTimeout: 1 * time.Second,
ContinuousTargetOccurence: 1,
}
response, err := stateConf.WaitForStateContext(ctx)

if err != nil {
diags = append(diags, diag.Diagnostic{
Severity: diag.Error,
Summary: "Cannot find enable language",
Detail: fmt.Sprintf("The language %s for environment %s cannot be enabled: %s", languageID, environmentID, err),
})

return diags
}

if response == nil {
return diags
}

if defaultValue && enabled {
languageResponse := response.(*management.Language)

if defaultValue && languageResponse.Enabled {

language.SetDefault(true)

Expand All @@ -323,7 +391,7 @@ func updateLanguageEnabledDefaultSequence(ctx context.Context, apiClient *manage
},
"UpdateLanguage-UpdateSequence2",
errorFunction,
nil,
retryLanguageUpdateSequence2,
)
if diags.HasError() {
return diags
Expand All @@ -334,3 +402,23 @@ func updateLanguageEnabledDefaultSequence(ctx context.Context, apiClient *manage
return diags

}

var retryLanguageUpdateSequence2 = func(ctx context.Context, r *http.Response, p1error *model.P1Error) bool {

if p1error != nil {

// Language may not be enabled yet
m, err := regexp.MatchString("^The language must be enabled before it is set as the default", p1error.GetMessage())
if err == nil && m {
tflog.Warn(ctx, "Language not yet enabled, retrying to set as default")
return true
}
if err != nil {
tflog.Warn(ctx, "Cannot match error string for retry")
return false
}

}

return false
}

0 comments on commit ff10442

Please sign in to comment.