From c02bbb38762961659b6905a22a930a8a8abe7dc1 Mon Sep 17 00:00:00 2001 From: Patrick Cowland <44225864+patrickcping@users.noreply.github.com> Date: Wed, 5 Jun 2024 10:49:45 +0100 Subject: [PATCH] Add `AU` region code support (#358) * Add `AU` region code support * changelogs * testing updates * update readme * update workflow tests * add warning for deprecated env var --- .github/workflows/acceptance-test.yml | 2 + .github/workflows/unit-test.yml | 2 + CHANGELOG.md | 2 + README.md | 6 +- management/CHANGELOG.md | 1 + management/api/openapi.yaml | 1 + management/docs/EnumRegionCode.md | 2 + management/generate/pingone-management.yml | 2 +- management/model_enum_region_code.go | 2 + pingone/client.go | 96 ++++++++++++++++-- pingone/client_test.go | 112 ++++++++++++++++++--- pingone/config.go | 42 +++++--- pingone/config_test.go | 15 +-- pingone/model/region.go | 7 ++ pingone/model/region_test.go | 7 +- 15 files changed, 255 insertions(+), 44 deletions(-) diff --git a/.github/workflows/acceptance-test.yml b/.github/workflows/acceptance-test.yml index 46ba495d..b883a04a 100644 --- a/.github/workflows/acceptance-test.yml +++ b/.github/workflows/acceptance-test.yml @@ -63,6 +63,7 @@ jobs: PINGONE_ENVIRONMENT_ID_TESTACC: ${{ secrets.EU_PINGONE_ENVIRONMENT_ID }} # Dummy values follow to test the env var defaulting behaviours PINGONE_REGION_TESTACC: Europe + PINGONE_REGION_CODE_TESTACC: EU PINGONE_API_ACCESS_TOKEN: DummyAccessToken PINGONE_API_SERVICE_HOSTNAME: api.ping-eng.com PINGONE_AUTH_SERVICE_HOSTNAME: auth.ping-eng.com @@ -70,6 +71,7 @@ jobs: PINGONE_CLIENT_SECRET: dummyclientsecret PINGONE_ENVIRONMENT_ID: 7682a4d9-15d6-405a-9fd2-d9e08d3adfbe PINGONE_REGION: AsiaPacific + PINGONE_REGION_CODE: AP timeout-minutes: 15 strategy: diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 3037d7f6..22fb6742 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -69,6 +69,7 @@ jobs: PINGONE_CLIENT_SECRET_TESTACC: ${{ secrets.EU_PINGONE_CLIENT_SECRET }} PINGONE_ENVIRONMENT_ID_TESTACC: ${{ secrets.EU_PINGONE_ENVIRONMENT_ID }} PINGONE_REGION_TESTACC: Europe + PINGONE_REGION_CODE_TESTACC: EU PINGONE_API_ACCESS_TOKEN: testtest PINGONE_API_SERVICE_HOSTNAME: api.ping-eng.com PINGONE_AUTH_SERVICE_HOSTNAME: auth.ping-eng.com @@ -76,6 +77,7 @@ jobs: PINGONE_CLIENT_SECRET: testtesttest PINGONE_ENVIRONMENT_ID: 9c052a8a-14be-44e4-8f07-2662569994ce PINGONE_REGION: AsiaPacific + PINGONE_REGION_CODE: AP timeout-minutes: 15 strategy: diff --git a/CHANGELOG.md b/CHANGELOG.md index 98c9cf7e..cfc209e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * `github.com/patrickcping/pingone-go-sdk-v2` : v0.12.0 * **Note** Removal of retracted module `github.com/patrickcping/pingone-go-sdk-v2/agreementmanagement`. [#352](https://github.com/patrickcping/pingone-go-sdk-v2/pull/352) + * **Note** Deprecated the region name. Region codes should be used instead. [#358](https://github.com/patrickcping/pingone-go-sdk-v2/pull/358) * `github.com/patrickcping/pingone-go-sdk-v2/agreementmanagement` : [v0.3.2](./agreementmanagement/CHANGELOG.md) * **MODULE RETRACTION** The API endpoint in this module suffers major loss of function. The module has been retracted but is retained in the source repo for the purpose of retration. [#352](https://github.com/patrickcping/pingone-go-sdk-v2/pull/352) * `github.com/patrickcping/pingone-go-sdk-v2/authorize` : [v0.5.0](./authorize/CHANGELOG.md) @@ -29,6 +30,7 @@ * **Enhancement** Added the `DeletePreviousResourceSecret` function to control resource secret rotation. [#347](https://github.com/patrickcping/pingone-go-sdk-v2/pull/347) * **Enhancement** Added `Previous` to the `ResourceSecret` model to control resource secret rotation. [#347](https://github.com/patrickcping/pingone-go-sdk-v2/pull/347) * **Enhancement** Add the `com.au` top level domain to the connection configuration. [#351](https://github.com/patrickcping/pingone-go-sdk-v2/pull/351) + * **Enhancement** Add the `AU` region code to the `EnumRegionCode` model. [#358](https://github.com/patrickcping/pingone-go-sdk-v2/pull/358) * `github.com/patrickcping/pingone-go-sdk-v2/mfa` : [v0.19.0](./mfa/CHANGELOG.md) * **Breaking change** Remove optional `DeviceAuthenticationPolicyMobileOtpWindow` from `DeviceAuthenticationPolicyMobileOtp` constructor. [#343](https://github.com/patrickcping/pingone-go-sdk-v2/pull/343) * **Enhancement** Added `PromptForNicknameOnPairing` boolean field to the `DeviceAuthenticationPolicyFido2`, `DeviceAuthenticationPolicyMobile`, `DeviceAuthenticationPolicyOfflineDevice` and `DeviceAuthenticationPolicyTotp` models. [#349](https://github.com/patrickcping/pingone-go-sdk-v2/pull/349) diff --git a/README.md b/README.md index b65d94bf..dd540c91 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ config := &pingone.Config{ ClientSecret: clientSecret, EnvironmentID: environmentId, AccessToken: accessToken, - Region: region, + RegionCode: regionCode, } client, err := config.APIClient(ctx) @@ -55,9 +55,9 @@ The result is an object with clients initialised for each service: * `client.RiskAPIClient` * `client.VerifyAPIClient` -In the above, if an `AccessToken` is provided, this will be verified and used. If the `AccessToken` is not provided, the SDK will retrieve an access token from the provided `ClientID`, `ClientSecret`, `EnvironmentID` and `Region` parameters. +In the above, if an `AccessToken` is provided, this will be verified and used. If the `AccessToken` is not provided, the SDK will retrieve an access token from the provided `ClientID`, `ClientSecret`, `EnvironmentID` and `RegionCode` parameters. -The client SDK defaults to production hostnames, and the `Region` is used to add the relevant suffix to the hostname. For example, `Europe` as a `Region` value with suffix the service hostname with `.eu`. Hostnames can be overridden with the optional `APIHostnameOverride`, and `AuthHostnameOverride` parameters. +The client SDK defaults to production hostnames, and the `RegionCode` is used to add the relevant suffix to the hostname. For example, `EU` as a `RegionCode` value with suffix the service hostname with `.eu`. Hostnames can be overridden with the optional `APIHostnameOverride`, and `AuthHostnameOverride` parameters. An API call can be made against the API objects, as in the following example to get all environments in a tenant: diff --git a/management/CHANGELOG.md b/management/CHANGELOG.md index 94f38f02..fea34d6f 100644 --- a/management/CHANGELOG.md +++ b/management/CHANGELOG.md @@ -10,6 +10,7 @@ * **Enhancement** Added the `DeletePreviousResourceSecret` function to control resource secret rotation. [#347](https://github.com/patrickcping/pingone-go-sdk-v2/pull/347) * **Enhancement** Added `Previous` to the `ResourceSecret` model to control resource secret rotation. [#347](https://github.com/patrickcping/pingone-go-sdk-v2/pull/347) * **Enhancement** Add the `com.au` top level domain to the connection configuration. [#351](https://github.com/patrickcping/pingone-go-sdk-v2/pull/351) +* **Enhancement** Add the `AU` region code to the `EnumRegionCode` model. [#358](https://github.com/patrickcping/pingone-go-sdk-v2/pull/358) # v0.39.0 (2024-05-01) diff --git a/management/api/openapi.yaml b/management/api/openapi.yaml index e6fe8d6a..00926571 100644 --- a/management/api/openapi.yaml +++ b/management/api/openapi.yaml @@ -27195,6 +27195,7 @@ components: is set when the environment is created and cannot be updated. enum: - AP + - AU - CA - EU - NA diff --git a/management/docs/EnumRegionCode.md b/management/docs/EnumRegionCode.md index a416dc16..66abc4ff 100644 --- a/management/docs/EnumRegionCode.md +++ b/management/docs/EnumRegionCode.md @@ -5,6 +5,8 @@ * `AP` (value: `"AP"`) +* `AU` (value: `"AU"`) + * `CA` (value: `"CA"`) * `EU` (value: `"EU"`) diff --git a/management/generate/pingone-management.yml b/management/generate/pingone-management.yml index 9dccfa1a..940fda88 100644 --- a/management/generate/pingone-management.yml +++ b/management/generate/pingone-management.yml @@ -505,7 +505,7 @@ components: default: JWT Bearer Token EnumRegionCode: type: string - enum: [AP, CA, EU, NA] + enum: [AP, AU, CA, EU, NA] description: A string that specifies the environment region code. The value is set when the environment is created and cannot be updated. EnumRegionCodeLicense: type: string diff --git a/management/model_enum_region_code.go b/management/model_enum_region_code.go index 69268d68..702ad5b5 100644 --- a/management/model_enum_region_code.go +++ b/management/model_enum_region_code.go @@ -21,6 +21,7 @@ type EnumRegionCode string // List of EnumRegionCode const ( ENUMREGIONCODE_AP EnumRegionCode = "AP" + ENUMREGIONCODE_AU EnumRegionCode = "AU" ENUMREGIONCODE_CA EnumRegionCode = "CA" ENUMREGIONCODE_EU EnumRegionCode = "EU" ENUMREGIONCODE_NA EnumRegionCode = "NA" @@ -29,6 +30,7 @@ const ( // All allowed values of EnumRegionCode enum var AllowedEnumRegionCodeEnumValues = []EnumRegionCode{ "AP", + "AU", "CA", "EU", "NA", diff --git a/pingone/client.go b/pingone/client.go index 52fdea24..92196a7b 100644 --- a/pingone/client.go +++ b/pingone/client.go @@ -64,6 +64,15 @@ func (c *Config) APIClient(ctx context.Context) (*Client, error) { return nil, err } + var region model.RegionMapping + if c.Region != "" { + region = model.FindRegionByName(c.Region) //nolint:staticcheck + } + + if v := c.RegionCode; v != nil { + region = model.FindRegionByAPICode(*v) + } + apiClient := &Client{ AuthorizeAPIClient: authorizeClient, CredentialsAPIClient: credentialsClient, @@ -71,7 +80,7 @@ func (c *Config) APIClient(ctx context.Context) (*Client, error) { MFAAPIClient: mfaClient, RiskAPIClient: riskClient, VerifyAPIClient: verifyClient, - Region: model.FindRegionByName(c.Region), + Region: region, } return apiClient, nil @@ -120,7 +129,17 @@ func (c *Config) AuthorizeAPIClient(ctx context.Context) (*authorize.APIClient, } } else { clientcfg.SetDefaultServerIndex(0) - err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", model.FindRegionByName(c.Region).URLSuffix) + + var region model.RegionMapping + if c.Region != "" { + region = model.FindRegionByName(c.Region) //nolint:staticcheck + } + + if v := c.RegionCode; v != nil { + region = model.FindRegionByAPICode(*v) + } + + err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", region.URLSuffix) if err != nil { return nil, err } @@ -193,7 +212,17 @@ func (c *Config) CredentialsAPIClient(ctx context.Context) (*credentials.APIClie } } else { clientcfg.SetDefaultServerIndex(0) - err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", model.FindRegionByName(c.Region).URLSuffix) + + var region model.RegionMapping + if c.Region != "" { + region = model.FindRegionByName(c.Region) //nolint:staticcheck + } + + if v := c.RegionCode; v != nil { + region = model.FindRegionByAPICode(*v) + } + + err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", region.URLSuffix) if err != nil { return nil, err } @@ -265,7 +294,17 @@ func (c *Config) ManagementAPIClient(ctx context.Context) (*management.APIClient } } else { clientcfg.SetDefaultServerIndex(0) - err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", model.FindRegionByName(c.Region).URLSuffix) + + var region model.RegionMapping + if c.Region != "" { + region = model.FindRegionByName(c.Region) //nolint:staticcheck + } + + if v := c.RegionCode; v != nil { + region = model.FindRegionByAPICode(*v) + } + + err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", region.URLSuffix) if err != nil { return nil, err } @@ -337,7 +376,17 @@ func (c *Config) MFAAPIClient(ctx context.Context) (*mfa.APIClient, error) { } } else { clientcfg.SetDefaultServerIndex(0) - err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", model.FindRegionByName(c.Region).URLSuffix) + + var region model.RegionMapping + if c.Region != "" { + region = model.FindRegionByName(c.Region) //nolint:staticcheck + } + + if v := c.RegionCode; v != nil { + region = model.FindRegionByAPICode(*v) + } + + err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", region.URLSuffix) if err != nil { return nil, err } @@ -409,7 +458,17 @@ func (c *Config) RiskAPIClient(ctx context.Context) (*risk.APIClient, error) { } } else { clientcfg.SetDefaultServerIndex(0) - err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", model.FindRegionByName(c.Region).URLSuffix) + + var region model.RegionMapping + if c.Region != "" { + region = model.FindRegionByName(c.Region) //nolint:staticcheck + } + + if v := c.RegionCode; v != nil { + region = model.FindRegionByAPICode(*v) + } + + err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", region.URLSuffix) if err != nil { return nil, err } @@ -481,7 +540,17 @@ func (c *Config) VerifyAPIClient(ctx context.Context) (*verify.APIClient, error) } } else { clientcfg.SetDefaultServerIndex(0) - err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", model.FindRegionByName(c.Region).URLSuffix) + + var region model.RegionMapping + if c.Region != "" { + region = model.FindRegionByName(c.Region) //nolint:staticcheck + } + + if v := c.RegionCode; v != nil { + region = model.FindRegionByAPICode(*v) + } + + err := clientcfg.SetDefaultServerVariableDefaultValue("suffix", region.URLSuffix) if err != nil { return nil, err } @@ -514,11 +583,20 @@ func (c *Config) getToken(ctx context.Context) error { if !checkForValue(c.AccessToken) { - if !checkForValue(c.ClientID) || !checkForValue(c.ClientSecret) || !checkForValue(c.EnvironmentID) || !checkForValue(c.Region) { + if !checkForValue(c.ClientID) || !checkForValue(c.ClientSecret) || !checkForValue(c.EnvironmentID) || (!checkForValue(c.Region) && !checkForValue(c.RegionCode)) { return fmt.Errorf("Required parameter missing. Must provide ClientID, ClientSecret, EnvironmentID and Region.") } - regionSuffix := model.FindRegionByName(c.Region).URLSuffix + var region model.RegionMapping + if c.Region != "" { + region = model.FindRegionByName(c.Region) //nolint:staticcheck + } + + if v := c.RegionCode; v != nil { + region = model.FindRegionByAPICode(*v) + } + + regionSuffix := region.URLSuffix //Get URL from SDK authURL := fmt.Sprintf("https://auth.pingone.%s", regionSuffix) diff --git a/pingone/client_test.go b/pingone/client_test.go index 05ba5f9a..6b49bf35 100644 --- a/pingone/client_test.go +++ b/pingone/client_test.go @@ -5,10 +5,11 @@ import ( "os" "testing" + "github.com/patrickcping/pingone-go-sdk-v2/management" "github.com/patrickcping/pingone-go-sdk-v2/pingone/model" ) -func TestAccAPIClient_Success(t *testing.T) { +func TestAccAPIClient_Deprecated_Success(t *testing.T) { t.Parallel() var ctx = context.Background() @@ -67,11 +68,75 @@ func TestAccAPIClient_Success(t *testing.T) { t.Fatalf("Verify Client not successfully retrieved") } - if client.Region != model.FindRegionByName(region) { + if client.Region != model.FindRegionByName(region) { //nolint:staticcheck t.Fatalf("Unexpected region. Expected %s, got %v", region, client.Region) } } +func TestAccAPIClient_Success(t *testing.T) { + t.Parallel() + + var ctx = context.Background() + + clientID := os.Getenv("PINGONE_CLIENT_ID_TESTACC") + clientSecret := os.Getenv("PINGONE_CLIENT_SECRET_TESTACC") + environmentID := os.Getenv("PINGONE_ENVIRONMENT_ID_TESTACC") + regionCode := management.EnumRegionCode(os.Getenv("PINGONE_REGION_CODE_TESTACC")) + + if err := os.Setenv("PINGONE_API_ACCESS_TOKEN", ""); err != nil { + t.Fatalf("Client not successfully retrieved: %s", err) + } + + if err := os.Setenv("PINGONE_API_SERVICE_HOSTNAME", ""); err != nil { + t.Fatalf("Client not successfully retrieved: %s", err) + } + + if err := os.Setenv("PINGONE_AUTH_SERVICE_HOSTNAME", ""); err != nil { + t.Fatalf("Client not successfully retrieved: %s", err) + } + + config := &Config{ + ClientID: &clientID, + ClientSecret: &clientSecret, + EnvironmentID: &environmentID, + RegionCode: ®ionCode, + } + + client, err := config.APIClient(ctx) + + if err != nil { + t.Fatalf("Client not successfully retrieved: %s", err) + } + + if client.AuthorizeAPIClient == nil { + t.Fatalf("Authorize Client not successfully retrieved") + } + + if client.CredentialsAPIClient == nil { + t.Fatalf("Credentials Client not successfully retrieved") + } + + if client.ManagementAPIClient == nil { + t.Fatalf("Management Client not successfully retrieved") + } + + if client.MFAAPIClient == nil { + t.Fatalf("MFA Client not successfully retrieved") + } + + if client.RiskAPIClient == nil { + t.Fatalf("Risk Client not successfully retrieved") + } + + if client.VerifyAPIClient == nil { + t.Fatalf("Verify Client not successfully retrieved") + } + + if client.Region != model.FindRegionByAPICode(regionCode) { + t.Fatalf("Unexpected region. Expected %s, got %v", string(regionCode), client.Region) + } +} + func TestAccAPIClient_MissingClientID(t *testing.T) { t.Parallel() @@ -80,13 +145,13 @@ func TestAccAPIClient_MissingClientID(t *testing.T) { clientID := "" clientSecret := os.Getenv("PINGONE_CLIENT_SECRET_TESTACC") environmentID := os.Getenv("PINGONE_ENVIRONMENT_ID_TESTACC") - region := os.Getenv("PINGONE_REGION_TESTACC") + regionCode := management.EnumRegionCode(os.Getenv("PINGONE_REGION_CODE_TESTACC")) config := &Config{ ClientID: &clientID, ClientSecret: &clientSecret, EnvironmentID: &environmentID, - Region: region, + RegionCode: ®ionCode, } client, err := config.APIClient(ctx) @@ -104,13 +169,13 @@ func TestAccAPIClient_MissingClientSecret(t *testing.T) { clientID := os.Getenv("PINGONE_CLIENT_ID_TESTACC") clientSecret := "" environmentID := os.Getenv("PINGONE_ENVIRONMENT_ID_TESTACC") - region := os.Getenv("PINGONE_REGION_TESTACC") + regionCode := management.EnumRegionCode(os.Getenv("PINGONE_REGION_CODE_TESTACC")) config := &Config{ ClientID: &clientID, ClientSecret: &clientSecret, EnvironmentID: &environmentID, - Region: region, + RegionCode: ®ionCode, } client, err := config.APIClient(ctx) @@ -128,13 +193,13 @@ func TestAccAPIClient_MissingClientEnvironment(t *testing.T) { clientID := os.Getenv("PINGONE_CLIENT_ID_TESTACC") clientSecret := os.Getenv("PINGONE_CLIENT_SECRET_TESTACC") environmentID := "" - region := os.Getenv("PINGONE_REGION_TESTACC") + regionCode := management.EnumRegionCode(os.Getenv("PINGONE_REGION_CODE_TESTACC")) config := &Config{ ClientID: &clientID, ClientSecret: &clientSecret, EnvironmentID: &environmentID, - Region: region, + RegionCode: ®ionCode, } client, err := config.APIClient(ctx) @@ -152,13 +217,12 @@ func TestAccAPIClient_MissingClientRegion(t *testing.T) { clientID := os.Getenv("PINGONE_CLIENT_ID_TESTACC") clientSecret := os.Getenv("PINGONE_CLIENT_SECRET_TESTACC") environmentID := os.Getenv("PINGONE_ENVIRONMENT_ID_TESTACC") - region := "" config := &Config{ ClientID: &clientID, ClientSecret: &clientSecret, EnvironmentID: &environmentID, - Region: region, + RegionCode: nil, } client, err := config.APIClient(ctx) @@ -176,13 +240,13 @@ func TestAccAPIClient_FailedAuth(t *testing.T) { clientID := os.Getenv("PINGONE_CLIENT_ID_TESTACC") clientSecret := os.Getenv("PINGONE_CLIENT_ID_TESTACC") environmentID := os.Getenv("PINGONE_ENVIRONMENT_ID_TESTACC") - region := os.Getenv("PINGONE_REGION_TESTACC") + regionCode := management.EnumRegionCode(os.Getenv("PINGONE_REGION_CODE_TESTACC")) config := &Config{ ClientID: &clientID, ClientSecret: &clientSecret, EnvironmentID: &environmentID, - Region: region, + RegionCode: ®ionCode, } client, err := config.APIClient(ctx) @@ -197,6 +261,30 @@ func TestAccAPIClient_BadRegion(t *testing.T) { var ctx = context.Background() + clientID := os.Getenv("PINGONE_CLIENT_ID_TESTACC") + clientSecret := os.Getenv("PINGONE_CLIENT_SECRET_TESTACC") + environmentID := os.Getenv("PINGONE_ENVIRONMENT_ID_TESTACC") + regionCode := management.EnumRegionCode("NZ") + + config := &Config{ + ClientID: &clientID, + ClientSecret: &clientSecret, + EnvironmentID: &environmentID, + RegionCode: ®ionCode, + } + + client, err := config.APIClient(ctx) + + if err == nil || client != nil { + t.Fatalf("Client not expected to be successfully retrieved") + } +} + +func TestAccAPIClient_Deprecated_BadRegion(t *testing.T) { + t.Parallel() + + var ctx = context.Background() + clientID := os.Getenv("PINGONE_CLIENT_ID_TESTACC") clientSecret := os.Getenv("PINGONE_CLIENT_SECRET_TESTACC") environmentID := os.Getenv("PINGONE_ENVIRONMENT_ID_TESTACC") diff --git a/pingone/config.go b/pingone/config.go index cc6a3091..c733afeb 100644 --- a/pingone/config.go +++ b/pingone/config.go @@ -2,11 +2,13 @@ package pingone import ( "fmt" + "log" "os" "regexp" "slices" "strings" + "github.com/patrickcping/pingone-go-sdk-v2/management" "github.com/patrickcping/pingone-go-sdk-v2/pingone/model" "golang.org/x/oauth2" ) @@ -20,10 +22,12 @@ type Config struct { ClientSecret *string EnvironmentID *string ProxyURL *string - Region string - UserAgentOverride *string - UserAgentSuffix *string - validated bool + // Deprecated: Use RegionCode instead + Region string + RegionCode *management.EnumRegionCode + UserAgentOverride *string + UserAgentSuffix *string + validated bool } var p1ResourceIDRegexp = regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`) @@ -114,18 +118,22 @@ func (c *Config) validateEnvironmentID() error { } func (c *Config) validateRegion() error { - if !checkForValue(c.Region) { - if v := envVar("PINGONE_REGION"); v != "" { + + if !checkForValue(c.Region) && !checkForValue(c.RegionCode) { + if v := management.EnumRegionCode(envVar("PINGONE_REGION_CODE")); v != "" && string(v) != "UNKNOWN" { + c.RegionCode = &v + } else if v := envVar("PINGONE_REGION"); v != "" { + log.Printf("WARNING: Use of the PINGONE_REGION environment variable is deprecated. Use PINGONE_REGION_CODE instead.") c.Region = v } } - if !checkForValue(c.Region) { - return fmt.Errorf("Must provide the region parameter.") - } else { - if !slices.Contains(model.RegionsAvailableList(), c.Region) { - return fmt.Errorf("Invalid region value. The region parameter is case sensitive and must be one of the following values: %s", strings.Join(model.RegionsAvailableList(), ", ")) - } + if !checkForValue(c.Region) && !checkForValue(c.RegionCode) { + return fmt.Errorf("Must provide the region code parameter.") + } + + if checkForValue(c.Region) && !slices.Contains(model.RegionsAvailableList(), c.Region) { + return fmt.Errorf("Invalid region value %s. The region parameter is case sensitive and must be one of the following values: %s", c.Region, strings.Join(model.RegionsAvailableList(), ", ")) } return nil @@ -218,6 +226,16 @@ func checkForValue(o any) bool { return false } return true + case *management.EnumRegionCode: + if v == nil || string(*v) == "UNKNOWN" || string(*v) == "" { + return false + } + return true + case management.EnumRegionCode: + if string(v) == "UNKNOWN" { + return false + } + return true } return false diff --git a/pingone/config_test.go b/pingone/config_test.go index 8fd96cf1..2b816492 100644 --- a/pingone/config_test.go +++ b/pingone/config_test.go @@ -4,6 +4,8 @@ import ( "os" "strings" "testing" + + "github.com/patrickcping/pingone-go-sdk-v2/management" ) func TestValidateAccessToken_ConfigSuccess(t *testing.T) { @@ -305,10 +307,11 @@ func TestValidateRegion_ConfigSuccess(t *testing.T) { func TestValidateRegion_EnvSuccess(t *testing.T) { - value := os.Getenv("PINGONE_REGION") + regionName := os.Getenv("PINGONE_REGION") + regionCode := management.EnumRegionCode(os.Getenv("PINGONE_REGION_CODE")) - if value == "" { - t.Fatalf("Required environment variable PINGONE_REGION not set") + if regionName == "" && (regionCode == "" || string(regionCode) == "UNKNOWN") { + t.Fatalf("Required environment variable PINGONE_REGION_CODE and deprecated environment variable PINGONE_REGION not set") } config := &Config{} @@ -317,12 +320,12 @@ func TestValidateRegion_EnvSuccess(t *testing.T) { t.Fatalf("Parameter not successfully verified: %s", err) } - if config.Region != value { - t.Fatalf("Parameter default not taken from environment") + if (config.Region != regionName) && (string(*config.RegionCode) != string(regionCode)) { + t.Fatalf("Parameter default not taken from environment: %#v, %#v, %s, %s", config.Region, config.RegionCode, *config.RegionCode, string(regionCode)) } } -func TestValidateRegion_InvalidValue(t *testing.T) { +func TestValidateRegion_Deprecated_InvalidValue(t *testing.T) { value := "Tatooine" config := &Config{ diff --git a/pingone/model/region.go b/pingone/model/region.go index 8e787b76..28dab3b7 100644 --- a/pingone/model/region.go +++ b/pingone/model/region.go @@ -9,6 +9,7 @@ import ( ) type RegionMapping struct { + // Deprecated: Use APICode instead Region string URLSuffix string APICode management.EnumRegionCode @@ -35,6 +36,11 @@ func init() { URLSuffix: "asia", APICode: management.ENUMREGIONCODE_AP, }, + { + Region: "Australia-AsiaPacific", + URLSuffix: "com.au", + APICode: management.ENUMREGIONCODE_AU, + }, { Region: "Canada", URLSuffix: "ca", @@ -43,6 +49,7 @@ func init() { } } +// Deprecated: Use FindRegionByAPICode instead func FindRegionByName(region string) RegionMapping { idx := slices.IndexFunc(regionMappingList, func(c RegionMapping) bool { return c.Region == region }) diff --git a/pingone/model/region_test.go b/pingone/model/region_test.go index 1c3695e5..e318f686 100644 --- a/pingone/model/region_test.go +++ b/pingone/model/region_test.go @@ -80,6 +80,11 @@ func TestFindRegionByAPICode(t *testing.T) { URLSuffix: "asia", APICode: management.ENUMREGIONCODE_AP, }, + management.ENUMREGIONCODE_AU: { + Region: "Australia-AsiaPacific", + URLSuffix: "com.au", + APICode: management.ENUMREGIONCODE_AU, + }, management.EnumRegionCode("DOES_NOT_EXIST"): { Region: "NorthAmerica", URLSuffix: "com", @@ -101,7 +106,7 @@ func TestFindRegionByAPICode(t *testing.T) { func TestAvailableRegionsList(t *testing.T) { - expectedList := []string{"AsiaPacific", "Canada", "Europe", "NorthAmerica"} + expectedList := []string{"AsiaPacific", "Australia-AsiaPacific", "Canada", "Europe", "NorthAmerica"} v := RegionsAvailableList() if !reflect.DeepEqual(v, expectedList) {