Repository: GoogleCloudPlatform/terraform-validator
Pull request #1217 (2022-12-20 18:30:49)

Promote Workforce Pool resources to GA from beta
<!-- Put a description of what this PR is for here, along with any references to issues that this resolves or contributes to -->

Promote Workforce Pool resources to GA from beta.

Fixed: https://github.com/hashicorp/terraform-provider-google/issues/13290

<!--
Replace each [ ] with [X] to check it. Switch to the preview view to make it easier to click on links.
These steps will speed up the review process, and we appreciate you spending time on them before sending
your code to be reviewed.
-->
If this PR is for Terraform, I acknowledge that I have:

- [X] Searched through the [issue tracker](https://github.com/hashicorp/terraform-provider-google/issues) for an open issue that this either resolves or contributes to, commented on it to claim it, and written "fixes {url}" or "part of {url}" in this PR description. If there were no relevant open issues, I opened one and commented that I would like to work on it (not necessary for very small changes).
- [X] [Generated Terraform](https://github.com/GoogleCloudPlatform/magic-modules#generating-the-terraform-providers), and ran `make test` and `make lint` to ensure it passes unit and linter tests.
- [X] Ensured that all new fields I added that can be set by a user appear in at least one [example](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/examples) (for generated resources) or [third_party test](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/tests) (for handwritten resources or update tests).
- [X] [Ran](https://github.com/hashicorp/terraform-provider-google/blob/main/.github/CONTRIBUTING.md#tests) relevant acceptance tests (If the acceptance tests do not yet pass or you are unable to run them, please let your reviewer know).
- [X] Read the [Release Notes Guide](https://github.com/GoogleCloudPlatform/magic-modules/blob/main/.ci/RELEASE_NOTES_GUIDE.md) before writing my release note below.

<!-- AUTOCHANGELOG for Downstream PRs.

Please select one of the following "release-note:" headings:
    - release-note:enhancement
    - release-note:bug
    - release-note:note
    - release-note:new-resource
    - release-note:new-datasource
    - release-note:deprecation
    - release-note:breaking-change
    - release-note:none
    
Unless you choose release-note:none, please add a release note.

See .ci/RELEASE_NOTES_GUIDE.md for writing good release notes.

You can add more release note blocks if you want more than one CHANGELOG
entry for this PR.
-->
**Release Note Template for Downstream PRs (will be copied)**

```release-note:new-resource
`google_iam_workforce_pool` (ga only)
```

```release-note:new-resource
`google_iam_workforce_pool_provider` (ga only)
```

Derived from https://github.com/GoogleCloudPlatform/magic-modules/pull/7001


Patch:
diff --git a/converters/google/resources/config.go b/converters/google/resources/config.go
index f5f4fb33..9b0502fc 100644
--- a/converters/google/resources/config.go
+++ b/converters/google/resources/config.go
@@ -219,6 +219,7 @@ type Config struct {
 	GKEHubBasePath               string
 	HealthcareBasePath           string
 	IAMBetaBasePath              string
+	IAMWorkforcePoolBasePath     string
 	IapBasePath                  string
 	IdentityPlatformBasePath     string
 	KMSBasePath                  string
@@ -318,6 +319,7 @@ const GameServicesBasePathKey = "GameServices"
 const GKEHubBasePathKey = "GKEHub"
 const HealthcareBasePathKey = "Healthcare"
 const IAMBetaBasePathKey = "IAMBeta"
+const IAMWorkforcePoolBasePathKey = "IAMWorkforcePool"
 const IapBasePathKey = "Iap"
 const IdentityPlatformBasePathKey = "IdentityPlatform"
 const KMSBasePathKey = "KMS"
@@ -411,6 +413,7 @@ var DefaultBasePaths = map[string]string{
 	GKEHubBasePathKey:               "https://gkehub.googleapis.com/v1/",
 	HealthcareBasePathKey:           "https://healthcare.googleapis.com/v1/",
 	IAMBetaBasePathKey:              "https://iam.googleapis.com/v1/",
+	IAMWorkforcePoolBasePathKey:     "https://iam.googleapis.com/v1/",
 	IapBasePathKey:                  "https://iap.googleapis.com/v1/",
 	IdentityPlatformBasePathKey:     "https://identitytoolkit.googleapis.com/v2/",
 	KMSBasePathKey:                  "https://cloudkms.googleapis.com/v1/",
@@ -1266,6 +1269,7 @@ func ConfigureBasePaths(c *Config) {
 	c.GKEHubBasePath = DefaultBasePaths[GKEHubBasePathKey]
 	c.HealthcareBasePath = DefaultBasePaths[HealthcareBasePathKey]
 	c.IAMBetaBasePath = DefaultBasePaths[IAMBetaBasePathKey]
+	c.IAMWorkforcePoolBasePath = DefaultBasePaths[IAMWorkforcePoolBasePathKey]
 	c.IapBasePath = DefaultBasePaths[IapBasePathKey]
 	c.IdentityPlatformBasePath = DefaultBasePaths[IdentityPlatformBasePathKey]
 	c.KMSBasePath = DefaultBasePaths[KMSBasePathKey]
diff --git a/converters/google/resources/iamworkforcepool_workforce_pool.go b/converters/google/resources/iamworkforcepool_workforce_pool.go
new file mode 100644
index 00000000..ff6e54a7
--- /dev/null
+++ b/converters/google/resources/iamworkforcepool_workforce_pool.go
@@ -0,0 +1,129 @@
+// ----------------------------------------------------------------------------
+//
+//     ***     AUTO GENERATED CODE    ***    Type: MMv1     ***
+//
+// ----------------------------------------------------------------------------
+//
+//     This file is automatically generated by Magic Modules and manual
+//     changes will be clobbered when the file is regenerated.
+//
+//     Please read more about how to change this file in
+//     .github/CONTRIBUTING.md.
+//
+// ----------------------------------------------------------------------------
+
+package google
+
+import (
+	"fmt"
+	"reflect"
+	"regexp"
+	"strings"
+)
+
+const workforcePoolIdRegexp = `^[a-z][a-z0-9-]{4,61}[a-z0-9]$`
+
+func validateWorkforcePoolId(v interface{}, k string) (ws []string, errors []error) {
+	value := v.(string)
+
+	if strings.HasPrefix(value, "gcp-") {
+		errors = append(errors, fmt.Errorf(
+			"%q (%q) can not start with \"gcp-\". "+
+				"The prefix `gcp-` is reserved for use by Google, and may not be specified.", k, value))
+	}
+
+	if !regexp.MustCompile(workforcePoolIdRegexp).MatchString(value) {
+		errors = append(errors, fmt.Errorf(
+			"Workforce Pool Id \"%q\" must contain only lowercase letters [a-z], digits [0-9], and hyphens "+
+				"[-]. The WorkforcePool ID must be between 6 and 63 characters, begin "+
+				"with a letter, and cannot have a trailing hyphen.", k))
+	}
+
+	return
+}
+
+const IAMWorkforcePoolWorkforcePoolAssetType string = "iam.googleapis.com/WorkforcePool"
+
+func resourceConverterIAMWorkforcePoolWorkforcePool() ResourceConverter {
+	return ResourceConverter{
+		AssetType: IAMWorkforcePoolWorkforcePoolAssetType,
+		Convert:   GetIAMWorkforcePoolWorkforcePoolCaiObject,
+	}
+}
+
+func GetIAMWorkforcePoolWorkforcePoolCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
+	name, err := assetName(d, config, "//iam.googleapis.com/locations/{{location}}/workforcePools/{{workforce_pool_id}}")
+	if err != nil {
+		return []Asset{}, err
+	}
+	if obj, err := GetIAMWorkforcePoolWorkforcePoolApiObject(d, config); err == nil {
+		return []Asset{{
+			Name: name,
+			Type: IAMWorkforcePoolWorkforcePoolAssetType,
+			Resource: &AssetResource{
+				Version:              "v1",
+				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/iam/v1/rest",
+				DiscoveryName:        "WorkforcePool",
+				Data:                 obj,
+			},
+		}}, nil
+	} else {
+		return []Asset{}, err
+	}
+}
+
+func GetIAMWorkforcePoolWorkforcePoolApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
+	obj := make(map[string]interface{})
+	parentProp, err := expandIAMWorkforcePoolWorkforcePoolParent(d.Get("parent"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("parent"); !isEmptyValue(reflect.ValueOf(parentProp)) && (ok || !reflect.DeepEqual(v, parentProp)) {
+		obj["parent"] = parentProp
+	}
+	displayNameProp, err := expandIAMWorkforcePoolWorkforcePoolDisplayName(d.Get("display_name"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("display_name"); !isEmptyValue(reflect.ValueOf(displayNameProp)) && (ok || !reflect.DeepEqual(v, displayNameProp)) {
+		obj["displayName"] = displayNameProp
+	}
+	descriptionProp, err := expandIAMWorkforcePoolWorkforcePoolDescription(d.Get("description"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
+		obj["description"] = descriptionProp
+	}
+	disabledProp, err := expandIAMWorkforcePoolWorkforcePoolDisabled(d.Get("disabled"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("disabled"); !isEmptyValue(reflect.ValueOf(disabledProp)) && (ok || !reflect.DeepEqual(v, disabledProp)) {
+		obj["disabled"] = disabledProp
+	}
+	sessionDurationProp, err := expandIAMWorkforcePoolWorkforcePoolSessionDuration(d.Get("session_duration"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("session_duration"); !isEmptyValue(reflect.ValueOf(sessionDurationProp)) && (ok || !reflect.DeepEqual(v, sessionDurationProp)) {
+		obj["sessionDuration"] = sessionDurationProp
+	}
+
+	return obj, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolParent(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolDisplayName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolDisabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolSessionDuration(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
diff --git a/converters/google/resources/iamworkforcepool_workforce_pool_provider.go b/converters/google/resources/iamworkforcepool_workforce_pool_provider.go
new file mode 100644
index 00000000..6518b644
--- /dev/null
+++ b/converters/google/resources/iamworkforcepool_workforce_pool_provider.go
@@ -0,0 +1,203 @@
+// ----------------------------------------------------------------------------
+//
+//     ***     AUTO GENERATED CODE    ***    Type: MMv1     ***
+//
+// ----------------------------------------------------------------------------
+//
+//     This file is automatically generated by Magic Modules and manual
+//     changes will be clobbered when the file is regenerated.
+//
+//     Please read more about how to change this file in
+//     .github/CONTRIBUTING.md.
+//
+// ----------------------------------------------------------------------------
+
+package google
+
+import (
+	"fmt"
+	"reflect"
+	"regexp"
+	"strings"
+)
+
+const workforcePoolProviderIdRegexp = `^[a-z0-9-]{4,32}$`
+
+func validateWorkforcePoolProviderId(v interface{}, k string) (ws []string, errors []error) {
+	value := v.(string)
+
+	if strings.HasPrefix(value, "gcp-") {
+		errors = append(errors, fmt.Errorf(
+			"%q \"%q\" can not start with \"gcp-\". "+
+				"The prefix `gcp-` is reserved for use by Google, and may not be specified.", k, value))
+	}
+
+	if !regexp.MustCompile(workforcePoolProviderIdRegexp).MatchString(value) {
+		errors = append(errors, fmt.Errorf(
+			"Workforce Pool Provider Id \"%q\" must be 4-32 characters, and may contain the characters [a-z0-9-].", value))
+	}
+
+	return
+}
+
+const IAMWorkforcePoolWorkforcePoolProviderAssetType string = "iam.googleapis.com/WorkforcePoolProvider"
+
+func resourceConverterIAMWorkforcePoolWorkforcePoolProvider() ResourceConverter {
+	return ResourceConverter{
+		AssetType: IAMWorkforcePoolWorkforcePoolProviderAssetType,
+		Convert:   GetIAMWorkforcePoolWorkforcePoolProviderCaiObject,
+	}
+}
+
+func GetIAMWorkforcePoolWorkforcePoolProviderCaiObject(d TerraformResourceData, config *Config) ([]Asset, error) {
+	name, err := assetName(d, config, "//iam.googleapis.com/locations/{{location}}/workforcePools/{{workforce_pool_id}}/providers/{{provider_id}}")
+	if err != nil {
+		return []Asset{}, err
+	}
+	if obj, err := GetIAMWorkforcePoolWorkforcePoolProviderApiObject(d, config); err == nil {
+		return []Asset{{
+			Name: name,
+			Type: IAMWorkforcePoolWorkforcePoolProviderAssetType,
+			Resource: &AssetResource{
+				Version:              "v1",
+				DiscoveryDocumentURI: "https://www.googleapis.com/discovery/v1/apis/iam/v1/rest",
+				DiscoveryName:        "WorkforcePoolProvider",
+				Data:                 obj,
+			},
+		}}, nil
+	} else {
+		return []Asset{}, err
+	}
+}
+
+func GetIAMWorkforcePoolWorkforcePoolProviderApiObject(d TerraformResourceData, config *Config) (map[string]interface{}, error) {
+	obj := make(map[string]interface{})
+	displayNameProp, err := expandIAMWorkforcePoolWorkforcePoolProviderDisplayName(d.Get("display_name"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("display_name"); !isEmptyValue(reflect.ValueOf(displayNameProp)) && (ok || !reflect.DeepEqual(v, displayNameProp)) {
+		obj["displayName"] = displayNameProp
+	}
+	descriptionProp, err := expandIAMWorkforcePoolWorkforcePoolProviderDescription(d.Get("description"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) {
+		obj["description"] = descriptionProp
+	}
+	disabledProp, err := expandIAMWorkforcePoolWorkforcePoolProviderDisabled(d.Get("disabled"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("disabled"); !isEmptyValue(reflect.ValueOf(disabledProp)) && (ok || !reflect.DeepEqual(v, disabledProp)) {
+		obj["disabled"] = disabledProp
+	}
+	attributeMappingProp, err := expandIAMWorkforcePoolWorkforcePoolProviderAttributeMapping(d.Get("attribute_mapping"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("attribute_mapping"); !isEmptyValue(reflect.ValueOf(attributeMappingProp)) && (ok || !reflect.DeepEqual(v, attributeMappingProp)) {
+		obj["attributeMapping"] = attributeMappingProp
+	}
+	attributeConditionProp, err := expandIAMWorkforcePoolWorkforcePoolProviderAttributeCondition(d.Get("attribute_condition"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("attribute_condition"); !isEmptyValue(reflect.ValueOf(attributeConditionProp)) && (ok || !reflect.DeepEqual(v, attributeConditionProp)) {
+		obj["attributeCondition"] = attributeConditionProp
+	}
+	samlProp, err := expandIAMWorkforcePoolWorkforcePoolProviderSaml(d.Get("saml"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("saml"); !isEmptyValue(reflect.ValueOf(samlProp)) && (ok || !reflect.DeepEqual(v, samlProp)) {
+		obj["saml"] = samlProp
+	}
+	oidcProp, err := expandIAMWorkforcePoolWorkforcePoolProviderOidc(d.Get("oidc"), d, config)
+	if err != nil {
+		return nil, err
+	} else if v, ok := d.GetOkExists("oidc"); !isEmptyValue(reflect.ValueOf(oidcProp)) && (ok || !reflect.DeepEqual(v, oidcProp)) {
+		obj["oidc"] = oidcProp
+	}
+
+	return obj, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderDisplayName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderDescription(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderDisabled(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderAttributeMapping(v interface{}, d TerraformResourceData, config *Config) (map[string]string, error) {
+	if v == nil {
+		return map[string]string{}, nil
+	}
+	m := make(map[string]string)
+	for k, val := range v.(map[string]interface{}) {
+		m[k] = val.(string)
+	}
+	return m, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderAttributeCondition(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderSaml(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedIdpMetadataXml, err := expandIAMWorkforcePoolWorkforcePoolProviderSamlIdpMetadataXml(original["idp_metadata_xml"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedIdpMetadataXml); val.IsValid() && !isEmptyValue(val) {
+		transformed["idpMetadataXml"] = transformedIdpMetadataXml
+	}
+
+	return transformed, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderSamlIdpMetadataXml(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderOidc(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	l := v.([]interface{})
+	if len(l) == 0 || l[0] == nil {
+		return nil, nil
+	}
+	raw := l[0]
+	original := raw.(map[string]interface{})
+	transformed := make(map[string]interface{})
+
+	transformedIssuerUri, err := expandIAMWorkforcePoolWorkforcePoolProviderOidcIssuerUri(original["issuer_uri"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedIssuerUri); val.IsValid() && !isEmptyValue(val) {
+		transformed["issuerUri"] = transformedIssuerUri
+	}
+
+	transformedClientId, err := expandIAMWorkforcePoolWorkforcePoolProviderOidcClientId(original["client_id"], d, config)
+	if err != nil {
+		return nil, err
+	} else if val := reflect.ValueOf(transformedClientId); val.IsValid() && !isEmptyValue(val) {
+		transformed["clientId"] = transformedClientId
+	}
+
+	return transformed, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderOidcIssuerUri(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}
+
+func expandIAMWorkforcePoolWorkforcePoolProviderOidcClientId(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
+	return v, nil
+}


Test patch:
diff --git a/converters/google/resources/config_test_utils.go b/converters/google/resources/config_test_utils.go
index a48c0609..4b00d826 100644
--- a/converters/google/resources/config_test_utils.go
+++ b/converters/google/resources/config_test_utils.go
@@ -66,6 +66,7 @@ func configureTestBasePaths(c *Config, url string) {
 	c.GKEHubBasePath = url
 	c.HealthcareBasePath = url
 	c.IAMBetaBasePath = url
+	c.IAMWorkforcePoolBasePath = url
 	c.IapBasePath = url
 	c.IdentityPlatformBasePath = url
 	c.KMSBasePath = url