diff --git a/go.mod b/go.mod index 60b5b6a6f..fe747bcce 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/hashicorp/hcl/v2 v2.19.1 github.com/hashicorp/terraform-json v0.17.1 github.com/hashicorp/terraform-plugin-sdk/v2 v2.29.0 - github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20231114234601-65d8914742aa + github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20231115160831-ccc8cdf9fb18 github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.3 diff --git a/go.sum b/go.sum index b72f5fe00..3e2d6d596 100644 --- a/go.sum +++ b/go.sum @@ -169,8 +169,8 @@ github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwU github.com/hashicorp/terraform-plugin-mux v0.8.0 h1:WCTP66mZ+iIaIrCNJnjPEYnVjawTshnDJu12BcXK1EI= github.com/hashicorp/terraform-plugin-sdk/v2 v2.29.0 h1:wcOKYwPI9IorAJEBLzgclh3xVolO7ZorYd6U1vnok14= github.com/hashicorp/terraform-plugin-sdk/v2 v2.29.0/go.mod h1:qH/34G25Ugdj5FcM95cSoXzUgIbgfhVLXCcEcYaMwq8= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20231114234601-65d8914742aa h1:9XJU4PBbNNIuOOKwZ0km+RLXVcehHFAUAyapWPIk6ZI= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20231114234601-65d8914742aa/go.mod h1:W/Ri6ztEJqzSaQcRxRLTlbjcguRWT5M0nGvNcnqmGps= +github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20231115160831-ccc8cdf9fb18 h1:SzCn271/9Nn482qL6XEIjy1pZcFCdL+9Ur3ACHVwP2o= +github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20231115160831-ccc8cdf9fb18/go.mod h1:W/Ri6ztEJqzSaQcRxRLTlbjcguRWT5M0nGvNcnqmGps= github.com/hashicorp/terraform-registry-address v0.2.2 h1:lPQBg403El8PPicg/qONZJDC6YlgCVbWDtNmmZKtBno= github.com/hashicorp/terraform-registry-address v0.2.2/go.mod h1:LtwNbCihUoUZ3RYriyS2wF/lGPB6gF9ICLRtuDk7hSo= github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= diff --git a/tfplan2cai/converters/google/resources/services/dataform/dataform_repository_iam.go b/tfplan2cai/converters/google/resources/services/dataform/dataform_repository_iam.go new file mode 100644 index 000000000..a5e0df3a1 --- /dev/null +++ b/tfplan2cai/converters/google/resources/services/dataform/dataform_repository_iam.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 dataform + +import ( + "fmt" + + "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +// Provide a separate asset type constant so we don't have to worry about name conflicts between IAM and non-IAM converter files +const DataformRepositoryIAMAssetType string = "dataform.googleapis.com/Repository" + +func ResourceConverterDataformRepositoryIamPolicy() cai.ResourceConverter { + return cai.ResourceConverter{ + AssetType: DataformRepositoryIAMAssetType, + Convert: GetDataformRepositoryIamPolicyCaiObject, + MergeCreateUpdate: MergeDataformRepositoryIamPolicy, + } +} + +func ResourceConverterDataformRepositoryIamBinding() cai.ResourceConverter { + return cai.ResourceConverter{ + AssetType: DataformRepositoryIAMAssetType, + Convert: GetDataformRepositoryIamBindingCaiObject, + FetchFullResource: FetchDataformRepositoryIamPolicy, + MergeCreateUpdate: MergeDataformRepositoryIamBinding, + MergeDelete: MergeDataformRepositoryIamBindingDelete, + } +} + +func ResourceConverterDataformRepositoryIamMember() cai.ResourceConverter { + return cai.ResourceConverter{ + AssetType: DataformRepositoryIAMAssetType, + Convert: GetDataformRepositoryIamMemberCaiObject, + FetchFullResource: FetchDataformRepositoryIamPolicy, + MergeCreateUpdate: MergeDataformRepositoryIamMember, + MergeDelete: MergeDataformRepositoryIamMemberDelete, + } +} + +func GetDataformRepositoryIamPolicyCaiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) ([]cai.Asset, error) { + return newDataformRepositoryIamAsset(d, config, cai.ExpandIamPolicyBindings) +} + +func GetDataformRepositoryIamBindingCaiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) ([]cai.Asset, error) { + return newDataformRepositoryIamAsset(d, config, cai.ExpandIamRoleBindings) +} + +func GetDataformRepositoryIamMemberCaiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) ([]cai.Asset, error) { + return newDataformRepositoryIamAsset(d, config, cai.ExpandIamMemberBindings) +} + +func MergeDataformRepositoryIamPolicy(existing, incoming cai.Asset) cai.Asset { + existing.IAMPolicy = incoming.IAMPolicy + return existing +} + +func MergeDataformRepositoryIamBinding(existing, incoming cai.Asset) cai.Asset { + return cai.MergeIamAssets(existing, incoming, cai.MergeAuthoritativeBindings) +} + +func MergeDataformRepositoryIamBindingDelete(existing, incoming cai.Asset) cai.Asset { + return cai.MergeDeleteIamAssets(existing, incoming, cai.MergeDeleteAuthoritativeBindings) +} + +func MergeDataformRepositoryIamMember(existing, incoming cai.Asset) cai.Asset { + return cai.MergeIamAssets(existing, incoming, cai.MergeAdditiveBindings) +} + +func MergeDataformRepositoryIamMemberDelete(existing, incoming cai.Asset) cai.Asset { + return cai.MergeDeleteIamAssets(existing, incoming, cai.MergeDeleteAdditiveBindings) +} + +func newDataformRepositoryIamAsset( + d tpgresource.TerraformResourceData, + config *transport_tpg.Config, + expandBindings func(d tpgresource.TerraformResourceData) ([]cai.IAMBinding, error), +) ([]cai.Asset, error) { + bindings, err := expandBindings(d) + if err != nil { + return []cai.Asset{}, fmt.Errorf("expanding bindings: %v", err) + } + + name, err := cai.AssetName(d, config, "//dataform.googleapis.com/projects/{{project}}/locations/{{region}}/repositories/{{repository}}") + if err != nil { + return []cai.Asset{}, err + } + + return []cai.Asset{{ + Name: name, + Type: DataformRepositoryIAMAssetType, + IAMPolicy: &cai.IAMPolicy{ + Bindings: bindings, + }, + }}, nil +} + +func FetchDataformRepositoryIamPolicy(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (cai.Asset, error) { + // Check if the identity field returns a value + if _, ok := d.GetOk("region"); !ok { + return cai.Asset{}, cai.ErrEmptyIdentityField + } + if _, ok := d.GetOk("repository"); !ok { + return cai.Asset{}, cai.ErrEmptyIdentityField + } + + return cai.FetchIamPolicy( + DataformRepositoryIamUpdaterProducer, + d, + config, + "//dataform.googleapis.com/projects/{{project}}/locations/{{region}}/repositories/{{repository}}", + DataformRepositoryIAMAssetType, + ) +} diff --git a/tfplan2cai/converters/google/resources/services/dataform/iam_dataform_repository.go b/tfplan2cai/converters/google/resources/services/dataform/iam_dataform_repository.go new file mode 100644 index 000000000..3a6608d6b --- /dev/null +++ b/tfplan2cai/converters/google/resources/services/dataform/iam_dataform_repository.go @@ -0,0 +1,242 @@ +// ---------------------------------------------------------------------------- +// +// *** 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 dataform + +import ( + "fmt" + + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "google.golang.org/api/cloudresourcemanager/v1" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgiamresource" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +var DataformRepositoryIamSchema = map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + }, + "region": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + }, + "repository": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + }, +} + +type DataformRepositoryIamUpdater struct { + project string + region string + repository string + d tpgresource.TerraformResourceData + Config *transport_tpg.Config +} + +func DataformRepositoryIamUpdaterProducer(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (tpgiamresource.ResourceIamUpdater, error) { + values := make(map[string]string) + + project, _ := tpgresource.GetProject(d, config) + if project != "" { + if err := d.Set("project", project); err != nil { + return nil, fmt.Errorf("Error setting project: %s", err) + } + } + values["project"] = project + region, _ := tpgresource.GetRegion(d, config) + if region != "" { + if err := d.Set("region", region); err != nil { + return nil, fmt.Errorf("Error setting region: %s", err) + } + } + values["region"] = region + if v, ok := d.GetOk("repository"); ok { + values["repository"] = v.(string) + } + + // We may have gotten either a long or short name, so attempt to parse long name if possible + m, err := tpgresource.GetImportIdQualifiers([]string{"projects/(?P[^/]+)/locations/(?P[^/]+)/repositories/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config, d.Get("repository").(string)) + if err != nil { + return nil, err + } + + for k, v := range m { + values[k] = v + } + + u := &DataformRepositoryIamUpdater{ + project: values["project"], + region: values["region"], + repository: values["repository"], + d: d, + Config: config, + } + + if err := d.Set("project", u.project); err != nil { + return nil, fmt.Errorf("Error setting project: %s", err) + } + if err := d.Set("region", u.region); err != nil { + return nil, fmt.Errorf("Error setting region: %s", err) + } + if err := d.Set("repository", u.GetResourceId()); err != nil { + return nil, fmt.Errorf("Error setting repository: %s", err) + } + + return u, nil +} + +func DataformRepositoryIdParseFunc(d *schema.ResourceData, config *transport_tpg.Config) error { + values := make(map[string]string) + + project, _ := tpgresource.GetProject(d, config) + if project != "" { + values["project"] = project + } + + region, _ := tpgresource.GetRegion(d, config) + if region != "" { + values["region"] = region + } + + m, err := tpgresource.GetImportIdQualifiers([]string{"projects/(?P[^/]+)/locations/(?P[^/]+)/repositories/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config, d.Id()) + if err != nil { + return err + } + + for k, v := range m { + values[k] = v + } + + u := &DataformRepositoryIamUpdater{ + project: values["project"], + region: values["region"], + repository: values["repository"], + d: d, + Config: config, + } + if err := d.Set("repository", u.GetResourceId()); err != nil { + return fmt.Errorf("Error setting repository: %s", err) + } + d.SetId(u.GetResourceId()) + return nil +} + +func (u *DataformRepositoryIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) { + url, err := u.qualifyRepositoryUrl("getIamPolicy") + if err != nil { + return nil, err + } + + project, err := tpgresource.GetProject(u.d, u.Config) + if err != nil { + return nil, err + } + var obj map[string]interface{} + + userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent) + if err != nil { + return nil, err + } + + policy, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: u.Config, + Method: "GET", + Project: project, + RawURL: url, + UserAgent: userAgent, + Body: obj, + }) + if err != nil { + return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err) + } + + out := &cloudresourcemanager.Policy{} + err = tpgresource.Convert(policy, out) + if err != nil { + return nil, errwrap.Wrapf("Cannot convert a policy to a resource manager policy: {{err}}", err) + } + + return out, nil +} + +func (u *DataformRepositoryIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error { + json, err := tpgresource.ConvertToMap(policy) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + obj["policy"] = json + + url, err := u.qualifyRepositoryUrl("setIamPolicy") + if err != nil { + return err + } + project, err := tpgresource.GetProject(u.d, u.Config) + if err != nil { + return err + } + + userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent) + if err != nil { + return err + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: u.Config, + Method: "POST", + Project: project, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: u.d.Timeout(schema.TimeoutCreate), + }) + if err != nil { + return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{err}}", u.DescribeResource()), err) + } + + return nil +} + +func (u *DataformRepositoryIamUpdater) qualifyRepositoryUrl(methodIdentifier string) (string, error) { + urlTemplate := fmt.Sprintf("{{DataformBasePath}}%s:%s", fmt.Sprintf("projects/%s/locations/%s/repositories/%s", u.project, u.region, u.repository), methodIdentifier) + url, err := tpgresource.ReplaceVars(u.d, u.Config, urlTemplate) + if err != nil { + return "", err + } + return url, nil +} + +func (u *DataformRepositoryIamUpdater) GetResourceId() string { + return fmt.Sprintf("projects/%s/locations/%s/repositories/%s", u.project, u.region, u.repository) +} + +func (u *DataformRepositoryIamUpdater) GetMutexKey() string { + return fmt.Sprintf("iam-dataform-repository-%s", u.GetResourceId()) +} + +func (u *DataformRepositoryIamUpdater) DescribeResource() string { + return fmt.Sprintf("dataform repository %q", u.GetResourceId()) +}