diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index 0b55bbdc268e..0b93ae88bb5f 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -416,6 +416,15 @@ resource "google_project_iam_member" "healthcare_agent_storage_object_admin" { member = "serviceAccount:service-${google_project.proj.number}@gcp-sa-healthcare.iam.gserviceaccount.com" } +# TestAccHealthcarePipelineJob_healthcarePipelineJobMappingReconDestExample +# TestAccHealthcarePipelineJob_healthcarePipelineJobReconciliationExample +# TestAccHealthcarePipelineJob_healthcarePipelineJobWhistleMappingExample +resource "google_project_iam_member" "healthcare_agent_fhir_resource_editor" { + project = google_project.proj.project_id + role = "roles/healthcare.fhirResourceEditor" + member = "serviceAccount:service-${google_project.proj.number}@gcp-sa-healthcare.iam.gserviceaccount.com" +} + # TestAccVertexAIEndpoint_vertexAiEndpointNetwork # TestAccVertexAIFeaturestoreEntitytype_vertexAiFeaturestoreEntitytypeExample # TestAccVertexAIFeaturestoreEntitytype_vertexAiFeaturestoreEntitytypeWithBetaFieldsExample diff --git a/.ci/magician/cmd/templates/vcr/non_exercised_tests.tmpl b/.ci/magician/cmd/templates/vcr/non_exercised_tests.tmpl index b3a6a21c02c5..9efae64310a5 100644 --- a/.ci/magician/cmd/templates/vcr/non_exercised_tests.tmpl +++ b/.ci/magician/cmd/templates/vcr/non_exercised_tests.tmpl @@ -1,13 +1,13 @@ -{{- if or (gt (len .NotRunBetaTests) 0) (gt (len .NotRunGATests) 0) -}} +{{- if or (gt (len .NotRunBetaTests) 0) (gt (len .NotRunGATests) 0)}} #### Non-exercised tests {{if gt (len .NotRunBetaTests) 0 -}} -Tests were added that are skipped in VCR: +{{color "red" "Tests were added that are skipped in VCR:"}} {{range .NotRunBetaTests}}{{. | printf "- %s\n"}}{{end}} {{end}} {{if gt (len .NotRunGATests) 0 -}} -Tests were added that are GA-only additions and require manual runs: +{{color "red" "Tests were added that are GA-only additions and require manual runs:"}} {{range .NotRunGATests}}{{. | printf "- %s\n"}}{{end}} {{end}} {{end}} diff --git a/.ci/magician/cmd/test_terraform_vcr_test.go b/.ci/magician/cmd/test_terraform_vcr_test.go index 8c7c931c3333..2110da3bbb72 100644 --- a/.ci/magician/cmd/test_terraform_vcr_test.go +++ b/.ci/magician/cmd/test_terraform_vcr_test.go @@ -356,7 +356,7 @@ func TestNonExercisedTestsComment(t *testing.T) { []string{ "#### Non-exercised tests", "", - "Tests were added that are skipped in VCR:", + color("red", "Tests were added that are skipped in VCR:"), "- beta-1", "- beta-2", }, @@ -374,7 +374,7 @@ func TestNonExercisedTestsComment(t *testing.T) { "", "", "", - "Tests were added that are GA-only additions and require manual runs:", + color("red", "Tests were added that are GA-only additions and require manual runs:"), "- ga-1", "- ga-2", }, @@ -391,13 +391,13 @@ func TestNonExercisedTestsComment(t *testing.T) { []string{ "#### Non-exercised tests", "", - "Tests were added that are skipped in VCR:", + color("red", "Tests were added that are skipped in VCR:"), "- beta-1", "- beta-2", "", "", "", - "Tests were added that are GA-only additions and require manual runs:", + color("red", "Tests were added that are GA-only additions and require manual runs:"), "- ga-1", "- ga-2", }, diff --git a/docs/content/best-practices/_index.md b/docs/content/best-practices/_index.md index 86683b8c510a..19c18f2d9d98 100644 --- a/docs/content/best-practices/_index.md +++ b/docs/content/best-practices/_index.md @@ -1,195 +1,4 @@ --- title: "Best practices" weight: 25 -aliases: - - /docs/best-practices --- - -# Best practices - -The following is a list of best practices that contributions are expected to follow in order to ensure a consistent UX for the Terraform provider for Google Cloud internally and also compared to other Terraform providers. - -## ForceNew - -[`ForceNew`](https://developer.hashicorp.com/terraform/intro#how-does-terraform-work) in a Terraform resource schema attribute that indicates that a field is immutable – that is, that a change to the field requires the resource to be destroyed and recreated. - -This is necessary and required for cases where a field can't be updated in-place, so that [Terraform's core workflow](https://developer.hashicorp.com/terraform/intro#how-does-terraform-work) of aligning real infrastructure with configuration can be achieved. If a field or resource can never be updated in-place and is not marked with `ForceNew`, that is considered a bug in the provider. - -Some fields or resources may be possible to update in place, but only under specific conditions. In these cases, you can treat the field as updatable - that is, do not mark it as ForceNew; instead, implement standard update functionality. Then, call `diff.ForceNew` inside a [`CustomizeDiff`](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/customizing-differences) if the appropriate conditions to allow update in place are not met. Any `CustomizeDiff` function like this must be thoroughly unit tested. Making a field conditionally updatable like this is considered a good and useful enhancement in cases where recreation is costly and conditional updates do not introduce undue complexity. - -In complex cases, it is better to mark the field `ForceNew` to ensure that users can apply their configurations successfully. - -### Mitigating data loss risk via deletion_protection {#deletion_protection} - -Some resources, such as databases, have a significant risk of unrecoverable data loss if the resource is accidentally deleted due to a change to a ForceNew field. For these resources, the best practice is to add a `deletion_protection` field that defaults to `true`, which prevents the resource from being deleted if enabled. Although it is a small breaking change, for users, the benefits of `deletion_protection` defaulting to `true` outweigh the cost. - -APIs also sometimes add `deletion_protection` fields, which will generally default to `false` for backwards-compatibility reasons. Any `deletion_protection` API field added to an existing Terraform resource must match the API default initially. The default may be set to `true` in the next major release. For new Terraform resources, any `deletion_protection` field should default to `true` in Terraform regardless of the API default. When creating the corresponding Terraform field, the name -should match the API field name (i.e. it need not literally be named `deletion_protection` if the API uses something different) and should be the same field type (example: if the API field is an enum, so should the Terraform field). - -A resource can have up to two `deletion_protection` fields (with different names): one that represents a field in the API, and one that is only in Terraform. This could happen because the API added its field after `deletion_protection` already existed in Terraform; it could also happen because a separate field was added in Terraform to make sure that `deletion_protection` is enabled by default. In either case, they should be reconciled into a single field (that defaults to enabled and whose name matches the API field) in the next major release. - -Resources that do not have a significant risk of unrecoverable data loss or similar critical concern will not be given `deletion_protection` fields. - -See [Client-side fields]({{< ref "/develop/client-side-fields" >}}) for information about adding `deletion_protection` fields. - -{{< hint info >}} -**Note:** The previous best practice was a field called `force_delete` that defaulted to `false`. This is still present on some resources for backwards-compatibility reasons, but `deletion_protection` is preferred going forward. -{{< /hint >}} - -## Deletion policy {#deletion_policy} - -Some resources need to let users control the actions taken add deletion time. For these resources, the best practice is to add a `deletion_policy` enum field that defaults to an empty string and allows special values that control the deletion behavior. - -One common example is `ABANDON`, which is useful if the resource is safe to delete from Terraform but could cause problems if deleted from the API - for example, `google_bigtable_gc_policy` deletion can fail in replicated instances. `ABANDON` indicates that attempts to delete the resource should remove it from state without actually deleting it. - -See [Client-side fields]({{< ref "/develop/client-side-fields" >}}) for information about adding `deletion_policy` fields. - -## Add labels and annotations support - -The new labels model and the new annotations model are introduced in [Terraform provider for Google Cloud 5.0.0](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_5_upgrade#provider). - -There are now three label-related fields with the new labels model: -* The `labels` field is now non-authoritative and only manages the label keys defined in your configuration for the resource. -* The `terraform_labels` cannot be specified directly by the user. It merges the labels defined in the resource's configuration and the default labels configured in the provider block. If the same label key exists on both the resource level and provider level, the value on the resource will override the provider-level default. -* The output-only `effective_labels` will list all the labels present on the resource in GCP, including the labels configured through Terraform, the system, and other clients. - -There are now two annotation-related fields with the new annotations model: -* The `annotations` field is now non-authoritative and only manages the annotation keys defined in your configuration for the resource. -* The output-only `effective_annotations` will list all the annotations present on the resource in GCP, including the annotations configured through Terraform, the system, and other clients. - -This document describes how to add `labels` and `annotations` field to resources to support the new models. - -### Labels support -When adding a new `labels` field, please make the changes below to support the new labels model. Otherwise, it has to wait for the next major release to make the changes. - -#### MMv1 resources - -1. Use the type `KeyValueLabels` for the standard resource `labels` field. The standard resource `labels` field could be the top level `labels` field or the nested `labels` field inside the top level `metadata` field. Don't add `default_from_api: true` to this field or don't use this type for other `labels` fields in the resource. `KeyValueLabels` will add all of changes required for the new model automatically. - -```yaml - - name: 'labels' - type: KeyValueLabels - description: | - The labels associated with this dataset. You can use these to - organize and group your datasets. -``` -2. In the handwritten acceptance tests, add `labels` and `terraform_labels` to `ImportStateVerifyIgnore` if `labels` field is in the configuration. - -```go -ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, -``` -3. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceLabels(d)` to make `labels` and `terraform_labels` have all of the labels on the resource. - -```go -err = resourceArtifactRegistryRepositoryRead(d, meta) -if err != nil { - return err -} - -if err := tpgresource.SetDataSourceLabels(d); err != nil { - return err -} -``` - -#### Handwritten resources - -1. Add `tpgresource.SetLabelsDiff` to `CustomizeDiff` of the resource. -```go -CustomizeDiff: customdiff.All( - tpgresource.SetLabelsDiff, -), -``` -2. Add `labels` field and add more attributes (such as `ForceNew: true,`, `Set: schema.HashString,`) to this field if necessary. -```go -"labels": { - Type: schema.TypeMap, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: `A set of key/value label pairs to assign to the project. - - **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. - Please refer to the field 'effective_labels' for all of the labels present on the resource.`, -}, -``` -3. Add output only field `terraform_labels` and add more attributes (such as `Set: schema.HashString,`) to this field if necessary. Don't add `ForceNew:true,` to this field. -```go -"terraform_labels": { - Type: schema.TypeMap, - Computed: true, - Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, - Elem: &schema.Schema{Type: schema.TypeString}, -}, -``` -4. Add output only field `effective_labels` and add more attributes (such as `ForceNew: true,`, `Set: schema.HashString,`) to this field if necessary. -```go -"effective_labels": { - Type: schema.TypeMap, - Computed: true, - Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, - Elem: &schema.Schema{Type: schema.TypeString}, -}, -``` -5. In the create method, use the value of `effective_labels` in API request. -6. In the update method, use the value of `effective_labels` in API request. -7. In the read mehtod, set `labels`, `terraform_labels` and `effective_labels` to state. -```go -if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { - return fmt.Errorf("Error setting labels: %s", err) -} -if err := tpgresource.SetLabels(res.Labels, d, "terraform_labels"); err != nil { - return fmt.Errorf("Error setting terraform_labels: %s", err) -} -if err := d.Set("effective_labels", res.Labels); err != nil { - return fmt.Errorf("Error setting effective_labels: %s", err) -} -``` -8. In the handwritten acceptance tests, add `labels` and `terraform_labels` to `ImportStateVerifyIgnore`. -9. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceLabels(d)` to make `labels` and `terraform_labels` have all of the labels on the resource. -10. Add the documentation for these label-related fields. - -### Annotations support -When adding a new `annotations` field, please make the changes below below to support the new annotations model. Otherwise, it has to wait for the next major release to make the breaking changes. - -#### MMv1 resources - -1. Use the type `KeyValueAnnotations` for the standard resource `annotations` field. The standard resource `annotations` field could be the top level `annotations` field or the nested `annotations` field inside the top level `metadata` field. Don't add `default_from_api: true` to this field or don't use this type for other `annotations` fields in the resource. `KeyValueAnnotations` will add all of changes required for the new model automatically. - -```yaml -- name: 'annotations' - type: KeyValueAnnotations - description: | - Client-specified annotations. This is distinct from labels. -``` -2. In the handwritten acceptance tests, add `annotations` to `ImportStateVerifyIgnore` if `annotations` field is in the configuration. - -```go -ImportStateVerifyIgnore: []string{"annotations"}, -``` -3. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceAnnotations(d)` to make `annotations` have all of the annotations on the resource. - -```go -err = resourceSecretManagerSecretRead(d, meta) -if err != nil { - return err -} - -if err := tpgresource.SetDataSourceLabels(d); err != nil { - return err -} - -if err := tpgresource.SetDataSourceAnnotations(d); err != nil { - return err -} -``` - -#### Handwritten resources - -1. Add `tpgresource.SetAnnotationsDiff` to `CustomizeDiff` of the resource. -2. Add `annotations` field and add more attributes (such as `ForceNew: true,`, `Set: schema.HashString,`) to this field if necessary. -3. Add output only field `effective_annotations` and add more attributes (such as `ForceNew: true,`, `Set: schema.HashString,`) to this field if necessary. -4. In the create method, use the value of `effective_annotations` in API request. -5. In the update method, use the value of `effective_annotations` in API request. -6. In the read mehtod, set `annotations`, and `effective_annotations` to state. -7. In the handwritten acceptance tests, add `annotations` to `ImportStateVerifyIgnore`. -8. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceAnnotations(d)` to make `annotations` have all of the labels on the resource. -9. Add the documentation for these annotation-related fields. diff --git a/docs/content/best-practices/deletion-behaviors.md b/docs/content/best-practices/deletion-behaviors.md new file mode 100644 index 000000000000..f88ae7da51bb --- /dev/null +++ b/docs/content/best-practices/deletion-behaviors.md @@ -0,0 +1,35 @@ +--- +title: "Deletion behaviors" +weight: 20 +--- + +# Deletion behaviors + +{{< hint info >}} +**Note:** This page covers best practices guidance for the Terraform provider for Google Cloud, which is used to ensure a consistent UX for Terraform users across providers or GCP users across the Google provider. Generally, this guidance should be followed and exceptions should be clearly demarcated / discussed. +{{< /hint >}} + +## Mitigating data loss risk via deletion_protection {#deletion_protection} + +Some resources, such as databases, have a significant risk of unrecoverable data loss if the resource is accidentally deleted due to a change to a ForceNew field. For these resources, the best practice is to add a `deletion_protection` field that defaults to `true`, which prevents the resource from being deleted if enabled. Although it is a small breaking change, for users, the benefits of `deletion_protection` defaulting to `true` outweigh the cost. + +APIs also sometimes add `deletion_protection` fields, which will generally default to `false` for backwards-compatibility reasons. Any `deletion_protection` API field added to an existing Terraform resource must match the API default initially. The default may be set to `true` in the next major release. For new Terraform resources, any `deletion_protection` field should default to `true` in Terraform regardless of the API default. When creating the corresponding Terraform field, the name +should match the API field name (i.e. it need not literally be named `deletion_protection` if the API uses something different) and should be the same field type (example: if the API field is an enum, so should the Terraform field). + +A resource can have up to two `deletion_protection` fields (with different names): one that represents a field in the API, and one that is only in Terraform. This could happen because the API added its field after `deletion_protection` already existed in Terraform; it could also happen because a separate field was added in Terraform to make sure that `deletion_protection` is enabled by default. In either case, they should be reconciled into a single field (that defaults to enabled and whose name matches the API field) in the next major release. + +Resources that do not have a significant risk of unrecoverable data loss or similar critical concern will not be given `deletion_protection` fields. + +See [Client-side fields]({{< ref "/develop/client-side-fields" >}}) for information about adding `deletion_protection` fields. + +{{< hint info >}} +**Note:** The previous best practice was a field called `force_delete` that defaulted to `false`. This is still present on some resources for backwards-compatibility reasons, but `deletion_protection` is preferred going forward. +{{< /hint >}} + +## Deletion policy {#deletion_policy} + +Some resources need to let users control the actions taken add deletion time. For these resources, the best practice is to add a `deletion_policy` enum field that defaults to an empty string and allows special values that control the deletion behavior. + +One common example is `ABANDON`, which is useful if the resource is safe to delete from Terraform but could cause problems if deleted from the API - for example, `google_bigtable_gc_policy` deletion can fail in replicated instances. `ABANDON` indicates that attempts to delete the resource should remove it from state without actually deleting it. + +See [Client-side fields]({{< ref "/develop/client-side-fields" >}}) for information about adding `deletion_policy` fields. diff --git a/docs/content/best-practices/immutable-fields.md b/docs/content/best-practices/immutable-fields.md new file mode 100644 index 000000000000..294e124cacbe --- /dev/null +++ b/docs/content/best-practices/immutable-fields.md @@ -0,0 +1,25 @@ +--- +title: "Immutable fields" +weight: 10 +aliases: + - /docs/best-practices + - /best-practices +--- + +# Immutable fields + +{{< hint info >}} +**Note:** This page covers best practices guidance for the Terraform provider for Google Cloud, which is used to ensure a consistent UX for Terraform users across providers or GCP users across the Google provider. Generally, this guidance should be followed and exceptions should be clearly demarcated / discussed. +{{< /hint >}} + +[`ForceNew`](https://developer.hashicorp.com/terraform/intro#how-does-terraform-work) in a Terraform resource schema attribute that indicates that a field is immutable – that is, that a change to the field requires the resource to be destroyed and recreated. + +This is necessary and required for cases where a field can't be updated in-place, so that [Terraform's core workflow](https://developer.hashicorp.com/terraform/intro#how-does-terraform-work) of aligning real infrastructure with configuration can be achieved. If a field or resource can never be updated in-place and is not marked with `ForceNew`, that is considered a bug in the provider. + +Some fields or resources may be possible to update in place, but only under specific conditions. In these cases, you can treat the field as updatable - that is, do not mark it as ForceNew; instead, implement standard update functionality. Then, call `diff.ForceNew` inside a [`CustomizeDiff`](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/customizing-differences) if the appropriate conditions to allow update in place are not met. Any `CustomizeDiff` function like this must be thoroughly unit tested. Making a field conditionally updatable like this is considered a good and useful enhancement in cases where recreation is costly and conditional updates do not introduce undue complexity. + +In complex cases, it is better to mark the field `ForceNew` to ensure that users can apply their configurations successfully. + +## Safeguarding against deletion + +See [Deletion behaviors]({{< ref "/best-practices/deletion-behaviors" >}}) for some mitigations against accidental deletion or other means to safeguard against deletion. diff --git a/docs/content/best-practices/labels-and-annotations.md b/docs/content/best-practices/labels-and-annotations.md new file mode 100644 index 000000000000..16382bde1811 --- /dev/null +++ b/docs/content/best-practices/labels-and-annotations.md @@ -0,0 +1,158 @@ +--- +title: "Labels and annotations" +weight: 30 +--- + +# Add labels and annotations support + +{{< hint info >}} +**Note:** This page covers best practices guidance for the Terraform provider for Google Cloud, which is used to ensure a consistent UX for Terraform users across providers or GCP users across the Google provider. Generally, this guidance should be followed and exceptions should be clearly demarcated / discussed. +{{< /hint >}} + +The new labels model and the new annotations model are introduced in [Terraform provider for Google Cloud 5.0.0](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_5_upgrade#provider). + +There are now three label-related fields with the new labels model: +* The `labels` field is now non-authoritative and only manages the label keys defined in your configuration for the resource. +* The `terraform_labels` cannot be specified directly by the user. It merges the labels defined in the resource's configuration and the default labels configured in the provider block. If the same label key exists on both the resource level and provider level, the value on the resource will override the provider-level default. +* The output-only `effective_labels` will list all the labels present on the resource in GCP, including the labels configured through Terraform, the system, and other clients. + +There are now two annotation-related fields with the new annotations model: +* The `annotations` field is now non-authoritative and only manages the annotation keys defined in your configuration for the resource. +* The output-only `effective_annotations` will list all the annotations present on the resource in GCP, including the annotations configured through Terraform, the system, and other clients. + +This document describes how to add `labels` and `annotations` field to resources to support the new models. + +## Labels support +When adding a new `labels` field, please make the changes below to support the new labels model. Otherwise, it has to wait for the next major release to make the changes. + +### MMv1 resources + +1. Use the type `KeyValueLabels` for the standard resource `labels` field. The standard resource `labels` field could be the top level `labels` field or the nested `labels` field inside the top level `metadata` field. Don't add `default_from_api: true` to this field or don't use this type for other `labels` fields in the resource. `KeyValueLabels` will add all of changes required for the new model automatically. + +```yaml + - name: 'labels' + type: KeyValueLabels + description: | + The labels associated with this dataset. You can use these to + organize and group your datasets. +``` +2. In the handwritten acceptance tests, add `labels` and `terraform_labels` to `ImportStateVerifyIgnore` if `labels` field is in the configuration. + +```go +ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, +``` +3. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceLabels(d)` to make `labels` and `terraform_labels` have all of the labels on the resource. + +```go +err = resourceArtifactRegistryRepositoryRead(d, meta) +if err != nil { + return err +} + +if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err +} +``` + +### Handwritten resources + +1. Add `tpgresource.SetLabelsDiff` to `CustomizeDiff` of the resource. +```go +CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, +), +``` +2. Add `labels` field and add more attributes (such as `ForceNew: true,`, `Set: schema.HashString,`) to this field if necessary. +```go +"labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A set of key/value label pairs to assign to the project. + + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. + Please refer to the field 'effective_labels' for all of the labels present on the resource.`, +}, +``` +3. Add output only field `terraform_labels` and add more attributes (such as `Set: schema.HashString,`) to this field if necessary. Don't add `ForceNew:true,` to this field. +```go +"terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, +}, +``` +4. Add output only field `effective_labels` and add more attributes (such as `ForceNew: true,`, `Set: schema.HashString,`) to this field if necessary. +```go +"effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, +}, +``` +5. In the create method, use the value of `effective_labels` in API request. +6. In the update method, use the value of `effective_labels` in API request. +7. In the read mehtod, set `labels`, `terraform_labels` and `effective_labels` to state. +```go +if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { + return fmt.Errorf("Error setting labels: %s", err) +} +if err := tpgresource.SetLabels(res.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) +} +if err := d.Set("effective_labels", res.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) +} +``` +8. In the handwritten acceptance tests, add `labels` and `terraform_labels` to `ImportStateVerifyIgnore`. +9. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceLabels(d)` to make `labels` and `terraform_labels` have all of the labels on the resource. +10. Add the documentation for these label-related fields. + +## Annotations support +When adding a new `annotations` field, please make the changes below below to support the new annotations model. Otherwise, it has to wait for the next major release to make the breaking changes. + +### MMv1 resources + +1. Use the type `KeyValueAnnotations` for the standard resource `annotations` field. The standard resource `annotations` field could be the top level `annotations` field or the nested `annotations` field inside the top level `metadata` field. Don't add `default_from_api: true` to this field or don't use this type for other `annotations` fields in the resource. `KeyValueAnnotations` will add all of changes required for the new model automatically. + +```yaml +- name: 'annotations' + type: KeyValueAnnotations + description: | + Client-specified annotations. This is distinct from labels. +``` +2. In the handwritten acceptance tests, add `annotations` to `ImportStateVerifyIgnore` if `annotations` field is in the configuration. + +```go +ImportStateVerifyIgnore: []string{"annotations"}, +``` +3. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceAnnotations(d)` to make `annotations` have all of the annotations on the resource. + +```go +err = resourceSecretManagerSecretRead(d, meta) +if err != nil { + return err +} + +if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err +} + +if err := tpgresource.SetDataSourceAnnotations(d); err != nil { + return err +} +``` + +### Handwritten resources + +1. Add `tpgresource.SetAnnotationsDiff` to `CustomizeDiff` of the resource. +2. Add `annotations` field and add more attributes (such as `ForceNew: true,`, `Set: schema.HashString,`) to this field if necessary. +3. Add output only field `effective_annotations` and add more attributes (such as `ForceNew: true,`, `Set: schema.HashString,`) to this field if necessary. +4. In the create method, use the value of `effective_annotations` in API request. +5. In the update method, use the value of `effective_annotations` in API request. +6. In the read mehtod, set `annotations`, and `effective_annotations` to state. +7. In the handwritten acceptance tests, add `annotations` to `ImportStateVerifyIgnore`. +8. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceAnnotations(d)` to make `annotations` have all of the labels on the resource. +9. Add the documentation for these annotation-related fields. diff --git a/docs/content/contribute/create-pr.md b/docs/content/contribute/create-pr.md index 3b2617016c25..4c8c24b95138 100644 --- a/docs/content/contribute/create-pr.md +++ b/docs/content/contribute/create-pr.md @@ -17,8 +17,9 @@ weight: 10 ## Code review 1. A reviewer will automatically be assigned to your PR. -1. Creating a new pull request or pushing a new commit automatically triggers our CI pipelines and workflows. After CI starts, downstream diff generation takes about 10 minutes; VCR tests can take up to 2 hours. If you are a community contributor, some tests will only run after approval from a reviewer. +1. Creating a new pull request or pushing a new commit automatically triggers our CI pipelines and workflows. After CI starts, downstream diff generation takes about 10 minutes; [VCR tests]({{< ref "/develop/test/test.md" >}}) can take up to 2 hours. If you are a community contributor, some tests will only run after approval from a reviewer. - While convenient, relying on CI to test iterative changes to PRs often adds extreme latency to reviews if there are errors in test configurations or at runtime. We **strongly** recommend you [test your changes locally before pushing]({{< ref "/develop/test/run-tests" >}}) even after the initial change. + - VCR tests will first attempt to play back recorded HTTP requests (REPLAYING mode). If any tests fail, they will run in RECORDING mode to generate a new cassette; then, the same tests will run again in REPLAYING mode to detect any nondeterministic behavior in the test (which can cause flaky tests.) 1. If your assigned reviewer does not respond to changes on a pull request within two US business days, ping them on the pull request. {{< hint info >}} diff --git a/docs/content/develop/permadiff.md b/docs/content/develop/permadiff.md index ca1b94c48b04..2b4bb3b1d8ad 100644 --- a/docs/content/develop/permadiff.md +++ b/docs/content/develop/permadiff.md @@ -234,15 +234,29 @@ Add a [custom flattener]({{< ref "/develop/custom-code#custom_flatten" >}}) for ```go func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - configValue := d.Get("path.0.to.0.parent_field.0.nested_field").([]string) + rawConfigValue := d.Get("path.0.to.0.parent_field.0.nested_field") - sorted, err := tpgresource.SortStringsByConfigOrder(configValue, v.([]string)) + // Convert config value to []string + configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue) + if err != nil { + log.Printf("[ERROR] Failed to convert config value: %s", err) + return v + } + + // Convert v to []string + apiStringValue, err := tpgresource.InterfaceSliceToStringSlice(v) + if err != nil { + log.Printf("[ERROR] Failed to convert API value: %s", err) + return v + } + + sortedStrings, err := tpgresource.SortStringsByConfigOrder(configValue, apiStringValue) if err != nil { log.Printf("[ERROR] Could not sort API response value: %s", err) return v } - return sorted.(interface{}) + return sortedStrings } ``` {{< /tab >}} @@ -251,15 +265,29 @@ Define resource-specific functions in your service package, for example at the t ```go func flattenResourceNameFieldName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - configValue := d.Get("path.0.to.0.parent_field.0.nested_field").([]string) + rawConfigValue := d.Get("path.0.to.0.parent_field.0.nested_field") + + // Convert config value to []string + configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue) + if err != nil { + log.Printf("[ERROR] Failed to convert config value: %s", err) + return v + } + + // Convert v to []string + apiStringValue, err := tpgresource.InterfaceSliceToStringSlice(v) + if err != nil { + log.Printf("[ERROR] Failed to convert API value: %s", err) + return v + } - sorted, err := tpgresource.SortStringsByConfigOrder(configValue, v.([]string)) + sortedStrings, err := tpgresource.SortStringsByConfigOrder(configValue, apiStringValue) if err != nil { log.Printf("[ERROR] Could not sort API response value: %s", err) return v } - return sorted.(interface{}) + return sortedStrings } ``` {{< /tab >}} diff --git a/docs/content/develop/test/test.md b/docs/content/develop/test/test.md index 38754fdff36a..69f97e9dd679 100644 --- a/docs/content/develop/test/test.md +++ b/docs/content/develop/test/test.md @@ -15,6 +15,13 @@ aliases: This page describes how to add tests to a new resource in the `google` or `google-beta` Terraform provider. +The providers have two basic types of tests: + +- Unit tests: test specific functions thoroughly. Unit tests do not interact with GCP APIs. +- Acceptance tests (aka VCR tests, or create and update tests): test that resources interact as expected with the APIs. Acceptance tests interact with GCP APIs, but should only test the provider's behavior in constructing the API requests and parsing the responses. + +Acceptance tests are also called "VCR tests" because they use [`go-vcr`](https://github.com/dnaeon/go-vcr) to record and play back HTTP requests. This allows tests to run more quickly on PRs because the resources don't actually need to be created, updated, or destroyed by the live API. + For more information about testing, see the [official Terraform documentation](https://developer.hashicorp.com/terraform/plugin/sdkv2/testing/acceptance-tests). ## Before you begin diff --git a/mmv1/api/product.go b/mmv1/api/product.go index 7539fa5eda9f..37e9dc932178 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -34,12 +34,12 @@ type Product struct { // original value of :name before the provider override happens // same as :name if not overridden in provider - ApiName string `yaml:"api_name"` + ApiName string `yaml:"api_name,omitempty"` // Display Name: The full name of the GCP product; eg "Cloud Bigtable" - DisplayName string `yaml:"display_name"` + DisplayName string `yaml:"display_name,omitempty"` - Objects []*Resource + Objects []*Resource `yaml:"objects,omitempty"` // The list of permission scopes available for the service // For example: `https://www.googleapis.com/auth/compute` @@ -50,19 +50,19 @@ type Product struct { // The base URL for the service API endpoint // For example: `https://www.googleapis.com/compute/v1/` - BaseUrl string `yaml:"base_url"` + BaseUrl string `yaml:"base_url,omitempty"` // A function reference designed for the rare case where you // need to use retries in operation calls. Used for the service api // as it enables itself (self referential) and can result in occasional // failures on operation_get. see github.com/hashicorp/terraform-provider-google/issues/9489 - OperationRetry string `yaml:"operation_retry"` + OperationRetry string `yaml:"operation_retry,omitempty"` - Async *Async + Async *Async `yaml:"async,omitempty"` - LegacyName string `yaml:"legacy_name"` + LegacyName string `yaml:"legacy_name,omitempty"` - ClientName string `yaml:"client_name"` + ClientName string `yaml:"client_name,omitempty"` } func (p *Product) UnmarshalYAML(unmarshal func(any) error) error { diff --git a/mmv1/api/product/version.go b/mmv1/api/product/version.go index 16ef54ae51b0..d94c0a41e8e5 100644 --- a/mmv1/api/product/version.go +++ b/mmv1/api/product/version.go @@ -26,7 +26,7 @@ var ORDER = []string{"ga", "beta", "alpha", "private"} // a superset of beta, and beta a superset of GA. Each version will have a // different version url. type Version struct { - CaiBaseUrl string `yaml:"cai_base_url"` + CaiBaseUrl string `yaml:"cai_base_url,omitempty"` BaseUrl string `yaml:"base_url"` Name string } diff --git a/mmv1/go.mod b/mmv1/go.mod index 79316b0a09ea..839dd55d3c5d 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -11,4 +11,15 @@ require github.com/golang/glog v1.2.0 require github.com/otiai10/copy v1.9.0 -require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect +require ( + github.com/getkin/kin-openapi v0.127.0 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect + github.com/invopop/yaml v0.3.1 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect + github.com/perimeterx/marshmallow v1.1.5 // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/mmv1/go.sum b/mmv1/go.sum index 14b659976106..8d1e3cdeb383 100644 --- a/mmv1/go.sum +++ b/mmv1/go.sum @@ -1,13 +1,29 @@ +github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY= +github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= +github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= +github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4= github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI= +github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= +github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= @@ -16,3 +32,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/mmv1/main.go b/mmv1/main.go index d7af7dec68c0..d71410cbc820 100644 --- a/mmv1/main.go +++ b/mmv1/main.go @@ -17,6 +17,7 @@ import ( "golang.org/x/exp/slices" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/openapi_generate" "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider" ) @@ -42,6 +43,8 @@ var doNotGenerateDocs = flag.Bool("no-docs", false, "do not generate docs") var forceProvider = flag.String("provider", "", "optional provider name. If specified, a non-default provider will be used.") +var openapiGenerate = flag.Bool("openapi-generate", false, "Generate MMv1 YAML from openapi directory (Experimental)") + // Example usage: --yaml var yamlMode = flag.Bool("yaml", false, "copy text over from ruby yaml to go yaml") @@ -56,10 +59,18 @@ var yamlTempMode = flag.Bool("yaml-temp", false, "copy text over from ruby yaml var handwrittenTempFiles = flag.String("handwritten-temp", "", "copy specific handwritten files over from .erb to go .tmpl.temp comma separated") var templateTempFiles = flag.String("template-temp", "", "copy specific templates over from .erb to go .tmpl.temp comma separated") +var showImportDiffs = flag.Bool("show-import-diffs", false, "write go import diffs to stdout") + func main() { flag.Parse() + if *openapiGenerate { + parser := openapi_generate.NewOpenapiParser("openapi_generate/openapi", "products") + parser.Run() + return + } + if *yamlMode || *yamlTempMode { CopyAllDescriptions(*yamlTempMode) } @@ -193,6 +204,8 @@ func main() { if generateCode { providerToGenerate.CompileCommonFiles(*outputPath, productsForVersion, "") } + + provider.FixImports(*outputPath, *showImportDiffs) } func GenerateProduct(productChannel chan string, providerToGenerate provider.Provider, productsForVersionChannel chan *api.Product, startTime time.Time, productsToGenerate []string, resourceToGenerate, overrideDirectory string, generateCode, generateDocs bool) { diff --git a/mmv1/openapi_generate/parser.go b/mmv1/openapi_generate/parser.go new file mode 100644 index 000000000000..3dbaa1edf634 --- /dev/null +++ b/mmv1/openapi_generate/parser.go @@ -0,0 +1,324 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generator for a library converting terraform state to gcp objects. + +package openapi_generate + +import ( + "bytes" + "context" + "fmt" + "os" + "path" + "path/filepath" + "strings" + + "log" + + "text/template" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" + "github.com/getkin/kin-openapi/openapi3" + "github.com/golang/glog" + "gopkg.in/yaml.v2" +) + +type Parser struct { + Folder string + Output string +} + +func NewOpenapiParser(folder, output string) Parser { + + wd, err := os.Getwd() + if err != nil { + log.Fatalf(err.Error()) + } + + parser := Parser{ + Folder: path.Join(wd, folder), + Output: path.Join(wd, output), + } + + return parser +} + +func (parser Parser) Run() { + + f, err := os.Open(parser.Folder) + if err != nil { + log.Fatalf(err.Error()) + return + } + defer f.Close() + files, err := f.Readdirnames(0) + if err != nil { + log.Fatalf(err.Error()) + } + + // check if folder is empty + if len(files) == 0 { + log.Fatalf("No OpenAPI files found in %s", parser.Folder) + } + + for _, file := range files { + parser.WriteYaml(path.Join(parser.Folder, file)) + } +} + +func (parser Parser) WriteYaml(filePath string) { + log.Printf("Reading from file path %s", filePath) + + ctx := context.Background() + loader := &openapi3.Loader{Context: ctx, IsExternalRefsAllowed: true} + doc, _ := loader.LoadFromFile(filePath) + _ = doc.Validate(ctx) + + resourcePaths := findResources(doc) + productPath := buildProduct(filePath, parser.Output, doc) + + log.Printf("Generated product %+v/product.yaml", productPath) + for _, pathArray := range resourcePaths { + resource := buildResource(filePath, pathArray[0], pathArray[1], doc) + + // template method + resourceOutPathTemplate := filepath.Join(productPath, fmt.Sprintf("%s_template.yaml", resource.Name)) + templatePath := "openapi_generate/resource_yaml.tmpl" + WriteGoTemplate(templatePath, resourceOutPathTemplate, resource) + log.Printf("Generated resource %s", resourceOutPathTemplate) + + // marshal method + resourceOutPathMarshal := filepath.Join(productPath, fmt.Sprintf("%s_marshal.yaml", resource.Name)) + bytes, err := yaml.Marshal(resource) + if err != nil { + log.Fatalf("error marshalling yaml %v: %v", resourceOutPathMarshal, err) + } + err = os.WriteFile(resourceOutPathMarshal, bytes, 0644) + if err != nil { + log.Fatalf("error writing product to path %v: %v", resourceOutPathMarshal, err) + } + log.Printf("Generated resource %s", resourceOutPathMarshal) + } +} + +func findResources(doc *openapi3.T) [][]string { + var resourcePaths [][]string + + pathMap := doc.Paths.Map() + for key, pathValue := range pathMap { + if pathValue.Post == nil { + continue + } + + // Not very clever way of identifying create resource methods + if strings.HasPrefix(pathValue.Post.OperationID, "Create") { + resourcePath := key + resourceName := strings.Replace(pathValue.Post.OperationID, "Create", "", 1) + resourcePaths = append(resourcePaths, []string{resourcePath, resourceName}) + } + } + + return resourcePaths +} + +func buildProduct(filePath, output string, root *openapi3.T) string { + + version := root.Info.Version + server := root.Servers[0].URL + + productName := strings.Split(filepath.Base(filePath), "_")[0] + productPath := filepath.Join(output, productName) + + if err := os.MkdirAll(productPath, os.ModePerm); err != nil { + log.Fatalf("error creating product output directory %v: %v", productPath, err) + } + + apiProduct := &api.Product{} + apiVersion := &product.Version{} + + apiVersion.BaseUrl = fmt.Sprintf("%s/%s/", server, version) + // TODO(slevenick) figure out how to tell the API version + apiVersion.Name = "ga" + apiProduct.Versions = []*product.Version{apiVersion} + + // Standard titling is "Service Name API" + displayName := strings.Replace(root.Info.Title, " API", "", 1) + apiProduct.Name = strings.ReplaceAll(displayName, " ", "") + apiProduct.DisplayName = displayName + + //Scopes should be added soon to OpenAPI, until then use global scope + apiProduct.Scopes = []string{"https://www.googleapis.com/auth/cloud-platform"} + + // productOutPath := filepath.Join(output, fmt.Sprintf("/%s/product.yaml", productName)) + templatePath := "openapi_generate/product_yaml.tmpl" + + productOutPathTemplate := filepath.Join(output, fmt.Sprintf("/%s/product_template.yaml", productName)) + WriteGoTemplate(templatePath, productOutPathTemplate, apiProduct) + + productOutPathMarshal := filepath.Join(output, fmt.Sprintf("/%s/product_marshal.yaml", productName)) + + // Default yaml marshaller + bytes, err := yaml.Marshal(apiProduct) + if err != nil { + log.Fatalf("error marshalling yaml %v: %v", productOutPathMarshal, err) + } + + err = os.WriteFile(productOutPathMarshal, bytes, 0644) + if err != nil { + log.Fatalf("error writing product to path %v: %v", productOutPathMarshal, err) + } + + return productPath +} + +func buildResource(filePath, resourcePath, resourceName string, root *openapi3.T) api.Resource { + resource := api.Resource{} + + parsedObjects := parseOpenApi(resourcePath, resourceName, root) + + parameters := parsedObjects[0].([]*api.Type) + properties := parsedObjects[1].([]*api.Type) + queryParam := parsedObjects[2].(string) + + // TODO base_url(resource_path) + baseUrl := resourcePath + selfLink := fmt.Sprintf("%s/%s", baseUrl, strings.ToLower(queryParam)) + + resource.Name = resourceName + resource.Parameters = parameters + resource.Properties = properties + resource.SelfLink = selfLink + + return resource +} + +func parseOpenApi(resourcePath, resourceName string, root *openapi3.T) []any { + returnArray := []any{} + path := root.Paths.Find(resourcePath) + + parameters := []*api.Type{} + var idParam string + for _, param := range path.Post.Parameters { + if strings.Contains(strings.ToLower(param.Value.Name), strings.ToLower(resourceName)) { + idParam = param.Value.Name + } + paramObj := writeObject(param.Value.Name, param.Value.Schema, *param.Value.Schema.Value.Type, true) + + if param.Value.Name == "requestId" || param.Value.Name == "validateOnly" || paramObj.Name == "" { + continue + } + + // All parameters are immutable + paramObj.Immutable = true + parameters = append(parameters, ¶mObj) + } + + // TODO build_properties + properties := []*api.Type{} + + returnArray = append(returnArray, parameters) + returnArray = append(returnArray, properties) + returnArray = append(returnArray, idParam) + + return returnArray +} + +func writeObject(name string, obj *openapi3.SchemaRef, objType openapi3.Types, urlParam bool) api.Type { + var field api.Type + + switch name { + case "projectsId", "project": + // projectsId and project are omitted in MMv1 as they are inferred from + // the presence of {{project}} in the URL + return field + case "locationsId": + name = "location" + } + additionalDescription := "" + + // log.Printf("%s %+v", name, obj.Value.AllOf) + + if len(obj.Value.AllOf) > 0 { + obj = obj.Value.AllOf[0] + objType = *obj.Value.Type + } + + if objType.Is("string") { + field.Type = "string" + field.Name = name + if len(obj.Value.Enum) > 0 { + var enums []string + for _, enum := range obj.Value.Enum { + enums = append(enums, fmt.Sprintf("%v", enum)) + } + additionalDescription = fmt.Sprintf("\n Possible values:\n %s", strings.Join(enums, "\n")) + } + } + + description := fmt.Sprintf("%s %s", obj.Value.Description, additionalDescription) + if strings.TrimSpace(description) == "" { + description = "No description" + } + + if urlParam { + field.UrlParamOnly = true + field.Required = true + } + + // These methods are only available when the field is set + if obj.Value.ReadOnly { + field.Output = true + } + + // x-google-identifier fields are described by AIP 203 and are represented + // as output only in Terraform. + xGoogleId, err := obj.JSONLookup("x-google-identifier") + if err == nil && xGoogleId != nil { + field.Output = true + } + + xGoogleImmutable, err := obj.JSONLookup("x-google-immutable") + if obj.Value.ReadOnly || (err == nil && xGoogleImmutable != nil) { + field.Immutable = true + } + + return field +} + +func WriteGoTemplate(templatePath, filePath string, input any) { + contents := bytes.Buffer{} + + templateFileName := filepath.Base(templatePath) + templates := []string{ + templatePath, + } + + tmpl, err := template.New(templateFileName).Funcs(google.TemplateFunctions).ParseFiles(templates...) + if err != nil { + glog.Exit(fmt.Sprintf("error parsing %s for filepath %s ", templatePath, filePath), err) + } + if err = tmpl.ExecuteTemplate(&contents, templateFileName, input); err != nil { + glog.Exit(fmt.Sprintf("error executing %s for filepath %s ", templatePath, filePath), err) + } + + bytes := contents.Bytes() + + err = os.WriteFile(filePath, bytes, 0644) + if err != nil { + log.Fatalf("error writing product to path %v: %v", filePath, err) + } + +} diff --git a/mmv1/openapi_generate/product_yaml.tmpl b/mmv1/openapi_generate/product_yaml.tmpl new file mode 100644 index 000000000000..38bd016db19c --- /dev/null +++ b/mmv1/openapi_generate/product_yaml.tmpl @@ -0,0 +1,25 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: '{{$.Name}}' +display_name: '{{$.DisplayName}}' +versions: +{{- range $version := $.Versions }} + - name: '{{$version.Name}}' + base_url: {{$version.BaseUrl}}' +{{- end }} +scopes: +{{- range $scope := $.Scopes }} + - '{{$scope}}' +{{- end }} diff --git a/mmv1/openapi_generate/resource_yaml.tmpl b/mmv1/openapi_generate/resource_yaml.tmpl new file mode 100644 index 000000000000..d6182b0a6233 --- /dev/null +++ b/mmv1/openapi_generate/resource_yaml.tmpl @@ -0,0 +1,15 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: '{{$.Name}}' diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index b13c7da10c9b..81ce2a80cdc9 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -160,6 +160,14 @@ examples: ignore_read_extra: - 'deletion_protection' external_providers: ["time"] + - name: 'cloudrunv2_service_invokeriam' + primary_resource_id: 'default' + primary_resource_name: 'fmt.Sprintf("tf-test-cloudrun-srv%s", context["random_suffix"])' + min_version: 'beta' + vars: + cloud_run_service_name: 'cloudrun-service' + ignore_read_extra: + - 'deletion_protection' virtual_fields: - name: 'deletion_protection' description: | @@ -950,6 +958,10 @@ properties: type: String description: | Indicates a string to be part of the URI to exclusively reference this target. + - name: 'invokerIamDisabled' + type: Boolean + description: | + Disables IAM permission check for run.routes.invoke for callers of this service. This feature is available by invitation only. For more information, visit https://cloud.google.com/run/docs/securing/managing-access#invoker_check. - name: 'observedGeneration' type: String description: | diff --git a/mmv1/products/compute/BackendService.yaml b/mmv1/products/compute/BackendService.yaml index 5bb6764e9975..931ccc5cc50f 100644 --- a/mmv1/products/compute/BackendService.yaml +++ b/mmv1/products/compute/BackendService.yaml @@ -754,6 +754,7 @@ properties: type: Boolean description: Whether the serving infrastructure will authenticate and authorize all incoming requests. required: true + send_empty_value: true - name: 'oauth2ClientId' type: String description: | diff --git a/mmv1/products/compute/RegionBackendService.yaml b/mmv1/products/compute/RegionBackendService.yaml index 76f9dbf223be..316921eaa92e 100644 --- a/mmv1/products/compute/RegionBackendService.yaml +++ b/mmv1/products/compute/RegionBackendService.yaml @@ -759,6 +759,7 @@ properties: type: Boolean description: Whether the serving infrastructure will authenticate and authorize all incoming requests. required: true + send_empty_value: true - name: 'oauth2ClientId' type: String description: | diff --git a/mmv1/products/dialogflowcx/Agent.yaml b/mmv1/products/dialogflowcx/Agent.yaml index 85270a9abc33..8d3f2b006552 100644 --- a/mmv1/products/dialogflowcx/Agent.yaml +++ b/mmv1/products/dialogflowcx/Agent.yaml @@ -40,6 +40,8 @@ examples: bucket_name: 'dialogflowcx-bucket' ignore_read_extra: - 'git_integration_settings.0.github_settings.0.access_token' + - 'enable_stackdriver_logging' + - 'advanced_settings.0.logging_settings' parameters: properties: - name: 'name' @@ -113,8 +115,11 @@ properties: Name of the SecuritySettings reference for the agent. Format: projects//locations//securitySettings/. - name: 'enableStackdriverLogging' type: Boolean + # Ignore read, field is deprecated and conflicts with advanced_settings.logging_settings.enable_stackdriver_logging when it's set + ignore_read: true description: | Determines whether this agent should log conversation queries. + deprecation_message: '`enable_stackdriver_logging` is deprecated and will be removed in a future major release. Please use `advanced_settings.logging_settings.enable_stackdriver_logging`instead.' - name: 'enableSpellCorrection' type: Boolean description: | @@ -138,6 +143,33 @@ properties: description: | The Google Cloud Storage URI for the exported objects. Whether a full object name, or just a prefix, its usage depends on the Dialogflow operation. Format: gs://bucket/object-name-or-prefix + - name: 'speechSettings' + type: NestedObject + description: | + Settings for speech to text detection. Exposed at the following levels: + * Agent level + * Flow level + * Page level + * Parameter level + properties: + - name: 'endpointerSensitivity' + type: Integer + description: | + Sensitivity of the speech model that detects the end of speech. Scale from 0 to 100. + - name: 'noSpeechTimeout' + type: String + description: | + Timeout before detecting no speech. + A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s". + - name: 'useTimeoutBasedEndpointing' + type: Boolean + description: | + Use timeout based endpointing, interpreting endpointer sensitivy as seconds of timeout value. + - name: 'models' + type: KeyValuePairs + description: | + Mapping from language to Speech-to-Text model. The mapped Speech-to-Text model will be selected for requests from its corresponding language. For more information, see [Speech models](https://cloud.google.com/dialogflow/cx/docs/concept/speech-models). + An object containing a list of **"key": value** pairs. Example: **{ "name": "wrench", "mass": "1.3kg", "count": "3" }**. - name: 'dtmfSettings' type: NestedObject description: | @@ -159,6 +191,26 @@ properties: type: String description: | The digit that terminates a DTMF digit sequence. + - name: 'loggingSettings' + type: NestedObject + # Due to inconsistent API behaviour http://b/303056144, ignore read can be removed once fixed + ignore_read: true + description: | + Settings for logging. Settings for Dialogflow History, Contact Center messages, StackDriver logs, and speech logging. Exposed at the following levels: + * Agent level + properties: + - name: 'enableStackdriverLogging' + type: Boolean + description: | + Enables Google Cloud Logging. + - name: 'enableInteractionLogging' + type: Boolean + description: | + Enables DF Interaction logging. + - name: 'enableConsentBasedRedaction' + type: Boolean + description: | + Enables consent-based end-user input redaction, if true, a pre-defined session parameter **$session.params.conversation-redaction** will be used to determine if the utterance should be redacted. - name: 'gitIntegrationSettings' type: NestedObject description: | diff --git a/mmv1/products/dialogflowcx/Flow.yaml b/mmv1/products/dialogflowcx/Flow.yaml index 22c11a4ac68b..c08b57be66bf 100644 --- a/mmv1/products/dialogflowcx/Flow.yaml +++ b/mmv1/products/dialogflowcx/Flow.yaml @@ -42,6 +42,8 @@ examples: primary_resource_id: 'basic_flow' vars: agent_name: 'dialogflowcx-agent' + ignore_read_extra: + - 'advanced_settings.0.logging_settings' - name: 'dialogflowcx_flow_full' primary_resource_id: 'basic_flow' vars: @@ -564,6 +566,33 @@ properties: description: | The Google Cloud Storage URI for the exported objects. Whether a full object name, or just a prefix, its usage depends on the Dialogflow operation. Format: gs://bucket/object-name-or-prefix + - name: 'speechSettings' + type: NestedObject + description: | + Settings for speech to text detection. Exposed at the following levels: + * Agent level + * Flow level + * Page level + * Parameter level + properties: + - name: 'endpointerSensitivity' + type: Integer + description: | + Sensitivity of the speech model that detects the end of speech. Scale from 0 to 100. + - name: 'noSpeechTimeout' + type: String + description: | + Timeout before detecting no speech. + A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s". + - name: 'useTimeoutBasedEndpointing' + type: Boolean + description: | + Use timeout based endpointing, interpreting endpointer sensitivy as seconds of timeout value. + - name: 'models' + type: KeyValuePairs + description: | + Mapping from language to Speech-to-Text model. The mapped Speech-to-Text model will be selected for requests from its corresponding language. For more information, see [Speech models](https://cloud.google.com/dialogflow/cx/docs/concept/speech-models). + An object containing a list of **"key": value** pairs. Example: **{ "name": "wrench", "mass": "1.3kg", "count": "3" }**. - name: 'dtmfSettings' type: NestedObject description: | @@ -585,3 +614,23 @@ properties: type: String description: | The digit that terminates a DTMF digit sequence. + - name: 'loggingSettings' + type: NestedObject + ignore_read: true + # Ignore read as API does not return loggingSettings back, only accepts in the /create/update API call + description: | + Settings for logging. Settings for Dialogflow History, Contact Center messages, StackDriver logs, and speech logging. Exposed at the following levels: + * Agent level + properties: + - name: 'enableStackdriverLogging' + type: Boolean + description: | + Enables Google Cloud Logging. + - name: 'enableInteractionLogging' + type: Boolean + description: | + Enables DF Interaction logging. + - name: 'enableConsentBasedRedaction' + type: Boolean + description: | + Enables consent-based end-user input redaction, if true, a pre-defined session parameter **$session.params.conversation-redaction** will be used to determine if the utterance should be redacted. diff --git a/mmv1/products/firebase/Project.yaml b/mmv1/products/firebase/Project.yaml index 8f68defa2b55..e4dfc44fc188 100644 --- a/mmv1/products/firebase/Project.yaml +++ b/mmv1/products/firebase/Project.yaml @@ -58,6 +58,8 @@ custom_code: constants: 'templates/terraform/constants/firebase_project.go.tmpl' pre_create: 'templates/terraform/pre_create/firebase_project.go.tmpl' exclude_sweeper: true +# The generated resource converter is not used. Instead, a handwritten converter is used. +exclude_tgc: true examples: - name: 'firebase_project_basic' primary_resource_id: 'default' diff --git a/mmv1/products/healthcare/Dataset.yaml b/mmv1/products/healthcare/Dataset.yaml index cfbe4d8e37a0..d8313d98ba65 100644 --- a/mmv1/products/healthcare/Dataset.yaml +++ b/mmv1/products/healthcare/Dataset.yaml @@ -46,6 +46,7 @@ examples: time_zone: 'America/New_York' - name: 'healthcare_dataset_cmek' primary_resource_id: 'default' + exclude_test: true vars: dataset_name: 'example-dataset' location: 'us-central1' diff --git a/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml b/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml index f45e2771b16d..13400e181be5 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml @@ -59,6 +59,11 @@ examples: vars: workload_identity_pool_id: 'example-pool' workload_identity_pool_provider_id: 'example-prvdr' + - name: 'iam_workload_identity_pool_provider_github_actions' + primary_resource_id: 'example' + vars: + workload_identity_pool_id: 'example-pool' + workload_identity_pool_provider_id: 'example-prvdr' - name: 'iam_workload_identity_pool_provider_oidc_basic' primary_resource_id: 'example' vars: diff --git a/mmv1/products/kms/KeyHandle.yaml b/mmv1/products/kms/KeyHandle.yaml index e9d4e39d0dd2..e4648a16f889 100644 --- a/mmv1/products/kms/KeyHandle.yaml +++ b/mmv1/products/kms/KeyHandle.yaml @@ -54,8 +54,9 @@ examples: primary_resource_id: 'example-keyhandle' min_version: 'beta' vars: + folder_name: 'my-folder' key_project_name: 'key-proj' - resource_project_name: 'resources' + resource_project_name: 'res-proj' test_env_vars: org_id: 'ORG_ID' billing_account: 'BILLING_ACCT' diff --git a/mmv1/products/networkconnectivity/InternalRange.yaml b/mmv1/products/networkconnectivity/InternalRange.yaml index 232c7a1ac139..6b84faa36a5c 100644 --- a/mmv1/products/networkconnectivity/InternalRange.yaml +++ b/mmv1/products/networkconnectivity/InternalRange.yaml @@ -71,6 +71,12 @@ examples: vars: internal_range_name: 'overlap-range' network_name: 'internal-ranges' + - name: 'network_connectivity_internal_ranges_migration' + primary_resource_id: 'default' + vars: + internal_range_name: 'migration' + network_name: 'internal-ranges' + source_subnet_name: 'source-subnet' parameters: properties: - name: 'name' @@ -108,6 +114,7 @@ properties: enum_values: - 'FOR_VPC' - 'EXTERNAL_TO_VPC' + - 'FOR_MIGRATION' - name: 'peering' type: Enum description: | @@ -149,3 +156,25 @@ properties: enum_values: - 'OVERLAP_ROUTE_RANGE' - 'OVERLAP_EXISTING_SUBNET_RANGE' + - name: 'migration' + type: NestedObject + description: | + Specification for migration with source and target resource names. + immutable: true + properties: + - name: 'source' + type: String + description: | + Resource path as an URI of the source resource, for example a subnet. + The project for the source resource should match the project for the + InternalRange. + An example /projects/{project}/regions/{region}/subnetworks/{subnet} + required: true + - name: 'target' + type: String + description: | + Resource path of the target resource. The target project can be + different, as in the cases when migrating to peer networks. The resource + may not exist yet. + For example /projects/{project}/regions/{region}/subnetworks/{subnet} + required: true diff --git a/mmv1/products/networkconnectivity/Spoke.yaml b/mmv1/products/networkconnectivity/Spoke.yaml index a2ffef94adff..f0e3df14e3d8 100644 --- a/mmv1/products/networkconnectivity/Spoke.yaml +++ b/mmv1/products/networkconnectivity/Spoke.yaml @@ -75,7 +75,7 @@ examples: hub_name: 'basic-hub1' vpn_tunnel_1_spoke_name: 'vpn-tunnel-1-spoke' vpn_tunnel_2_spoke_name: 'vpn-tunnel-2-spoke' - # Failing in replaying mode (https://github.com/hashicorp/terraform-provider-google/issues/19592) + # Skip due to multiple fine-grained resources skip_vcr: true - name: 'network_connectivity_spoke_interconnect_attachment_basic' primary_resource_id: 'primary' @@ -85,6 +85,14 @@ examples: router_name: 'external-vpn-gateway' interconnect_attachment_name: 'partner-interconnect1' interconnect_attachment_spoke_name: 'interconnect-attachment-spoke' + - name: 'network_connectivity_spoke_linked_producer_vpc_network_basic' + primary_resource_id: 'primary' + vars: + network_name: "net-spoke" + global_name: 'test-address' + hub_name: "hub-basic" + spoke_name: "vpc-spoke" + producer_spoke_name: "producer-spoke" parameters: - name: 'location' type: String @@ -128,6 +136,7 @@ properties: - linked_interconnect_attachments - linked_router_appliance_instances - linked_vpc_network + - linked_producer_vpc_network properties: - name: 'uris' type: Array @@ -156,6 +165,7 @@ properties: - linked_vpn_tunnels - linked_router_appliance_instances - linked_vpc_network + - linked_producer_vpc_network properties: - name: 'uris' type: Array @@ -184,6 +194,7 @@ properties: - linked_interconnect_attachments - linked_vpn_tunnels - linked_vpc_network + - linked_producer_vpc_network properties: - name: 'instances' type: Array @@ -223,6 +234,7 @@ properties: - linked_interconnect_attachments - linked_router_appliance_instances - linked_vpn_tunnels + - linked_producer_vpc_network properties: - name: 'uri' type: String @@ -242,6 +254,44 @@ properties: immutable: true item_type: type: String + - name: linkedProducerVpcNetwork + type: NestedObject + description: Producer VPC network that is associated with the spoke. + immutable: true + conflicts: + - linked_interconnect_attachments + - linked_router_appliance_instances + - linked_vpn_tunnels + - linked_vpc_network + properties: + - name: network + type: String + description: The URI of the Service Consumer VPC that the Producer VPC is peered with. + required: true + immutable: true + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + - name: peering + type: String + description: The name of the VPC peering between the Service Consumer VPC and the Producer VPC (defined in the Tenant project) which is added to the NCC hub. This peering must be in ACTIVE state. + required: true + immutable: true + - name: producerNetwork + type: String + description: The URI of the Producer VPC. + output: true + immutable: true + - name: includeExportRanges + type: Array + description: IP ranges allowed to be included from peering. + immutable: true + item_type: + type: String + - name: excludeExportRanges + type: Array + description: IP ranges encompassing the subnets to be excluded from peering. + immutable: true + item_type: + type: String - name: 'uniqueId' type: String description: Output only. The Google-generated UUID for the spoke. This value is unique across all spoke resources. If a spoke is deleted and another with the same name is created, the new spoke is assigned a different unique_id. diff --git a/mmv1/products/networksecurity/ServerTlsPolicy.yaml b/mmv1/products/networksecurity/ServerTlsPolicy.yaml index 9508b010e684..ed91c2b05616 100644 --- a/mmv1/products/networksecurity/ServerTlsPolicy.yaml +++ b/mmv1/products/networksecurity/ServerTlsPolicy.yaml @@ -14,7 +14,7 @@ --- name: 'ServerTlsPolicy' description: | - ClientTlsPolicy is a resource that specifies how a client should authenticate connections to backends of a service. This resource itself does not affect configuration unless it is attached to a backend service resource. + ServerTlsPolicy is a resource that specifies how a server should authenticate incoming requests. This resource itself does not affect configuration unless it is attached to a target HTTPS proxy or endpoint config selector resource. references: guides: api: 'https://cloud.google.com/traffic-director/docs/reference/network-security/rest/v1beta1/projects.locations.serverTlsPolicies' diff --git a/mmv1/products/networkservices/Gateway.yaml b/mmv1/products/networkservices/Gateway.yaml index 99e3df6ad299..d68da1c01f5d 100644 --- a/mmv1/products/networkservices/Gateway.yaml +++ b/mmv1/products/networkservices/Gateway.yaml @@ -54,7 +54,7 @@ async: custom_code: constants: 'templates/terraform/constants/network_services_gateway.go.tmpl' post_delete: 'templates/terraform/post_delete/network_services_gateway.go.tmpl' - pre_update: 'templates/terraform/pre_update/network_services_gateway.tmpl' + pre_update: 'templates/terraform/pre_update/network_services_gateway.go.tmpl' examples: - name: 'network_services_gateway_basic' primary_resource_id: 'default' @@ -206,3 +206,9 @@ properties: This feature only applies to gateways of type 'SECURE_WEB_GATEWAY'. item_type: type: String + - name: 'routingMode' + type: Enum + description: | + The routing mode of the Gateway. This field is configurable only for gateways of type SECURE_WEB_GATEWAY. This field is required for gateways of type SECURE_WEB_GATEWAY. + enum_values: + - 'NEXT_HOP_ROUTING_MODE' diff --git a/mmv1/products/oracledatabase/CloudExadataInfrastructure.yaml b/mmv1/products/oracledatabase/CloudExadataInfrastructure.yaml new file mode 100644 index 000000000000..981e026aa0f7 --- /dev/null +++ b/mmv1/products/oracledatabase/CloudExadataInfrastructure.yaml @@ -0,0 +1,300 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +name: 'CloudExadataInfrastructure' +description: A CloudExadataInfrastructure resource. +references: + guides: + 'Create Exadata Infrastructure instances': 'https://cloud.google.com/oracle/database/docs/create-instances' + api: 'https://cloud.google.com/oracle/database/docs/reference/rest/v1/projects.locations.cloudExadataInfrastructures' +docs: +id_format: 'projects/{{project}}/locations/{{location}}/cloudExadataInfrastructures/{{cloud_exadata_infrastructure_id}}' +base_url: 'projects/{{project}}/locations/{{location}}/cloudExadataInfrastructures' +self_link: 'projects/{{project}}/locations/{{location}}/cloudExadataInfrastructures/{{cloud_exadata_infrastructure_id}}' +create_url: 'projects/{{project}}/locations/{{location}}/cloudExadataInfrastructures?cloudExadataInfrastructureId={{cloud_exadata_infrastructure_id}}' +immutable: true +import_format: + - 'projects/{{project}}/locations/{{location}}/cloudExadataInfrastructures/{{cloud_exadata_infrastructure_id}}' +timeouts: + insert_minutes: 240 + update_minutes: 120 + delete_minutes: 120 +autogen_async: true +async: + actions: ['create', 'delete', 'update'] + type: 'OpAsync' + operation: + base_url: '{{op_id}}' + path: 'name' + wait_ms: 1000 + timeouts: + insert_minutes: 240 + update_minutes: 120 + delete_minutes: 120 + result: + path: 'response' + resource_inside_response: true + error: + path: 'error' + message: 'message' +custom_code: +examples: + - name: 'oracledatabase_cloud_exadata_infrastructure_basic' + primary_resource_id: 'my-cloud-exadata' + vars: + project: 'my-project' + cloud_exadata_infrastructure_id: 'my-instance' + test_vars_overrides: + 'project': '"oci-terraform-testing"' + 'cloud_exadata_infrastructure_id': '"ofake-exadata-basic"' + - name: 'oracledatabase_cloud_exadata_infrastructure_full' + primary_resource_id: 'my-cloud-exadata' + vars: + project: 'my-project' + cloud_exadata_infrastructure_id: 'my-instance' + test_vars_overrides: + 'project': '"oci-terraform-testing"' + 'cloud_exadata_infrastructure_id': '"ofake-exadata-full"' +parameters: + - name: 'location' + type: String + description: 'Resource ID segment making up resource `name`. See documentation + for resource type `oracledatabase.googleapis.com/DbServer`. ' + url_param_only: true + required: true + immutable: true + - name: 'cloudExadataInfrastructureId' + type: String + description: "The ID of the Exadata Infrastructure to create. This value + is restricted\nto (^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$) and must be a maximum of + 63\ncharacters in length. The value must start with a letter and end with\na letter + or a number. " + url_param_only: true + required: true + immutable: true +properties: + - name: 'name' + type: String + description: "Identifier. The name of the Exadata Infrastructure resource with the + following format:\nprojects/{project}/locations/{region}/cloudExadataInfrastructures/{cloud_exadata_infrastructure} " + output: true + - name: 'displayName' + type: String + description: 'User friendly name for this resource. ' + - name: 'gcpOracleZone' + type: String + description: 'GCP location where Oracle Exadata is hosted. ' + default_from_api: true + - name: 'entitlementId' + type: String + description: "Entitlement ID of the private offer against which this + infrastructure\nresource is provisioned. " + output: true + - name: 'properties' + type: NestedObject + description: 'Various properties of Exadata Infrastructure. ' + properties: + - name: 'ocid' + type: String + description: "OCID of created infra.\nhttps://docs.oracle.com/en-us/iaas/Content/General/Concepts/identifiers.htm#Oracle " + output: true + - name: 'computeCount' + type: Integer + description: 'The number of compute servers for the Exadata Infrastructure. ' + - name: 'storageCount' + type: Integer + description: 'The number of Cloud Exadata storage servers for the Exadata + Infrastructure. ' + - name: 'totalStorageSizeGb' + type: Integer + description: "The total storage allocated to the Exadata Infrastructure\nresource, + in gigabytes (GB). " + default_from_api: true + - name: 'availableStorageSizeGb' + type: Integer + description: "The available storage can be allocated to the Exadata + Infrastructure\nresource, in gigabytes (GB). " + output: true + - name: 'maintenanceWindow' + type: NestedObject + description: "Maintenance window as defined by Oracle.\nhttps://docs.oracle.com/en-us/iaas/api/#/en/database/20160918/datatypes/MaintenanceWindow " + default_from_api: true + properties: + - name: 'preference' + type: String + description: "The maintenance window scheduling preference. \n + Possible values:\n MAINTENANCE_WINDOW_PREFERENCE_UNSPECIFIED\nCUSTOM_PREFERENCE\nNO_PREFERENCE" + default_from_api: true + - name: 'months' + type: Array + description: 'Months during the year when maintenance should be performed. ' + default_from_api: true + item_type: + type: String + - name: 'weeksOfMonth' + type: Array + description: "Weeks during the month when maintenance should be performed. + Weeks start on\nthe 1st, 8th, 15th, and 22nd days of the month, and have a + duration of 7\ndays. Weeks start and end based on calendar dates, not days + of the week. " + default_from_api: true + item_type: + type: Integer + - name: 'daysOfWeek' + type: Array + description: 'Days during the week when maintenance should be performed. ' + default_from_api: true + item_type: + type: String + - name: 'hoursOfDay' + type: Array + description: "The window of hours during the day when maintenance + should be performed.\nThe window is a 4 hour slot. Valid values are:\n 0 + - represents time slot 0:00 - 3:59 UTC\n 4 - represents time slot 4:00 - + 7:59 UTC\n 8 - represents time slot 8:00 - 11:59 UTC\n 12 - represents time + slot 12:00 - 15:59 UTC\n 16 - represents time slot 16:00 - 19:59 UTC\n 20 + - represents time slot 20:00 - 23:59 UTC " + default_from_api: true + item_type: + type: Integer + - name: 'leadTimeWeek' + type: Integer + description: "Lead time window allows user to set a lead time to prepare + for a down time.\nThe lead time is in weeks and valid value is between 1 to + 4. " + default_from_api: true + - name: 'patchingMode' + type: String + description: "Cloud CloudExadataInfrastructure node patching method, + either \"ROLLING\"\n or \"NONROLLING\". Default value is ROLLING. \n + Possible values:\n PATCHING_MODE_UNSPECIFIED\nROLLING\nNON_ROLLING" + default_from_api: true + - name: 'customActionTimeoutMins' + type: Integer + description: "Determines the amount of time the system will wait before + the start of each\ndatabase server patching operation. Custom action timeout + is in minutes and\nvalid value is between 15 to 120 (inclusive). " + default_from_api: true + - name: 'isCustomActionTimeoutEnabled' + type: Boolean + description: "If true, enables the configuration of a custom action + timeout (waiting\nperiod) between database server patching operations. " + default_from_api: true + - name: 'state' + type: String + description: "The current lifecycle state of the Exadata Infrastructure. + \n Possible values:\n STATE_UNSPECIFIED\nPROVISIONING\nAVAILABLE\nUPDATING\nTERMINATING\nTERMINATED\nFAILED\nMAINTENANCE_IN_PROGRESS" + output: true + - name: 'shape' + type: String + description: "The shape of the Exadata Infrastructure. The shape determines + the\namount of CPU, storage, and memory resources allocated to the instance. " + required: true + - name: 'ociUrl' + type: String + description: 'Deep link to the OCI console to view this resource. ' + output: true + - name: 'cpuCount' + type: Integer + description: 'The number of enabled CPU cores. ' + output: true + - name: 'maxCpuCount' + type: Integer + description: 'The total number of CPU cores available. ' + output: true + - name: 'memorySizeGb' + type: Integer + description: 'The memory allocated in GBs. ' + output: true + - name: 'maxMemoryGb' + type: Integer + description: 'The total memory available in GBs. ' + output: true + - name: 'dbNodeStorageSizeGb' + type: Integer + description: 'The local node storage allocated in GBs. ' + output: true + - name: 'maxDbNodeStorageSizeGb' + type: Integer + description: 'The total local node storage available in GBs. ' + output: true + - name: 'dataStorageSizeTb' + type: Double + description: 'Size, in terabytes, of the DATA disk group. ' + output: true + - name: 'maxDataStorageTb' + type: Double + description: 'The total available DATA disk group size. ' + output: true + - name: 'activatedStorageCount' + type: Integer + description: "The requested number of additional storage servers + activated for the\nExadata Infrastructure. " + output: true + - name: 'additionalStorageCount' + type: Integer + description: "The requested number of additional storage servers + for the Exadata\nInfrastructure. " + output: true + - name: 'dbServerVersion' + type: String + description: "The software version of the database servers (dom0) + in the Exadata\nInfrastructure. " + output: true + - name: 'storageServerVersion' + type: String + description: "The software version of the storage servers (cells) + in the Exadata\nInfrastructure. " + output: true + - name: 'nextMaintenanceRunId' + type: String + description: 'The OCID of the next maintenance run. ' + output: true + - name: 'nextMaintenanceRunTime' + type: String + description: 'The time when the next maintenance run will occur. ' + output: true + - name: 'nextSecurityMaintenanceRunTime' + type: String + description: 'The time when the next security maintenance run will + occur. ' + output: true + - name: 'customerContacts' + type: Array + description: 'The list of customer contacts. ' + item_type: + type: NestedObject + properties: + - name: 'email' + type: String + description: "The email address used by Oracle to send notifications + regarding databases\nand infrastructure. " + required: true + - name: 'monthlyStorageServerVersion' + type: String + description: "The monthly software version of the storage servers + (cells)\nin the Exadata Infrastructure. Example: 20.1.15 " + output: true + - name: 'monthlyDbServerVersion' + type: String + description: "The monthly software version of the database servers + (dom0)\nin the Exadata Infrastructure. Example: 20.1.15 " + output: true + - name: 'labels' + type: KeyValueLabels + description: 'Labels or tags associated with the resource. ' + - name: 'createTime' + type: String + description: 'The date and time that the Exadata Infrastructure was + created. ' + output: true diff --git a/mmv1/products/oracledatabase/CloudVmCluster.yaml b/mmv1/products/oracledatabase/CloudVmCluster.yaml new file mode 100644 index 000000000000..ddc28f039c1e --- /dev/null +++ b/mmv1/products/oracledatabase/CloudVmCluster.yaml @@ -0,0 +1,281 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +name: 'CloudVmCluster' +description: A CloudVmCluster resource. +references: + guides: + 'Create VM clusters': 'https://cloud.google.com/oracle/database/docs/create-clusters' + api: 'https://cloud.google.com/oracle/database/docs/reference/rest/v1/projects.locations.cloudVmClusters' +docs: +id_format: 'projects/{{project}}/locations/{{location}}/cloudVmClusters/{{cloud_vm_cluster_id}}' +base_url: 'projects/{{project}}/locations/{{location}}/cloudVmClusters' +self_link: 'projects/{{project}}/locations/{{location}}/cloudVmClusters/{{cloud_vm_cluster_id}}' +create_url: 'projects/{{project}}/locations/{{location}}/cloudVmClusters?cloudVmClusterId={{cloud_vm_cluster_id}}' +immutable: true +import_format: + - 'projects/{{project}}/locations/{{location}}/cloudVmClusters/{{cloud_vm_cluster_id}}' +timeouts: + insert_minutes: 120 + update_minutes: 60 + delete_minutes: 60 +autogen_async: true +async: + actions: ['create', 'delete', 'update'] + type: 'OpAsync' + operation: + base_url: '{{op_id}}' + path: 'name' + wait_ms: 1000 + timeouts: + insert_minutes: 120 + update_minutes: 60 + delete_minutes: 60 + result: + path: 'response' + resource_inside_response: true + error: + path: 'error' + message: 'message' +examples: + - name: 'oracledatabase_cloud_vmcluster_basic' + primary_resource_id: 'my_vmcluster' + vars: + project: 'my-project' + cloud_vm_cluster_id: 'my-instance' + cloud_exadata_infrastructure_id: 'my-exadata' + test_vars_overrides: + 'project': '"oci-terraform-testing"' + 'cloud_vm_cluster_id': '"ofake-vmcluster-basic"' + 'cloud_exadata_infrastructure_id': '"ofake-exadata-for-vm-basic"' + - name: 'oracledatabase_cloud_vmcluster_full' + primary_resource_id: 'my_vmcluster' + vars: + project: 'my-project' + cloud_vm_cluster_id: 'my-instance' + cloud_exadata_infrastructure_id: 'my-exadata' + test_vars_overrides: + 'project': '"oci-terraform-testing"' + 'cloud_vm_cluster_id': '"ofake-vmcluster-full"' + 'cloud_exadata_infrastructure_id': '"ofake-exadata-for-vm-full"' +parameters: + - name: 'location' + type: String + description: 'Resource ID segment making up resource `name`. See documentation + for resource type `oracledatabase.googleapis.com/DbNode`. ' + url_param_only: true + required: true + immutable: true + - name: 'cloudVmClusterId' + type: String + description: "The ID of the VM Cluster to create. This value is restricted\nto + (^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$) and must be a maximum of 63\ncharacters in + length. The value must start with a letter and end with\na letter or a number. " + url_param_only: true + required: true + immutable: true +properties: + - name: 'name' + type: String + description: "Identifier. The name of the VM Cluster resource with the format:\nprojects/{project}/locations/{region}/cloudVmClusters/{cloud_vm_cluster} " + output: true + - name: 'exadataInfrastructure' + type: String + description: "The name of the Exadata Infrastructure resource on which + VM cluster\nresource is created, in the following format:\nprojects/{project}/locations/{region}/cloudExadataInfrastuctures/{cloud_extradata_infrastructure} " + required: true + - name: 'displayName' + type: String + description: 'User friendly name for this resource. ' + - name: 'gcpOracleZone' + type: String + description: "GCP location where Oracle Exadata is hosted. It is same + as GCP Oracle zone\nof Exadata infrastructure. " + output: true + - name: 'properties' + type: NestedObject + description: 'Various properties and settings associated with Exadata VM cluster. ' + properties: + - name: 'ocid' + type: String + description: 'Oracle Cloud Infrastructure ID of VM Cluster. ' + output: true + - name: 'licenseType' + type: String + description: "License type of VM Cluster. \n Possible values:\n LICENSE_TYPE_UNSPECIFIED\nLICENSE_INCLUDED\nBRING_YOUR_OWN_LICENSE" + required: true + - name: 'giVersion' + type: String + description: 'Grid Infrastructure Version. ' + ignore_read: true + - name: 'timeZone' + type: NestedObject + description: "Represents a time zone from the\n[IANA Time Zone Database](https://www.iana.org/time-zones). " + default_from_api: true + properties: + - name: 'id' + type: String + description: 'IANA Time Zone Database time zone, e.g. "America/New_York". ' + default_from_api: true + - name: 'sshPublicKeys' + type: Array + description: 'SSH public keys to be stored with cluster. ' + item_type: + type: String + - name: 'nodeCount' + type: Integer + description: 'Number of database servers. ' + default_from_api: true + - name: 'shape' + type: String + description: 'Shape of VM Cluster. ' + output: true + - name: 'ocpuCount' + type: Double + description: 'OCPU count per VM. Minimum is 0.1. ' + default_from_api: true + - name: 'memorySizeGb' + type: Integer + description: 'Memory allocated in GBs. ' + default_from_api: true + - name: 'dbNodeStorageSizeGb' + type: Integer + description: 'Local storage per VM ' + default_from_api: true + - name: 'storageSizeGb' + type: Integer + description: 'The storage allocation for the disk group, in gigabytes + (GB). ' + output: true + - name: 'dataStorageSizeTb' + type: Double + description: 'The data disk group size to be allocated in TBs. ' + default_from_api: true + - name: 'diskRedundancy' + type: String + description: "The type of redundancy. \n Possible values:\n DISK_REDUNDANCY_UNSPECIFIED\nHIGH\nNORMAL" + default_from_api: true + - name: 'sparseDiskgroupEnabled' + type: Boolean + description: 'Use exadata sparse snapshots. ' + default_from_api: true + - name: 'localBackupEnabled' + type: Boolean + description: 'Use local backup. ' + - name: 'hostnamePrefix' + type: String + description: 'Prefix for VM cluster host names. ' + ignore_read: true + - name: 'diagnosticsDataCollectionOptions' + type: NestedObject + description: 'Data collection options for diagnostics. ' + properties: + - name: 'diagnosticsEventsEnabled' + type: Boolean + description: 'Indicates whether diagnostic collection is enabled for + the VM cluster ' + - name: 'healthMonitoringEnabled' + type: Boolean + description: 'Indicates whether health monitoring is enabled for the + VM cluster ' + - name: 'incidentLogsEnabled' + type: Boolean + description: "Indicates whether incident logs and trace collection + are enabled for the VM\ncluster " + - name: 'state' + type: String + description: "State of the cluster. \n Possible values:\n STATE_UNSPECIFIED\nPROVISIONING\nAVAILABLE\nUPDATING\nTERMINATING\nTERMINATED\nFAILED\nMAINTENANCE_IN_PROGRESS" + output: true + - name: 'scanListenerPortTcp' + type: Integer + description: 'SCAN listener port - TCP ' + output: true + - name: 'scanListenerPortTcpSsl' + type: Integer + description: 'SCAN listener port - TLS ' + output: true + - name: 'domain' + type: String + description: "Parent DNS domain where SCAN DNS and hosts names are + qualified.\nex: ocispdelegated.ocisp10jvnet.oraclevcn.com " + output: true + - name: 'scanDns' + type: String + description: "SCAN DNS name.\nex: sp2-yi0xq-scan.ocispdelegated.ocisp10jvnet.oraclevcn.com " + output: true + - name: 'hostname' + type: String + description: "host name without domain.\nformat: \"-\" with some + suffix.\nex: sp2-yi0xq where \"sp2\" is the hostname_prefix. " + output: true + - name: 'cpuCoreCount' + type: Integer + description: 'Number of enabled CPU cores. ' + required: true + - name: 'systemVersion' + type: String + description: 'Operating system version of the image. ' + output: true + - name: 'scanIpIds' + type: Array + description: 'OCIDs of scan IPs. ' + output: true + item_type: + type: String + - name: 'scanDnsRecordId' + type: String + description: 'OCID of scan DNS record. ' + output: true + - name: 'ociUrl' + type: String + description: 'Deep link to the OCI console to view this resource. ' + output: true + - name: 'dbServerOcids' + type: Array + description: 'OCID of database servers. ' + default_from_api: true + item_type: + type: String + - name: 'compartmentId' + type: String + description: 'Compartment ID of cluster. ' + output: true + - name: 'dnsListenerIp' + type: String + description: 'DNS listener IP. ' + output: true + - name: 'clusterName' + type: String + description: 'OCI Cluster name. ' + default_from_api: true + - name: 'labels' + type: KeyValueLabels + description: 'Labels or tags associated with the VM Cluster. ' + - name: 'createTime' + type: String + description: 'The date and time that the VM cluster was created. ' + output: true + - name: 'cidr' + type: String + description: 'Network settings. CIDR to use for cluster IP allocation. ' + required: true + - name: 'backupSubnetCidr' + type: String + description: 'CIDR range of the backup subnet. ' + required: true + - name: 'network' + type: String + description: "The name of the VPC network.\nFormat: projects/{project}/global/networks/{network} " + required: true diff --git a/mmv1/products/oracledatabase/product.yaml b/mmv1/products/oracledatabase/product.yaml new file mode 100644 index 000000000000..9356d79a4a2e --- /dev/null +++ b/mmv1/products/oracledatabase/product.yaml @@ -0,0 +1,22 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +--- +name: 'OracleDatabase' +display_name: 'OracleDatabase' +versions: + - name: 'ga' + base_url: 'https://oracledatabase.googleapis.com/v1/' + - name: 'beta' + base_url: 'https://oracledatabase.googleapis.com/v1/' +scopes: + - 'https://www.googleapis.com/auth/cloud-platform' diff --git a/mmv1/products/pubsub/Subscription.yaml b/mmv1/products/pubsub/Subscription.yaml index 5ed3ea7988db..637be094da13 100644 --- a/mmv1/products/pubsub/Subscription.yaml +++ b/mmv1/products/pubsub/Subscription.yaml @@ -471,6 +471,8 @@ properties: A duration in seconds with up to nine fractional digits, terminated by 's'. Example: "3.5s". default_from_api: true diff_suppress_func: 'tpgresource.DurationDiffSuppress' + send_empty_value: true + allow_empty_object: true - name: 'enableMessageOrdering' type: Boolean description: | diff --git a/mmv1/products/securesourcemanager/BranchRule.yaml b/mmv1/products/securesourcemanager/BranchRule.yaml new file mode 100644 index 000000000000..5d5bd25580f9 --- /dev/null +++ b/mmv1/products/securesourcemanager/BranchRule.yaml @@ -0,0 +1,142 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: 'BranchRule' +description: 'BranchRule is the protection rule to enforce pre-defined rules on designated branches within a repository.' +references: + guides: + 'Official Documentation': 'https://cloud.google.com/secure-source-manager/docs/overview' +docs: +id_format: 'projects/{{project}}/locations/{{location}}/repositories/{{repository_id}}/branchRules/{{branch_rule_id}}' +base_url: 'projects/{{project}}/locations/{{location}}/repositories/{{repository_id}}/branchRules?branch_rule_id={{branch_rule_id}}' +self_link: 'projects/{{project}}/locations/{{location}}/repositories/{{repository_id}}/branchRules/{{branch_rule_id}}' +import_format: + - 'projects/{{project}}/locations/{{location}}/repositories/{{repository_id}}/branchRules/{{branch_rule_id}}' + - '{{branch_rule_id}}' +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +autogen_async: true +update_verb: 'PATCH' +update_mask: true +async: + actions: ['create', 'delete'] + type: 'OpAsync' + operation: + base_url: '{{op_id}}' + wait_ms: 1000 + result: + path: 'response' + resource_inside_response: false + error: + path: 'error' + message: 'message' +custom_code: +examples: + - name: 'secure_source_manager_branch_rule_basic' + primary_resource_id: 'basic' + vars: + branch_rule_id: 'my-basic-branchrule' + repository_id: 'my-basic-repository' + instance_id: 'my-basic-instance' + prevent_destroy: 'true' + test_vars_overrides: + 'prevent_destroy': 'false' + oics_vars_overrides: + 'prevent_destroy': 'false' + - name: 'secure_source_manager_branch_rule_with_fields' + primary_resource_id: 'default' + vars: + branch_rule_id: 'my-initial-branchrule' + repository_id: 'my-initial-repository' + instance_id: 'my-initial-instance' + prevent_destroy: 'true' + test_vars_overrides: + 'prevent_destroy': 'false' + oics_vars_overrides: + 'prevent_destroy': 'false' +parameters: + - name: 'branch_rule_id' + type: String + description: | + The ID for the BranchRule. + url_param_only: true + required: true + - name: 'location' + type: String + description: | + The location for the Repository. + url_param_only: true + required: true + - name: 'repository_id' + type: String + description: | + The ID for the Repository. + url_param_only: true + required: true +properties: + - name: 'name' + type: String + description: | + The resource name for the BranchRule. + output: true + - name: 'uid' + type: String + description: | + Unique identifier of the BranchRule. + output: true + - name: 'createTime' + type: Time + description: | + Time the BranchRule was created in UTC. + output: true + - name: 'updateTime' + type: Time + description: | + Time the BranchRule was updated in UTC. + output: true + - name: 'includePattern' + type: String + description: | + The BranchRule matches branches based on the specified regular expression. Use .* to match all branches. + required: true + - name: 'disabled' + type: Boolean + description: | + Determines if the branch rule is disabled or not. + - name: 'requirePullRequest' + type: Boolean + description: | + Determines if the branch rule requires a pull request or not. + - name: 'minimumReviewsCount' + type: Integer + description: | + The minimum number of reviews required for the branch rule to be matched. + - name: 'minimumApprovalsCount' + type: Integer + description: | + The minimum number of approvals required for the branch rule to be matched. + - name: 'requireCommentsResolved' + type: Boolean + description: | + Determines if require comments resolved before merging to the branch. + - name: 'allowStaleReviews' + type: Boolean + description: | + Determines if allow stale reviews or approvals before merging to the branch. + - name: 'requireLinearHistory' + type: Boolean + description: | + Determines if require linear history before merging to the branch. diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index 5e0eca341608..ad4a0c45ecbd 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -150,8 +150,22 @@ properties: description: | Fully qualified name of the KMS key to use to encrypt this database. This key must exist in the same location as the Spanner Database. - required: true immutable: true + exactly_one_of: + - encryption_config.0.kms_key_name + - encryption_config.0.kms_key_names + - name: 'kmsKeyNames' + type: Array + description: | + Fully qualified name of the KMS keys to use to encrypt this database. The keys must exist + in the same locations as the Spanner Database. + immutable: true + custom_flatten: templates/terraform/custom_flatten/spanner_database_kms_key_names.go.tmpl + item_type: + type: String + exactly_one_of: + - encryption_config.0.kms_key_name + - encryption_config.0.kms_key_names - name: 'databaseDialect' type: Enum description: | diff --git a/mmv1/products/transcoder/Job.yaml b/mmv1/products/transcoder/Job.yaml new file mode 100644 index 000000000000..258864d35ac2 --- /dev/null +++ b/mmv1/products/transcoder/Job.yaml @@ -0,0 +1,571 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: 'Job' +description: "Transcoding Job Resource" +references: + guides: + 'Transcoder': 'https://cloud.google.com/transcoder/docs/' + api: 'https://cloud.google.com/transcoder/docs/reference/rest/v1/projects.locations.jobs' +docs: +base_url: 'projects/{{project}}/locations/{{location}}/jobs' +self_link: '{{name}}' +create_url: 'projects/{{project}}/locations/{{location}}/jobs' +immutable: true +import_format: + - '{{name}}' +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +custom_code: + custom_import: 'templates/terraform/custom_import/self_link_as_name.tmpl' +examples: + - name: 'transcoder_job_basic' + primary_resource_id: 'default' + vars: + job_template_id: 'example-job-template' + bucket_name: 'transcoder-job' + ignore_read_extra: + - 'state' + - 'end_time' + - name: 'transcoder_job_pubsub' + primary_resource_id: 'default' + vars: + job_template_id: 'example-job-template' + bucket_name: 'transcoder-job' + pub_sub_topic_name: 'transcoder-notifications' + ignore_read_extra: + - 'state' + - 'end_time' + - name: 'transcoder_job_encryptions' + primary_resource_id: 'default' + min_version: 'beta' + vars: + job_template_id: 'example-job-template' + bucket_name: 'transcoder-job' + secret_manager_secret_id: 'transcoder-encryption-key' + ignore_read_extra: + - 'state' + - 'end_time' + - name: 'transcoder_job_overlays' + primary_resource_id: 'default' + vars: + job_template_id: 'example-job-template' + bucket_name: 'transcoder-job' + ignore_read_extra: + - 'state' + - 'end_time' + - name: 'transcoder_job_manifests' + primary_resource_id: 'default' + vars: + job_template_id: 'example-job-template' + bucket_name: 'transcoder-job' + ignore_read_extra: + - 'state' + - 'end_time' +parameters: + - name: 'location' + type: String + description: | + The location of the transcoding job resource. + url_param_only: true + required: true + immutable: true +properties: + - name: 'name' + type: String + description: | + The resource name of the job. + output: true + - name: 'createTime' + type: Time + description: | + The time the job was created. + output: true + - name: 'startTime' + type: Time + description: | + The time the transcoding started. + output: true + - name: 'endTime' + type: Time + description: | + The time the transcoding finished. + output: true + - name: 'state' + type: Enum + description: | + The current state of the job. + output: true + enum_values: + - 'PROCESSING_STATE_UNSPECIFIED' + - 'PENDING' + - 'RUNNING' + - 'SUCCEEDED' + - 'FAILED' + - name: 'labels' + type: KeyValueLabels + description: | + The labels associated with this job. You can use these to organize and group your jobs. + - name: 'templateId' + type: String + description: | + Specify the templateId to use for populating Job.config. + The default is preset/web-hd, which is the only supported preset. + ignore_read: true + default_from_api: true + - name: 'config' + type: NestedObject + description: | + The configuration for this template. + default_from_api: true + properties: + - name: 'inputs' + type: Array + description: | + List of input assets stored in Cloud Storage. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'key' + type: String + description: | + A unique key for this input. Must be specified when using advanced mapping and edit lists. + default_from_api: true + - name: 'uri' + type: String + description: | + URI of the media. Input files must be at least 5 seconds in duration and stored in Cloud Storage (for example, gs://bucket/inputs/file.mp4). + If empty, the value is populated from Job.input_uri. + default_from_api: true + - name: 'editList' + type: Array + description: | + List of input assets stored in Cloud Storage. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'key' + type: String + description: | + A unique key for this atom. + default_from_api: true + - name: 'inputs' + type: Array + description: | + List of values identifying files that should be used in this atom. + default_from_api: true + item_type: + type: String + - name: 'startTimeOffset' + type: Time + description: | + Start time in seconds for the atom, relative to the input file timeline. The default is `0s`. + default_from_api: true + - name: 'elementaryStreams' + type: Array + description: | + List of input assets stored in Cloud Storage. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'key' + type: String + description: | + A unique key for this atom. + default_from_api: true + - name: 'videoStream' + type: NestedObject + description: | + Encoding of a video stream. + default_from_api: true + properties: + - name: 'h264' + type: NestedObject + description: | + H264 codec settings + default_from_api: true + properties: + - name: 'widthPixels' + type: Integer + description: | + The width of the video in pixels. + default_from_api: true + - name: 'heightPixels' + type: Integer + description: | + The height of the video in pixels. + default_from_api: true + - name: 'frameRate' + type: Integer + description: The target video frame rate in frames per second (FPS). + required: true + - name: 'bitrateBps' + type: Integer + description: The video bitrate in bits per second. + required: true + - name: 'pixelFormat' + type: String + description: Pixel format to use. The default is `yuv420p`. + default_from_api: true + - name: 'rateControlMode' + type: String + description: Specify the mode. The default is `vbr`. + default_from_api: true + - name: 'crfLevel' + type: Integer + description: Target CRF level. The default is `21`. + default_from_api: true + - name: 'vbvSizeBits' + type: Integer + description: Size of the Video Buffering Verifier (VBV) buffer in bits. + default_from_api: true + - name: 'vbvFullnessBits' + type: Integer + description: Initial fullness of the Video Buffering Verifier (VBV) buffer in bits. + default_from_api: true + - name: 'entropyCoder' + type: String + description: The entropy coder to use. The default is `cabac`. + default_from_api: true + - name: 'profile' + type: String + description: Enforces the specified codec profile. + default_from_api: true + - name: 'preset' + type: String + description: Enforces the specified codec preset. The default is `veryfast`. + default_from_api: true + - name: 'gopDuration' + type: Time + description: Select the GOP size based on the specified duration. The default is `3s`. + default_from_api: true + - name: 'sdr' + type: NestedObject + description: SDR color format setting for H264. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'hlg' + type: NestedObject + description: HLG color format setting for H264. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'audioStream' + type: NestedObject + description: | + Encoding of an audio stream. + default_from_api: true + properties: + - name: 'codec' + type: String + description: The codec for this audio stream. The default is `aac`. + default_from_api: true + - name: 'bitrateBps' + type: Integer + description: Audio bitrate in bits per second. + required: true + - name: 'channelCount' + type: Integer + description: Number of audio channels. The default is `2`. + default_from_api: true + - name: 'channelLayout' + type: Array + description: | + A list of channel names specifying layout of the audio channels. The default is ["fl", "fr"]. + default_from_api: true + item_type: + type: String + - name: 'sampleRateHertz' + type: Integer + description: | + The audio sample rate in Hertz. The default is `48000`. + default_from_api: true + - name: 'muxStreams' + type: Array + description: | + Multiplexing settings for output stream. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'key' + type: String + description: | + A unique key for this multiplexed stream. + default_from_api: true + - name: 'fileName' + type: String + description: | + The name of the generated file. + default_from_api: true + - name: 'container' + type: String + description: | + The container format. The default is `mp4`. + default_from_api: true + - name: 'elementaryStreams' + type: Array + description: | + List of ElementaryStream.key values multiplexed in this stream. + default_from_api: true + item_type: + type: String + - name: 'segmentSettings' + type: NestedObject + description: | + Segment settings for ts, fmp4 and vtt. + default_from_api: true + properties: + - name: 'segmentDuration' + type: Time + description: | + Duration of the segments in seconds. The default is `6.0s`. + default_from_api: true + - name: 'encryptionId' + type: String + description: | + Identifier of the encryption configuration to use. + default_from_api: true + - name: 'manifests' + type: Array + description: | + Manifest configuration. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'fileName' + type: String + description: | + The name of the generated file. The default is `manifest`. + default_from_api: true + - name: 'type' + type: Enum + description: | + Type of the manifest. + required: true + default_from_api: true + enum_values: + - 'MANIFEST_TYPE_UNSPECIFIED' + - 'HLS' + - 'DASH' + - name: 'muxStreams' + type: Array + description: | + List of user supplied MuxStream.key values that should appear in this manifest. + default_from_api: true + item_type: + type: String + - name: 'output' + type: NestedObject + description: | + Location of output file(s) in a Cloud Storage bucket. + default_from_api: true + properties: + - name: 'uri' + type: String + description: | + URI for the output file(s). For example, gs://my-bucket/outputs/. + default_from_api: true + - name: 'adBreaks' + type: Array + description: | + Ad break. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'startTimeOffset' + type: Time + description: | + Start time in seconds for the ad break, relative to the output file timeline + default_from_api: true + - name: 'pubsubDestination' + type: NestedObject + description: | + Pub/Sub destination. + default_from_api: true + properties: + - name: 'topic' + type: String + description: | + The name of the Pub/Sub topic to publish job completion notification to. For example: projects/{project}/topics/{topic}. + - name: 'overlays' + type: Array + description: | + List of overlays on the output video, in descending Z-order. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'image' + type: NestedObject + description: | + Image overlay. + default_from_api: true + properties: + - name: 'uri' + type: String + description: | + URI of the image in Cloud Storage. For example, gs://bucket/inputs/image.png. + required: true + - name: 'animations' + type: Array + description: | + List of animations. The list should be chronological, without any time overlap. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'animationFade' + type: NestedObject + description: | + Display overlay object with fade animation. + default_from_api: true + properties: + - name: 'xy' + type: NestedObject + description: | + Normalized coordinates based on output video resolution. + default_from_api: true + properties: + - name: 'x' + type: Double + description: | + Normalized x coordinate. + default_from_api: true + - name: 'y' + type: Double + description: | + Normalized y coordinate. + default_from_api: true + - name: 'startTimeOffset' + type: Time + description: | + The time to start the fade animation, in seconds. + default_from_api: true + - name: 'endTimeOffset' + type: Time + description: | + The time to end the fade animation, in seconds. + default_from_api: true + - name: 'fadeType' + type: Enum + description: | + Required. Type of fade animation: `FADE_IN` or `FADE_OUT`. + The possible values are: + + * `FADE_TYPE_UNSPECIFIED`: The fade type is not specified. + + * `FADE_IN`: Fade the overlay object into view. + + * `FADE_OUT`: Fade the overlay object out of view. + required: true + enum_values: + - 'FADE_TYPE_UNSPECIFIED' + - 'FADE_IN' + - 'FADE_OUT' + - name: 'encryptions' + type: Array + description: | + List of encryption configurations for the content. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'id' + type: String + description: | + Identifier for this set of encryption options. + required: true + - name: 'drmSystems' + type: NestedObject + description: | + DRM system(s) to use; at least one must be specified. If a DRM system is omitted, it is considered disabled. + default_from_api: true + properties: + - name: 'widevine' + type: NestedObject + description: Widevine configuration. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'fairplay' + type: NestedObject + description: Fairplay configuration. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'playready' + type: NestedObject + description: Playready configuration. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'clearkey' + type: NestedObject + description: Clearkey configuration. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'aes128' + type: NestedObject + description: | + Configuration for AES-128 encryption. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'sampleAes' + type: NestedObject + description: | + Configuration for SAMPLE-AES encryption. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'mpegCenc' + type: NestedObject + description: | + Configuration for MPEG Common Encryption (MPEG-CENC). + default_from_api: true + properties: + - name: 'scheme' + type: String + description: | + Specify the encryption scheme. + required: true + - name: 'secretManagerKeySource' + type: NestedObject + description: | + Configuration for secrets stored in Google Secret Manager. + default_from_api: true + properties: + - name: 'secretVersion' + type: String + description: | + The name of the Secret Version containing the encryption key in the following format: projects/{project}/secrets/{secret_id}/versions/{version_number}. + required: true diff --git a/mmv1/products/transcoder/JobTemplate.yaml b/mmv1/products/transcoder/JobTemplate.yaml new file mode 100644 index 000000000000..6c04ff35c55e --- /dev/null +++ b/mmv1/products/transcoder/JobTemplate.yaml @@ -0,0 +1,520 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: 'JobTemplate' +description: "Transcoding Job Template Resource" +references: + guides: + 'Transcoder': 'https://cloud.google.com/transcoder/docs/' + api: 'https://cloud.google.com/transcoder/docs/reference/rest/v1/projects.locations.jobTemplates' +docs: +base_url: 'projects/{{project}}/locations/{{location}}/jobTemplates' +self_link: 'projects/{{project}}/locations/{{location}}/jobTemplates/{{job_template_id}}' +create_url: 'projects/{{project}}/locations/{{location}}/jobTemplates?jobTemplateId={{job_template_id}}' +immutable: true +import_format: + - 'projects/{{project}}/locations/{{location}}/jobTemplates/{{job_template_id}}' +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +custom_code: +examples: + - name: 'transcoder_job_template_basic' + primary_resource_id: 'default' + vars: + job_template_id: 'example-job-template' + - name: 'transcoder_job_template_overlays' + primary_resource_id: 'default' + vars: + job_template_id: 'example-job-template' + - name: 'transcoder_job_template_encryptions' + primary_resource_id: 'default' + vars: + job_template_id: 'example-job-template' + secret_manager_secret_id: 'transcoder-encryption-key' + - name: 'transcoder_job_template_pubsub' + primary_resource_id: 'default' + vars: + job_template_id: 'example-job-template' + pub_sub_topic_name: 'transcoder-notifications' +parameters: + - name: 'jobTemplateId' + type: String + description: | + ID to use for the Transcoding job template. + url_param_only: true + required: true + immutable: true + - name: 'location' + type: String + description: | + The location of the transcoding job template resource. + url_param_only: true + required: true + immutable: true +properties: + - name: 'name' + type: String + description: | + The resource name of the job template. + output: true + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.tmpl' + - name: 'labels' + type: KeyValueLabels + description: | + The labels associated with this job template. You can use these to organize and group your job templates. + - name: 'config' + type: NestedObject + description: | + The configuration for this template. + default_from_api: true + properties: + - name: 'inputs' + type: Array + description: | + List of input assets stored in Cloud Storage. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'key' + type: String + description: | + A unique key for this input. Must be specified when using advanced mapping and edit lists. + default_from_api: true + - name: 'uri' + type: String + description: | + URI of the media. Input files must be at least 5 seconds in duration and stored in Cloud Storage (for example, gs://bucket/inputs/file.mp4). + If empty, the value is populated from Job.input_uri. + default_from_api: true + - name: 'editList' + type: Array + description: | + List of input assets stored in Cloud Storage. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'key' + type: String + description: | + A unique key for this atom. + default_from_api: true + - name: 'inputs' + type: Array + description: | + List of values identifying files that should be used in this atom. + default_from_api: true + item_type: + type: String + - name: 'startTimeOffset' + type: Time + description: | + Start time in seconds for the atom, relative to the input file timeline. The default is `0s`. + default_from_api: true + - name: 'elementaryStreams' + type: Array + description: | + List of input assets stored in Cloud Storage. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'key' + type: String + description: | + A unique key for this atom. + default_from_api: true + - name: 'videoStream' + type: NestedObject + description: | + Encoding of a video stream. + default_from_api: true + properties: + - name: 'h264' + type: NestedObject + description: | + H264 codec settings + default_from_api: true + properties: + - name: 'widthPixels' + type: Integer + description: | + The width of the video in pixels. + default_from_api: true + - name: 'heightPixels' + type: Integer + description: | + The height of the video in pixels. + default_from_api: true + - name: 'frameRate' + type: Integer + description: The target video frame rate in frames per second (FPS). + required: true + - name: 'bitrateBps' + type: Integer + description: The video bitrate in bits per second. + required: true + - name: 'pixelFormat' + type: String + description: Pixel format to use. The default is `yuv420p`. + default_from_api: true + - name: 'rateControlMode' + type: String + description: Specify the mode. The default is `vbr`. + default_from_api: true + - name: 'crfLevel' + type: Integer + description: Target CRF level. The default is `21`. + default_from_api: true + - name: 'vbvSizeBits' + type: Integer + description: Size of the Video Buffering Verifier (VBV) buffer in bits. + default_from_api: true + - name: 'vbvFullnessBits' + type: Integer + description: Initial fullness of the Video Buffering Verifier (VBV) buffer in bits. + default_from_api: true + - name: 'entropyCoder' + type: String + description: The entropy coder to use. The default is `cabac`. + default_from_api: true + - name: 'profile' + type: String + description: Enforces the specified codec profile. + default_from_api: true + - name: 'preset' + type: String + description: Enforces the specified codec preset. The default is `veryfast`. + default_from_api: true + - name: 'gopDuration' + type: Time + description: Select the GOP size based on the specified duration. The default is `3s`. + default_from_api: true + - name: 'sdr' + type: NestedObject + description: SDR color format setting for H264. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'hlg' + type: NestedObject + description: HLG color format setting for H264. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'audioStream' + type: NestedObject + description: | + Encoding of an audio stream. + default_from_api: true + properties: + - name: 'codec' + type: String + description: The codec for this audio stream. The default is `aac`. + default_from_api: true + - name: 'bitrateBps' + type: Integer + description: Audio bitrate in bits per second. + required: true + - name: 'channelCount' + type: Integer + description: Number of audio channels. The default is `2`. + default_from_api: true + - name: 'channelLayout' + type: Array + description: | + A list of channel names specifying layout of the audio channels. The default is ["fl", "fr"]. + default_from_api: true + item_type: + type: String + - name: 'sampleRateHertz' + type: Integer + description: | + The audio sample rate in Hertz. The default is `48000`. + default_from_api: true + - name: 'muxStreams' + type: Array + description: | + Multiplexing settings for output stream. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'key' + type: String + description: | + A unique key for this multiplexed stream. + default_from_api: true + - name: 'fileName' + type: String + description: | + The name of the generated file. + default_from_api: true + - name: 'container' + type: String + description: | + The container format. The default is `mp4`. + default_from_api: true + - name: 'elementaryStreams' + type: Array + description: | + List of ElementaryStream.key values multiplexed in this stream. + default_from_api: true + item_type: + type: String + - name: 'segmentSettings' + type: NestedObject + description: | + Segment settings for ts, fmp4 and vtt. + default_from_api: true + properties: + - name: 'segmentDuration' + type: Time + description: | + Duration of the segments in seconds. The default is `6.0s`. + default_from_api: true + - name: 'encryptionId' + type: String + description: | + Identifier of the encryption configuration to use. + default_from_api: true + - name: 'manifests' + type: Array + description: | + Manifest configuration. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'fileName' + type: String + description: | + The name of the generated file. The default is `manifest`. + default_from_api: true + - name: 'type' + type: Enum + description: | + Type of the manifest. + required: true + default_from_api: true + enum_values: + - 'MANIFEST_TYPE_UNSPECIFIED' + - 'HLS' + - 'DASH' + - name: 'muxStreams' + type: Array + description: | + List of user supplied MuxStream.key values that should appear in this manifest. + default_from_api: true + item_type: + type: String + - name: 'output' + type: NestedObject + description: | + Location of output file(s) in a Cloud Storage bucket. + default_from_api: true + properties: + - name: 'uri' + type: String + description: | + URI for the output file(s). For example, gs://my-bucket/outputs/. + default_from_api: true + - name: 'adBreaks' + type: Array + description: | + Ad break. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'startTimeOffset' + type: Time + description: | + Start time in seconds for the ad break, relative to the output file timeline + default_from_api: true + - name: 'pubsubDestination' + type: NestedObject + description: | + Pub/Sub destination. + default_from_api: true + properties: + - name: 'topic' + type: String + description: | + The name of the Pub/Sub topic to publish job completion notification to. For example: projects/{project}/topics/{topic}. + - name: 'overlays' + type: Array + description: | + List of overlays on the output video, in descending Z-order. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'image' + type: NestedObject + description: | + Image overlay. + default_from_api: true + properties: + - name: 'uri' + type: String + description: | + URI of the image in Cloud Storage. For example, gs://bucket/inputs/image.png. + required: true + - name: 'animations' + type: Array + description: | + List of animations. The list should be chronological, without any time overlap. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'animationFade' + type: NestedObject + description: | + Display overlay object with fade animation. + default_from_api: true + properties: + - name: 'xy' + type: NestedObject + description: | + Normalized coordinates based on output video resolution. + default_from_api: true + properties: + - name: 'x' + type: Double + description: | + Normalized x coordinate. + default_from_api: true + - name: 'y' + type: Double + description: | + Normalized y coordinate. + default_from_api: true + - name: 'startTimeOffset' + type: Time + description: | + The time to start the fade animation, in seconds. + default_from_api: true + - name: 'endTimeOffset' + type: Time + description: | + The time to end the fade animation, in seconds. + default_from_api: true + - name: 'fadeType' + type: Enum + description: | + Required. Type of fade animation: `FADE_IN` or `FADE_OUT`. + The possible values are: + + * `FADE_TYPE_UNSPECIFIED`: The fade type is not specified. + + * `FADE_IN`: Fade the overlay object into view. + + * `FADE_OUT`: Fade the overlay object out of view. + required: true + enum_values: + - 'FADE_TYPE_UNSPECIFIED' + - 'FADE_IN' + - 'FADE_OUT' + - name: 'encryptions' + type: Array + description: | + List of encryption configurations for the content. + default_from_api: true + item_type: + type: NestedObject + properties: + - name: 'id' + type: String + description: | + Identifier for this set of encryption options. + required: true + - name: 'drmSystems' + type: NestedObject + description: | + DRM system(s) to use; at least one must be specified. If a DRM system is omitted, it is considered disabled. + default_from_api: true + properties: + - name: 'widevine' + type: NestedObject + description: Widevine configuration. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'fairplay' + type: NestedObject + description: Fairplay configuration. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'playready' + type: NestedObject + description: Playready configuration. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'clearkey' + type: NestedObject + description: Clearkey configuration. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'aes128' + type: NestedObject + description: | + Configuration for AES-128 encryption. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'sampleAes' + type: NestedObject + description: | + Configuration for SAMPLE-AES encryption. + send_empty_value: true + allow_empty_object: true + properties: + [] + - name: 'mpegCenc' + type: NestedObject + description: | + Configuration for MPEG Common Encryption (MPEG-CENC). + default_from_api: true + properties: + - name: 'scheme' + type: String + description: | + Specify the encryption scheme. + required: true + - name: 'secretManagerKeySource' + type: NestedObject + description: | + Configuration for secrets stored in Google Secret Manager. + default_from_api: true + properties: + - name: 'secretVersion' + type: String + description: | + The name of the Secret Version containing the encryption key in the following format: projects/{project}/secrets/{secret_id}/versions/{version_number}. + required: true diff --git a/mmv1/products/transcoder/product.yaml b/mmv1/products/transcoder/product.yaml new file mode 100644 index 000000000000..fc39c1c39ab8 --- /dev/null +++ b/mmv1/products/transcoder/product.yaml @@ -0,0 +1,21 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +name: 'Transcoder' +display_name: 'Transcoder' +versions: + - name: 'ga' + base_url: 'https://transcoder.googleapis.com/v1/' +scopes: + - 'https://www.googleapis.com/auth/cloud-platform' diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index 0fe975169399..0fa00f89cfac 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -119,6 +119,12 @@ examples: account_id: 'my-account' workstation_cluster_name: 'workstation-cluster' workstation_config_name: 'workstation-config' + - name: 'workstation_config_allowed_ports' + primary_resource_id: 'default' + min_version: 'beta' + vars: + workstation_cluster_name: 'workstation-cluster' + workstation_config_name: 'workstation-config' parameters: - name: 'workstationConfigId' type: String @@ -650,6 +656,25 @@ properties: description: | Disables support for plain TCP connections in the workstation. By default the service supports TCP connections via a websocket relay. Setting this option to true disables that relay, which prevents the usage of services that require plain tcp connections, such as ssh. When enabled, all communication must occur over https or wss. min_version: 'beta' + - name: 'allowedPorts' + type: Array + default_from_api: true + description: | + A list of port ranges specifying single ports or ranges of ports that are externally accessible in the workstation. Allowed ports must be one of 22, 80, or within range 1024-65535. If not specified defaults to ports 22, 80, and ports 1024-65535. + min_version: 'beta' + item_type: + type: NestedObject + properties: + - name: 'first' + type: Integer + description: | + Starting port number for the current range of ports. Valid ports are 22, 80, and ports within the range 1024-65535. + min_version: 'beta' + - name: 'last' + type: Integer + description: | + Ending port number for the current range of ports. Valid ports are 22, 80, and ports within the range 1024-65535. + min_version: 'beta' - name: 'conditions' type: Array description: |- diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go index eadc67ffe24d..862f85a84cb4 100644 --- a/mmv1/provider/template_data.go +++ b/mmv1/provider/template_data.go @@ -15,6 +15,7 @@ package provider import ( "bytes" + "errors" "fmt" "go/format" "log" @@ -22,6 +23,7 @@ import ( "os/exec" "path/filepath" "strings" + "sync" "text/template" @@ -48,6 +50,8 @@ var BETA_VERSION = "beta" var ALPHA_VERSION = "alpha" var PRIVATE_VERSION = "private" +var goimportFiles sync.Map + func NewTemplateData(outputFolder string, versionName string) *TemplateData { td := TemplateData{OutputFolder: outputFolder, VersionName: versionName} @@ -208,20 +212,15 @@ func (td *TemplateData) GenerateFile(filePath, templatePath string, input any, g } else { sourceByte = formattedByte } + if !strings.Contains(templatePath, "third_party/terraform") { + goimportFiles.Store(filePath, struct{}{}) + } } err = os.WriteFile(filePath, sourceByte, 0644) if err != nil { glog.Exit(err) } - - if goFormat && !strings.Contains(templatePath, "third_party/terraform") { - cmd := exec.Command("goimports", "-w", filepath.Base(filePath)) - cmd.Dir = filepath.Dir(filePath) - if err := cmd.Run(); err != nil { - log.Fatal(err) - } - } } func (td *TemplateData) ImportPath() string { @@ -233,6 +232,44 @@ func (td *TemplateData) ImportPath() string { return "github.com/hashicorp/terraform-provider-google-beta/google-beta" } +func FixImports(outputPath string, dumpDiffs bool) { + log.Printf("Fixing go import paths") + + baseArgs := []string{"-w"} + if dumpDiffs { + baseArgs = []string{"-d", "-w"} + } + + // -w and -d are mutually exclusive; if dumpDiffs is requested we need to run twice. + for _, base := range baseArgs { + hasFiles := false + args := []string{base} + goimportFiles.Range(func(filePath, _ any) bool { + p, err := filepath.Rel(outputPath, filePath.(string)) + if err != nil { + log.Fatal(err) + } + args = append(args, p) + hasFiles = true + return true + }) + + if hasFiles { + cmd := exec.Command("goimports", args...) + cmd.Dir = outputPath + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + if err := cmd.Run(); err != nil { + var exitErr *exec.ExitError + if errors.As(err, &exitErr) && len(exitErr.Stderr) > 0 { + glog.Error(string(exitErr.Stderr)) + } + log.Fatal(err) + } + } + } +} + type TestInput struct { Res api.Resource ImportPath string diff --git a/mmv1/provider/terraform_tgc.go b/mmv1/provider/terraform_tgc.go index d3e45ef44d32..392db06b21e2 100644 --- a/mmv1/provider/terraform_tgc.go +++ b/mmv1/provider/terraform_tgc.go @@ -207,7 +207,7 @@ func (tgc TerraformGoogleConversion) CompileCommonFiles(outputFolder string, pro "converters/google/resources/services/kms/iam_kms_key_ring.go": "third_party/terraform/services/kms/iam_kms_key_ring.go.tmpl", "converters/google/resources/services/kms/iam_kms_crypto_key.go": "third_party/terraform/services/kms/iam_kms_crypto_key.go.tmpl", "converters/google/resources/services/compute/metadata.go": "third_party/terraform/services/compute/metadata.go.tmpl", - "converters/google/resources/services/compute/compute_instance.go": "third_party/tgc/compute_instance.go.tmpl", + "converters/google/resources/services/compute/compute_instance.go": "third_party/tgc/services/compute/compute_instance.go.tmpl", } tgc.CompileFileList(outputFolder, resourceConverters, *templateData, products) } @@ -352,81 +352,82 @@ func (tgc TerraformGoogleConversion) CopyCommonFiles(outputFolder string, genera tgc.CopyFileList(outputFolder, retrieveTestSourceCodeWithLocation(".go")) resourceConverters := map[string]string{ - "converters/google/resources/cai/constants.go": "third_party/tgc/cai/constants.go", - "converters/google/resources/constants.go": "third_party/tgc/constants.go", - "converters/google/resources/cai.go": "third_party/tgc/cai.go", - "converters/google/resources/cai/cai.go": "third_party/tgc/cai/cai.go", - "converters/google/resources/cai/cai_test.go": "third_party/tgc/cai/cai_test.go", - "converters/google/resources/org_policy_policy.go": "third_party/tgc/org_policy_policy.go", - "converters/google/resources/getconfig.go": "third_party/tgc/getconfig.go", - "converters/google/resources/folder.go": "third_party/tgc/folder.go", - "converters/google/resources/getconfig_test.go": "third_party/tgc/getconfig_test.go", - "converters/google/resources/cai/json_map.go": "third_party/tgc/cai/json_map.go", - "converters/google/resources/project.go": "third_party/tgc/project.go", - "converters/google/resources/sql_database_instance.go": "third_party/tgc/sql_database_instance.go", - "converters/google/resources/storage_bucket.go": "third_party/tgc/storage_bucket.go", - "converters/google/resources/cloudfunctions_function.go": "third_party/tgc/cloudfunctions_function.go", - "converters/google/resources/cloudfunctions_cloud_function.go": "third_party/tgc/cloudfunctions_cloud_function.go", - "converters/google/resources/bigquery_table.go": "third_party/tgc/bigquery_table.go", - "converters/google/resources/bigtable_cluster.go": "third_party/tgc/bigtable_cluster.go", - "converters/google/resources/bigtable_instance.go": "third_party/tgc/bigtable_instance.go", - "converters/google/resources/cai/iam_helpers.go": "third_party/tgc/cai/iam_helpers.go", - "converters/google/resources/cai/iam_helpers_test.go": "third_party/tgc/cai/iam_helpers_test.go", - "converters/google/resources/services/resourcemanager/organization_iam.go": "third_party/tgc/organization_iam.go", - "converters/google/resources/services/resourcemanager/project_iam.go": "third_party/tgc/project_iam.go", - "converters/google/resources/project_organization_policy.go": "third_party/tgc/project_organization_policy.go", - "converters/google/resources/folder_organization_policy.go": "third_party/tgc/folder_organization_policy.go", - "converters/google/resources/services/resourcemanager/folder_iam.go": "third_party/tgc/folder_iam.go", - "converters/google/resources/container.go": "third_party/tgc/container.go", - "converters/google/resources/project_service.go": "third_party/tgc/project_service.go", - "converters/google/resources/services/monitoring/monitoring_slo_helper.go": "third_party/tgc/monitoring_slo_helper.go", - "converters/google/resources/service_account.go": "third_party/tgc/service_account.go", - "converters/google/resources/services/compute/image.go": "third_party/terraform/services/compute/image.go", - "converters/google/resources/services/compute/disk_type.go": "third_party/terraform/services/compute/disk_type.go", - "converters/google/resources/services/kms/kms_utils.go": "third_party/terraform/services/kms/kms_utils.go", - "converters/google/resources/services/sourcerepo/source_repo_utils.go": "third_party/terraform/services/sourcerepo/source_repo_utils.go", - "converters/google/resources/services/pubsub/pubsub_utils.go": "third_party/terraform/services/pubsub/pubsub_utils.go", - "converters/google/resources/services/resourcemanager/iam_organization.go": "third_party/terraform/services/resourcemanager/iam_organization.go", - "converters/google/resources/services/resourcemanager/iam_folder.go": "third_party/terraform/services/resourcemanager/iam_folder.go", - "converters/google/resources/services/resourcemanager/iam_project.go": "third_party/terraform/services/resourcemanager/iam_project.go", - "converters/google/resources/services/privateca/privateca_utils.go": "third_party/terraform/services/privateca/privateca_utils.go", - "converters/google/resources/services/bigquery/iam_bigquery_dataset.go": "third_party/terraform/services/bigquery/iam_bigquery_dataset.go", - "converters/google/resources/services/bigquery/bigquery_dataset_iam.go": "third_party/tgc/bigquery_dataset_iam.go", - "converters/google/resources/compute_security_policy.go": "third_party/tgc/compute_security_policy.go", - "converters/google/resources/kms_key_ring_iam.go": "third_party/tgc/kms_key_ring_iam.go", - "converters/google/resources/kms_crypto_key_iam.go": "third_party/tgc/kms_crypto_key_iam.go", - "converters/google/resources/project_iam_custom_role.go": "third_party/tgc/project_iam_custom_role.go", - "converters/google/resources/organization_iam_custom_role.go": "third_party/tgc/organization_iam_custom_role.go", - "converters/google/resources/services/pubsub/iam_pubsub_subscription.go": "third_party/terraform/services/pubsub/iam_pubsub_subscription.go", - "converters/google/resources/services/pubsub/pubsub_subscription_iam.go": "third_party/tgc/pubsub_subscription_iam.go", - "converters/google/resources/services/spanner/iam_spanner_database.go": "third_party/terraform/services/spanner/iam_spanner_database.go", - "converters/google/resources/services/spanner/spanner_database_iam.go": "third_party/tgc/spanner_database_iam.go", - "converters/google/resources/services/spanner/iam_spanner_instance.go": "third_party/terraform/services/spanner/iam_spanner_instance.go", - "converters/google/resources/services/spanner/spanner_instance_iam.go": "third_party/tgc/spanner_instance_iam.go", - "converters/google/resources/storage_bucket_iam.go": "third_party/tgc/storage_bucket_iam.go", - "converters/google/resources/organization_policy.go": "third_party/tgc/organization_policy.go", - "converters/google/resources/iam_storage_bucket.go": "third_party/tgc/iam_storage_bucket.go", - "ancestrymanager/ancestrymanager.go": "third_party/tgc/ancestrymanager/ancestrymanager.go", - "ancestrymanager/ancestrymanager_test.go": "third_party/tgc/ancestrymanager/ancestrymanager_test.go", - "ancestrymanager/ancestryutil.go": "third_party/tgc/ancestrymanager/ancestryutil.go", - "ancestrymanager/ancestryutil_test.go": "third_party/tgc/ancestrymanager/ancestryutil_test.go", - "converters/google/convert.go": "third_party/tgc/convert.go", - "converters/google/convert_test.go": "third_party/tgc/convert_test.go", - "converters/google/resources/compute_instance_group.go": "third_party/tgc/compute_instance_group.go", - "converters/google/resources/job.go": "third_party/tgc/job.go", - "converters/google/resources/service_account_key.go": "third_party/tgc/service_account_key.go", - "converters/google/resources/compute_target_pool.go": "third_party/tgc/compute_target_pool.go", - "converters/google/resources/dataproc_cluster.go": "third_party/tgc/dataproc_cluster.go", - "converters/google/resources/composer_environment.go": "third_party/tgc/composer_environment.go", - "converters/google/resources/commitment.go": "third_party/tgc/commitment.go", - "converters/google/resources/firebase_project.go": "third_party/tgc/firebase_project.go", - "converters/google/resources/appengine_application.go": "third_party/tgc/appengine_application.go", - "converters/google/resources/apikeys_key.go": "third_party/tgc/apikeys_key.go", - "converters/google/resources/logging_folder_bucket_config.go": "third_party/tgc/logging_folder_bucket_config.go", - "converters/google/resources/logging_organization_bucket_config.go": "third_party/tgc/logging_organization_bucket_config.go", - "converters/google/resources/logging_project_bucket_config.go": "third_party/tgc/logging_project_bucket_config.go", - "converters/google/resources/logging_billing_account_bucket_config.go": "third_party/tgc/logging_billing_account_bucket_config.go", - "converters/google/resources/appengine_standard_version.go": "third_party/tgc/appengine_standard_version.go", + "converters/google/resources/cai/constants.go": "third_party/tgc/cai/constants.go", + "converters/google/resources/constants.go": "third_party/tgc/constants.go", + "converters/google/resources/cai.go": "third_party/tgc/cai.go", + "converters/google/resources/cai/cai.go": "third_party/tgc/cai/cai.go", + "converters/google/resources/cai/cai_test.go": "third_party/tgc/cai/cai_test.go", + "converters/google/resources/services/resourcemanager/org_policy_policy.go": "third_party/tgc/services/resourcemanager/org_policy_policy.go", + "converters/google/resources/getconfig.go": "third_party/tgc/getconfig.go", + "converters/google/resources/services/resourcemanager/folder.go": "third_party/tgc/services/resourcemanager/folder.go", + "converters/google/resources/getconfig_test.go": "third_party/tgc/getconfig_test.go", + "converters/google/resources/cai/json_map.go": "third_party/tgc/cai/json_map.go", + "converters/google/resources/cai/string_helpers.go": "third_party/tgc/cai/string_helpers.go", + "converters/google/resources/services/resourcemanager/project.go": "third_party/tgc/services/resourcemanager/project.go", + "converters/google/resources/services/sql/sql_database_instance.go": "third_party/tgc/services/sql/sql_database_instance.go", + "converters/google/resources/services/storage/storage_bucket.go": "third_party/tgc/services/storage/storage_bucket.go", + "converters/google/resources/services/cloudfunctions/cloudfunctions_function.go": "third_party/tgc/services/cloudfunctions/cloudfunctions_function.go", + "converters/google/resources/services/cloudfunctions/cloudfunctions_cloud_function.go": "third_party/tgc/services/cloudfunctions/cloudfunctions_cloud_function.go", + "converters/google/resources/services/bigquery/bigquery_table.go": "third_party/tgc/services/bigquery/bigquery_table.go", + "converters/google/resources/services/bigtable/bigtable_cluster.go": "third_party/tgc/services/bigtable/bigtable_cluster.go", + "converters/google/resources/services/bigtable/bigtable_instance.go": "third_party/tgc/services/bigtable/bigtable_instance.go", + "converters/google/resources/cai/iam_helpers.go": "third_party/tgc/cai/iam_helpers.go", + "converters/google/resources/cai/iam_helpers_test.go": "third_party/tgc/cai/iam_helpers_test.go", + "converters/google/resources/services/resourcemanager/organization_iam.go": "third_party/tgc/services/resourcemanager/organization_iam.go", + "converters/google/resources/services/resourcemanager/project_iam.go": "third_party/tgc/services/resourcemanager/project_iam.go", + "converters/google/resources/services/resourcemanager/project_organization_policy.go": "third_party/tgc/services/resourcemanager/project_organization_policy.go", + "converters/google/resources/services/resourcemanager/folder_organization_policy.go": "third_party/tgc/services/resourcemanager/folder_organization_policy.go", + "converters/google/resources/services/resourcemanager/folder_iam.go": "third_party/tgc/services/resourcemanager/folder_iam.go", + "converters/google/resources/services/container/container.go": "third_party/tgc/services/container/container.go", + "converters/google/resources/services/resourcemanager/project_service.go": "third_party/tgc/services/resourcemanager/project_service.go", + "converters/google/resources/services/monitoring/monitoring_slo_helper.go": "third_party/tgc/services/monitoring/monitoring_slo_helper.go", + "converters/google/resources/services/resourcemanager/service_account.go": "third_party/tgc/services/resourcemanager/service_account.go", + "converters/google/resources/services/compute/image.go": "third_party/terraform/services/compute/image.go", + "converters/google/resources/services/compute/disk_type.go": "third_party/terraform/services/compute/disk_type.go", + "converters/google/resources/services/kms/kms_utils.go": "third_party/terraform/services/kms/kms_utils.go", + "converters/google/resources/services/sourcerepo/source_repo_utils.go": "third_party/terraform/services/sourcerepo/source_repo_utils.go", + "converters/google/resources/services/pubsub/pubsub_utils.go": "third_party/terraform/services/pubsub/pubsub_utils.go", + "converters/google/resources/services/resourcemanager/iam_organization.go": "third_party/terraform/services/resourcemanager/iam_organization.go", + "converters/google/resources/services/resourcemanager/iam_folder.go": "third_party/terraform/services/resourcemanager/iam_folder.go", + "converters/google/resources/services/resourcemanager/iam_project.go": "third_party/terraform/services/resourcemanager/iam_project.go", + "converters/google/resources/services/privateca/privateca_utils.go": "third_party/terraform/services/privateca/privateca_utils.go", + "converters/google/resources/services/bigquery/iam_bigquery_dataset.go": "third_party/terraform/services/bigquery/iam_bigquery_dataset.go", + "converters/google/resources/services/bigquery/bigquery_dataset_iam.go": "third_party/tgc/services/bigquery/bigquery_dataset_iam.go", + "converters/google/resources/services/compute/compute_security_policy.go": "third_party/tgc/services/compute/compute_security_policy.go", + "converters/google/resources/services/kms/kms_key_ring_iam.go": "third_party/tgc/services/kms/kms_key_ring_iam.go", + "converters/google/resources/services/kms/kms_crypto_key_iam.go": "third_party/tgc/services/kms/kms_crypto_key_iam.go", + "converters/google/resources/services/resourcemanager/project_iam_custom_role.go": "third_party/tgc/services/resourcemanager/project_iam_custom_role.go", + "converters/google/resources/services/resourcemanager/organization_iam_custom_role.go": "third_party/tgc/services/resourcemanager/organization_iam_custom_role.go", + "converters/google/resources/services/pubsub/iam_pubsub_subscription.go": "third_party/terraform/services/pubsub/iam_pubsub_subscription.go", + "converters/google/resources/services/pubsub/pubsub_subscription_iam.go": "third_party/tgc/services/pubsub/pubsub_subscription_iam.go", + "converters/google/resources/services/spanner/iam_spanner_database.go": "third_party/terraform/services/spanner/iam_spanner_database.go", + "converters/google/resources/services/spanner/spanner_database_iam.go": "third_party/tgc/services/spanner/spanner_database_iam.go", + "converters/google/resources/services/spanner/iam_spanner_instance.go": "third_party/terraform/services/spanner/iam_spanner_instance.go", + "converters/google/resources/services/spanner/spanner_instance_iam.go": "third_party/tgc/services/spanner/spanner_instance_iam.go", + "converters/google/resources/services/storage/storage_bucket_iam.go": "third_party/tgc/services/storage/storage_bucket_iam.go", + "converters/google/resources/services/resourcemanager/organization_policy.go": "third_party/tgc/services/resourcemanager/organization_policy.go", + "converters/google/resources/services/storage/iam_storage_bucket.go": "third_party/tgc/services/storage/iam_storage_bucket.go", + "ancestrymanager/ancestrymanager.go": "third_party/tgc/ancestrymanager/ancestrymanager.go", + "ancestrymanager/ancestrymanager_test.go": "third_party/tgc/ancestrymanager/ancestrymanager_test.go", + "ancestrymanager/ancestryutil.go": "third_party/tgc/ancestrymanager/ancestryutil.go", + "ancestrymanager/ancestryutil_test.go": "third_party/tgc/ancestrymanager/ancestryutil_test.go", + "converters/google/convert.go": "third_party/tgc/convert.go", + "converters/google/convert_test.go": "third_party/tgc/convert_test.go", + "converters/google/resources/services/compute/compute_instance_group.go": "third_party/tgc/services/compute/compute_instance_group.go", + "converters/google/resources/services/dataflow/job.go": "third_party/tgc/services/dataflow/job.go", + "converters/google/resources/services/resourcemanager/service_account_key.go": "third_party/tgc/services/resourcemanager/service_account_key.go", + "converters/google/resources/services/compute/compute_target_pool.go": "third_party/tgc/services/compute/compute_target_pool.go", + "converters/google/resources/services/dataproc/dataproc_cluster.go": "third_party/tgc/services/dataproc/dataproc_cluster.go", + "converters/google/resources/services/composer/composer_environment.go": "third_party/tgc/services/composer/composer_environment.go", + "converters/google/resources/services/compute/commitment.go": "third_party/tgc/services/compute/commitment.go", + "converters/google/resources/services/firebase/firebase_project.go": "third_party/tgc/services/firebase/firebase_project.go", + "converters/google/resources/services/appengine/appengine_application.go": "third_party/tgc/services/appengine/appengine_application.go", + "converters/google/resources/services/apikeys/apikeys_key.go": "third_party/tgc/services/apikeys/apikeys_key.go", + "converters/google/resources/services/logging/logging_folder_bucket_config.go": "third_party/tgc/services/logging/logging_folder_bucket_config.go", + "converters/google/resources/services/logging/logging_organization_bucket_config.go": "third_party/tgc/services/logging/logging_organization_bucket_config.go", + "converters/google/resources/services/logging/logging_project_bucket_config.go": "third_party/tgc/services/logging/logging_project_bucket_config.go", + "converters/google/resources/services/logging/logging_billing_account_bucket_config.go": "third_party/tgc/services/logging/logging_billing_account_bucket_config.go", + "converters/google/resources/services/appengine/appengine_standard_version.go": "third_party/tgc/services/appengine/appengine_standard_version.go", } tgc.CopyFileList(outputFolder, resourceConverters) } diff --git a/mmv1/templates/terraform/custom_flatten/spanner_database_kms_key_names.go.tmpl b/mmv1/templates/terraform/custom_flatten/spanner_database_kms_key_names.go.tmpl new file mode 100644 index 000000000000..526fc566165c --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/spanner_database_kms_key_names.go.tmpl @@ -0,0 +1,31 @@ +func flatten{{$.GetPrefix}}{{$.TitlelizeProperty}}(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Ignore `kms_key_names` if `kms_key_name` is set, because that field takes precedence. + _, kmsNameSet := d.GetOk("encryption_config.0.kms_key_name") + if kmsNameSet { + return nil + } + + rawConfigValue := d.Get("encryption_config.0.kms_key_names") + + // Convert config value to []string + configValue, err := tpgresource.InterfaceSliceToStringSlice(rawConfigValue) + if err != nil { + log.Printf("[ERROR] Failed to convert config value: %s", err) + return v + } + + // Convert v to []string + apiStringValue, err := tpgresource.InterfaceSliceToStringSlice(v) + if err != nil { + log.Printf("[ERROR] Failed to convert API value: %s", err) + return v + } + + sortedStrings, err := tpgresource.SortStringsByConfigOrder(configValue, apiStringValue) + if err != nil { + log.Printf("[ERROR] Could not sort API response value: %s", err) + return v + } + + return sortedStrings +} diff --git a/mmv1/templates/terraform/examples/cloudrunv2_service_invokeriam.tf.tmpl b/mmv1/templates/terraform/examples/cloudrunv2_service_invokeriam.tf.tmpl new file mode 100644 index 000000000000..0c0607255a1a --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudrunv2_service_invokeriam.tf.tmpl @@ -0,0 +1,15 @@ +resource "google_cloud_run_v2_service" "{{$.PrimaryResourceId}}" { + provider = google-beta + name = "{{index $.Vars "cloud_run_service_name"}}" + location = "us-central1" + deletion_protection = false + invoker_iam_disabled = true + description = "The serving URL of this service will not perform any IAM check when invoked" + ingress = "INGRESS_TRAFFIC_ALL" + + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } +} diff --git a/mmv1/templates/terraform/examples/datastream_stream_postgresql.tf.tmpl b/mmv1/templates/terraform/examples/datastream_stream_postgresql.tf.tmpl index f83b8d3bfa16..3c2dbc7814d5 100644 --- a/mmv1/templates/terraform/examples/datastream_stream_postgresql.tf.tmpl +++ b/mmv1/templates/terraform/examples/datastream_stream_postgresql.tf.tmpl @@ -5,7 +5,7 @@ resource "google_datastream_connection_profile" "source" { postgresql_profile { hostname = "hostname" - port = 3306 + port = 5432 username = "user" password = "pass" database = "postgres" diff --git a/mmv1/templates/terraform/examples/dialogflowcx_agent_full.tf.tmpl b/mmv1/templates/terraform/examples/dialogflowcx_agent_full.tf.tmpl index c58d83218701..4e76cd8876e5 100644 --- a/mmv1/templates/terraform/examples/dialogflowcx_agent_full.tf.tmpl +++ b/mmv1/templates/terraform/examples/dialogflowcx_agent_full.tf.tmpl @@ -21,11 +21,26 @@ resource "google_dialogflow_cx_agent" "{{$.PrimaryResourceId}}" { audio_export_gcs_destination { uri = "${google_storage_bucket.bucket.url}/prefix-" } + speech_settings { + endpointer_sensitivity = 30 + no_speech_timeout = "3.500s" + use_timeout_based_endpointing = true + models = { + name : "wrench" + mass : "1.3kg" + count : "3" + } + } dtmf_settings { - enabled = true - max_digits = 1 + enabled = true + max_digits = 1 finish_digit = "#" } + logging_settings { + enable_stackdriver_logging = true + enable_interaction_logging = true + enable_consent_based_redaction = true + } } git_integration_settings { github_settings { diff --git a/mmv1/templates/terraform/examples/dialogflowcx_flow_full.tf.tmpl b/mmv1/templates/terraform/examples/dialogflowcx_flow_full.tf.tmpl index 0ed8216c4812..774be2521980 100644 --- a/mmv1/templates/terraform/examples/dialogflowcx_flow_full.tf.tmpl +++ b/mmv1/templates/terraform/examples/dialogflowcx_flow_full.tf.tmpl @@ -273,10 +273,25 @@ resource "google_dialogflow_cx_flow" "{{$.PrimaryResourceId}}" { audio_export_gcs_destination { uri = "${google_storage_bucket.bucket.url}/prefix-" } + speech_settings { + endpointer_sensitivity = 30 + no_speech_timeout = "3.500s" + use_timeout_based_endpointing = true + models = { + name : "wrench" + mass : "1.3kg" + count : "3" + } + } dtmf_settings { enabled = true max_digits = 1 finish_digit = "#" } + logging_settings { + enable_stackdriver_logging = true + enable_interaction_logging = true + enable_consent_based_redaction = true + } } -} \ No newline at end of file +} diff --git a/mmv1/templates/terraform/examples/gkehub_feature_multi_cluster_ingress.tf.tmpl b/mmv1/templates/terraform/examples/gkehub_feature_multi_cluster_ingress.tf.tmpl index 3a286936114d..dcd8b57517aa 100644 --- a/mmv1/templates/terraform/examples/gkehub_feature_multi_cluster_ingress.tf.tmpl +++ b/mmv1/templates/terraform/examples/gkehub_feature_multi_cluster_ingress.tf.tmpl @@ -11,7 +11,6 @@ resource "google_gke_hub_membership" "membership" { resource_link = "//container.googleapis.com/${google_container_cluster.cluster.id}" } } - description = "Membership" } resource "google_gke_hub_feature" "feature" { diff --git a/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_github_actions.tf.tmpl b/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_github_actions.tf.tmpl new file mode 100644 index 000000000000..a891a7c59417 --- /dev/null +++ b/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_github_actions.tf.tmpl @@ -0,0 +1,26 @@ +resource "google_iam_workload_identity_pool" "pool" { + workload_identity_pool_id = "{{index $.Vars "workload_identity_pool_id"}}" +} + +resource "google_iam_workload_identity_pool_provider" "{{$.PrimaryResourceId}}" { + workload_identity_pool_id = google_iam_workload_identity_pool.pool.workload_identity_pool_id + workload_identity_pool_provider_id = "{{index $.Vars "workload_identity_pool_provider_id"}}" + display_name = "Name of provider" + description = "GitHub Actions identity pool provider for automated test" + disabled = true + attribute_condition = <.%d", i)) diff --git a/mmv1/templates/terraform/unordered_list_customize_diff.go.tmpl b/mmv1/templates/terraform/unordered_list_customize_diff.go.tmpl index e80c7d5d1b10..f3a3fa6566c3 100644 --- a/mmv1/templates/terraform/unordered_list_customize_diff.go.tmpl +++ b/mmv1/templates/terraform/unordered_list_customize_diff.go.tmpl @@ -15,8 +15,8 @@ if oldCount.(int) < newCount.(int) { if count < 1 { return nil } -old := make([]interface{}, count) -new := make([]interface{}, count) +old := make([]interface{}, 0, count) +new := make([]interface{}, 0, count) for i := 0; i < count; i++ { o, n := diff.GetChange(fmt.Sprintf("{{ underscore $.Name }}.%d", i)) diff --git a/mmv1/templates/tgc/resource_converters.go.tmpl b/mmv1/templates/tgc/resource_converters.go.tmpl deleted file mode 100644 index 8c8e5baf6beb..000000000000 --- a/mmv1/templates/tgc/resource_converters.go.tmpl +++ /dev/null @@ -1,192 +0,0 @@ -{{/* The license inside this block applies to this file - Copyright 2024 Google LLC. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ -}} -// ---------------------------------------------------------------------------- -// -// *** 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 ( - "sort" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/compute" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/resourcemanager" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/spanner" - "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" -) - - -// ResourceConverter returns a map of terraform resource types (i.e. `google_project`) -// to a slice of ResourceConverters. -// -// Modelling of relationships: -// terraform resources to CAI assets as []cai.ResourceConverter: -// 1:1 = [ResourceConverter{Convert: convertAbc}] (len=1) -// 1:N = [ResourceConverter{Convert: convertAbc}, ...] (len=N) -// N:1 = [ResourceConverter{Convert: convertAbc, merge: mergeAbc}] (len=1) -func ResourceConverters() map[string][]cai.ResourceConverter { - return map[string][]cai.ResourceConverter{ - "google_artifact_registry_repository": {artifactregistry.ResourceConverterArtifactRegistryRepository()}, - "google_app_engine_application": {resourceConverterAppEngineApplication()}, - "google_alloydb_cluster": {alloydb.ResourceConverterAlloydbCluster()}, - "google_alloydb_instance": {alloydb.ResourceConverterAlloydbInstance()}, - "google_apikeys_key": {resourceConverterApikeysKey()}, - "google_compute_address": {compute.ResourceConverterComputeAddress()}, - "google_compute_autoscaler": {compute.ResourceConverterComputeAutoscaler()}, - "google_compute_firewall": {compute.ResourceConverterComputeFirewall()}, - "google_compute_disk": {compute.ResourceConverterComputeDisk()}, - "google_compute_forwarding_rule": {compute.ResourceConverterComputeForwardingRule()}, - "google_gke_hub_membership": {gkehub.ResourceConverterGKEHubMembership()}, - "google_compute_global_address": {compute.ResourceConverterComputeGlobalAddress()}, - "google_compute_global_forwarding_rule": {compute.ResourceConverterComputeGlobalForwardingRule()}, - "google_compute_health_check": {compute.ResourceConverterComputeHealthCheck()}, - "google_compute_instance": {compute.ResourceConverterComputeInstance()}, - "google_compute_instance_group": {resourceConverterComputeInstanceGroup()}, - "google_compute_network": {compute.ResourceConverterComputeNetwork()}, - "google_compute_node_template": {compute.ResourceConverterComputeNodeTemplate()}, - "google_compute_route": {compute.ResourceConverterComputeRoute()}, - "google_compute_router": {compute.ResourceConverterComputeRouter()}, - "google_compute_vpn_tunnel": {compute.ResourceConverterComputeVpnTunnel()}, - "google_compute_resource_policy": {compute.ResourceConverterComputeResourcePolicy()}, - "google_compute_security_policy": {resourceConverterComputeSecurityPolicy()}, - "google_compute_snapshot": {compute.ResourceConverterComputeSnapshot()}, - "google_compute_subnetwork": {compute.ResourceConverterComputeSubnetwork()}, - "google_compute_ssl_policy": {compute.ResourceConverterComputeSslPolicy()}, - "google_compute_ssl_certificate": {compute.ResourceConverterComputeSslCertificate()}, - "google_compute_url_map": {compute.ResourceConverterComputeUrlMap()}, - "google_compute_target_http_proxy": {compute.ResourceConverterComputeTargetHttpProxy()}, - "google_compute_target_https_proxy": {compute.ResourceConverterComputeTargetHttpsProxy()}, - "google_compute_target_ssl_proxy": {compute.ResourceConverterComputeTargetSslProxy()}, - "google_compute_target_pool": {resourceConverterComputeTargetPool()}, - "google_composer_environment": {resourceConverterComposerEnvironment()}, - "google_compute_region_commitment": {resourceConverterCommitment()}, - "google_dataflow_job": {resourceDataflowJob()}, - "google_dataproc_autoscaling_policy": {dataproc.ResourceConverterDataprocAutoscalingPolicy()}, - "google_dataproc_cluster": {resourceConverterDataprocCluster()}, - "google_dns_managed_zone": {dns.ResourceConverterDNSManagedZone()}, - "google_dns_policy": {dns.ResourceConverterDNSPolicy()}, - "google_kms_key_ring_import_job": {kms.ResourceConverterKMSKeyRingImportJob()}, - "google_gke_hub_feature": {gkehub2.ResourceConverterGKEHub2Feature()}, - "google_storage_bucket": {resourceConverterStorageBucket()}, - "google_sql_database_instance": {resourceConverterSQLDatabaseInstance()}, - "google_sql_database": {sql.ResourceConverterSQLDatabase()}, - "google_container_cluster": {resourceConverterContainerCluster()}, - "google_container_node_pool": {resourceConverterContainerNodePool()}, - "google_bigquery_dataset": {bigquery.ResourceConverterBigQueryDataset()}, - "google_bigquery_dataset_iam_policy": {bigquery.ResourceConverterBigqueryDatasetIamPolicy()}, - "google_bigquery_dataset_iam_binding": {bigquery.ResourceConverterBigqueryDatasetIamBinding()}, - "google_bigquery_dataset_iam_member": {bigquery.ResourceConverterBigqueryDatasetIamMember()}, - "google_bigquery_table": {resourceConverterBigQueryTable()}, - "google_datastream_connection_profile": {datastream.ResourceConverterDatastreamConnectionProfile()}, - "google_datastream_private_connection": {datastream.ResourceConverterDatastreamPrivateConnection()}, - "google_datastream_stream": {datastream.ResourceConverterDatastreamStream()}, - "google_firebase_project": {resourceConverterFirebaseProject()}, - "google_org_policy_policy": {resourceConverterOrgPolicyPolicy()}, - "google_redis_instance": {redis.ResourceConverterRedisInstance()}, - "google_spanner_database": {spanner.ResourceConverterSpannerDatabase()}, - "google_spanner_database_iam_policy": {spanner.ResourceConverterSpannerDatabaseIamPolicy()}, - "google_spanner_database_iam_binding": {spanner.ResourceConverterSpannerDatabaseIamBinding()}, - "google_spanner_database_iam_member": {spanner.ResourceConverterSpannerDatabaseIamMember()}, - "google_spanner_instance": {spanner.ResourceConverterSpannerInstance()}, - "google_spanner_instance_iam_policy": {spanner.ResourceConverterSpannerInstanceIamPolicy()}, - "google_spanner_instance_iam_binding": {spanner.ResourceConverterSpannerInstanceIamBinding()}, - "google_spanner_instance_iam_member": {spanner.ResourceConverterSpannerInstanceIamMember()}, - "google_project_service": {resourceConverterServiceUsage()}, - "google_secret_manager_secret_version": {secretmanager.ResourceConverterSecretManagerSecretVersion()}, - "google_pubsub_lite_reservation": {pubsublite.ResourceConverterPubsubLiteReservation()}, - "google_pubsub_lite_subscription": {pubsublite.ResourceConverterPubsubLiteSubscription()}, - "google_pubsub_lite_topic": {pubsublite.ResourceConverterPubsubLiteTopic()}, - "google_pubsub_schema": {pubsub.ResourceConverterPubsubSchema()}, - "google_pubsub_subscription": {pubsub.ResourceConverterPubsubSubscription()}, - "google_pubsub_subscription_iam_policy": {pubsub.ResourceConverterPubsubSubscriptionIamPolicy()}, - "google_pubsub_subscription_iam_binding": {pubsub.ResourceConverterPubsubSubscriptionIamBinding()}, - "google_pubsub_subscription_iam_member": {pubsub.ResourceConverterPubsubSubscriptionIamMember()}, - "google_storage_bucket_iam_policy": {resourceConverterStorageBucketIamPolicy()}, - "google_storage_bucket_iam_binding": {resourceConverterStorageBucketIamBinding()}, - "google_storage_bucket_iam_member": {resourceConverterStorageBucketIamMember()}, - "google_compute_node_group": {compute.ResourceConverterComputeNodeGroup()}, - "google_logging_folder_bucket_config": {resourceConverterLogFolderBucket()}, - "google_app_engine_standard_app_version": {resourceAppEngineStandardAppVersion()}, - "google_logging_organization_bucket_config": {resourceConverterLogOrganizationBucket()}, - "google_logging_project_bucket_config": {resourceConverterLogProjectBucket()}, - "google_logging_billing_account_bucket_config": {resourceConverterLogBillingAccountBucket()}, - "google_cloud_tasks_queue": {cloudtasks.ResourceConverterCloudTasksQueue()}, - "google_pubsub_topic": {pubsub.ResourceConverterPubsubTopic()}, - "google_kms_crypto_key": {kms.ResourceConverterKMSCryptoKey()}, - "google_kms_key_ring": {kms.ResourceConverterKMSKeyRing()}, - "google_filestore_instance": {filestore.ResourceConverterFilestoreInstance()}, - "google_access_context_manager_service_perimeter": {accesscontextmanager.ResourceConverterAccessContextManagerServicePerimeter()}, - "google_access_context_manager_access_policy": {accesscontextmanager.ResourceConverterAccessContextManagerAccessPolicy()}, - "google_cloud_run_service": {cloudrun.ResourceConverterCloudRunService()}, - "google_cloud_run_domain_mapping": {cloudrun.ResourceConverterCloudRunDomainMapping()}, - "google_cloud_run_v2_job": {cloudrunv2.ResourceConverterCloudRunV2Job()}, - "google_cloudfunctions_function": {resourceConverterCloudFunctionsCloudFunction()}, - "google_monitoring_notification_channel": {monitoring.ResourceConverterMonitoringNotificationChannel()}, - "google_monitoring_alert_policy": {monitoring.ResourceConverterMonitoringAlertPolicy()}, - "google_vertex_ai_dataset": {vertexai.ResourceConverterVertexAIDataset()}, - {{- range $object := $.ResourcesForVersion }} - {{- if $object.ResourceName }} - "{{ $object.TerraformName }}": {{ $object.ResourceName }}(), - {{- end }} - {{- if $object.IamClassName }} - "{{ $object.TerraformName }}_iam_binding": tpgiamresource.ResourceIamBinding({{ $object.IamClassName }}IamSchema, {{ $object.IamClassName }}IamUpdaterProducer, {{ $object.IamClassName }}IdParseFunc), - "{{ $object.TerraformName }}_iam_member": tpgiamresource.ResourceIamMember({{ $object.IamClassName }}IamSchema, {{ $object.IamClassName }}IamUpdaterProducer, {{ $object.IamClassName }}IdParseFunc), - "{{ $object.TerraformName }}_iam_policy": tpgiamresource.ResourceIamPolicy({{ $object.IamClassName }}IamSchema, {{ $object.IamClassName }}IamUpdaterProducer, {{ $object.IamClassName }}IdParseFunc), - {{- end }} - {{- end }} - "google_project": { - resourceConverterProject(), - resourceConverterProjectBillingInfo(), - }, - "google_bigtable_instance": { - resourceConverterBigtableInstance(), - resourceConverterBigtableCluster(), - }, - "google_organization_iam_policy": {resourcemanager.ResourceConverterOrganizationIamPolicy()}, - "google_organization_iam_binding": {resourcemanager.ResourceConverterOrganizationIamBinding()}, - "google_organization_iam_member": {resourcemanager.ResourceConverterOrganizationIamMember()}, - "google_organization_policy": {resourceConverterOrganizationPolicy()}, - "google_project_organization_policy": {resourceConverterProjectOrgPolicy()}, - "google_folder": {resourceConverterFolder()}, - "google_folder_iam_policy": {resourcemanager.ResourceConverterFolderIamPolicy()}, - "google_folder_iam_binding": {resourcemanager.ResourceConverterFolderIamBinding()}, - "google_folder_iam_member": {resourcemanager.ResourceConverterFolderIamMember()}, - "google_folder_organization_policy": {resourceConverterFolderOrgPolicy()}, - "google_kms_crypto_key_iam_policy": {resourceConverterKmsCryptoKeyIamPolicy()}, - "google_kms_crypto_key_iam_binding": {resourceConverterKmsCryptoKeyIamBinding()}, - "google_kms_crypto_key_iam_member": {resourceConverterKmsCryptoKeyIamMember()}, - "google_kms_key_ring_iam_policy": {resourceConverterKmsKeyRingIamPolicy()}, - "google_kms_key_ring_iam_binding": {resourceConverterKmsKeyRingIamBinding()}, - "google_kms_key_ring_iam_member": {resourceConverterKmsKeyRingIamMember()}, - "google_project_iam_policy": {resourcemanager.ResourceConverterProjectIamPolicy()}, - "google_project_iam_binding": {resourcemanager.ResourceConverterProjectIamBinding()}, - "google_project_iam_member": {resourcemanager.ResourceConverterProjectIamMember()}, - "google_project_iam_custom_role": {resourceConverterProjectIAMCustomRole()}, - "google_organization_iam_custom_role": {resourceConverterOrganizationIAMCustomRole()}, - "google_vpc_access_connector": {vpcaccess.ResourceConverterVPCAccessConnector()}, - "google_logging_metric": {logging.ResourceConverterLoggingMetric()}, - "google_service_account": {resourceConverterServiceAccount()}, - "google_service_account_key": {resourceConverterServiceAccountKey()}, - - } -} diff --git a/mmv1/third_party/terraform/.teamcity/CONTRIBUTION_GUIDE.md b/mmv1/third_party/terraform/.teamcity/CONTRIBUTION_GUIDE.md index 01da8c75c787..b8e5b3d281d6 100644 --- a/mmv1/third_party/terraform/.teamcity/CONTRIBUTION_GUIDE.md +++ b/mmv1/third_party/terraform/.teamcity/CONTRIBUTION_GUIDE.md @@ -89,7 +89,12 @@ If you want to test a feature branch on a schedule ahead of a release you can up First, make sure that the feature branch `FEATURE-BRANCH-major-release-X.0.0` is created in the downstream TPG and TPGB repositories, where X is the major version. -See this PR as an example of adding a major release testing project: https://github.com/SarahFrench/magic-modules/pull/9/files +See these PRs as examples of adding a major release testing project: +- v6.0.0: + - https://github.com/GoogleCloudPlatform/magic-modules/pull/11104 + - https://github.com/GoogleCloudPlatform/magic-modules/pull/11143 (a fix to the one above) +- v7.0.0: + - https://github.com/GoogleCloudPlatform/magic-modules/pull/11887 That PR creates a new file at `.teamcity/components/projects/feature_branches/FEATURE-BRANCH-major-release-X.0.0.kt` (replacing `X` with the version number). This file defines a new project that will contain all the builds run against the feature branch. See [FEATURE-BRANCH-major-release-6.0.0.kt](https://github.com/GoogleCloudPlatform/magic-modules/blob/main/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-major-release-6.0.0.kt) as an example. diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt index 68d9aa0a0206..2f1ce2a79ad5 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt @@ -7,7 +7,6 @@ package builds -import DefaultTerraformCoreVersion import jetbrains.buildServer.configs.kotlin.BuildSteps import jetbrains.buildServer.configs.kotlin.buildSteps.ScriptBuildStep diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index 26258f910ad3..9e603729ef7c 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -546,6 +546,11 @@ var ServicesListBeta = mapOf( "displayName" to "Notebooks", "path" to "./google-beta/services/notebooks" ), + "oracledatabase" to mapOf( + "name" to "oracledatabase", + "displayName" to "OracleDatabase", + "path" to "./google-beta/services/oracledatabase" + ), "orgpolicy" to mapOf( "name" to "orgpolicy", "displayName" to "Orgpolicy", @@ -725,6 +730,11 @@ var ServicesListBeta = mapOf( "name" to "tpuv2", "displayName" to "Tpuv2", "path" to "./google-beta/services/tpuv2" + ), + "transcoder" to mapOf( + "name" to "transcoder", + "displayName" to "Transcoder", + "path" to "./google-beta/services/transcoder" ), "vertexai" to mapOf( "name" to "vertexai", diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index 1cfbab121519..fd82f4c01bae 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -541,6 +541,11 @@ var ServicesListGa = mapOf( "displayName" to "Notebooks", "path" to "./google/services/notebooks" ), + "oracledatabase" to mapOf( + "name" to "oracledatabase", + "displayName" to "OracleDatabase", + "path" to "./google/services/oracledatabase" + ), "orgpolicy" to mapOf( "name" to "orgpolicy", "displayName" to "Orgpolicy", @@ -721,6 +726,11 @@ var ServicesListGa = mapOf( "displayName" to "Tpuv2", "path" to "./google/services/tpuv2" ), + "transcoder" to mapOf( + "name" to "transcoder", + "displayName" to "Transcoder", + "path" to "./google/services/transcoder" + ), "vertexai" to mapOf( "name" to "vertexai", "displayName" to "Vertexai", diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt new file mode 100644 index 000000000000..de3e5f426229 --- /dev/null +++ b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-ephemeral-resource.kt @@ -0,0 +1,102 @@ +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. + +package projects.feature_branches + +import ProviderNameBeta +import ProviderNameGa +import SharedResourceNameBeta +import SharedResourceNameGa +import SharedResourceNameVcr +import builds.* +import generated.ServicesListBeta +import generated.ServicesListGa +import jetbrains.buildServer.configs.kotlin.Project +import replaceCharsId +import vcs_roots.HashiCorpVCSRootBeta +import vcs_roots.HashiCorpVCSRootGa +import vcs_roots.ModularMagicianVCSRootBeta +import vcs_roots.ModularMagicianVCSRootGa + +const val featureBranchEphemeralResources = "FEATURE-BRANCH-ephemeral-resource" +const val EphemeralResourcesTfCoreVersion = "1.10.0-alpha20240926" // TODO - update with correct release + +// featureBranchEphemeralResourcesSubProject creates a project just for testing ephemeral resources. +// We know that all ephemeral resources we're adding are part of the Resource Manager service, so we only include those builds. +// We create builds for testing the resourcemanager service: +// - Against the GA hashicorp repo +// - Against the GA modular-magician repo +// - Against the Beta hashicorp repo +// - Against the Beta modular-magician repo +// These resemble existing projects present in TeamCity, but these all use a more recent version of Terraform including +// the new ephemeral values feature. +fun featureBranchEphemeralResourcesSubProject(allConfig: AllContextParameters): Project { + + val projectId = replaceCharsId(featureBranchEphemeralResources) + + val packageName = "resourcemanager" // All ephemeral resources will be in the resourcemanager package + val vcrConfig = getVcrAcceptanceTestConfig(allConfig) // Reused below for both MM testing build configs + val trigger = NightlyTriggerConfiguration( + branch = "refs/heads/$featureBranchEphemeralResources" // triggered builds must test the feature branch + ) + + + // GA + val gaConfig = getGaAcceptanceTestConfig(allConfig) + // How to make only build configuration to the relevant package(s) + val resourceManagerPackageGa = ServicesListGa.getValue(packageName) + + // Enable testing using hashicorp/terraform-provider-google + var parentId = "${projectId}_HC_GA" + val buildConfigHashiCorpGa = BuildConfigurationForSinglePackage(packageName, resourceManagerPackageGa.getValue("path"), "Ephemeral resources in $packageName (GA provider, HashiCorp downstream)", ProviderNameGa, parentId, HashiCorpVCSRootGa, listOf(SharedResourceNameGa), gaConfig) + buildConfigHashiCorpGa.addTrigger(trigger) + + // Enable testing using modular-magician/terraform-provider-google + parentId = "${projectId}_MM_GA" + val buildConfigModularMagicianGa = BuildConfigurationForSinglePackage(packageName, resourceManagerPackageGa.getValue("path"), "Ephemeral resources in $packageName (GA provider, MM upstream)", ProviderNameGa, parentId, ModularMagicianVCSRootGa, listOf(SharedResourceNameVcr), vcrConfig) + // No trigger added here (MM upstream is manual only) + + // Beta + val betaConfig = getBetaAcceptanceTestConfig(allConfig) + val resourceManagerPackageBeta = ServicesListBeta.getValue(packageName) + + // Enable testing using hashicorp/terraform-provider-google-beta + parentId = "${projectId}_HC_BETA" + val buildConfigHashiCorpBeta = BuildConfigurationForSinglePackage(packageName, resourceManagerPackageBeta.getValue("path"), "Ephemeral resources in $packageName (Beta provider, HashiCorp downstream)", ProviderNameBeta, parentId, HashiCorpVCSRootBeta, listOf(SharedResourceNameBeta), betaConfig) + buildConfigHashiCorpBeta.addTrigger(trigger) + + // Enable testing using modular-magician/terraform-provider-google-beta + parentId = "${projectId}_MM_BETA" + val buildConfigModularMagicianBeta = BuildConfigurationForSinglePackage(packageName, resourceManagerPackageBeta.getValue("path"), "Ephemeral resources in $packageName (Beta provider, MM upstream)", ProviderNameBeta, parentId, ModularMagicianVCSRootBeta, listOf(SharedResourceNameVcr), vcrConfig) + // No trigger added here (MM upstream is manual only) + + + // ------ + + // Make all builds use a 1.10.0-ish version of TF core + val allBuildConfigs = listOf(buildConfigHashiCorpGa, buildConfigModularMagicianGa, buildConfigHashiCorpBeta, buildConfigModularMagicianBeta) + allBuildConfigs.forEach{ b -> + b.overrideTerraformCoreVersion(EphemeralResourcesTfCoreVersion) + } + + // ------ + + return Project{ + id(projectId) + name = featureBranchEphemeralResources + description = "Subproject for testing feature branch $featureBranchEphemeralResources" + + // Register all build configs in the project + allBuildConfigs.forEach{ b -> + buildType(b) + } + + params { + readOnlySettings() + } + } +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt index 288df583bf25..7d1d79b15b63 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt @@ -14,12 +14,7 @@ import ServiceSweeperCronName import ServiceSweeperManualName import SharedResourceNameVcr import builds.* -import generated.PackagesListBeta -import generated.PackagesListGa -import generated.ServicesListBeta -import generated.ServicesListGa -import generated.SweepersListBeta -import generated.SweepersListGa +import generated.* import jetbrains.buildServer.configs.kotlin.BuildType import jetbrains.buildServer.configs.kotlin.Project import jetbrains.buildServer.configs.kotlin.vcs.GitVcsRoot diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt index 8df65299015f..89d6ffa04431 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt @@ -9,7 +9,8 @@ package projects.reused import SharedResourceNameVcr import VcrRecordingProjectId -import builds.* +import builds.AccTestConfiguration +import builds.VcrDetails import jetbrains.buildServer.configs.kotlin.Project import jetbrains.buildServer.configs.kotlin.vcs.GitVcsRoot import replaceCharsId diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt index 7130a9c35ea8..d0a4308a2702 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt @@ -18,6 +18,7 @@ import generated.ServicesListBeta import generated.ServicesListGa import jetbrains.buildServer.configs.kotlin.Project import jetbrains.buildServer.configs.kotlin.sharedResource +import projects.feature_branches.featureBranchEphemeralResourcesSubProject // googleCloudRootProject returns a root project that contains a subprojects for the GA and Beta version of the // Google provider. There are also resources to help manage the test projects used for acceptance tests. @@ -62,6 +63,10 @@ fun googleCloudRootProject(allConfig: AllContextParameters): Project { subProject(googleSubProjectBeta(allConfig)) subProject(projectSweeperSubProject(allConfig)) + // Feature branch-testing projects - these will be added and removed as needed + subProject(featureBranchEphemeralResourcesSubProject(allConfig)) + + params { readOnlySettings() } diff --git a/mmv1/third_party/terraform/.teamcity/settings.kts b/mmv1/third_party/terraform/.teamcity/settings.kts index 518323d7bdef..ac329c4bd6b3 100644 --- a/mmv1/third_party/terraform/.teamcity/settings.kts +++ b/mmv1/third_party/terraform/.teamcity/settings.kts @@ -5,9 +5,9 @@ // This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. -import projects.googleCloudRootProject import builds.AllContextParameters import jetbrains.buildServer.configs.kotlin.* +import projects.googleCloudRootProject version = "2024.03" diff --git a/mmv1/third_party/terraform/.teamcity/tests/FEATURE-BRANCH-ephemeral-resource.kt b/mmv1/third_party/terraform/.teamcity/tests/FEATURE-BRANCH-ephemeral-resource.kt new file mode 100644 index 000000000000..9b52c2c9d2fe --- /dev/null +++ b/mmv1/third_party/terraform/.teamcity/tests/FEATURE-BRANCH-ephemeral-resource.kt @@ -0,0 +1,79 @@ +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. + +package tests + +import jetbrains.buildServer.configs.kotlin.triggers.ScheduleTrigger +import org.junit.Assert +import org.junit.Test +import projects.feature_branches.featureBranchEphemeralResources +import projects.googleCloudRootProject + +class FeatureBranchEphemeralResourcesSubProject { + @Test + fun buildsUsingHashiCorpReposAreOnSchedule() { + val root = googleCloudRootProject(testContextParameters()) + + // Find feature branch project + val project = getSubProject(root, featureBranchEphemeralResources) + + // All builds using the HashiCorp owned GitHub repos + val hashiBuilds = project.buildTypes.filter { bt -> + bt.name.contains("HashiCorp downstream") + } + + hashiBuilds.forEach{bt -> + Assert.assertTrue( + "Build configuration `${bt.name}` should contain at least one trigger", + bt.triggers.items.isNotEmpty() + ) + // Look for at least one CRON trigger + var found = false + lateinit var schedulingTrigger: ScheduleTrigger + for (item in bt.triggers.items){ + if (item.type == "schedulingTrigger") { + schedulingTrigger = item as ScheduleTrigger + found = true + break + } + } + + Assert.assertTrue( + "Build configuration `${bt.name}` should contain a CRON/'schedulingTrigger' trigger", + found + ) + + // Check that triggered builds are being run on the feature branch + val isCorrectBranch: Boolean = schedulingTrigger.branchFilter == "+:refs/heads/$featureBranchEphemeralResources" + + Assert.assertTrue( + "Build configuration `${bt.name}` is using the $featureBranchEphemeralResources branch filter", + isCorrectBranch + ) + } + } + + @Test + fun buildsUsingModularMagicianReposAreNotTriggered() { + val root = googleCloudRootProject(testContextParameters()) + + // Find feature branch project + val project = getSubProject(root, featureBranchEphemeralResources) + + // All builds using the HashiCorp owned GitHub repos + val magicianBuilds = project.buildTypes.filter { bt -> + bt.name.contains("MM upstream") + } + + magicianBuilds.forEach{bt -> + Assert.assertTrue( + "Build configuration `${bt.name}` should not have any triggers", + bt.triggers.items.isEmpty() + ) + } + } +} diff --git a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt index f6babaa4807a..6fd5c9e0efc0 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt @@ -8,9 +8,9 @@ package tests import ProjectSweeperName -import ServiceSweeperName import ServiceSweeperCronName import ServiceSweeperManualName +import ServiceSweeperName import jetbrains.buildServer.configs.kotlin.BuildType import jetbrains.buildServer.configs.kotlin.Project import jetbrains.buildServer.configs.kotlin.triggers.ScheduleTrigger @@ -136,7 +136,7 @@ class SweeperTests { // Find Project sweeper project's build val projectSweeperProject = getSubProject(root, projectSweeperProjectName) - val projectSweeper: BuildType = getBuildFromProject(projectSweeperProject!!, ProjectSweeperName) + val projectSweeper: BuildType = getBuildFromProject(projectSweeperProject, ProjectSweeperName) // Check only one schedule trigger is on the builds in question assertTrue(sweeperGa.triggers.items.size == 1) diff --git a/mmv1/third_party/terraform/provider/provider_impersonate_service_account_delegates_test.go b/mmv1/third_party/terraform/provider/provider_impersonate_service_account_delegates_test.go index a6418e4162a6..ffe38c791bd7 100644 --- a/mmv1/third_party/terraform/provider/provider_impersonate_service_account_delegates_test.go +++ b/mmv1/third_party/terraform/provider/provider_impersonate_service_account_delegates_test.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/acctest" ) -func TestAccFwProvider_impersonate_service_account_delegates(t *testing.T) { +func TestAccSdkProvider_impersonate_service_account_delegates(t *testing.T) { testCases := map[string]func(t *testing.T){ // Configuring the provider using inputs // There are no environment variables for this field @@ -96,6 +96,9 @@ func testAccSdkProvider_impersonate_service_account_delegates_usage(t *testing.T acctest.VcrTest(t, resource.TestCase{ // No PreCheck for checking ENVs ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, Steps: []resource.TestStep{ { Config: testAccSdkProvider_impersonate_service_account_delegates_testViaFailure_1(context), @@ -168,6 +171,22 @@ resource "google_service_account_iam_member" "delegate_create_target_token" { role = "roles/iam.serviceAccountTokenCreator" member = "serviceAccount:${google_service_account.delegate.email}" } + +# Despite provisioning all the needed service accounts and permissions above +# this test sometimes fails with "Permission 'iam.serviceAccounts.getAccessToken' denied on resource (or it may not exist)" +# This error can be caused by either of: +# - the IAM Service Account Credentials API not being enabled +# - the service account not existing +# - eventual consistency affecting IAM policies set on the service accounts +# Splitting this test into 2 steps is not sufficient to help with timing issues, so we add this sleep +resource "time_sleep" "wait_5_minutes" { + depends_on = [ + google_service_account_iam_member.base_create_delegate_token, + google_service_account_iam_member.delegate_create_target_token + ] + + create_duration = "300s" +} `, context) } diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl index 1d77a3fb8f29..4d4cf2f26fdd 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl @@ -168,6 +168,9 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_monitoring_app_engine_service": monitoring.DataSourceMonitoringServiceAppEngine(), "google_monitoring_uptime_check_ips": monitoring.DataSourceGoogleMonitoringUptimeCheckIps(), "google_netblock_ip_ranges": resourcemanager.DataSourceGoogleNetblockIpRanges(), + "google_oracle_database_db_servers": oracledatabase.DataSourceOracleDatabaseDbServers(), + "google_oracle_database_cloud_vm_cluster": oracledatabase.DataSourceOracleDatabaseCloudVmCluster(), + "google_oracle_database_cloud_exadata_infrastructure":oracledatabase.DataSourceOracleDatabaseCloudExadataInfrastructure(), "google_organization": resourcemanager.DataSourceGoogleOrganization(), "google_privateca_certificate_authority": privateca.DataSourcePrivatecaCertificateAuthority(), "google_privileged_access_manager_entitlement": privilegedaccessmanager.DataSourceGooglePrivilegedAccessManagerEntitlement(), diff --git a/mmv1/third_party/terraform/services/bigquery/iam_bigquery_dataset.go b/mmv1/third_party/terraform/services/bigquery/iam_bigquery_dataset.go index 740da92602ad..9bc72a48cf24 100644 --- a/mmv1/third_party/terraform/services/bigquery/iam_bigquery_dataset.go +++ b/mmv1/third_party/terraform/services/bigquery/iam_bigquery_dataset.go @@ -189,7 +189,7 @@ func policyToAccess(policy *cloudresourcemanager.Policy) ([]map[string]interface } for _, member := range binding.Members { // Do not append any deleted members - if strings.HasPrefix(member, "deleted:") { + if strings.HasPrefix(member, "iamMember:deleted:") { continue } access := map[string]interface{}{ @@ -211,7 +211,7 @@ func policyToAccess(policy *cloudresourcemanager.Policy) ([]map[string]interface // Dataset access uses different member types to identify groups, domains, etc. // these types are used as keys in the access JSON payload func iamMemberToAccess(member string) (string, string, error) { - if strings.HasPrefix(member, "deleted:") { + if strings.HasPrefix(member, "iamMember:deleted:") { return "", "", fmt.Errorf("BigQuery Dataset IAM member is deleted: %s", member) } pieces := strings.SplitN(member, ":", 2) diff --git a/mmv1/third_party/terraform/services/bigquery/iam_bigquery_member_dataset.go b/mmv1/third_party/terraform/services/bigquery/iam_bigquery_member_dataset.go index a4b58ae67ca8..a42a701912ea 100644 --- a/mmv1/third_party/terraform/services/bigquery/iam_bigquery_member_dataset.go +++ b/mmv1/third_party/terraform/services/bigquery/iam_bigquery_member_dataset.go @@ -231,7 +231,7 @@ func policyToAccessForIamMember(policy *cloudresourcemanager.Policy) ([]map[stri } for _, member := range binding.Members { // Do not append any deleted members - if strings.HasPrefix(member, "deleted:") { + if strings.HasPrefix(member, "iamMember:deleted:") { continue } access := map[string]interface{}{ @@ -253,7 +253,7 @@ func policyToAccessForIamMember(policy *cloudresourcemanager.Policy) ([]map[stri // Dataset access uses different member types to identify groups, domains, etc. // these types are used as keys in the access JSON payload func iamMemberToAccessForIamMember(member string) (string, string, error) { - if strings.HasPrefix(member, "deleted:") { + if strings.HasPrefix(member, "iamMember:deleted:") { return "", "", fmt.Errorf("BigQuery Dataset IAM member is deleted: %s", member) } pieces := strings.SplitN(member, ":", 2) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_iam_member_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_iam_member_test.go index 099bd43cbad2..794581f1b960 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_iam_member_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_iam_member_test.go @@ -3,7 +3,7 @@ package bigquery_test import ( "fmt" "reflect" - "strings" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-testing/helper/resource" @@ -114,6 +114,48 @@ func TestAccBigqueryDatasetIamMember_iamMember(t *testing.T) { }) } +func TestAccBigqueryDatasetIamMember_withDeletedServiceAccount(t *testing.T) { + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + serviceAccountID := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + serviceAccountEmail := fmt.Sprintf("%s@%s.iam.gserviceaccount.com", serviceAccountID, envvar.GetTestProjectFromEnv()) + + expected := map[string]interface{}{ + "role": "roles/viewer", + "userByEmail": serviceAccountEmail, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBigqueryDatasetIamMember_withServiceAccount(datasetID, serviceAccountID), + Check: testAccCheckBigQueryDatasetIamMemberPresent(t, "google_bigquery_dataset.dataset", expected), + }, + { + // No change from Step 1 except for hard-coding the service account email to remove the explicit resource reference in preparation for the service accoutn deletion. + Config: testAccBigqueryDatasetIamMember_withServiceAccountEmail(datasetID, serviceAccountID, serviceAccountEmail), + Check: testAccCheckBigQueryDatasetIamMemberPresent(t, "google_bigquery_dataset.dataset", expected), + }, + { + // Delete the service account but keep the rest the same. + // The service account will show up with a "deleted:serviceAccount:" prefix and a "?uid=" suffix when getting dataset access from now on. + // The plan should show an attempt to recreate the IAM member resource because the dataset access no longer contains the original account email so there is a diff. + Config: testAccBigqueryDatasetIamMember_withServiceAccountDeleted(datasetID, serviceAccountEmail), + ExpectNonEmptyPlan: true, + }, + { + // Apply the same plan as the previous step. + // It should fail because the specified account has now been deleted, so the account email is invalid. + Config: testAccBigqueryDatasetIamMember_withServiceAccountDeleted(datasetID, serviceAccountEmail), + ExpectError: regexp.MustCompile(fmt.Sprintf(".+Service account %s does not exist.+", serviceAccountEmail)), + }, + }, + }) +} + func testAccCheckBigQueryDatasetIamMemberPresent(t *testing.T, n string, expected map[string]interface{}) resource.TestCheckFunc { return testAccCheckBigQueryDatasetIamMember(t, n, expected, true) } @@ -146,15 +188,6 @@ func testAccCheckBigQueryDatasetIamMember(t *testing.T, n string, expected map[s } access := ds["access"].([]interface{}) for _, a := range access { - if aMap, ok := a.(map[string]interface{}); ok { - if iamMember, ok := aMap["iamMember"].(string); ok { - // The iam account may have been deleted but the binding may be present for the dataset. - // This case is supposed to always throw an error. - if strings.HasPrefix(iamMember, "deleted:") { - return fmt.Errorf("Found deleted service account: %s", iamMember) - } - } - } if reflect.DeepEqual(a, expected) { if !expectPresent { return fmt.Errorf("Found access %+v, expected not present", expected) @@ -258,3 +291,53 @@ resource "google_iam_workload_identity_pool_provider" "wif_provider" { } `, datasetID, wifIDs, wifIDs) } + +func testAccBigqueryDatasetIamMember_withServiceAccount(datasetID, serviceAccountID string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "dataset" { + dataset_id = "%s" +} + +resource "google_service_account" "sa" { + account_id = "%s" +} + +resource "google_bigquery_dataset_iam_member" "access" { + dataset_id = google_bigquery_dataset.dataset.dataset_id + role = "roles/viewer" + member = "serviceAccount:${google_service_account.sa.email}" +} +`, datasetID, serviceAccountID) +} + +func testAccBigqueryDatasetIamMember_withServiceAccountEmail(datasetID, serviceAccountID, serviceAccountEmail string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "dataset" { + dataset_id = "%s" +} + +resource "google_service_account" "sa" { + account_id = "%s" +} + +resource "google_bigquery_dataset_iam_member" "access" { + dataset_id = google_bigquery_dataset.dataset.dataset_id + role = "roles/viewer" + member = "serviceAccount:%s" +} +`, datasetID, serviceAccountID, serviceAccountEmail) +} + +func testAccBigqueryDatasetIamMember_withServiceAccountDeleted(datasetID, serviceAccountEmail string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "dataset" { + dataset_id = "%s" +} + +resource "google_bigquery_dataset_iam_member" "access" { + dataset_id = google_bigquery_dataset.dataset.dataset_id + role = "roles/viewer" + member = "serviceAccount:%s" +} +`, datasetID, serviceAccountEmail) +} diff --git a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go index b5ca76ee8b28..746e162dd21d 100644 --- a/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go +++ b/mmv1/third_party/terraform/services/bigtable/resource_bigtable_instance.go @@ -182,7 +182,7 @@ func ResourceBigtableInstance() *schema.Resource { Type: schema.TypeBool, Optional: true, Default: true, - Description: ` When the field is set to true or unset in Terraform state, a terraform apply or terraform destroy that would delete the instance will fail. When the field is set to false, deleting the instance is allowed.`, + Description: `When the field is set to true or unset in Terraform state, a terraform apply or terraform destroy that would delete the instance will fail. When the field is set to false, deleting the instance is allowed.`, }, "labels": { diff --git a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go index 0be8a90f4676..afb8458f2974 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go @@ -136,10 +136,10 @@ func ResourceCloudFunctionsFunction() *schema.Resource { }, Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(5 * time.Minute), - Read: schema.DefaultTimeout(5 * time.Minute), - Update: schema.DefaultTimeout(5 * time.Minute), - Delete: schema.DefaultTimeout(5 * time.Minute), + Create: schema.DefaultTimeout(20 * time.Minute), + Read: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), }, CustomizeDiff: customdiff.All( diff --git a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.tmpl b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.tmpl index 57f9aa652cd6..e1f925ce86d2 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.tmpl +++ b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.tmpl @@ -1389,7 +1389,7 @@ resource "time_sleep" "wait_iam_roles_%[3]s" { google_project_iam_member.artifact_registry_writer_%[3]s, google_project_iam_member.log_writer_%[3]s, ] - create_duration = "60s" + create_duration = "120s" } resource "google_cloudfunctions_function" "function" { diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl index 04334717ba43..c4da960cb631 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.tmpl @@ -852,6 +852,9 @@ func TestAccComposer1Environment_withNodeConfig(t *testing.T) { PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, Steps: []resource.TestStep{ { Config: testAccComposer1Environment_nodeCfg(envName, network, subnetwork, serviceAccount), @@ -2760,7 +2763,7 @@ resource "google_composer_environment" "test" { image_version = "composer-1-airflow-2" } } - depends_on = [google_project_iam_member.composer-worker] + depends_on = [time_sleep.wait_3_minutes] } resource "google_compute_network" "test" { @@ -2775,6 +2778,11 @@ resource "google_compute_subnetwork" "test" { network = google_compute_network.test.self_link } +resource "time_sleep" "wait_3_minutes" { + depends_on = [google_project_iam_member.composer-worker] + create_duration = "3m" +} + resource "google_service_account" "test" { account_id = "%s" display_name = "Test Service Account for Composer Environment" diff --git a/mmv1/third_party/terraform/services/compute/metadata.go.tmpl b/mmv1/third_party/terraform/services/compute/metadata.go.tmpl index 813ebd486a4b..542bc60f6802 100644 --- a/mmv1/third_party/terraform/services/compute/metadata.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/metadata.go.tmpl @@ -96,7 +96,7 @@ func BetaMetadataUpdate(oldMDMap map[string]interface{}, newMDMap map[string]int } func expandComputeMetadata(m map[string]interface{}) []*compute.MetadataItems { - metadata := make([]*compute.MetadataItems, len(m)) + metadata := make([]*compute.MetadataItems, 0, len(m)) var keys []string for key := range m { keys = append(keys, key) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_backend_service_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_backend_service_test.go.tmpl index c918404dfa9e..229198175489 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_backend_service_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_backend_service_test.go.tmpl @@ -146,6 +146,39 @@ func TestAccComputeBackendService_withBackendAndIAP(t *testing.T) { }) } +func TestAccComputeBackendService_updateIAPEnabled(t *testing.T) { + t.Parallel() + + serviceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeBackendServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeBackendService_withIAPEnabled( + serviceName, 10), + }, + { + ResourceName: "google_compute_backend_service.lipsum", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeBackendService_withIAPDisabled( + serviceName, 10), + }, + { + ResourceName: "google_compute_backend_service.lipsum", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"iap.0.oauth2_client_secret"}, + }, + }, + }) +} + func TestAccComputeBackendService_updatePreservesOptionalParameters(t *testing.T) { t.Parallel() @@ -1370,6 +1403,40 @@ resource "google_compute_http_health_check" "default" { `, serviceName, timeout, igName, itName, checkName) } +func testAccComputeBackendService_withIAPEnabled( + serviceName string, timeout int64) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "lipsum" { + name = "%s" + description = "Hello World 1234" + port_name = "http" + protocol = "HTTP" + timeout_sec = %v + + iap { + enabled = true + } +} +`, serviceName, timeout) +} + +func testAccComputeBackendService_withIAPDisabled( + serviceName string, timeout int64) string { + return fmt.Sprintf(` +resource "google_compute_backend_service" "lipsum" { + name = "%s" + description = "Hello World 1234" + port_name = "http" + protocol = "HTTP" + timeout_sec = %v + + iap { + enabled = false + } +} +`, serviceName, timeout) +} + func testAccComputeBackendService_withSessionAffinity(serviceName, checkName, description, affinityName string) string { return fmt.Sprintf(` resource "google_compute_backend_service" "foobar" { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl index 9363286c6b0b..e16551759592 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.tmpl @@ -178,7 +178,15 @@ func ResourceComputeInstanceTemplate() *schema.Resource { Optional: true, ForceNew: true, Computed: true, - Description: `Indicates how many IOPS to provision for the disk. This sets the number of I/O operations per second that the disk can handle. Values must be between 10,000 and 120,000. For more details, see the [Extreme persistent disk documentation](https://cloud.google.com/compute/docs/disks/extreme-persistent-disk).`, + Description: `Indicates how many IOPS to provision for the disk. This sets the number of I/O operations per second that the disk can handle. For more details, see the [Extreme persistent disk documentation](https://cloud.google.com/compute/docs/disks/extreme-persistent-disk) or the [Hyperdisk documentation](https://cloud.google.com/compute/docs/disks/hyperdisks) depending on the selected disk_type.`, + }, + + "provisioned_throughput": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Computed: true, + Description: `Indicates how much throughput to provision for the disk, in MB/s. This sets the amount of data that can be read or written from the disk per second. Values must greater than or equal to 1. For more details, see the [Hyperdisk documentation](https://cloud.google.com/compute/docs/disks/hyperdisks).`, }, "resource_manager_tags": { @@ -1233,7 +1241,7 @@ func buildDisks(d *schema.ResourceData, config *transport_tpg.Config) ([]*comput } if v, ok := d.GetOk(prefix + ".source"); ok { disk.Source = v.(string) - conflicts := []string{"disk_size_gb", "disk_name", "disk_type", "provisioned_iops", "source_image", "source_snapshot", "labels"} + conflicts := []string{"disk_size_gb", "disk_name", "disk_type", "provisioned_iops", "provisioned_throughput", "source_image", "source_snapshot", "labels"} for _, conflict := range conflicts { if _, ok := d.GetOk(prefix + "." + conflict); ok { return nil, fmt.Errorf("Cannot use `source` with any of the fields in %s", conflicts) @@ -1256,6 +1264,9 @@ func buildDisks(d *schema.ResourceData, config *transport_tpg.Config) ([]*comput if v, ok := d.GetOk(prefix + ".provisioned_iops"); ok { disk.InitializeParams.ProvisionedIops = int64(v.(int)) } + if v, ok := d.GetOk(prefix + ".provisioned_throughput"); ok { + disk.InitializeParams.ProvisionedThroughput = int64(v.(int)) + } if _, ok := d.GetOk(prefix + ".resource_manager_tags"); ok { disk.InitializeParams.ResourceManagerTags = tpgresource.ExpandStringMap(d, prefix + ".resource_manager_tags") } @@ -1486,6 +1497,7 @@ type diskCharacteristics struct { autoDelete bool sourceImage string provisionedIops string + provisionedThroughput string } func diskCharacteristicsFromMap(m map[string]interface{}) diskCharacteristics { @@ -1520,6 +1532,12 @@ func diskCharacteristicsFromMap(m map[string]interface{}) diskCharacteristics { // use strings to compare for simplicity. dc.provisionedIops = fmt.Sprintf("%v", v) } + + if v := m["provisioned_throughput"]; v != nil { + // Terraform and GCP return ints as different types (int vs int64), so just + // use strings to compare for simplicity. + dc.provisionedThroughput = fmt.Sprintf("%v", v) + } return dc } @@ -1545,6 +1563,7 @@ func flattenDisk(disk *compute.AttachedDisk, configDisk map[string]any, defaultP } diskMap["disk_type"] = disk.InitializeParams.DiskType diskMap["provisioned_iops"] = disk.InitializeParams.ProvisionedIops + diskMap["provisioned_throughput"] = disk.InitializeParams.ProvisionedThroughput diskMap["disk_name"] = disk.InitializeParams.DiskName diskMap["labels"] = disk.InitializeParams.Labels // The API does not return a disk size value for scratch disks. They are largely only one size, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl index 21855cad3db8..df076213b9e0 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.tmpl @@ -404,6 +404,26 @@ func TestAccComputeInstanceTemplate_diskIops(t *testing.T) { }) } +func TestAccComputeInstanceTemplate_diskIopsThroughput(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceTemplate_diskIopsThroughput(acctest.RandString(t, 10)), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccComputeInstanceTemplate_subnet_auto(t *testing.T) { t.Parallel() @@ -2922,6 +2942,37 @@ resource "google_compute_instance_template" "foobar" { `, suffix) } +func testAccComputeInstanceTemplate_diskIopsThroughput(suffix string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance_template" "foobar" { + name = "tf-test-instance-template-%s" + machine_type = "e2-medium" + + disk { + source_image = data.google_compute_image.my_image.self_link + auto_delete = true + disk_size_gb = 100 + boot = true + disk_type = "hyperdisk-balanced" + provisioned_iops = 10000 + provisioned_throughput = 1024 + labels = { + foo = "bar" + } + } + + network_interface { + network = "default" + } +} +`, suffix) +} + func testAccComputeInstanceTemplate_subnet_auto(network, suffix string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_backend_service_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_backend_service_test.go.tmpl index 9d3d9e1bfbce..74ceab88911a 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_backend_service_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_backend_service_test.go.tmpl @@ -283,6 +283,39 @@ func TestAccComputeRegionBackendService_withBackendAndIAP(t *testing.T) { }) } +func TestAccComputeRegionBackendService_updateIAPEnabled(t *testing.T) { + t.Parallel() + + serviceName := fmt.Sprintf("foo-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeRegionBackendServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionBackendService_withIAPEnabled( + serviceName, 10), + }, + { + ResourceName: "google_compute_region_backend_service.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeRegionBackendService_withIAPDisabled( + serviceName, 10), + }, + { + ResourceName: "google_compute_region_backend_service.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"iap.0.oauth2_client_secret"}, + }, + }, + }) +} + func TestAccComputeRegionBackendService_UDPFailOverPolicyUpdate(t *testing.T) { t.Parallel() @@ -1021,6 +1054,44 @@ resource "google_compute_health_check" "zero" { `, serviceName, drainingTimeout, checkName) } +func testAccComputeRegionBackendService_withIAPEnabled( + serviceName string, timeout int64) string { + return fmt.Sprintf(` +resource "google_compute_region_backend_service" "foobar" { + name = "%s" + description = "Hello World 1234" + port_name = "http" + protocol = "HTTP" + load_balancing_scheme = "INTERNAL_MANAGED" + region = "us-central1" + timeout_sec = %v + + iap { + enabled = true + } +} +`, serviceName, timeout) +} + +func testAccComputeRegionBackendService_withIAPDisabled( + serviceName string, timeout int64) string { + return fmt.Sprintf(` +resource "google_compute_region_backend_service" "foobar" { + name = "%s" + description = "Hello World 1234" + port_name = "http" + protocol = "HTTP" + load_balancing_scheme = "INTERNAL_MANAGED" + region = "us-central1" + timeout_sec = %v + + iap { + enabled = false + } +} +`, serviceName, timeout) +} + func testAccComputeRegionBackendService_ilbBasicwithIAP(serviceName, checkName string) string { return fmt.Sprintf(` resource "google_compute_region_backend_service" "foobar" { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl index aab1d45eaa34..0dbcead3a2d7 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.tmpl @@ -155,7 +155,15 @@ func ResourceComputeRegionInstanceTemplate() *schema.Resource { Optional: true, ForceNew: true, Computed: true, - Description: `Indicates how many IOPS to provision for the disk. This sets the number of I/O operations per second that the disk can handle. Values must be between 10,000 and 120,000. For more details, see the [Extreme persistent disk documentation](https://cloud.google.com/compute/docs/disks/extreme-persistent-disk).`, + Description: `Indicates how many IOPS to provision for the disk. This sets the number of I/O operations per second that the disk can handle. For more details, see the [Extreme persistent disk documentation](https://cloud.google.com/compute/docs/disks/extreme-persistent-disk) or the [Hyperdisk documentation](https://cloud.google.com/compute/docs/disks/hyperdisks) depending on the selected disk_type.`, + }, + + "provisioned_throughput": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Computed: true, + Description: `Indicates how much throughput to provision for the disk, in MB/s. This sets the amount of data that can be read or written from the disk per second. Values must greater than or equal to 1. For more details, see the [Hyperdisk documentation](https://cloud.google.com/compute/docs/disks/hyperdisks).`, }, "resource_manager_tags": { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl index 1610efeaa26c..b6c7e832b2ae 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.tmpl @@ -303,6 +303,26 @@ func TestAccComputeRegionInstanceTemplate_diskIops(t *testing.T) { }) } +func TestAccComputeRegionInstanceTemplate_diskIopsThroughput(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeRegionInstanceTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionInstanceTemplate_diskIopsThroughput(acctest.RandString(t, 10)), + }, + { + ResourceName: "google_compute_region_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccComputeRegionInstanceTemplate_subnet_auto(t *testing.T) { t.Parallel() @@ -2279,6 +2299,35 @@ resource "google_compute_region_instance_template" "foobar" { `, suffix) } +func testAccComputeRegionInstanceTemplate_diskIopsThroughput(suffix string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_region_instance_template" "foobar" { + name = "tf-test-instance-template-%s" + machine_type = "e2-medium" + region = "us-central1" + + disk { + source_image = data.google_compute_image.my_image.self_link + auto_delete = true + disk_size_gb = 100 + boot = true + disk_type = "hyperdisk-balanced" + provisioned_iops = 10000 + provisioned_throughput = 1024 + } + + network_interface { + network = "default" + } +} +`, suffix) +} + func testAccComputeRegionInstanceTemplate_subnet_auto(network, suffix string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { diff --git a/mmv1/third_party/terraform/services/container/node_config.go.tmpl b/mmv1/third_party/terraform/services/container/node_config.go.tmpl index 98b422e4b21a..22fdd47d505b 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.tmpl +++ b/mmv1/third_party/terraform/services/container/node_config.go.tmpl @@ -595,6 +595,7 @@ func schemaNodeConfig() *schema.Schema { "kubelet_config": { Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Description: `Node kubelet configs.`, Elem: &schema.Resource{ @@ -813,6 +814,7 @@ func schemaNodePoolAutoConfigNodeKubeletConfig() *schema.Schema { return &schema.Schema{ Type: schema.TypeList, Optional: true, + Computed: true, MaxItems: 1, Description: `Node kubelet configs.`, Elem: &schema.Resource{ diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl index 715083b1c716..f4864da23dc6 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.tmpl @@ -1041,10 +1041,10 @@ func ResourceContainerCluster() *schema.Resource { "enable_components": { Type: schema.TypeList, Required: true, - Description: `GKE components exposing logs. Valid values include SYSTEM_COMPONENTS, APISERVER, CONTROLLER_MANAGER, SCHEDULER, and WORKLOADS.`, + Description: `GKE components exposing logs. Valid values include SYSTEM_COMPONENTS, APISERVER, CONTROLLER_MANAGER, KCP_CONNECTION, KCP_SSHD, SCHEDULER, and WORKLOADS.`, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validation.StringInSlice([]string{"SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER", "WORKLOADS"}, false), + ValidateFunc: validation.StringInSlice([]string{"SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "KCP_CONNECTION", "KCP_SSHD", "SCHEDULER", "WORKLOADS"}, false), }, }, }, @@ -3423,6 +3423,7 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er req := &container.UpdateClusterRequest{ Update: &container.ClusterUpdate{ DesiredEnableCiliumClusterwideNetworkPolicy: enabled, + ForceSendFields: []string{"DesiredEnableCiliumClusterwideNetworkPolicy"}, }, } updateF := updateFunc(req, "updating cilium clusterwide network policy") diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.tmpl index fdbc31fcc2ed..4a4731962b8b 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.tmpl @@ -755,10 +755,10 @@ func resourceContainerClusterResourceV1() *schema.Resource { "enable_components": { Type: schema.TypeList, Required: true, - Description: `GKE components exposing logs. Valid values include SYSTEM_COMPONENTS, APISERVER, CONTROLLER_MANAGER, SCHEDULER, and WORKLOADS.`, + Description: `GKE components exposing logs. Valid values include SYSTEM_COMPONENTS, APISERVER, CONTROLLER_MANAGER, KCP_CONNECTION, KCP_SSHD, SCHEDULER, and WORKLOADS.`, Elem: &schema.Schema{ Type: schema.TypeString, - ValidateFunc: validation.StringInSlice([]string{"SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER", "WORKLOADS"}, false), + ValidateFunc: validation.StringInSlice([]string{"SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "KCP_CONNECTION", "KCP_SSHD", "SCHEDULER", "WORKLOADS"}, false), }, }, }, diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl index 0ce588f744ad..739a31c8c773 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.tmpl @@ -4245,10 +4245,10 @@ func TestAccContainerCluster_autoprovisioningLocations(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("google_container_cluster.with_autoprovisioning_locations", "cluster_autoscaling.0.enabled", "true"), - + resource.TestCheckResourceAttr("google_container_cluster.with_autoprovisioning_locations", "cluster_autoscaling.0.auto_provisioning_locations.0", "us-central1-a"), - + resource.TestCheckResourceAttr("google_container_cluster.with_autoprovisioning_locations", "cluster_autoscaling.0.auto_provisioning_locations.1", "us-central1-f"), ), @@ -4264,10 +4264,10 @@ func TestAccContainerCluster_autoprovisioningLocations(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("google_container_cluster.with_autoprovisioning_locations", "cluster_autoscaling.0.enabled", "true"), - + resource.TestCheckResourceAttr("google_container_cluster.with_autoprovisioning_locations", "cluster_autoscaling.0.auto_provisioning_locations.0", "us-central1-b"), - + resource.TestCheckResourceAttr("google_container_cluster.with_autoprovisioning_locations", "cluster_autoscaling.0.auto_provisioning_locations.1", "us-central1-c"), ), @@ -4591,6 +4591,18 @@ func TestAccContainerCluster_enableCiliumPolicies(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{"deletion_protection"}, }, + { + Config: testAccContainerCluster_enableCiliumPolicies(clusterName, networkName, subnetworkName, false), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_container_cluster.primary", "enable_cilium_clusterwide_network_policy", "false"), + ), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, }, }) } @@ -9916,7 +9928,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 logging_config { - enable_components = [ "SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER"] + enable_components = [ "SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER", "KCP_CONNECTION", "KCP_SSHD"] } monitoring_config { enable_components = [ "SYSTEM_COMPONENTS" ] @@ -11331,30 +11343,30 @@ func TestAccContainerCluster_privateRegistry(t *testing.T) { func testAccContainerCluster_privateRegistryEnabled(secretID, clusterName, networkName, subnetworkName string) string { return fmt.Sprintf(` -data "google_project" "test_project" { +data "google_project" "test_project" { } -resource "google_secret_manager_secret" "secret-basic" { +resource "google_secret_manager_secret" "secret-basic" { secret_id = "%s" - replication { - user_managed { - replicas { - location = "us-central1" - } - } - } -} - -resource "google_secret_manager_secret_version" "secret-version-basic" { - secret = google_secret_manager_secret.secret-basic.id - secret_data = "dummypassword" - } - -resource "google_secret_manager_secret_iam_member" "secret_iam" { - secret_id = google_secret_manager_secret.secret-basic.id - role = "roles/secretmanager.admin" - member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" - depends_on = [google_secret_manager_secret_version.secret-version-basic] + replication { + user_managed { + replicas { + location = "us-central1" + } + } + } +} + +resource "google_secret_manager_secret_version" "secret-version-basic" { + secret = google_secret_manager_secret.secret-basic.id + secret_data = "dummypassword" + } + +resource "google_secret_manager_secret_iam_member" "secret_iam" { + secret_id = google_secret_manager_secret.secret-basic.id + role = "roles/secretmanager.admin" + member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" + depends_on = [google_secret_manager_secret_version.secret-version-basic] } resource "google_container_cluster" "primary" { @@ -11391,7 +11403,7 @@ resource "google_container_cluster" "primary" { } } } -} +} `, secretID, clusterName, networkName, subnetworkName) } @@ -11420,29 +11432,29 @@ resource "google_container_cluster" "primary" { func testAccContainerCluster_withNodePoolPrivateRegistry(secretID, clusterName, nodePoolName, networkName, subnetworkName string) string { return fmt.Sprintf(` -data "google_project" "test_project" { +data "google_project" "test_project" { } -resource "google_secret_manager_secret" "secret-basic" { +resource "google_secret_manager_secret" "secret-basic" { secret_id = "%s" - replication { - user_managed { - replicas { - location = "us-central1" - } - } - } -} -resource "google_secret_manager_secret_version" "secret-version-basic" { - secret = google_secret_manager_secret.secret-basic.id - secret_data = "dummypassword" - } - -resource "google_secret_manager_secret_iam_member" "secret_iam" { - secret_id = google_secret_manager_secret.secret-basic.id - role = "roles/secretmanager.admin" - member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" - depends_on = [google_secret_manager_secret_version.secret-version-basic] + replication { + user_managed { + replicas { + location = "us-central1" + } + } + } +} +resource "google_secret_manager_secret_version" "secret-version-basic" { + secret = google_secret_manager_secret.secret-basic.id + secret_data = "dummypassword" + } + +resource "google_secret_manager_secret_iam_member" "secret_iam" { + secret_id = google_secret_manager_secret.secret-basic.id + role = "roles/secretmanager.admin" + member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" + depends_on = [google_secret_manager_secret_version.secret-version-basic] } resource "google_container_cluster" "primary" { name = "%s" @@ -11479,29 +11491,29 @@ resource "google_container_cluster" "primary" { func testAccContainerCluster_withNodeConfigPrivateRegistry(secretID, clusterName, networkName, subnetworkName string) string { return fmt.Sprintf(` -data "google_project" "test_project" { +data "google_project" "test_project" { } resource "google_secret_manager_secret" "secret-basic" { secret_id = "%s" - replication { - user_managed { - replicas { - location = "us-central1" - } - } - } -} -resource "google_secret_manager_secret_version" "secret-version-basic" { - secret = google_secret_manager_secret.secret-basic.id - secret_data = "dummypassword" - } - -resource "google_secret_manager_secret_iam_member" "secret_iam" { - secret_id = google_secret_manager_secret.secret-basic.id - role = "roles/secretmanager.admin" - member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" - depends_on = [google_secret_manager_secret_version.secret-version-basic] + replication { + user_managed { + replicas { + location = "us-central1" + } + } + } +} +resource "google_secret_manager_secret_version" "secret-version-basic" { + secret = google_secret_manager_secret.secret-basic.id + secret_data = "dummypassword" + } + +resource "google_secret_manager_secret_iam_member" "secret_iam" { + secret_id = google_secret_manager_secret.secret-basic.id + role = "roles/secretmanager.admin" + member = "serviceAccount:${data.google_project.test_project.number}-compute@developer.gserviceaccount.com" + depends_on = [google_secret_manager_secret_version.secret-version-basic] } resource "google_container_cluster" "primary" { name = "%s" diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.tmpl b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.tmpl index 3a0badc171c7..f1a2b374fe39 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.tmpl +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.tmpl @@ -1759,6 +1759,7 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node d.Get(prefix + "node_config.0.workload_metadata_config")), } if req.WorkloadMetadataConfig == nil { + req.WorkloadMetadataConfig = &container.WorkloadMetadataConfig{} req.ForceSendFields = []string{"WorkloadMetadataConfig"} } updateF := func() error { @@ -1826,6 +1827,7 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node d.Get(prefix + "node_config.0.kubelet_config")), } if req.KubeletConfig == nil { + req.KubeletConfig = &container.NodeKubeletConfig{} req.ForceSendFields = []string{"KubeletConfig"} } updateF := func() error { @@ -1859,6 +1861,7 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node d.Get(prefix + "node_config.0.linux_node_config")), } if req.LinuxNodeConfig == nil { + req.LinuxNodeConfig = &container.LinuxNodeConfig{} req.ForceSendFields = []string{"LinuxNodeConfig"} } updateF := func() error { diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go index 66e53985a69c..e6b7c6e27d1a 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster.go @@ -2177,6 +2177,7 @@ func expandGceClusterConfig(d *schema.ResourceData, config *transport_tpg.Config } if v, ok := cfg["internal_ip_only"]; ok { conf.InternalIpOnly = v.(bool) + conf.ForceSendFields = append(conf.ForceSendFields, "InternalIpOnly") } if v, ok := cfg["metadata"]; ok { conf.Metadata = tpgresource.ConvertStringMap(v.(map[string]interface{})) diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl index 962b8f521239..7cb8c98bd466 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.tmpl @@ -28,7 +28,7 @@ func TestAccDataprocCluster_missingZoneGlobalRegion1(t *testing.T) { rnd := acctest.RandString(t, 10) acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { @@ -44,7 +44,7 @@ func TestAccDataprocCluster_missingZoneGlobalRegion2(t *testing.T) { rnd := acctest.RandString(t, 10) acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { @@ -559,7 +559,6 @@ func TestAccDataprocCluster_spotWithAuxiliaryNodeGroups(t *testing.T) { resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group.0.node_group_config.0.accelerators.0.accelerator_count", "1"), resource.TestCheckResourceAttr("google_dataproc_cluster.with_auxiliary_node_groups", "cluster_config.0.auxiliary_node_groups.0.node_group_id", "node-group-id"), testAccCheckDataprocAuxiliaryNodeGroupAccelerator(&cluster, project), - ), }, }, @@ -707,7 +706,7 @@ func TestAccDataprocCluster_withServiceAcc(t *testing.T) { ExternalProviders: map[string]resource.ExternalProvider{ "time": {}, }, - CheckDestroy: testAccCheckDataprocClusterDestroy(t), + CheckDestroy: testAccCheckDataprocClusterDestroy(t), Steps: []resource.TestStep{ { Config: testAccDataprocCluster_withServiceAcc(sa, rnd, subnetworkName), @@ -827,13 +826,13 @@ func TestAccDataprocCluster_withLifecycleConfigAutoDeletion(t *testing.T) { CheckDestroy: testAccCheckDataprocClusterDestroy(t), Steps: []resource.TestStep{ { - Config: testAccDataprocCluster_withLifecycleConfigAutoDeletionTime(rnd, now.Add(time.Hour * 10).Format(fmtString), subnetworkName), + Config: testAccDataprocCluster_withLifecycleConfigAutoDeletionTime(rnd, now.Add(time.Hour*10).Format(fmtString), subnetworkName), Check: resource.ComposeTestCheckFunc( testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_lifecycle_config", &cluster), ), }, { - Config: testAccDataprocCluster_withLifecycleConfigAutoDeletionTime(rnd, now.Add(time.Hour * 20).Format(fmtString), subnetworkName), + Config: testAccDataprocCluster_withLifecycleConfigAutoDeletionTime(rnd, now.Add(time.Hour*20).Format(fmtString), subnetworkName), Check: resource.ComposeTestCheckFunc( testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_lifecycle_config", &cluster), ), @@ -1046,7 +1045,7 @@ func TestAccDataprocCluster_withMetastoreConfig(t *testing.T) { updateServiceId := "tf-test-metastore-srv-update-" + acctest.RandString(t, 10) msName_basic := fmt.Sprintf("projects/%s/locations/us-central1/services/%s", pid, basicServiceId) msName_update := fmt.Sprintf("projects/%s/locations/us-central1/services/%s", pid, updateServiceId) - + var cluster dataproc.Cluster clusterName := "tf-test-" + acctest.RandString(t, 10) acctest.VcrTest(t, resource.TestCase{ @@ -1058,8 +1057,7 @@ func TestAccDataprocCluster_withMetastoreConfig(t *testing.T) { Config: testAccDataprocCluster_withMetastoreConfig(clusterName, basicServiceId), Check: resource.ComposeTestCheckFunc( testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_metastore_config", &cluster), - resource.TestCheckResourceAttr("google_dataproc_cluster.with_metastore_config", "cluster_config.0.metastore_config.0.dataproc_metastore_service",msName_basic), - + resource.TestCheckResourceAttr("google_dataproc_cluster.with_metastore_config", "cluster_config.0.metastore_config.0.dataproc_metastore_service", msName_basic), ), }, { @@ -1067,7 +1065,6 @@ func TestAccDataprocCluster_withMetastoreConfig(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_metastore_config", &cluster), resource.TestCheckResourceAttr("google_dataproc_cluster.with_metastore_config", "cluster_config.0.metastore_config.0.dataproc_metastore_service", msName_update), - ), }, }, @@ -1417,6 +1414,10 @@ resource "google_dataproc_cluster" "accelerated_cluster" { region = "us-central1" cluster_config { + software_config { + image_version = "2.0.35-debian10" + } + gce_cluster_config { subnetwork = "%s" zone = "%s" @@ -1652,6 +1653,9 @@ resource "google_dataproc_cluster" "basic" { region = "us-central1" cluster_config { + software_config { + image_version = "2.0.35-debian10" + } gce_cluster_config { subnetwork = "%s" zone = "us-central1-f" @@ -1764,6 +1768,7 @@ resource "google_dataproc_cluster" "with_init_action" { # Keep the costs down with smallest config we can get away with software_config { + image_version = "2.0.35-debian10" override_properties = { "dataproc:dataproc.allow.zero.workers" = "true" } @@ -2028,6 +2033,7 @@ resource "google_dataproc_cluster" "with_bucket" { # Keep the costs down with smallest config we can get away with software_config { + image_version = "2.0.35-debian10" override_properties = { "dataproc:dataproc.allow.zero.workers" = "true" } @@ -2061,6 +2067,7 @@ resource "google_dataproc_cluster" "with_bucket" { # Keep the costs down with smallest config we can get away with software_config { + image_version = "2.0.35-debian10" override_properties = { "dataproc:dataproc.allow.zero.workers" = "true" } @@ -2250,6 +2257,7 @@ resource "google_dataproc_cluster" "with_service_account" { cluster_config { # Keep the costs down with smallest config we can get away with software_config { + image_version = "2.0.35-debian10" override_properties = { "dataproc:dataproc.allow.zero.workers" = "true" } diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job_test.go.tmpl b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job_test.go.tmpl index afb392cf6ec2..247e6b5c834b 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job_test.go.tmpl +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job_test.go.tmpl @@ -862,6 +862,7 @@ resource "google_dataproc_cluster" "basic" { cluster_config { # Keep the costs down with smallest config we can get away with software_config { + image_version = "2.0.35-debian10" override_properties = { "dataproc:dataproc.allow.zero.workers" = "true" } diff --git a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_agent_test.go.tmpl b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_agent_test.go.tmpl index d6d7f1b16f17..9e4965209503 100644 --- a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_agent_test.go.tmpl +++ b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_agent_test.go.tmpl @@ -29,7 +29,7 @@ func TestAccDialogflowCXAgent_update(t *testing.T) { ResourceName: "google_dialogflow_cx_agent.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"git_integration_settings.0.github_settings.0.access_token"}, + ImportStateVerifyIgnore: []string{"git_integration_settings.0.github_settings.0.access_token", "enable_stackdriver_logging", "advanced_settings.0.logging_settings"}, }, { Config: testAccDialogflowCXAgent_full(context), @@ -38,7 +38,7 @@ func TestAccDialogflowCXAgent_update(t *testing.T) { ResourceName: "google_dialogflow_cx_agent.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"git_integration_settings.0.github_settings.0.access_token"}, + ImportStateVerifyIgnore: []string{"git_integration_settings.0.github_settings.0.access_token", "enable_stackdriver_logging", "advanced_settings.0.logging_settings"}, }, { Config: testAccDialogflowCXAgent_removeSettings(context), @@ -47,7 +47,7 @@ func TestAccDialogflowCXAgent_update(t *testing.T) { ResourceName: "google_dialogflow_cx_agent.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"git_integration_settings.0.github_settings.0.access_token"}, + ImportStateVerifyIgnore: []string{"git_integration_settings.0.github_settings.0.access_token", "enable_stackdriver_logging", "advanced_settings.0.logging_settings"}, }, }, }) @@ -92,11 +92,26 @@ func testAccDialogflowCXAgent_full(context map[string]interface{}) string { audio_export_gcs_destination { uri = "${google_storage_bucket.bucket.url}/prefix-" } + speech_settings { + endpointer_sensitivity = 30 + no_speech_timeout = "3.500s" + use_timeout_based_endpointing = true + models = { + name : "wrench" + mass : "1.3kg" + count : "3" + } + } dtmf_settings { - enabled = true - max_digits = 1 + enabled = true + max_digits = 1 finish_digit = "#" } + logging_settings { + enable_stackdriver_logging = true + enable_interaction_logging = true + enable_consent_based_redaction = true + } } git_integration_settings { github_settings { diff --git a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_flow_test.go b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_flow_test.go index e4a7b516aa15..b3745305614e 100644 --- a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_flow_test.go +++ b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_flow_test.go @@ -25,17 +25,19 @@ func TestAccDialogflowCXFlow_update(t *testing.T) { Config: testAccDialogflowCXFlow_basic(context), }, { - ResourceName: "google_dialogflow_cx_flow.my_flow", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_dialogflow_cx_flow.my_flow", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"advanced_settings.0.logging_settings"}, }, { Config: testAccDialogflowCXFlow_full(context), }, { - ResourceName: "google_dialogflow_cx_flow.my_flow", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_dialogflow_cx_flow.my_flow", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"advanced_settings.0.logging_settings"}, }, }, }) @@ -341,11 +343,26 @@ func testAccDialogflowCXFlow_full(context map[string]interface{}) string { audio_export_gcs_destination { uri = "${google_storage_bucket.bucket.url}/prefix-" } + speech_settings { + endpointer_sensitivity = 30 + no_speech_timeout = "3.500s" + use_timeout_based_endpointing = true + models = { + name : "wrench" + mass : "1.3kg" + count : "3" + } + } dtmf_settings { enabled = true max_digits = 1 finish_digit = "#" } + logging_settings { + enable_stackdriver_logging = true + enable_interaction_logging = true + enable_consent_based_redaction = true + } } } `, context) diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config.go.tmpl index 261a700a2a10..cb8aef4a8a2d 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app_config.go.tmpl @@ -75,6 +75,7 @@ func (d *GoogleFirebaseAndroidAppConfigDataSource) Schema(ctx context.Context, r Computed: true, }, + // This is included for backwards compatibility with the original, SDK-implemented data source. "id": schema.StringAttribute{ Description: "Firebase Android App Config identifier", MarkdownDescription: "Firebase Android App Config identifier", @@ -116,25 +117,26 @@ func (d *GoogleFirebaseAndroidAppConfigDataSource) Read(ctx context.Context, req return } - d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) - - client := firebase.NewProjectsAndroidAppsService(d.client) - // Read Terraform configuration data into the model resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) if resp.Diagnostics.HasError() { return } + // Use provider_meta to set User-Agent + d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) + data.Project = fwresource.GetProjectFramework(data.Project, d.project, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - appName := fmt.Sprintf("projects/%s/androidApps/%s/config", data.Project.ValueString(), data.AppId.ValueString()) - data.Id = types.StringValue(appName) - clientResp, err := client.GetConfig(appName).Do() + + // GET Request + service := firebase.NewProjectsAndroidAppsService(d.client) + appName := fmt.Sprintf("projects/%s/androidApps/%s/config", data.Project.ValueString(), data.AppId.ValueString()) + clientResp, err := service.GetConfig(appName).Do() if err != nil { fwtransport.HandleDatasourceNotFoundError(ctx, err, &resp.State, fmt.Sprintf("dataSourceFirebaseAndroidAppConfig %q", data.AppId.ValueString()), &resp.Diagnostics) if resp.Diagnostics.HasError() { @@ -144,6 +146,8 @@ func (d *GoogleFirebaseAndroidAppConfigDataSource) Read(ctx context.Context, req tflog.Trace(ctx, "read firebase android app config data source") + // Put data in model + data.Id = types.StringValue(appName) data.ConfigFilename = types.StringValue(clientResp.ConfigFilename) data.ConfigFileContents = types.StringValue(clientResp.ConfigFileContents) diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config.go.tmpl index f7f5b137fafb..69d1da3451ea 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app_config.go.tmpl @@ -75,6 +75,7 @@ func (d *GoogleFirebaseAppleAppConfigDataSource) Schema(ctx context.Context, req Computed: true, }, + // This is included for backwards compatibility with the original, SDK-implemented data source. "id": schema.StringAttribute{ Description: "Firebase Apple App Config identifier", MarkdownDescription: "Firebase Apple App Config identifier", @@ -116,25 +117,24 @@ func (d *GoogleFirebaseAppleAppConfigDataSource) Read(ctx context.Context, req d return } - d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) - - client := firebase.NewProjectsIosAppsService(d.client) - // Read Terraform configuration data into the model resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) if resp.Diagnostics.HasError() { return } + // Use provider_meta to set User-Agent + d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) + data.Project = fwresource.GetProjectFramework(data.Project, d.project, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } + // GET Request + service := firebase.NewProjectsIosAppsService(d.client) appName := fmt.Sprintf("projects/%s/iosApps/%s/config", data.Project.ValueString(), data.AppId.ValueString()) - data.Id = types.StringValue(appName) - - clientResp, err := client.GetConfig(appName).Do() + clientResp, err := service.GetConfig(appName).Do() if err != nil { fwtransport.HandleDatasourceNotFoundError(ctx, err, &resp.State, fmt.Sprintf("dataSourceFirebaseAppleAppConfig %q", data.AppId.ValueString()), &resp.Diagnostics) if resp.Diagnostics.HasError() { @@ -144,10 +144,12 @@ func (d *GoogleFirebaseAppleAppConfigDataSource) Read(ctx context.Context, req d tflog.Trace(ctx, "read firebase apple app config data source") + // Put data in model + data.Id = types.StringValue(appName) data.ConfigFilename = types.StringValue(clientResp.ConfigFilename) data.ConfigFileContents = types.StringValue(clientResp.ConfigFileContents) // Save data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } -{{- end }} +{{- end }} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config.go.tmpl index 7479139af4f4..8782d08fdbc7 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config.go.tmpl +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config.go.tmpl @@ -87,17 +87,17 @@ func (d *GoogleFirebaseWebAppConfigDataSource) Schema(ctx context.Context, req d }, "location_id": schema.StringAttribute{ - Description: "The ID of the project's default GCP resource location. The location is one of the available GCP resource locations. " + - "This field is omitted if the default GCP resource location has not been finalized yet. To set your project's " + + Description: "The ID of the project's default GCP resource location. The location is one of the available GCP resource locations. " + + "This field is omitted if the default GCP resource location has not been finalized yet. To set your project's " + "default GCP resource location, call defaultLocation.finalize after you add Firebase services to your project.", MarkdownDescription: "The ID of the project's default GCP resource location. The location is one of the available GCP resource locations. " + - "This field is omitted if the default GCP resource location has not been finalized yet. To set your project's " + + "This field is omitted if the default GCP resource location has not been finalized yet. To set your project's " + "default GCP resource location, call defaultLocation.finalize after you add Firebase services to your project.", - Computed: true, + Computed: true, }, "measurement_id": schema.StringAttribute{ - Description: "The unique Google-assigned identifier of the Google Analytics web stream associated with the Firebase Web App. " + + Description: "The unique Google-assigned identifier of the Google Analytics web stream associated with the Firebase Web App. " + "Firebase SDKs use this ID to interact with Google Analytics APIs. " + "This field is only present if the App is linked to a web stream in a Google Analytics App + Web property. " + "Learn more about this ID and Google Analytics web streams in the Analytics documentation. " + @@ -107,7 +107,7 @@ func (d *GoogleFirebaseWebAppConfigDataSource) Schema(ctx context.Context, req d "This field is only present if the App is linked to a web stream in a Google Analytics App + Web property. " + "Learn more about this ID and Google Analytics web streams in the Analytics documentation. " + "To generate a measurementId and link the Web App with a Google Analytics web stream, call projects.addGoogleAnalytics.", - Computed: true, + Computed: true, }, "messaging_sender_id": schema.StringAttribute{ @@ -122,6 +122,7 @@ func (d *GoogleFirebaseWebAppConfigDataSource) Schema(ctx context.Context, req d Computed: true, }, + // This is included for backwards compatibility with the original, SDK-implemented data source. "id": schema.StringAttribute{ Description: "Firebase Web App Config identifier", MarkdownDescription: "Firebase Web App Config identifier", @@ -163,25 +164,24 @@ func (d *GoogleFirebaseWebAppConfigDataSource) Read(ctx context.Context, req dat return } - d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) - - client := firebase.NewProjectsWebAppsService(d.client) - // Read Terraform configuration data into the model resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) if resp.Diagnostics.HasError() { return } + // Use provider_meta to set User-Agent + d.client.UserAgent = fwtransport.GenerateFrameworkUserAgentString(metaData, d.client.UserAgent) + data.Project = fwresource.GetProjectFramework(data.Project, d.project, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } + // GET Request + service := firebase.NewProjectsWebAppsService(d.client) appName := fmt.Sprintf("projects/%s/webApps/%s/config", data.Project.ValueString(), data.WebAppId.ValueString()) - data.Id = data.WebAppId - - clientResp, err := client.GetConfig(appName).Do() + clientResp, err := service.GetConfig(appName).Do() if err != nil { fwtransport.HandleDatasourceNotFoundError(ctx, err, &resp.State, fmt.Sprintf("dataSourceFirebaseWebAppConfig %q", data.WebAppId.ValueString()), &resp.Diagnostics) if resp.Diagnostics.HasError() { @@ -191,6 +191,8 @@ func (d *GoogleFirebaseWebAppConfigDataSource) Read(ctx context.Context, req dat tflog.Trace(ctx, "read firebase web app config data source") + // Put data in model + data.Id = data.WebAppId data.ApiKey = types.StringValue(clientResp.ApiKey) data.AuthDomain = types.StringValue(clientResp.AuthDomain) data.DatabaseUrl = types.StringValue(clientResp.DatabaseURL) diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config_test.go.tmpl b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config_test.go.tmpl new file mode 100644 index 000000000000..6358866e69ed --- /dev/null +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_config_test.go.tmpl @@ -0,0 +1,51 @@ +package firebase_test +{{- if ne $.TargetVersionName "ga" }} + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceGoogleFirebaseWebAppConfig(t *testing.T) { + // TODO: https://github.com/hashicorp/terraform-provider-google/issues/14158 + acctest.SkipIfVcr(t) + t.Parallel() + context := map[string]interface{}{ + "project_id": envvar.GetTestProjectFromEnv(), + "display_name": "tf_test Display Name WebApp DataSource", + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckFirebaseWebAppDestroyProducer(t), + Steps: []resource.TestStep{ + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Config: testAccDataSourceGoogleFirebaseWebAppConfig(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.my_app_config", "api_key"), + resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.my_app_config", "auth_domain"), + resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.my_app_config", "database_url"), + resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.my_app_config", "storage_bucket"), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleFirebaseWebAppConfig(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_firebase_web_app" "my_app" { + project = "%{project_id}" + display_name = "%{display_name}" +} + +data "google_firebase_web_app_config" "my_app_config" { + web_app_id = google_firebase_web_app.my_app.app_id +} +`, context) +} +{{- end }} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.tmpl b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.tmpl index b6be9477fbb1..40202e09d081 100644 --- a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.tmpl +++ b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.tmpl @@ -31,6 +31,9 @@ func TestAccGKEHubFeatureMembership_gkehubFeatureAcmUpdate(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, CheckDestroy: testAccCheckGKEHubFeatureDestroyProducer(t), Steps: []resource.TestStep{ { @@ -97,7 +100,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member_1" { @@ -148,7 +151,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "changed" } - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member_1" { @@ -206,7 +209,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "changed" } - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member_2" { @@ -228,7 +231,7 @@ resource "google_gke_hub_feature_membership" "feature_member_2" { enabled = true audit_interval_seconds = "9" exemptable_namespaces = ["different", "1234"] - template_library_installed = false + template_library_installed = true } hierarchy_controller { enable_hierarchical_resource_quota = true @@ -285,9 +288,6 @@ resource "google_gke_hub_feature_membership" "feature_member_4" { } } } - - - `, context) } @@ -301,7 +301,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "changed" } - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member_3" { @@ -336,6 +336,9 @@ func TestAccGKEHubFeatureMembership_gkehubFeatureAcmAllFields(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, CheckDestroy: testAccCheckGKEHubFeatureDestroyProducer(t), Steps: []resource.TestStep{ { @@ -394,7 +397,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 deletion_protection = false - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_membership" "membership" { @@ -418,7 +421,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member" { @@ -461,7 +464,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 deletion_protection = false - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_membership" "membership" { @@ -485,7 +488,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member" { @@ -529,7 +532,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 deletion_protection = false - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub, google_project_service.acm] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_membership" "membership" { @@ -553,7 +556,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_service_account" "feature_sa" { @@ -594,6 +597,9 @@ func TestAccGKEHubFeatureMembership_gkehubFeatureAcmOci(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, CheckDestroy: testAccCheckGKEHubFeatureDestroyProducer(t), Steps: []resource.TestStep{ { @@ -643,7 +649,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_service_account" "feature_sa" { @@ -693,7 +699,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_service_account" "feature_sa" { @@ -743,7 +749,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_service_account" "feature_sa" { @@ -785,6 +791,9 @@ func TestAccGKEHubFeatureMembership_gkehubFeatureMesh(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, CheckDestroy: testAccCheckGKEHubFeatureDestroyProducer(t), Steps: []resource.TestStep{ { @@ -832,7 +841,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 deletion_protection = false - depends_on = [google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_membership" "membership" { @@ -856,7 +865,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.container, google_project_service.gkehub, google_project_service.mesh] + depends_on = [time_sleep.wait_120s] } resource "google_service_account" "feature_sa" { @@ -885,7 +894,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 deletion_protection = false - depends_on = [google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_membership" "membership" { @@ -909,7 +918,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.container, google_project_service.gkehub, google_project_service.mesh] + depends_on = [time_sleep.wait_120s] } resource "google_service_account" "feature_sa" { @@ -937,7 +946,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 deletion_protection = false - depends_on = [google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_membership" "membership" { @@ -961,7 +970,7 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - depends_on = [google_project_service.container, google_project_service.gkehub, google_project_service.mesh] + depends_on = [time_sleep.wait_120s] } resource "google_service_account" "feature_sa" { @@ -995,6 +1004,9 @@ func TestAccGKEHubFeatureMembership_gkehubFeaturePolicyController(t *testing.T) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, CheckDestroy: testAccCheckGKEHubFeatureDestroyProducer(t), Steps: []resource.TestStep{ { @@ -1040,7 +1052,7 @@ resource "google_gke_hub_feature" "feature" { project = google_project.project.project_id name = "policycontroller" location = "global" - depends_on = [google_project_service.container, google_project_service.gkehub, google_project_service.poco] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member" { @@ -1066,7 +1078,7 @@ resource "google_gke_hub_feature" "feature" { project = google_project.project.project_id name = "policycontroller" location = "global" - depends_on = [google_project_service.container, google_project_service.gkehub, google_project_service.poco] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member" { @@ -1137,7 +1149,7 @@ resource "google_gke_hub_feature" "feature" { project = google_project.project.project_id name = "policycontroller" location = "global" - depends_on = [google_project_service.container, google_project_service.gkehub, google_project_service.poco] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_feature_membership" "feature_member" { @@ -1189,7 +1201,7 @@ resource "google_container_cluster" "primary" { initial_node_count = 1 project = google_project.project.project_id deletion_protection = false - depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_container_cluster" "secondary" { @@ -1198,7 +1210,7 @@ resource "google_container_cluster" "secondary" { initial_node_count = 1 project = google_project.project.project_id deletion_protection = false - depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_container_cluster" "tertiary" { @@ -1207,7 +1219,7 @@ resource "google_container_cluster" "tertiary" { initial_node_count = 1 project = google_project.project.project_id deletion_protection = false - depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } @@ -1217,7 +1229,7 @@ resource "google_container_cluster" "quarternary" { initial_node_count = 1 project = google_project.project.project_id deletion_protection = false - depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_membership" "membership" { @@ -1281,7 +1293,7 @@ resource "google_compute_network" "testnetwork" { project = google_project.project.project_id name = "testnetwork" auto_create_subnetworks = true - depends_on = [google_project_service.compute] + depends_on = [time_sleep.wait_120s] } resource "google_container_cluster" "container_acmoci" { @@ -1291,7 +1303,7 @@ resource "google_container_cluster" "container_acmoci" { network = google_compute_network.testnetwork.self_link project = google_project.project.project_id deletion_protection = false - depends_on = [google_project_service.container, google_project_service.container, google_project_service.gkehub] + depends_on = [time_sleep.wait_120s] } resource "google_gke_hub_membership" "membership_acmoci" { @@ -1407,6 +1419,22 @@ resource "google_project_service" "gkehub" { service = "gkehub.googleapis.com" disable_on_destroy = false } + +// It needs waiting until the API services are really activated. +resource "time_sleep" "wait_120s" { + create_duration = "120s" + depends_on = [ + google_project_service.anthos, + google_project_service.mesh, + google_project_service.mci, + google_project_service.acm, + google_project_service.poco, + google_project_service.mcsd, + google_project_service.compute, + google_project_service.container, + google_project_service.gkehub, + ] +} `, context) } diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_sink.go b/mmv1/third_party/terraform/services/logging/resource_logging_sink.go index 65fcdae6f3a7..61d4b5559b75 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_sink.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_sink.go @@ -63,9 +63,10 @@ func resourceLoggingSinkSchema() map[string]*schema.Schema { Description: `A description of this exclusion.`, }, "filter": { - Type: schema.TypeString, - Required: true, - Description: `An advanced logs filter that matches the log entries to be excluded. By using the sample function, you can exclude less than 100% of the matching log entries`, + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: OptionalSurroundingSpacesSuppress, + Description: `An advanced logs filter that matches the log entries to be excluded. By using the sample function, you can exclude less than 100% of the matching log entries`, }, "disabled": { Type: schema.TypeBool, diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_vault_sweeper.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_vault_sweeper.go index f8d0a250ae96..4639cebeff64 100644 --- a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_vault_sweeper.go +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_vault_sweeper.go @@ -36,7 +36,7 @@ func testSweepNetappBackupVault(region string) error { t := &testing.T{} billingId := envvar.GetTestBillingAccountFromEnv(t) - regions := []string{"us-central1", "us-west2", "us-east4"} + regions := []string{"us-central1", "us-west1", "us-west2", "us-east4"} for _, r := range regions { log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s in %s", resourceName, r) diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_vault_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_vault_test.go index c0420fd24f5f..75ca67d5fac1 100644 --- a/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_vault_test.go +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_backup_vault_test.go @@ -50,7 +50,7 @@ func testAccNetappBackupVault_NetappBackupVaultExample_basic(context map[string] return acctest.Nprintf(` resource "google_netapp_backup_vault" "test_backup_vault" { name = "tf-test-test-backup-vault%{random_suffix}" - location = "us-central1" + location = "us-east4" } `, context) } @@ -59,7 +59,7 @@ func testAccNetappBackupVault_NetappBackupVaultExample_update(context map[string return acctest.Nprintf(` resource "google_netapp_backup_vault" "test_backup_vault" { name = "tf-test-test-backup-vault%{random_suffix}" - location = "us-central1" + location = "us-east4" description = "Terraform created vault" labels = { "creator": "testuser", diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_gateway_test.go b/mmv1/third_party/terraform/services/networkservices/resource_network_services_gateway_test.go index b889daba865e..6f20ec7a7dae 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_gateway_test.go +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_gateway_test.go @@ -169,7 +169,7 @@ resource "google_network_services_gateway" "default" { return config } -func TestAccNetworkServicesGateway_updateSwp(t *testing.T) { +func TestAccNetworkServicesGateway_swpUpdate(t *testing.T) { cmName := fmt.Sprintf("tf-test-gateway-swp-cm-%s", acctest.RandString(t, 10)) netName := fmt.Sprintf("tf-test-gateway-swp-net-%s", acctest.RandString(t, 10)) subnetName := fmt.Sprintf("tf-test-gateway-swp-subnet-%s", acctest.RandString(t, 10)) @@ -914,3 +914,218 @@ resource "google_network_services_gateway" "foobar" { } `, netName, subnetName, pSubnetName, policyName, ruleName, gatewayName) } + +func TestAccNetworkServicesGateway_swpAsNextHop(t *testing.T) { + context := map[string]interface{}{ + "region": "us-east1", + "random_suffix": fmt.Sprintf("-%s", acctest.RandString(t, 10)), + "name_prefix": "tf-test-gateway-", + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkServicesGatewayDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkServicesGateway_swpAsNextHop(context), + }, + { + ResourceName: "google_network_services_gateway.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "delete_swg_autogen_router_on_destroy"}, + }, + }, + }) +} + +func testAccNetworkServicesGateway_swpAsNextHop(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + name = "%{name_prefix}network%{random_suffix}" + routing_mode = "REGIONAL" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "proxyonlysubnet" { + name = "%{name_prefix}proxysubnet%{random_suffix}" + purpose = "REGIONAL_MANAGED_PROXY" + ip_cidr_range = "192.168.0.0/23" + region = "%{region}" + network = google_compute_network.default.id + role = "ACTIVE" +} + +resource "google_compute_subnetwork" "default" { + name = "%{name_prefix}subnet%{random_suffix}" + purpose = "PRIVATE" + ip_cidr_range = "10.128.0.0/20" + region = "%{region}" + network = google_compute_network.default.id + role = "ACTIVE" +} + +resource "google_privateca_ca_pool" "default" { + name = "%{name_prefix}ca-pool%{random_suffix}" + location = "%{region}" + tier = "DEVOPS" + + publishing_options { + publish_ca_cert = false + publish_crl = false + } + + issuance_policy { + maximum_lifetime = "1209600s" + baseline_values { + ca_options { + is_ca = false + } + key_usage { + base_key_usage {} + extended_key_usage { + server_auth = true + } + } + } + } +} + +resource "google_privateca_certificate_authority" "default" { + pool = google_privateca_ca_pool.default.name + certificate_authority_id = "%{name_prefix}certificate-authority%{random_suffix}" + location = "%{region}" + lifetime = "86400s" + type = "SELF_SIGNED" + deletion_protection = false + skip_grace_period = true + ignore_active_certificates_on_deletion = true + + config { + subject_config { + subject { + organization = "Test LLC" + common_name = "private-certificate-authority" + } + } + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = false + } + } + } + } + + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } +} + +resource "google_certificate_manager_certificate" "default" { + name = "%{name_prefix}certificate%{random_suffix}" + location = "%{region}" + + self_managed { + pem_certificate = file("test-fixtures/cert.pem") + pem_private_key = file("test-fixtures/private-key.pem") + } +} + +resource "google_network_security_tls_inspection_policy" "default" { + name = "%{name_prefix}tls-insp-policy%{random_suffix}" + location = "%{region}" + ca_pool = google_privateca_ca_pool.default.id + + depends_on = [ + google_privateca_ca_pool.default, + google_privateca_certificate_authority.default + ] +} + +resource "google_network_security_gateway_security_policy" "default" { + name = "%{name_prefix}sec-policy%{random_suffix}" + location = "%{region}" + description = "my description" + tls_inspection_policy = google_network_security_tls_inspection_policy.default.id + + depends_on = [ + google_network_security_tls_inspection_policy.default + ] +} + +resource "google_network_security_gateway_security_policy_rule" "default" { + name = "%{name_prefix}sec-policy-rule%{random_suffix}" + location = "%{region}" + gateway_security_policy = google_network_security_gateway_security_policy.default.name + enabled = true + description = "my description" + priority = 0 + session_matcher = "host() == 'example.com'" + application_matcher = "request.method == 'POST'" + tls_inspection_enabled = true + basic_profile = "ALLOW" +} + +resource "google_network_services_gateway" "default" { + name = "%{name_prefix}swp%{random_suffix}" + location = "%{region}" + addresses = ["10.128.0.99"] + type = "SECURE_WEB_GATEWAY" + routing_mode = "NEXT_HOP_ROUTING_MODE" + ports = [443] + description = "my description" + scope = "%s" + certificate_urls = [google_certificate_manager_certificate.default.id] + gateway_security_policy = google_network_security_gateway_security_policy.default.id + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + delete_swg_autogen_router_on_destroy = true + depends_on = [google_compute_subnetwork.proxyonlysubnet] +} + +resource "google_compute_route" "default" { + name = "%{name_prefix}route%{random_suffix}" + dest_range = "15.0.0.0/24" + network = google_compute_network.default.name + next_hop_ip = google_network_services_gateway.default.addresses[0] + priority = 100 +} + +resource "google_network_connectivity_policy_based_route" "swproute" { + name = "%{name_prefix}policy-based-swp-route%{random_suffix}" + description = "My routing policy" + network = google_compute_network.default.id + next_hop_ilb_ip = google_network_services_gateway.default.addresses[0] + priority = 2 + + filter { + protocol_version = "IPV4" + src_range = "10.0.0.0/24" + dest_range = "15.0.0.0/24" + } +} + +resource "google_network_connectivity_policy_based_route" "default" { + name = "%{name_prefix}policy-based-route%{random_suffix}" + description = "My routing policy" + network = google_compute_network.default.id + next_hop_other_routes = "DEFAULT_ROUTING" + priority = 1 + + filter { + protocol_version = "IPV4" + src_range = "10.0.0.0/24" + dest_range = "15.0.0.0/24" + } +} + `, context) +} diff --git a/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_exadata_infrastructure.go b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_exadata_infrastructure.go new file mode 100644 index 000000000000..b0cc4e8684d2 --- /dev/null +++ b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_exadata_infrastructure.go @@ -0,0 +1,36 @@ +package oracledatabase + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceOracleDatabaseCloudExadataInfrastructure() *schema.Resource { + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceOracleDatabaseCloudExadataInfrastructure().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "location", "cloud_exadata_infrastructure_id") + tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") + return &schema.Resource{ + Read: dataSourceOracleDatabaseCloudExadataInfrastructureRead, + Schema: dsSchema, + } + +} + +func dataSourceOracleDatabaseCloudExadataInfrastructureRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/cloudExadataInfrastructures/{{cloud_exadata_infrastructure_id}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + err = resourceOracleDatabaseCloudExadataInfrastructureRead(d, meta) + if err != nil { + return err + } + d.SetId(id) + + return nil +} diff --git a/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_exadata_infrastructure_test.go b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_exadata_infrastructure_test.go new file mode 100644 index 000000000000..ac0f3cdb3143 --- /dev/null +++ b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_exadata_infrastructure_test.go @@ -0,0 +1,42 @@ +package oracledatabase_test + +import ( + "fmt" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "testing" +) + +func TestAccOracleDatabaseCloudExadataInfrastructure_basic(t *testing.T) { + t.Parallel() + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccOracleDatabaseCloudExadataInfrastructure_basic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "display_name"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "name"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "gcp_oracle_zone"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "properties.#"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "properties.0.compute_count"), + resource.TestCheckResourceAttr("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "display_name", "ofake-exadata-for-vm display name"), + resource.TestCheckResourceAttr("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "gcp_oracle_zone", "us-east4-b-r1"), + resource.TestCheckResourceAttr("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "properties.0.state", "AVAILABLE"), + resource.TestCheckResourceAttr("data.google_oracle_database_cloud_exadata_infrastructure.my-exadata", "properties.0.shape", "Exadata.X9M"), + ), + }, + }, + }) +} + +func testAccOracleDatabaseCloudExadataInfrastructure_basic() string { + return fmt.Sprintf(` +data "google_oracle_database_cloud_exadata_infrastructure" "my-exadata"{ + cloud_exadata_infrastructure_id = "ofake-do-not-delete-tf-exadata" + project = "oci-terraform-testing" + location = "us-east4" +} +`) +} diff --git a/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_vm_cluster.go b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_vm_cluster.go new file mode 100644 index 000000000000..9c17579349dc --- /dev/null +++ b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_vm_cluster.go @@ -0,0 +1,36 @@ +package oracledatabase + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceOracleDatabaseCloudVmCluster() *schema.Resource { + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceOracleDatabaseCloudVmCluster().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "location", "cloud_vm_cluster_id") + tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") + return &schema.Resource{ + Read: dataSourceOracleDatabaseCloudVmClusterRead, + Schema: dsSchema, + } + +} + +func dataSourceOracleDatabaseCloudVmClusterRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/cloudVmClusters/{{cloud_vm_cluster_id}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + err = resourceOracleDatabaseCloudVmClusterRead(d, meta) + if err != nil { + return err + } + d.SetId(id) + + return nil +} diff --git a/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_vm_cluster_test.go b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_vm_cluster_test.go new file mode 100644 index 000000000000..4d5f55afba42 --- /dev/null +++ b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_cloud_vm_cluster_test.go @@ -0,0 +1,44 @@ +package oracledatabase_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccOracleDatabaseCloudVmCluster_basic(t *testing.T) { + t.Parallel() + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccOracleDatabaseCloudVmCluster_basic(), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "display_name"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "exadata_infrastructure"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "cidr"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "properties.#"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "properties.0.cpu_core_count"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "properties.0.cluster_name"), + resource.TestCheckResourceAttr("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "gcp_oracle_zone", "us-east4-b-r1"), + resource.TestCheckResourceAttr("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "properties.0.node_count", "2"), + resource.TestCheckResourceAttr("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "properties.0.state", "AVAILABLE"), + resource.TestCheckResourceAttr("data.google_oracle_database_cloud_vm_cluster.my-vmcluster", "properties.0.shape", "Exadata.X9M"), + ), + }, + }, + }) +} + +func testAccOracleDatabaseCloudVmCluster_basic() string { + return fmt.Sprintf(` +data "google_oracle_database_cloud_vm_cluster" "my-vmcluster"{ + cloud_vm_cluster_id = "ofake-do-not-delete-tf-vmcluster" + project = "oci-terraform-testing" + location = "us-east4" +} +`) +} diff --git a/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_db_servers.go b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_db_servers.go new file mode 100644 index 000000000000..fca2c56888b3 --- /dev/null +++ b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_db_servers.go @@ -0,0 +1,247 @@ +package oracledatabase + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceOracleDatabaseDbServers() *schema.Resource { + dsSchema := map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Optional: true, + Description: "The ID of the project in which the dataset is located. If it is not provided, the provider project is used.", + }, + "location": { + Type: schema.TypeString, + Required: true, + Description: "location", + }, + "cloud_exadata_infrastructure": { + Type: schema.TypeString, + Required: true, + Description: "exadata", + }, + "db_servers": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "display_name": { + Type: schema.TypeString, + Computed: true, + Description: "The Display name", + }, + "properties": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "ocid": { + Type: schema.TypeString, + Computed: true, + Description: "Output only", + }, + "ocpu_count": { + Type: schema.TypeInt, + Computed: true, + Description: "Output only", + }, + "max_ocpu_count": { + Type: schema.TypeInt, + Computed: true, + Description: "Output only", + }, + "memory_size_gb": { + Type: schema.TypeInt, + Computed: true, + Description: "Output only", + }, + "max_memory_size_gb": { + Type: schema.TypeInt, + Computed: true, + Description: "Output only", + }, + "db_node_storage_size_gb": { + Type: schema.TypeInt, + Computed: true, + Description: "Output only", + }, + "max_db_node_storage_size_gb": { + Type: schema.TypeInt, + Computed: true, + Description: "Output only", + }, + "vm_count": { + Type: schema.TypeInt, + Computed: true, + Description: "Output only", + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: "Output only", + }, + "db_node_ids": { + Type: schema.TypeList, + Computed: true, + Description: "Output only", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, + } + return &schema.Resource{ + Read: DataSourceOracleDatabaseDbServersRead, + Schema: dsSchema, + UseJSONNumber: true, + } +} + +func DataSourceOracleDatabaseDbServersRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for DbServer: %s", err) + } + billingProject = project + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + url, err := tpgresource.ReplaceVars(d, config, "{{OracleDatabaseBasePath}}projects/{{project}}/locations/{{location}}/cloudExadataInfrastructures/{{cloud_exadata_infrastructure}}/dbServers") + if err != nil { + return err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return fmt.Errorf("Error reading DbServer: %s", err) + } + if res["dbServers"] == nil { + return fmt.Errorf("Error reading DbServer: %s", err) + } + dbServers, err := flattenOracleDatabaseDbServerList(config, res["dbServers"]) + if err != nil { + return fmt.Errorf("error flattening dbserver list: %s", err) + } + + if err := d.Set("db_servers", dbServers); err != nil { + return fmt.Errorf("error setting dbserver: %s", err) + } + + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/cloudExadataInfrastructures/{{cloud_exadata_infrastructure_id}}/dbServers") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + return nil +} + +func flattenOracleDatabaseDbServerList(config *transport_tpg.Config, dbServerList interface{}) (interface{}, error) { + + if dbServerList == nil { + return nil, nil + } + + l := dbServerList.([]interface{}) + transformed := make([]interface{}, 0) + for _, raw := range l { + original := raw.(map[string]interface{}) + transformed = append(transformed, map[string]interface{}{ + "display_name": flattenOracleDatabaseDbServerDisplayName(original["displayName"], config), + "properties": flattenOracleDatabaseDbServerProperties(original["properties"], config), + }) + } + return transformed, nil + +} + +func flattenOracleDatabaseDbServerDisplayName(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerProperties(v interface{}, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["ocid"] = flattenOracleDatabaseDbServerPropertiesOcid(original["ocid"], config) + transformed["ocpu_count"] = flattenOracleDatabaseDbServerPropertiesOcpuCount(original["ocpuCount"], config) + transformed["max_ocpu_count"] = flattenOracleDatabaseDbServerPropertiesMaxOcpuCount(original["maxOcpuCount"], config) + transformed["memory_size_gb"] = flattenOracleDatabaseDbServerPropertiesMemorySizeGb(original["memorySizeGb"], config) + transformed["max_memory_size_gb"] = flattenOracleDatabaseDbServerPropertiesMaxMemorySizeGb(original["maxMemorySizeGb"], config) + transformed["db_node_storage_size_gb"] = flattenOracleDatabaseDbServerPropertiesDbNodeStorageSizeGb(original["dbNodeStorageSizeGb"], config) + transformed["max_db_node_storage_size_gb"] = flattenOracleDatabaseDbServerPropertiesMaxDbNodeStorageSizeGb(original["maxDbNodeStorageSizeGb"], config) + transformed["vm_count"] = flattenOracleDatabaseDbServerPropertiesVmcount(original["vmCount"], config) + transformed["state"] = flattenOracleDatabaseDbServerPropertiesState(original["state"], config) + transformed["db_node_ids"] = flattenOracleDatabaseDbServerPropertiesDbNodeIds(original["dbNodeIds"], config) + + return []interface{}{transformed} +} + +func flattenOracleDatabaseDbServerPropertiesOcid(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesOcpuCount(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesMaxOcpuCount(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesMemorySizeGb(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesMaxMemorySizeGb(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesDbNodeStorageSizeGb(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesMaxDbNodeStorageSizeGb(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesVmcount(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesState(v interface{}, config *transport_tpg.Config) interface{} { + return v +} + +func flattenOracleDatabaseDbServerPropertiesDbNodeIds(v interface{}, config *transport_tpg.Config) interface{} { + return v +} diff --git a/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_db_servers_test.go b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_db_servers_test.go new file mode 100644 index 000000000000..04e265c7ff48 --- /dev/null +++ b/mmv1/third_party/terraform/services/oracledatabase/data_source_oracle_database_db_servers_test.go @@ -0,0 +1,41 @@ +package oracledatabase_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccOracleDatabaseDbServers_basic(t *testing.T) { + t.Parallel() + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccOracleDatabaseDbServers_basic, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_oracle_database_db_servers.my_db_servers", "db_servers.0.display_name"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_db_servers.my_db_servers", "db_servers.0.properties.#"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_db_servers.my_db_servers", "db_servers.0.properties.0.max_ocpu_count"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_db_servers.my_db_servers", "db_servers.1.display_name"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_db_servers.my_db_servers", "db_servers.1.properties.#"), + resource.TestCheckResourceAttrSet("data.google_oracle_database_db_servers.my_db_servers", "db_servers.1.properties.0.max_ocpu_count"), + resource.TestCheckResourceAttr("data.google_oracle_database_db_servers.my_db_servers", "db_servers.0.display_name", "dbServer-1"), + resource.TestCheckResourceAttr("data.google_oracle_database_db_servers.my_db_servers", "db_servers.1.display_name", "dbServer-2"), + resource.TestCheckResourceAttr("data.google_oracle_database_db_servers.my_db_servers", "db_servers.0.properties.0.max_ocpu_count", "126"), + resource.TestCheckResourceAttr("data.google_oracle_database_db_servers.my_db_servers", "db_servers.1.properties.0.max_ocpu_count", "126"), + ), + }, + }, + }) +} + +const testAccOracleDatabaseDbServers_basic = ` +data "google_oracle_database_db_servers" "my_db_servers"{ + location = "us-east4" + project = "oci-terraform-testing" + cloud_exadata_infrastructure = "ofake-do-not-delete-tf-exadata" +} +` diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go index af40a3411333..403a732ded4d 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go @@ -36,6 +36,30 @@ func TestAccPubsubSubscription_emptyTTL(t *testing.T) { }) } +func TestAccPubsubSubscription_emptyRetryPolicy(t *testing.T) { + t.Parallel() + + topic := fmt.Sprintf("tf-test-topic-%s", acctest.RandString(t, 10)) + subscription := fmt.Sprintf("tf-test-sub-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckPubsubSubscriptionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccPubsubSubscription_emptyRetryPolicy(topic, subscription), + }, + { + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscription, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccPubsubSubscription_basic(t *testing.T) { t.Parallel() @@ -494,6 +518,22 @@ resource "google_pubsub_subscription" "foo" { `, topic, subscription) } +func testAccPubsubSubscription_emptyRetryPolicy(topic, subscription string) string { + return fmt.Sprintf(` +resource "google_pubsub_topic" "foo" { + name = "%s" +} + +resource "google_pubsub_subscription" "foo" { + name = "%s" + topic = google_pubsub_topic.foo.id + + retry_policy { + } +} +`, topic, subscription) +} + func testAccPubsubSubscription_push(topicFoo, saAccount, subscription string) string { return fmt.Sprintf(` data "google_project" "project" { } diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_folder.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_folder.go index 78f68ae7506d..37b89229e998 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_folder.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_folder.go @@ -76,7 +76,7 @@ func ResourceGoogleFolder() *schema.Resource { Optional: true, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty.`, + Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty. This field is only set at create time and modifying this field after creation will trigger recreation. To apply tags to an existing resource, see the google_tags_tag_value resource.`, }, }, UseJSONNumber: true, diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go index 077152128a2f..835473882ded 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go @@ -139,7 +139,7 @@ func ResourceGoogleProject() *schema.Resource { Optional: true, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty.`, + Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty. This field is only set at create time and modifying this field after creation will trigger recreation. To apply tags to an existing resource, see the google_tags_tag_value resource.`, }, }, UseJSONNumber: true, diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version.go index 29f7db23dcbb..70156caf6fc3 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version.go @@ -52,6 +52,11 @@ func DataSourceSecretManagerSecretVersion() *schema.Resource { Computed: true, Sensitive: true, }, + "is_secret_data_base64": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -147,11 +152,17 @@ func dataSourceSecretManagerSecretVersionRead(d *schema.ResourceData, meta inter } data := resp["payload"].(map[string]interface{}) - secretData, err := base64.StdEncoding.DecodeString(data["data"].(string)) - if err != nil { - return fmt.Errorf("Error decoding secret manager secret version data: %s", err.Error()) + var secretData string + if d.Get("is_secret_data_base64").(bool) { + secretData = data["data"].(string) + } else { + payloadData, err := base64.StdEncoding.DecodeString(data["data"].(string)) + if err != nil { + return fmt.Errorf("error decoding secret manager secret version data: %s", err.Error()) + } + secretData = string(payloadData) } - if err := d.Set("secret_data", string(secretData)); err != nil { + if err := d.Set("secret_data", secretData); err != nil { return fmt.Errorf("Error setting secret_data: %s", err) } diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access.go index 0d51e8060cda..f60707b5ce89 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access.go @@ -40,6 +40,11 @@ func DataSourceSecretManagerSecretVersionAccess() *schema.Resource { Computed: true, Sensitive: true, }, + "is_secret_data_base64": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -112,11 +117,17 @@ func dataSourceSecretManagerSecretVersionAccessRead(d *schema.ResourceData, meta } data := resp["payload"].(map[string]interface{}) - secretData, err := base64.StdEncoding.DecodeString(data["data"].(string)) - if err != nil { - return fmt.Errorf("Error decoding secret manager secret version data: %s", err.Error()) + var secretData string + if d.Get("is_secret_data_base64").(bool) { + secretData = data["data"].(string) + } else { + payloadData, err := base64.StdEncoding.DecodeString(data["data"].(string)) + if err != nil { + return fmt.Errorf("error decoding secret manager secret version data: %s", err.Error()) + } + secretData = string(payloadData) } - if err := d.Set("secret_data", string(secretData)); err != nil { + if err := d.Set("secret_data", secretData); err != nil { return fmt.Errorf("Error setting secret_data: %s", err) } diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access_test.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access_test.go index 23497bcc2046..15c3cee73c0f 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access_test.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_access_test.go @@ -1,14 +1,12 @@ package secretmanager_test import ( - "errors" "fmt" "testing" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "github.com/hashicorp/terraform-plugin-testing/terraform" ) func TestAccDatasourceSecretManagerSecretVersionAccess_basic(t *testing.T) { @@ -24,7 +22,8 @@ func TestAccDatasourceSecretManagerSecretVersionAccess_basic(t *testing.T) { { Config: testAccDatasourceSecretManagerSecretVersionAccess_basic(randomString), Check: resource.ComposeTestCheckFunc( - testAccCheckDatasourceSecretManagerSecretVersionAccess("data.google_secret_manager_secret_version_access.basic", "1"), + testAccCheckDatasourceSecretManagerSecretVersion("data.google_secret_manager_secret_version_access.basic", "1"), + testAccCheckSecretManagerSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_secret_version_access.basic", "google_secret_manager_secret_version.secret-version-basic"), ), }, }, @@ -44,34 +43,34 @@ func TestAccDatasourceSecretManagerSecretVersionAccess_latest(t *testing.T) { { Config: testAccDatasourceSecretManagerSecretVersionAccess_latest(randomString), Check: resource.ComposeTestCheckFunc( - testAccCheckDatasourceSecretManagerSecretVersionAccess("data.google_secret_manager_secret_version_access.latest", "2"), + testAccCheckDatasourceSecretManagerSecretVersion("data.google_secret_manager_secret_version_access.latest", "2"), + testAccCheckSecretManagerSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_secret_version_access.latest", "google_secret_manager_secret_version.secret-version-basic-2"), ), }, }, }) } -func testAccCheckDatasourceSecretManagerSecretVersionAccess(n, expected string) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Can't find Secret Version data source: %s", n) - } - - if rs.Primary.ID == "" { - return errors.New("data source ID not set.") - } +func TestAccDatasourceSecretManagerSecretVersionAccess_withBase64SecretData(t *testing.T) { + t.Parallel() - version, ok := rs.Primary.Attributes["version"] - if !ok { - return errors.New("can't find 'version' attribute") - } + randomString := acctest.RandString(t, 10) + data := "./test-fixtures/binary-file.pfx" - if version != expected { - return fmt.Errorf("expected %s, got %s, version not found", expected, version) - } - return nil - } + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSecretManagerSecretVersionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDatasourceSecretManagerSecretVersionAccess_withBase64SecretData(randomString, data), + Check: resource.ComposeTestCheckFunc( + testAccCheckDatasourceSecretManagerSecretVersion("data.google_secret_manager_secret_version_access.basic-base64", "1"), + testAccCheckSecretManagerSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_secret_version_access.basic-base64", "google_secret_manager_secret_version.secret-version-basic-base64"), + ), + }, + }, + }) } func testAccDatasourceSecretManagerSecretVersionAccess_latest(randomString string) string { @@ -127,3 +126,28 @@ data "google_secret_manager_secret_version_access" "basic" { } `, randomString, randomString) } + +func testAccDatasourceSecretManagerSecretVersionAccess_withBase64SecretData(randomString, data string) string { + return fmt.Sprintf(` +resource "google_secret_manager_secret" "secret-basic-base64" { + secret_id = "tf-test-secret-version-%s" + labels = { + label = "my-label" + } + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "secret-version-basic-base64" { + secret = google_secret_manager_secret.secret-basic-base64.name + is_secret_data_base64 = true + secret_data = filebase64("%s") +} + +data "google_secret_manager_secret_version_access" "basic-base64" { + secret = google_secret_manager_secret_version.secret-version-basic-base64.secret + is_secret_data_base64 = true +} +`, randomString, data) +} diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_test.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_test.go index 33c7753b56d8..68890cf857d2 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_test.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_version_test.go @@ -25,6 +25,7 @@ func TestAccDatasourceSecretManagerSecretVersion_basic(t *testing.T) { Config: testAccDatasourceSecretManagerSecretVersion_basic(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDatasourceSecretManagerSecretVersion("data.google_secret_manager_secret_version.basic", "1"), + testAccCheckSecretManagerSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_secret_version.basic", "google_secret_manager_secret_version.secret-version-basic"), ), }, }, @@ -45,6 +46,29 @@ func TestAccDatasourceSecretManagerSecretVersion_latest(t *testing.T) { Config: testAccDatasourceSecretManagerSecretVersion_latest(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDatasourceSecretManagerSecretVersion("data.google_secret_manager_secret_version.latest", "2"), + testAccCheckSecretManagerSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_secret_version.latest", "google_secret_manager_secret_version.secret-version-basic-2"), + ), + }, + }, + }) +} + +func TestAccDatasourceSecretManagerSecretVersion_withBase64SecretData(t *testing.T) { + t.Parallel() + + randomString := acctest.RandString(t, 10) + data := "./test-fixtures/binary-file.pfx" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSecretManagerSecretVersionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDatasourceSecretManagerSecretVersion_withBase64SecretData(randomString, data), + Check: resource.ComposeTestCheckFunc( + testAccCheckDatasourceSecretManagerSecretVersion("data.google_secret_manager_secret_version.basic-base64", "1"), + testAccCheckSecretManagerSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_secret_version.basic-base64", "google_secret_manager_secret_version.secret-version-basic-base64"), ), }, }, @@ -74,6 +98,43 @@ func testAccCheckDatasourceSecretManagerSecretVersion(n, expected string) resour } } +func testAccCheckSecretManagerSecretVersionSecretDataDatasourceMatchesResource(datasource, resource string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resource] + if !ok { + return fmt.Errorf("can't find Secret Version resource: %s", resource) + } + + ds, ok := s.RootModule().Resources[datasource] + if !ok { + return fmt.Errorf("can't find Secret Version data source: %s", datasource) + } + + if rs.Primary.ID == "" { + return errors.New("resource ID not set.") + } + + if ds.Primary.ID == "" { + return errors.New("data source ID not set.") + } + + resourceSecretData, ok := rs.Primary.Attributes["secret_data"] + if !ok { + return errors.New("can't find 'secret_data' attribute in Secret Version resource") + } + + datasourceSecretData, ok := ds.Primary.Attributes["secret_data"] + if !ok { + return errors.New("can't find 'secret_data' attribute in Secret Version data source") + } + + if resourceSecretData != datasourceSecretData { + return fmt.Errorf("expected %s, got %s, secret_data doesn't match", resourceSecretData, datasourceSecretData) + } + return nil + } +} + func testAccDatasourceSecretManagerSecretVersion_latest(randomString string) string { return fmt.Sprintf(` resource "google_secret_manager_secret" "secret-basic" { @@ -127,3 +188,28 @@ data "google_secret_manager_secret_version" "basic" { } `, randomString, randomString) } + +func testAccDatasourceSecretManagerSecretVersion_withBase64SecretData(randomString, data string) string { + return fmt.Sprintf(` +resource "google_secret_manager_secret" "secret-basic-base64" { + secret_id = "tf-test-secret-version-%s" + labels = { + label = "my-label" + } + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "secret-version-basic-base64" { + secret = google_secret_manager_secret.secret-basic-base64.name + is_secret_data_base64 = true + secret_data = filebase64("%s") +} + +data "google_secret_manager_secret_version" "basic-base64" { + secret = google_secret_manager_secret_version.secret-version-basic-base64.secret + is_secret_data_base64 = true +} +`, randomString, data) +} diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secrets.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secrets.go index 877f9ed4b253..3b571af7a6a3 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secrets.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secrets.go @@ -144,17 +144,21 @@ func flattenSecretManagerSecretsSecrets(v interface{}, d *schema.ResourceData, c continue } transformed = append(transformed, map[string]interface{}{ - "replication": flattenSecretManagerSecretReplication(original["replication"], d, config), - "annotations": flattenSecretManagerSecretAnnotations(original["annotations"], d, config), - "expire_time": flattenSecretManagerSecretExpireTime(original["expireTime"], d, config), - "labels": flattenSecretManagerSecretLabels(original["labels"], d, config), - "rotation": flattenSecretManagerSecretRotation(original["rotation"], d, config), - "topics": flattenSecretManagerSecretTopics(original["topics"], d, config), - "version_aliases": flattenSecretManagerSecretVersionAliases(original["versionAliases"], d, config), - "create_time": flattenSecretManagerSecretCreateTime(original["createTime"], d, config), - "name": flattenSecretManagerSecretName(original["name"], d, config), - "project": getDataFromName(original["name"], 1), - "secret_id": getDataFromName(original["name"], 3), + "replication": flattenSecretManagerSecretReplication(original["replication"], d, config), + "annotations": flattenSecretManagerSecretEffectiveAnnotations(original["annotations"], d, config), + "effective_annotations": flattenSecretManagerSecretEffectiveAnnotations(original["annotations"], d, config), + "expire_time": flattenSecretManagerSecretExpireTime(original["expireTime"], d, config), + "labels": flattenSecretManagerSecretEffectiveLabels(original["labels"], d, config), + "effective_labels": flattenSecretManagerSecretEffectiveLabels(original["labels"], d, config), + "terraform_labels": flattenSecretManagerSecretEffectiveLabels(original["labels"], d, config), + "rotation": flattenSecretManagerSecretRotation(original["rotation"], d, config), + "topics": flattenSecretManagerSecretTopics(original["topics"], d, config), + "version_aliases": flattenSecretManagerSecretVersionAliases(original["versionAliases"], d, config), + "version_destroy_ttl": flattenSecretManagerSecretVersionDestroyTtl(original["versionDestroyTtl"], d, config), + "create_time": flattenSecretManagerSecretCreateTime(original["createTime"], d, config), + "name": flattenSecretManagerSecretName(original["name"], d, config), + "project": getDataFromName(original["name"], 1), + "secret_id": getDataFromName(original["name"], 3), }) } return transformed diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secrets_test.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secrets_test.go index afe3300036eb..d457afe6a505 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secrets_test.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secrets_test.go @@ -30,11 +30,8 @@ func TestAccDataSourceSecretManagerSecrets_basic(t *testing.T) { "data.google_secret_manager_secrets.foo", "google_secret_manager_secret.foo", map[string]struct{}{ - "id": {}, - "project": {}, - "effective_labels": {}, - "labels": {}, - "terraform_labels": {}, + "id": {}, + "project": {}, }, ), ), @@ -59,6 +56,16 @@ resource "google_secret_manager_secret" "foo" { } } } + + labels = { + label = "my-label" + } + + annotations = { + key1 = "value1" + } + + version_destroy_ttl = "360000s" } data "google_secret_manager_secrets" "foo" { @@ -89,11 +96,8 @@ func TestAccDataSourceSecretManagerSecrets_filter(t *testing.T) { "google_secret_manager_secret.foo", "google_secret_manager_secret.bar", map[string]struct{}{ - "id": {}, - "project": {}, - "effective_labels": {}, - "labels": {}, - "terraform_labels": {}, + "id": {}, + "project": {}, }, ), ), @@ -118,6 +122,14 @@ resource "google_secret_manager_secret" "foo" { } } } + + labels = { + label = "my-label" + } + + annotations = { + key1 = "value1" + } } resource "google_secret_manager_secret" "bar" { @@ -130,6 +142,14 @@ resource "google_secret_manager_secret" "bar" { } } } + + labels = { + label= "my-label2" + } + + annotations = { + key1 = "value1" + } } data "google_secret_manager_secrets" "foo" { diff --git a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version.go b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version.go index b4afe3e1558d..0f7889b54736 100644 --- a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version.go +++ b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version.go @@ -69,6 +69,11 @@ func DataSourceSecretManagerRegionalRegionalSecretVersion() *schema.Resource { }, }, }, + "is_secret_data_base64": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -193,12 +198,17 @@ func dataSourceSecretManagerRegionalRegionalSecretVersionRead(d *schema.Resource } data := resp["payload"].(map[string]interface{}) - secretData, err := base64.StdEncoding.DecodeString(data["data"].(string)) - if err != nil { - return fmt.Errorf("Error decoding secret manager regional secret version data: %s", err.Error()) + var secretData string + if d.Get("is_secret_data_base64").(bool) { + secretData = data["data"].(string) + } else { + payloadData, err := base64.StdEncoding.DecodeString(data["data"].(string)) + if err != nil { + return fmt.Errorf("error decoding secret manager regional secret version data: %s", err.Error()) + } + secretData = string(payloadData) } - - if err := d.Set("secret_data", string(secretData)); err != nil { + if err := d.Set("secret_data", secretData); err != nil { return fmt.Errorf("Error setting secret_data: %s", err) } diff --git a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access.go b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access.go index e4de924c3d90..734173a3b145 100644 --- a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access.go +++ b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access.go @@ -45,6 +45,11 @@ func DataSourceSecretManagerRegionalRegionalSecretVersionAccess() *schema.Resour Computed: true, Sensitive: true, }, + "is_secret_data_base64": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -148,11 +153,17 @@ func dataSourceSecretManagerRegionalRegionalSecretVersionAccessRead(d *schema.Re } data := resp["payload"].(map[string]interface{}) - secretData, err := base64.StdEncoding.DecodeString(data["data"].(string)) - if err != nil { - return fmt.Errorf("error decoding secret manager regional secret version data: %s", err.Error()) + var secretData string + if d.Get("is_secret_data_base64").(bool) { + secretData = data["data"].(string) + } else { + payloadData, err := base64.StdEncoding.DecodeString(data["data"].(string)) + if err != nil { + return fmt.Errorf("error decoding secret manager regional secret version data: %s", err.Error()) + } + secretData = string(payloadData) } - if err := d.Set("secret_data", string(secretData)); err != nil { + if err := d.Set("secret_data", secretData); err != nil { return fmt.Errorf("error setting secret_data: %s", err) } diff --git a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access_test.go b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access_test.go index dfd6ab7896bc..b9ba52d542de 100644 --- a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access_test.go +++ b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_access_test.go @@ -23,6 +23,7 @@ func TestAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_basicWith Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_basicWithResourceReference(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version_access.basic-1", "1"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version_access.basic-1", "google_secret_manager_regional_secret_version.secret-version-basic"), ), }, }, @@ -43,6 +44,7 @@ func TestAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_basicWith Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_basicWithSecretName(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version_access.basic-2", "1"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version_access.basic-2", "google_secret_manager_regional_secret_version.secret-version-basic"), ), }, }, @@ -63,6 +65,7 @@ func TestAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_latest(t Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_latest(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version_access.latest-1", "2"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version_access.latest-1", "google_secret_manager_regional_secret_version.secret-version-basic-2"), ), }, }, @@ -83,6 +86,29 @@ func TestAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_versionFi Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_versionField(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version_access.version-access", "1"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version_access.version-access", "google_secret_manager_regional_secret_version.secret-version-basic-1"), + ), + }, + }, + }) +} + +func TestAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_withBase64SecretData(t *testing.T) { + t.Parallel() + + randomString := acctest.RandString(t, 10) + data := "./test-fixtures/binary-file.pfx" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSecretManagerRegionalRegionalSecretVersionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_withBase64SecretData(randomString, data), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version_access.basic-base64", "1"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version_access.basic-base64", "google_secret_manager_regional_secret_version.secret-version-basic-base64"), ), }, }, @@ -176,3 +202,26 @@ data "google_secret_manager_regional_secret_version_access" "version-access" { } `, randomString) } + +func testAccDataSourceSecretManagerRegionalRegionalSecretVersionAccess_withBase64SecretData(randomString, data string) string { + return fmt.Sprintf(` +resource "google_secret_manager_regional_secret" "secret-basic-base64" { + secret_id = "tf-test-secret-version-%s" + location = "us-central1" + labels = { + label = "my-label" + } +} + +resource "google_secret_manager_regional_secret_version" "secret-version-basic-base64" { + secret = google_secret_manager_regional_secret.secret-basic-base64.name + is_secret_data_base64 = true + secret_data = filebase64("%s") +} + +data "google_secret_manager_regional_secret_version_access" "basic-base64" { + secret = google_secret_manager_regional_secret_version.secret-version-basic-base64.secret + is_secret_data_base64 = true +} +`, randomString, data) +} diff --git a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_test.go b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_test.go index 7aa4930e750f..9c03b695ab5a 100644 --- a/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_test.go +++ b/mmv1/third_party/terraform/services/secretmanagerregional/data_source_secret_manager_regional_secret_version_test.go @@ -25,6 +25,7 @@ func TestAccDataSourceSecretManagerRegionalRegionalSecretVersion_basicWithResour Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersion_basicWithResourceReference(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version.basic-1", "1"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version.basic-1", "google_secret_manager_regional_secret_version.secret-version-basic"), ), }, }, @@ -45,6 +46,7 @@ func TestAccDataSourceSecretManagerRegionalRegionalSecretVersion_basicWithSecret Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersion_basicWithSecretName(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version.basic-2", "1"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version.basic-2", "google_secret_manager_regional_secret_version.secret-version-basic"), ), }, }, @@ -65,6 +67,7 @@ func TestAccDataSourceSecretManagerRegionalRegionalSecretVersion_latest(t *testi Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersion_latest(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version.latest", "2"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version.latest", "google_secret_manager_regional_secret_version.secret-version-basic-2"), ), }, }, @@ -85,6 +88,29 @@ func TestAccDataSourceSecretManagerRegionalRegionalSecretVersion_versionField(t Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersion_versionField(randomString), Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version.version", "1"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version.version", "google_secret_manager_regional_secret_version.secret-version-basic-1"), + ), + }, + }, + }) +} + +func TestAccDataSourceSecretManagerRegionalRegionalSecretVersion_withBase64SecretData(t *testing.T) { + t.Parallel() + + randomString := acctest.RandString(t, 10) + data := "./test-fixtures/binary-file.pfx" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSecretManagerRegionalRegionalSecretVersionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceSecretManagerRegionalRegionalSecretVersion_withBase64SecretData(randomString, data), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion("data.google_secret_manager_regional_secret_version.basic-base64", "1"), + testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource("data.google_secret_manager_regional_secret_version.basic-base64", "google_secret_manager_regional_secret_version.secret-version-basic-base64"), ), }, }, @@ -179,6 +205,29 @@ data "google_secret_manager_regional_secret_version" "version" { `, randomString) } +func testAccDataSourceSecretManagerRegionalRegionalSecretVersion_withBase64SecretData(randomString, data string) string { + return fmt.Sprintf(` +resource "google_secret_manager_regional_secret" "secret-basic-base64" { + secret_id = "tf-test-secret-version-%s" + location = "us-central1" + labels = { + label = "my-label" + } +} + +resource "google_secret_manager_regional_secret_version" "secret-version-basic-base64" { + secret = google_secret_manager_regional_secret.secret-basic-base64.name + is_secret_data_base64 = true + secret_data = filebase64("%s") +} + +data "google_secret_manager_regional_secret_version" "basic-base64" { + secret = google_secret_manager_regional_secret_version.secret-version-basic-base64.secret + is_secret_data_base64 = true +} +`, randomString, data) +} + func testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion(n, expected string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -201,3 +250,40 @@ func testAccCheckDataSourceSecretManagerRegionalRegionalSecretVersion(n, expecte return nil } } + +func testAccCheckSecretManagerRegionalRegionalSecretVersionSecretDataDatasourceMatchesResource(datasource, resource string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resource] + if !ok { + return fmt.Errorf("can't find Regional Secret Version resource: %s", resource) + } + + ds, ok := s.RootModule().Resources[datasource] + if !ok { + return fmt.Errorf("can't find Regional Secret Version data source: %s", datasource) + } + + if rs.Primary.ID == "" { + return errors.New("resource ID not set.") + } + + if ds.Primary.ID == "" { + return errors.New("data source ID not set.") + } + + resourceSecretData, ok := rs.Primary.Attributes["secret_data"] + if !ok { + return errors.New("can't find 'secret_data' attribute in Regional Secret Version resource") + } + + datasourceSecretData, ok := ds.Primary.Attributes["secret_data"] + if !ok { + return errors.New("can't find 'secret_data' attribute in Regional Secret Version data source") + } + + if resourceSecretData != datasourceSecretData { + return fmt.Errorf("expected %s, got %s, secret_data doesn't match", resourceSecretData, datasourceSecretData) + } + return nil + } +} diff --git a/mmv1/third_party/terraform/services/securesourcemanager/resource_secure_source_manager_branch_rule_update_test.go b/mmv1/third_party/terraform/services/securesourcemanager/resource_secure_source_manager_branch_rule_update_test.go new file mode 100644 index 000000000000..3e219e5659b7 --- /dev/null +++ b/mmv1/third_party/terraform/services/securesourcemanager/resource_secure_source_manager_branch_rule_update_test.go @@ -0,0 +1,112 @@ +package securesourcemanager_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccSecureSourceManagerBranchRule_secureSourceManagerBranchRuleWithFieldsExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "prevent_destroy": false, + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecureSourceManagerBranchRule_secureSourceManagerBranchRuleWithFieldsExample_full(context), + }, + { + ResourceName: "google_secure_source_manager_branch_rule.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"branch_rule_id", "location", "repository_id"}, + }, + { + Config: testAccSecureSourceManagerBranchRule_secureSourceManagerBranchRuleWithFieldsExample_update(context), + }, + { + ResourceName: "google_secure_source_manager_branch_rule.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"branch_rule_id", "location", "repository_id"}, + }, + }, + }) +} + +func testAccSecureSourceManagerBranchRule_secureSourceManagerBranchRuleWithFieldsExample_full(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secure_source_manager_instance" "instance" { + location = "us-central1" + instance_id = "tf-test-my-initial-instance%{random_suffix}" + # Prevent accidental deletions. + lifecycle { + prevent_destroy = "%{prevent_destroy}" + } +} + +resource "google_secure_source_manager_repository" "repository" { + repository_id = "tf-test-my-initial-repository%{random_suffix}" + instance = google_secure_source_manager_instance.instance.name + location = google_secure_source_manager_instance.instance.location + # Prevent accidental deletions. + lifecycle { + prevent_destroy = "%{prevent_destroy}" + } +} + +resource "google_secure_source_manager_branch_rule" "default" { + branch_rule_id = "tf-test-my-initial-branchrule%{random_suffix}" + location = google_secure_source_manager_repository.repository.location + repository_id = google_secure_source_manager_repository.repository.repository_id + include_pattern = "test" + minimum_approvals_count = 2 + minimum_reviews_count = 2 + require_comments_resolved = true + require_linear_history = true + require_pull_request = true + disabled = false + allow_stale_reviews = false +} +`, context) +} + +func testAccSecureSourceManagerBranchRule_secureSourceManagerBranchRuleWithFieldsExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secure_source_manager_instance" "instance" { + location = "us-central1" + instance_id = "tf-test-my-initial-instance%{random_suffix}" + # Prevent accidental deletions. + lifecycle { + prevent_destroy = "%{prevent_destroy}" + } +} + +resource "google_secure_source_manager_repository" "repository" { + repository_id = "tf-test-my-initial-repository%{random_suffix}" + instance = google_secure_source_manager_instance.instance.name + location = google_secure_source_manager_instance.instance.location + # Prevent accidental deletions. + lifecycle { + prevent_destroy = "%{prevent_destroy}" + } +} + +resource "google_secure_source_manager_branch_rule" "default" { + branch_rule_id = "tf-test-my-initial-branchrule%{random_suffix}" + location = google_secure_source_manager_repository.repository.location + repository_id = google_secure_source_manager_repository.repository.repository_id + include_pattern = "test" + minimum_approvals_count = 1 + minimum_reviews_count = 1 + require_linear_history = false +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/securitycenter/resource_scc_project_big_query_export_config_test.go b/mmv1/third_party/terraform/services/securitycenter/resource_scc_project_big_query_export_config_test.go index dc62387189b4..7c6f24313c0e 100644 --- a/mmv1/third_party/terraform/services/securitycenter/resource_scc_project_big_query_export_config_test.go +++ b/mmv1/third_party/terraform/services/securitycenter/resource_scc_project_big_query_export_config_test.go @@ -73,9 +73,12 @@ resource "google_bigquery_dataset" "default" { } } -resource "time_sleep" "wait_1_minute" { +resource "time_sleep" "wait_x_minutes" { depends_on = [google_bigquery_dataset.default] create_duration = "3m" + # need to wait for destruction due to + # 'still in use' error from api + destroy_duration = "1m" } resource "google_scc_project_scc_big_query_export" "default" { @@ -85,7 +88,7 @@ resource "google_scc_project_scc_big_query_export" "default" { description = "Cloud Security Command Center Findings Big Query Export Config" filter = "state=\"ACTIVE\" AND NOT mute=\"MUTED\"" - depends_on = [time_sleep.wait_1_minute] + depends_on = [time_sleep.wait_x_minutes] } `, context) diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.tmpl b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.tmpl index ebbd3e9db26a..eba30f8dd202 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.tmpl +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.tmpl @@ -539,7 +539,7 @@ func TestAccSpannerDatabase_cmek(t *testing.T) { ResourceName: "google_spanner_database.database", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ddl", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"ddl", "deletion_protection", "encryption_config.0.kms_key_names"}, }, }, }) @@ -605,4 +605,74 @@ resource "google_project_service_identity" "ck_sa" { `, context) } + +func TestAccSpannerDatabase_mrcmek(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + kms1 := acctest.BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", "us-central1", "tf-mr-cmek-test-key-us-central1") + kms2 := acctest.BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", "us-east1", "tf-mr-cmek-test-key-us-east1") + kms3 := acctest.BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", "us-east4", "tf-mr-cmek-test-key-us-east4") + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "key_ring1": kms1.KeyRing.Name, + "key_name1": kms1.CryptoKey.Name, + "key_ring2": kms2.KeyRing.Name, + "key_name2": kms2.CryptoKey.Name, + "key_ring3": kms3.KeyRing.Name, + "key_name3": kms3.CryptoKey.Name, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckSpannerDatabaseDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSpannerDatabase_mrcmek(context), + }, + { + ResourceName: "google_spanner_database.database", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"ddl", "deletion_protection"}, + }, + }, + }) +} + +func testAccSpannerDatabase_mrcmek(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_spanner_instance" "main" { + provider = google-beta + config = "nam3" + display_name = "main-instance1" + num_nodes = 1 +} + +resource "google_spanner_database" "database" { + provider = google-beta + instance = google_spanner_instance.main.name + name = "tf-test-mrcmek-db%{random_suffix}" + ddl = [ + "CREATE TABLE t1 (t1 INT64 NOT NULL,) PRIMARY KEY(t1)", + "CREATE TABLE t2 (t2 INT64 NOT NULL,) PRIMARY KEY(t2)", + ] + + encryption_config { + kms_key_names = [ + "%{key_name1}", + "%{key_name2}", + "%{key_name3}", + ] + } + + deletion_protection = false + +} + + +`, context) +} + {{- end }} diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go index 9a46191d0599..fbc32c3efaed 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go @@ -319,6 +319,7 @@ resource "google_spanner_instance" "basic" { config = "regional-us-central1" display_name = "%s-dname" num_nodes = 1 + edition = "ENTERPRISE" } `, name, name) } @@ -390,6 +391,7 @@ resource "google_spanner_instance" "basic" { storage_utilization_percent = 95 } } + edition = "ENTERPRISE" } `, name, name) } @@ -410,6 +412,7 @@ resource "google_spanner_instance" "basic" { storage_utilization_percent = %v } } + edition = "ENTERPRISE" } `, name, name, maxProcessingUnits, minProcessingUnits, cupUtilizationPercent, storageUtilizationPercent) } @@ -430,6 +433,7 @@ resource "google_spanner_instance" "basic" { storage_utilization_percent = 95 } } + edition = "ENTERPRISE" } `, name, name) } @@ -450,6 +454,7 @@ resource "google_spanner_instance" "basic" { storage_utilization_percent = %v } } + edition = "ENTERPRISE" } `, name, name, maxNodes, minNodes, cupUtilizationPercent, storageUtilizationPercent) } diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index ee76c51dd43d..40cd23f6eec8 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -2488,6 +2488,50 @@ func TestAccSqlDatabaseInstance_useInternalCaByDefault(t *testing.T) { }) } +func TestAccSqlDatabaseInstance_useCasBasedServerCa(t *testing.T) { + t.Parallel() + + databaseName := "tf-test-" + acctest.RandString(t, 10) + resourceName := "google_sql_database_instance.instance" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + + Steps: []resource.TestStep{ + { + Config: testGoogleSqlDatabaseInstance_setCasServerCa(databaseName, "GOOGLE_MANAGED_CAS_CA"), + Check: resource.ComposeTestCheckFunc(resource.TestCheckResourceAttr(resourceName, "settings.0.ip_configuration.0.server_ca_mode", "GOOGLE_MANAGED_CAS_CA")), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +func testGoogleSqlDatabaseInstance_setCasServerCa(databaseName, serverCaMode string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "instance" { + name = "%s" + region = "us-central1" + database_version = "POSTGRES_15" + deletion_protection = false + settings { + tier = "db-f1-micro" + ip_configuration { + ipv4_enabled = "true" + server_ca_mode = "%s" + } + } +} +`, databaseName, serverCaMode) +} + func testGoogleSqlDatabaseInstance_setSslOptionsForPostgreSQL(databaseName string, databaseVersion string, sslMode string) string { return fmt.Sprintf(` resource "google_sql_database_instance" "instance" { diff --git a/mmv1/third_party/terraform/services/transcoder/test-fixtures/example.mp4 b/mmv1/third_party/terraform/services/transcoder/test-fixtures/example.mp4 new file mode 100644 index 000000000000..b11552f9cb69 Binary files /dev/null and b/mmv1/third_party/terraform/services/transcoder/test-fixtures/example.mp4 differ diff --git a/mmv1/third_party/terraform/services/transcoder/test-fixtures/overlay.png b/mmv1/third_party/terraform/services/transcoder/test-fixtures/overlay.png new file mode 100644 index 000000000000..276ac3412656 Binary files /dev/null and b/mmv1/third_party/terraform/services/transcoder/test-fixtures/overlay.png differ diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.tmpl b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.tmpl index dbc2c620580f..2c53172487ba 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.tmpl +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.tmpl @@ -1397,4 +1397,159 @@ resource "google_workstations_workstation_config" "default" { `, context) } -{{ end }} +func TestAccWorkstationsWorkstationConfig_workstationConfigAllowedPortsUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationConfig_workstationConfigAllowedPorts(context), + }, + { + ResourceName: "google_workstations_workstation_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations", "enable_audit_agent", "labels", "location", "terraform_labels", "workstation_cluster_id", "workstation_config_id"}, + }, + { + Config: testAccWorkstationsWorkstationConfig_workstationConfigAllowedPortsUpdate(context), + }, + { + ResourceName: "google_workstations_workstation_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations", "enable_audit_agent", "labels", "location", "terraform_labels", "workstation_cluster_id", "workstation_config_id"}, + }, + }, + }) +} + +func testAccWorkstationsWorkstationConfig_workstationConfigAllowedPorts(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + "label" = "key" + } + + annotations = { + label-one = "value-one" + } +} + +resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + + host { + gce_instance { + machine_type = "e2-standard-4" + boot_disk_size_gb = 35 + disable_public_ip_addresses = true + } + } + + # Allow only port 80 (HTTP) + allowed_ports { + first = 80 + last = 80 + } +} +`, context) +} + +func testAccWorkstationsWorkstationConfig_workstationConfigAllowedPortsUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + "label" = "key" + } + + annotations = { + label-one = "value-one" + } +} + +resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + + host { + gce_instance { + machine_type = "e2-standard-4" + boot_disk_size_gb = 35 + disable_public_ip_addresses = true + } + } + + # Allow only port 80 (HTTP) + allowed_ports { + first = 80 + last = 80 + } + + # Allow only port 22 (SSH) + allowed_ports { + first = 22 + last = 22 + } + + # Allow port range 1024-65535 + allowed_ports { + first = 1024 + last = 65535 + } +} +`, context) +} +{{- end }} diff --git a/mmv1/third_party/terraform/tpgresource/utils.go b/mmv1/third_party/terraform/tpgresource/utils.go index 2f83608ad77f..30be51214971 100644 --- a/mmv1/third_party/terraform/tpgresource/utils.go +++ b/mmv1/third_party/terraform/tpgresource/utils.go @@ -238,6 +238,25 @@ func ExpandStringMap(d TerraformResourceData, key string) map[string]string { return ConvertStringMap(v.(map[string]interface{})) } +// InterfaceSliceToStringSlice converts a []interface{} containing strings to []string +func InterfaceSliceToStringSlice(v interface{}) ([]string, error) { + interfaceSlice, ok := v.([]interface{}) + if !ok { + return nil, fmt.Errorf("expected []interface{}, got %T", v) + } + + stringSlice := make([]string, len(interfaceSlice)) + for i, item := range interfaceSlice { + strItem, ok := item.(string) + if !ok { + return nil, fmt.Errorf("expected string, got %T at index %d", item, i) + } + stringSlice[i] = strItem + } + + return stringSlice, nil +} + // SortStringsByConfigOrder takes a slice of map[string]interface{} from a TF config // and API data, and returns a new slice containing the API data, reorderd to match // the TF config as closely as possible (with new items at the end of the list.) diff --git a/mmv1/third_party/terraform/version/version.go b/mmv1/third_party/terraform/version/version.go index b2d946a5d206..f21ad9d7203c 100644 --- a/mmv1/third_party/terraform/version/version.go +++ b/mmv1/third_party/terraform/version/version.go @@ -2,5 +2,5 @@ package version var ( // ProviderVersion is set during the release process to the release version of the binary - ProviderVersion = "dev" + ProviderVersion = "dev6" ) diff --git a/mmv1/third_party/terraform/website/docs/d/artifact_registry_docker_image.html.markdown b/mmv1/third_party/terraform/website/docs/d/artifact_registry_docker_image.html.markdown index 62bed15ebcd0..730c7706972c 100644 --- a/mmv1/third_party/terraform/website/docs/d/artifact_registry_docker_image.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/artifact_registry_docker_image.html.markdown @@ -4,7 +4,7 @@ description: |- Get information about a Docker Image within a Google Artifact Registry Repository. --- -# google\_artifact\_registry\_docker\_image +# google_artifact_registry_docker_image This data source fetches information from a provided Artifact Registry repository, including the fully qualified name and URI for an image, based on a the latest version of image name and optional digest or tag. diff --git a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown index 6640e7fbecc3..f582d646df88 100644 --- a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_config_map.html.markdown @@ -4,7 +4,7 @@ description: |- User workloads ConfigMap used by Airflow tasks that run with Kubernetes Executor or KubernetesPodOperator. --- -# google\_composer\_user\_workloads\_config\_map +# google_composer_user_workloads_config_map Provides access to Kubernetes ConfigMap configuration for a given project, region and Composer Environment. diff --git a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown index 8eea28a0f52f..93f5356a781f 100644 --- a/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/composer_user_workloads_secret.html.markdown @@ -4,7 +4,7 @@ description: |- User workloads Secret used by Airflow tasks that run with Kubernetes Executor or KubernetesPodOperator. --- -# google\_composer\_user\_workloads\_secret +# google_composer_user_workloads_secret Provides access to Kubernetes Secret configuration for a given project, region and Composer Environment. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_global_forwarding_rule.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_global_forwarding_rule.html.markdown index 50f04270d4f5..e8abc6b59815 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_global_forwarding_rule.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_global_forwarding_rule.html.markdown @@ -4,7 +4,7 @@ description: |- Get a global forwarding rule within GCE. --- -# google_compute_global_\forwarding_rule +# google_compute_global_forwarding_rule Get a global forwarding rule within GCE from its name. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_instance.html.markdown index 743fc9f1aae0..b6c32b263ff2 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_instance.html.markdown @@ -139,7 +139,7 @@ The following arguments are supported: The `attached_disk` block supports: -* `source` - The name or self_link of the disk attached to this instance. +* `source` - The self_link of the disk attached to this instance. * `device_name` - Name with which the attached disk is accessible under `/dev/disk/by-id/` diff --git a/mmv1/third_party/terraform/website/docs/d/compute_region_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_region_instance_group_manager.html.markdown index 99990ac1785e..c127a16b2541 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_region_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_region_instance_group_manager.html.markdown @@ -1,10 +1,11 @@ +--- subcategory: "Compute Engine" page_title: "Google: google_compute_region_instance_group_manager" description: |- Get a Compute Region Instance Group within GCE. --- -# google\_compute\_region\_instance\_group\_manager +# google_compute_region_instance_group_manager Get a Compute Region Instance Group Manager within GCE. For more information, see [the official documentation](https://cloud.google.com/compute/docs/instance-groups/distributing-instances-with-regional-instance-groups) @@ -35,4 +36,4 @@ The following arguments are supported: ## Attributes Reference -See [google_compute_region_instance_group_manager](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_region_instance_group_manager) resource for details of all the available attributes. \ No newline at end of file +See [google_compute_region_instance_group_manager](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_region_instance_group_manager) resource for details of all the available attributes. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_subnetworks.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_subnetworks.html.markdown index 4bc84ee870ea..f62f951c366f 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_subnetworks.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_subnetworks.html.markdown @@ -4,7 +4,7 @@ description: |- Get subnetworks within GCE. --- -# google\_compute\_subnetworks +# google_compute_subnetworks Get subnetworks within GCE. See [the official documentation](https://cloud.google.com/vpc/docs/subnets) diff --git a/mmv1/third_party/terraform/website/docs/d/oracle_database_cloud_exadata_infrastructure.html.markdown b/mmv1/third_party/terraform/website/docs/d/oracle_database_cloud_exadata_infrastructure.html.markdown new file mode 100644 index 000000000000..035a9fe9708d --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/oracle_database_cloud_exadata_infrastructure.html.markdown @@ -0,0 +1,34 @@ +--- +subcategory: "Oracle Database" +description: |- + Get information about an ExadataInfrastructure. +--- + +# google_oracle_database_cloud_exadata_infrastructure + +Get information about an ExadataInfrastructure. + +## Example Usage + +```hcl +data "google_oracle_database_cloud_exadata_infrastructure" "my-instance"{ + location = "us-east4" + cloud_exadata_infrastructure_id = "exadata-id" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `cloud_exadata_infrastructure_id` - (Required) The ID of the ExadataInfrastructure. + +* `location` - (Required) The location of the resource. + +- - - +* `project` - (Optional) The project to which the resource belongs. If it + is not provided, the provider project is used. + +## Attributes Reference + +See [google_oracle_database_cloud_exadata_infrastructure](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_oracle_database_cloud_exadata_infrastructure#argument-reference) resource for details of the available attributes. \ No newline at end of file diff --git a/mmv1/third_party/terraform/website/docs/d/oracle_database_cloud_vm_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/d/oracle_database_cloud_vm_cluster.html.markdown new file mode 100644 index 000000000000..fa669947abc0 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/oracle_database_cloud_vm_cluster.html.markdown @@ -0,0 +1,34 @@ +--- +subcategory: "Oracle Database" +description: |- + Get information about a CloudVmCluster. +--- + +# google_oracle_database_cloud_vm_cluster + +Get information about a CloudVmCluster. + +## Example Usage + +```hcl +data "google_oracle_database_cloud_vm_cluster" "my-vmcluster"{ + location = "us-east4" + cloud_vm_cluster_id = "vmcluster-id" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `cloud_vm_cluster_id` - (Required) The ID of the VM Cluster. + +* `location` - (Required) The location of the resource. + +- - - +* `project` - (Optional) The project in which the resource belongs. If it + is not provided, the provider project is used. + +## Attributes Reference + +See [google_oracle_database_cloud_vm_cluster](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_oracle_database_cloud_vm_cluster#argument-reference) resource for details of the available attributes. \ No newline at end of file diff --git a/mmv1/third_party/terraform/website/docs/d/oracle_database_db_servers.html.markdown b/mmv1/third_party/terraform/website/docs/d/oracle_database_db_servers.html.markdown new file mode 100644 index 000000000000..ae1ad60ba11d --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/oracle_database_db_servers.html.markdown @@ -0,0 +1,67 @@ +--- +subcategory: "Oracle Database" +description: |- + List all DbServers of a Cloud ExdataInfrastructure. +--- + +# google_oracle_database_db_servers + +List all DbServers of a Cloud Exdata Infrastructure. + +## Example Usage + +```hcl +data "google_oracle_database_db_servers" "my_db_servers"{ + location = "us-east4" + cloud_exadata_infrastructure = "exadata-id" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `cloud_exadata_infrastructure` - (Required) The Exadata Infrastructure id. + +* `location` - (Required) The location of resource. + +- - - +* `project` - (Optional) The project to which the resource belongs. If it + is not provided, the provider project is used. + +* `db_servers` - (Output) List of dbServers + + The `db_servers` block supports: + +* `display_name` - User friendly name for the resource. + +* `properties` - Various properties of the databse server. + + The `properties` block supports: + +* `ocid` - The OCID of database server. + +* `ocpu_count` - The OCPU count per database. + +* `max_ocpu_count` - The total number of CPU cores available. + +* `memory_size_gb` - The allocated memory in gigabytes on the database server. + +* `max_memory_size_gb` - The total memory available in gigabytes. + +* `db_node_storage_size_gb` - The local storage per VM. + +* `max_db_node_storage_size_gb` - The total local node storage available in GBs. + +* `vm_count` - The VM count per database. + +* `state` - The current state of the database server. +Allowed values for `state` are:
+`STATE_UNSPECIFIED` - Default unspecified value.
+`CREATING` - Indicates that the resource is being created.
+`AVAILABLE` - Indicates that the resource is available.
+`UNAVAILABLE` - Indicates that the resource is unavailable.
+`DELETING` - Indicates that the resource is being deleted.
+`DELETED` - Indicates that the resource has been deleted.
+ +* `db_node_ids` - The OCID of database nodes associated with the database server. diff --git a/mmv1/third_party/terraform/website/docs/d/secret_manager_regional_secret_version.html.markdown b/mmv1/third_party/terraform/website/docs/d/secret_manager_regional_secret_version.html.markdown index b93dba8039ae..daf52bad6f9a 100644 --- a/mmv1/third_party/terraform/website/docs/d/secret_manager_regional_secret_version.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/secret_manager_regional_secret_version.html.markdown @@ -33,6 +33,9 @@ The following arguments are supported: * `version` - (Optional) The version of the regional secret to get. If it is not provided, the latest version is retrieved. +* `is_secret_data_base64` - (Optional) If set to 'true', the secret data is + expected to be base64-encoded string. + ## Attributes Reference The following attributes are exported: diff --git a/mmv1/third_party/terraform/website/docs/d/secret_manager_regional_secret_version_access.html.markdown b/mmv1/third_party/terraform/website/docs/d/secret_manager_regional_secret_version_access.html.markdown index bfb607fc7dfd..fb60cf2762f1 100644 --- a/mmv1/third_party/terraform/website/docs/d/secret_manager_regional_secret_version_access.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/secret_manager_regional_secret_version_access.html.markdown @@ -34,6 +34,9 @@ The following arguments are supported: - `version` - (Optional) The version of the regional secret to get. If it is not provided, the latest version is retrieved. +- `is_secret_data_base64` - (Optional) If set to 'true', the secret data is + expected to be base64-encoded string. + ## Attributes Reference The following attributes are exported: diff --git a/mmv1/third_party/terraform/website/docs/d/secret_manager_secret_version.html.markdown b/mmv1/third_party/terraform/website/docs/d/secret_manager_secret_version.html.markdown index 35c1bd4499d6..a12499283f5d 100644 --- a/mmv1/third_party/terraform/website/docs/d/secret_manager_secret_version.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/secret_manager_secret_version.html.markdown @@ -28,6 +28,8 @@ The following arguments are supported: * `version` - (Optional) The version of the secret to get. If it is not provided, the latest version is retrieved. +* `is_secret_data_base64` - (Optional) If set to 'true', the secret data is + expected to be base64-encoded string. ## Attributes Reference diff --git a/mmv1/third_party/terraform/website/docs/d/secret_manager_secret_version_access.html.markdown b/mmv1/third_party/terraform/website/docs/d/secret_manager_secret_version_access.html.markdown index 44d6088e8b51..cd8546b95a2e 100644 --- a/mmv1/third_party/terraform/website/docs/d/secret_manager_secret_version_access.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/secret_manager_secret_version_access.html.markdown @@ -29,6 +29,8 @@ The following arguments are supported: * `version` - (Optional) The version of the secret to get. If it is not provided, the latest version is retrieved. +* `is_secret_data_base64` - (Optional) If set to 'true', the secret data is + expected to be base64-encoded string. ## Attributes Reference diff --git a/mmv1/third_party/terraform/website/docs/d/secret_manager_secrets.html.markdown b/mmv1/third_party/terraform/website/docs/d/secret_manager_secrets.html.markdown index 463266f0127b..e6ad5da99d42 100644 --- a/mmv1/third_party/terraform/website/docs/d/secret_manager_secrets.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/secret_manager_secrets.html.markdown @@ -43,6 +43,8 @@ exported: * `version_aliases` - Mapping from version alias to version name. +* `version_destroy_ttl` - The version destroy ttl for the secret version. + * `topics` - A list of up to 10 Pub/Sub topics to which messages are published when control plane operations are called on the secret or its versions. Structure is [documented below](#nested_topics). diff --git a/mmv1/third_party/terraform/website/docs/d/site_verification_token.html.markdown b/mmv1/third_party/terraform/website/docs/d/site_verification_token.html.markdown index 066370eda29d..287080e694d0 100644 --- a/mmv1/third_party/terraform/website/docs/d/site_verification_token.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/site_verification_token.html.markdown @@ -1,3 +1,4 @@ +--- subcategory: "Site Verification" description: |- A verification token is used to demonstrate ownership of a website or domain. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index ab0e0f752037..b18f1594ce09 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -124,7 +124,9 @@ The following arguments are supported: **Note:** If you want to update this value (resize the VM) after initial creation, you must set [`allow_stopping_for_update`](#allow_stopping_for_update) to `true`. - [Custom machine types](https://cloud.google.com/dataproc/docs/concepts/compute/custom-machine-types) can be formatted as `custom-NUMBER_OF_CPUS-AMOUNT_OF_MEMORY_MB`, e.g. `custom-6-20480` for 6 vCPU and 20GB of RAM. + [Custom machine types](https://cloud.google.com/dataproc/docs/concepts/compute/custom-machine-types) can be formatted as `custom-NUMBER_OF_CPUS-AMOUNT_OF_MEMORY_MB`, e.g. `custom-6-20480` for 6 vCPU and 20GB of RAM. + Because of current API limitations some custom machine types may get converted to different machine types (such as an equivalent standard type) and cause non-empty plans in your configuration. Use + `lifecycle.ignore_changes` on `machine_type` in these cases. There is a limit of 6.5 GB per CPU unless you add [extended memory](https://cloud.google.com/compute/docs/instances/creating-instance-with-custom-machine-type#extendedmemory). You must do this explicitly by adding the suffix `-ext`, e.g. `custom-2-15360-ext` for 2 vCPU and 15 GB of memory. @@ -386,7 +388,7 @@ is desired, you will need to modify your state file manually using is not accessible from the Internet. If omitted, ssh provisioners will not work unless Terraform can send traffic to the instance's network (e.g. via tunnel or because it is running on another cloud instance on that network). - This block can be repeated multiple times. Structure [documented below](#nested_access_config). + This block can be specified once per `network_interface`. Structure [documented below](#nested_access_config). * `alias_ip_range` - (Optional) An array of alias IP ranges for this network interface. Can only be specified for network diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index e02439fe1233..afe75854b4e5 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -553,7 +553,7 @@ The following arguments are supported: is not accessible from the Internet (this means that ssh provisioners will not work unless you are running Terraform can send traffic to the instance's network (e.g. via tunnel or because it is running on another cloud instance - on that network). This block can be repeated multiple times. Structure [documented below](#nested_access_config). + on that network). This block can be specified once per `network_interface`. Structure [documented below](#nested_access_config). * `alias_ip_range` - (Optional) An array of alias IP ranges for this network interface. Can only be specified for network diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown index 84cbcae282cd..facff74df4b6 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown @@ -519,7 +519,7 @@ The following arguments are supported: is not accessible from the Internet (this means that ssh provisioners will not work unless you are running Terraform can send traffic to the instance's network (e.g. via tunnel or because it is running on another cloud instance - on that network). This block can be repeated multiple times. Structure [documented below](#nested_access_config). + on that network). This block can be specified once per `network_interface`. Structure [documented below](#nested_access_config). * `alias_ip_range` - (Optional) An array of alias IP ranges for this network interface. Can only be specified for network diff --git a/mmv1/third_party/terraform/website/docs/r/google_folder.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_folder.html.markdown index 8d977035ea8b..404437cbec67 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_folder.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_folder.html.markdown @@ -55,7 +55,7 @@ The following arguments are supported: * `parent` - (Required) The resource name of the parent Folder or Organization. Must be of the form `folders/{folder_id}` or `organizations/{org_id}`. -* `tags` - (Optional) A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty. The field is immutable and causes resource replacement when mutated. +* `tags` - (Optional) A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty. The field is immutable and causes resource replacement when mutated. This field is only set at create time and modifying this field after creation will trigger recreation. To apply tags to an existing resource, see the `google_tags_tag_value` resource. ## Attributes Reference diff --git a/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown index fea0203890ea..cfddb18397c0 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_project.html.markdown @@ -113,7 +113,7 @@ The following arguments are supported: to be abandoned rather than deleted, i.e., the Terraform resource can be deleted without deleting the Project via the Google API. Possible values are: "PREVENT", "ABANDON", "DELETE". Default value is `PREVENT`. -* `tags` - (Optional) A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty. The field is immutable and causes resource replacement when mutated. +* `tags` - (Optional) A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored when empty. The field is immutable and causes resource replacement when mutated. This field is only set at create time and modifying this field after creation will trigger recreation. To apply tags to an existing resource, see the `google_tags_tag_value` resource. ## Attributes Reference diff --git a/mmv1/third_party/terraform/website/docs/r/site_verification_owner.html.markdown b/mmv1/third_party/terraform/website/docs/r/site_verification_owner.html.markdown index 48894cea3122..d1eec2889f13 100644 --- a/mmv1/third_party/terraform/website/docs/r/site_verification_owner.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/site_verification_owner.html.markdown @@ -1,3 +1,4 @@ +--- subcategory: "Site Verification" description: |- Manages additional owners on verified web resources. @@ -134,4 +135,4 @@ verified owners is to delete the web resource itself. ## User Project Overrides -This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override). \ No newline at end of file +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override). diff --git a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown index 9f2c3cde444a..e6847a79f6fd 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown @@ -119,9 +119,10 @@ The following arguments are supported: * `type` - (Optional) The user type. It determines the method to authenticate the user during login. The default is the database's built-in user type. Flags - include "BUILT_IN", "CLOUD_IAM_USER", and "CLOUD_IAM_SERVICE_ACCOUNT" for both - [Postgres](https://cloud.google.com/sql/docs/postgres/admin-api/rest/v1beta4/users#sqlusertype) and [MySQL](https://cloud.google.com/sql/docs/mysql/admin-api/rest/v1beta4/users#sqlusertype). - MySQL also includes "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" and "CLOUD_IAM_GROUP_SERVICE_ACCOUNT". + include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", "CLOUD_IAM_GROUP", + "CLOUD_IAM_GROUP_USER" and "CLOUD_IAM_GROUP_SERVICE_ACCOUNT" for + [Postgres](https://cloud.google.com/sql/docs/postgres/admin-api/rest/v1beta4/users#sqlusertype) + and [MySQL](https://cloud.google.com/sql/docs/mysql/admin-api/rest/v1beta4/users#sqlusertype). * `deletion_policy` - (Optional) The deletion policy for the user. Setting `ABANDON` allows the resource to be abandoned rather than deleted. This is useful diff --git a/mmv1/third_party/tgc/cai/string_helpers.go b/mmv1/third_party/tgc/cai/string_helpers.go new file mode 100644 index 000000000000..33395886a3bc --- /dev/null +++ b/mmv1/third_party/tgc/cai/string_helpers.go @@ -0,0 +1,9 @@ +package cai + +func ConvertInterfaceToStringArray(values []interface{}) []string { + stringArray := make([]string, len(values)) + for i, v := range values { + stringArray[i] = v.(string) + } + return stringArray +} diff --git a/mmv1/third_party/tgc/resource_converters.go.tmpl b/mmv1/third_party/tgc/resource_converters.go.tmpl index 1acd324f3d8a..08d1dee5bae6 100644 --- a/mmv1/third_party/tgc/resource_converters.go.tmpl +++ b/mmv1/third_party/tgc/resource_converters.go.tmpl @@ -29,6 +29,8 @@ package google import ( "sort" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/appengine" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/container" "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/compute" "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/kms" "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/resourcemanager" @@ -36,6 +38,7 @@ import ( "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/secretmanagerregional" "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/securesourcemanager" "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/securitycenterv2" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/storage" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" ) @@ -51,10 +54,10 @@ import ( func ResourceConverters() map[string][]cai.ResourceConverter { return map[string][]cai.ResourceConverter{ "google_artifact_registry_repository": {artifactregistry.ResourceConverterArtifactRegistryRepository()}, - "google_app_engine_application": {resourceConverterAppEngineApplication()}, + "google_app_engine_application": {appengine.ResourceConverterAppEngineApplication()}, "google_alloydb_cluster": {alloydb.ResourceConverterAlloydbCluster()}, "google_alloydb_instance": {alloydb.ResourceConverterAlloydbInstance()}, - "google_apikeys_key": {resourceConverterApikeysKey()}, + "google_apikeys_key": {apikeys.ResourceConverterApikeysKey()}, "google_compute_address": {compute.ResourceConverterComputeAddress()}, "google_compute_autoscaler": {compute.ResourceConverterComputeAutoscaler()}, "google_compute_firewall": {compute.ResourceConverterComputeFirewall()}, @@ -65,14 +68,14 @@ func ResourceConverters() map[string][]cai.ResourceConverter { "google_compute_global_forwarding_rule": {compute.ResourceConverterComputeGlobalForwardingRule()}, "google_compute_health_check": {compute.ResourceConverterComputeHealthCheck()}, "google_compute_instance": {compute.ResourceConverterComputeInstance()}, - "google_compute_instance_group": {resourceConverterComputeInstanceGroup()}, + "google_compute_instance_group": {compute.ResourceConverterComputeInstanceGroup()}, "google_compute_network": {compute.ResourceConverterComputeNetwork()}, "google_compute_node_template": {compute.ResourceConverterComputeNodeTemplate()}, "google_compute_route": {compute.ResourceConverterComputeRoute()}, "google_compute_router": {compute.ResourceConverterComputeRouter()}, "google_compute_vpn_tunnel": {compute.ResourceConverterComputeVpnTunnel()}, "google_compute_resource_policy": {compute.ResourceConverterComputeResourcePolicy()}, - "google_compute_security_policy": {resourceConverterComputeSecurityPolicy()}, + "google_compute_security_policy": {compute.ResourceConverterComputeSecurityPolicy()}, "google_compute_snapshot": {compute.ResourceConverterComputeSnapshot()}, "google_compute_subnetwork": {compute.ResourceConverterComputeSubnetwork()}, "google_compute_ssl_policy": {compute.ResourceConverterComputeSslPolicy()}, @@ -81,31 +84,31 @@ func ResourceConverters() map[string][]cai.ResourceConverter { "google_compute_target_http_proxy": {compute.ResourceConverterComputeTargetHttpProxy()}, "google_compute_target_https_proxy": {compute.ResourceConverterComputeTargetHttpsProxy()}, "google_compute_target_ssl_proxy": {compute.ResourceConverterComputeTargetSslProxy()}, - "google_compute_target_pool": {resourceConverterComputeTargetPool()}, - "google_composer_environment": {resourceConverterComposerEnvironment()}, - "google_compute_region_commitment": {resourceConverterCommitment()}, - "google_dataflow_job": {resourceDataflowJob()}, + "google_compute_target_pool": {compute.ResourceConverterComputeTargetPool()}, + "google_composer_environment": {composer.ResourceConverterComposerEnvironment()}, + "google_compute_region_commitment": {compute.ResourceConverterCommitment()}, + "google_dataflow_job": {dataflow.ResourceDataflowJob()}, "google_dataproc_autoscaling_policy": {dataproc.ResourceConverterDataprocAutoscalingPolicy()}, - "google_dataproc_cluster": {resourceConverterDataprocCluster()}, + "google_dataproc_cluster": {dataproc.ResourceConverterDataprocCluster()}, "google_dns_managed_zone": {dns.ResourceConverterDNSManagedZone()}, "google_dns_policy": {dns.ResourceConverterDNSPolicy()}, "google_kms_key_ring_import_job": {kms.ResourceConverterKMSKeyRingImportJob()}, "google_gke_hub_feature": {gkehub2.ResourceConverterGKEHub2Feature()}, - "google_storage_bucket": {resourceConverterStorageBucket()}, - "google_sql_database_instance": {resourceConverterSQLDatabaseInstance()}, + "google_storage_bucket": {storage.ResourceConverterStorageBucket()}, + "google_sql_database_instance": {sql.ResourceConverterSQLDatabaseInstance()}, "google_sql_database": {sql.ResourceConverterSQLDatabase()}, - "google_container_cluster": {resourceConverterContainerCluster()}, - "google_container_node_pool": {resourceConverterContainerNodePool()}, + "google_container_cluster": {container.ResourceConverterContainerCluster()}, + "google_container_node_pool": {container.ResourceConverterContainerNodePool()}, "google_bigquery_dataset": {bigquery.ResourceConverterBigQueryDataset()}, "google_bigquery_dataset_iam_policy": {bigquery.ResourceConverterBigqueryDatasetIamPolicy()}, "google_bigquery_dataset_iam_binding": {bigquery.ResourceConverterBigqueryDatasetIamBinding()}, "google_bigquery_dataset_iam_member": {bigquery.ResourceConverterBigqueryDatasetIamMember()}, - "google_bigquery_table": {resourceConverterBigQueryTable()}, + "google_bigquery_table": {bigquery.ResourceConverterBigQueryTable()}, "google_datastream_connection_profile": {datastream.ResourceConverterDatastreamConnectionProfile()}, "google_datastream_private_connection": {datastream.ResourceConverterDatastreamPrivateConnection()}, "google_datastream_stream": {datastream.ResourceConverterDatastreamStream()}, - "google_firebase_project": {resourceConverterFirebaseProject()}, - "google_org_policy_policy": {resourceConverterOrgPolicyPolicy()}, + "google_firebase_project": {firebase.ResourceConverterFirebaseProject()}, + "google_org_policy_policy": {resourcemanager.ResourceConverterOrgPolicyPolicy()}, "google_redis_instance": {redis.ResourceConverterRedisInstance()}, "google_spanner_database": {spanner.ResourceConverterSpannerDatabase()}, "google_spanner_database_iam_policy": {spanner.ResourceConverterSpannerDatabaseIamPolicy()}, @@ -115,7 +118,7 @@ func ResourceConverters() map[string][]cai.ResourceConverter { "google_spanner_instance_iam_policy": {spanner.ResourceConverterSpannerInstanceIamPolicy()}, "google_spanner_instance_iam_binding": {spanner.ResourceConverterSpannerInstanceIamBinding()}, "google_spanner_instance_iam_member": {spanner.ResourceConverterSpannerInstanceIamMember()}, - "google_project_service": {resourceConverterServiceUsage()}, + "google_project_service": {resourcemanager.ResourceConverterServiceUsage()}, "google_secret_manager_secret_version": {secretmanager.ResourceConverterSecretManagerSecretVersion()}, "google_pubsub_lite_reservation": {pubsublite.ResourceConverterPubsubLiteReservation()}, "google_pubsub_lite_subscription": {pubsublite.ResourceConverterPubsubLiteSubscription()}, @@ -125,15 +128,15 @@ func ResourceConverters() map[string][]cai.ResourceConverter { "google_pubsub_subscription_iam_policy": {pubsub.ResourceConverterPubsubSubscriptionIamPolicy()}, "google_pubsub_subscription_iam_binding": {pubsub.ResourceConverterPubsubSubscriptionIamBinding()}, "google_pubsub_subscription_iam_member": {pubsub.ResourceConverterPubsubSubscriptionIamMember()}, - "google_storage_bucket_iam_policy": {resourceConverterStorageBucketIamPolicy()}, - "google_storage_bucket_iam_binding": {resourceConverterStorageBucketIamBinding()}, - "google_storage_bucket_iam_member": {resourceConverterStorageBucketIamMember()}, + "google_storage_bucket_iam_policy": {storage.ResourceConverterStorageBucketIamPolicy()}, + "google_storage_bucket_iam_binding": {storage.ResourceConverterStorageBucketIamBinding()}, + "google_storage_bucket_iam_member": {storage.ResourceConverterStorageBucketIamMember()}, "google_compute_node_group": {compute.ResourceConverterComputeNodeGroup()}, - "google_logging_folder_bucket_config": {resourceConverterLogFolderBucket()}, - "google_app_engine_standard_app_version": {resourceAppEngineStandardAppVersion()}, - "google_logging_organization_bucket_config": {resourceConverterLogOrganizationBucket()}, - "google_logging_project_bucket_config": {resourceConverterLogProjectBucket()}, - "google_logging_billing_account_bucket_config": {resourceConverterLogBillingAccountBucket()}, + "google_logging_folder_bucket_config": {logging.ResourceConverterLogFolderBucket()}, + "google_app_engine_standard_app_version": {appengine.ResourceAppEngineStandardAppVersion()}, + "google_logging_organization_bucket_config": {logging.ResourceConverterLogOrganizationBucket()}, + "google_logging_project_bucket_config": {logging.ResourceConverterLogProjectBucket()}, + "google_logging_billing_account_bucket_config": {logging.ResourceConverterLogBillingAccountBucket()}, "google_cloud_tasks_queue": {cloudtasks.ResourceConverterCloudTasksQueue()}, "google_pubsub_topic": {pubsub.ResourceConverterPubsubTopic()}, "google_kms_crypto_key": {kms.ResourceConverterKMSCryptoKey()}, @@ -144,7 +147,7 @@ func ResourceConverters() map[string][]cai.ResourceConverter { "google_cloud_run_service": {cloudrun.ResourceConverterCloudRunService()}, "google_cloud_run_domain_mapping": {cloudrun.ResourceConverterCloudRunDomainMapping()}, "google_cloud_run_v2_job": {cloudrunv2.ResourceConverterCloudRunV2Job()}, - "google_cloudfunctions_function": {resourceConverterCloudFunctionsCloudFunction()}, + "google_cloudfunctions_function": {cloudfunctions.ResourceConverterCloudFunctionsCloudFunction()}, "google_monitoring_notification_channel": {monitoring.ResourceConverterMonitoringNotificationChannel()}, "google_monitoring_alert_policy": {monitoring.ResourceConverterMonitoringAlertPolicy()}, "google_vertex_ai_dataset": {vertexai.ResourceConverterVertexAIDataset()}, @@ -156,38 +159,38 @@ func ResourceConverters() map[string][]cai.ResourceConverter { {{- end }} {{- end }} "google_project": { - resourceConverterProject(), - resourceConverterProjectBillingInfo(), + resourcemanager.ResourceConverterProject(), + resourcemanager.ResourceConverterProjectBillingInfo(), }, "google_bigtable_instance": { - resourceConverterBigtableInstance(), - resourceConverterBigtableCluster(), + bigtable.ResourceConverterBigtableInstance(), + bigtable.ResourceConverterBigtableCluster(), }, "google_organization_iam_policy": {resourcemanager.ResourceConverterOrganizationIamPolicy()}, "google_organization_iam_binding": {resourcemanager.ResourceConverterOrganizationIamBinding()}, "google_organization_iam_member": {resourcemanager.ResourceConverterOrganizationIamMember()}, - "google_organization_policy": {resourceConverterOrganizationPolicy()}, - "google_project_organization_policy": {resourceConverterProjectOrgPolicy()}, - "google_folder": {resourceConverterFolder()}, + "google_organization_policy": {resourcemanager.ResourceConverterOrganizationPolicy()}, + "google_project_organization_policy": {resourcemanager.ResourceConverterProjectOrgPolicy()}, + "google_folder": {resourcemanager.ResourceConverterFolder()}, "google_folder_iam_policy": {resourcemanager.ResourceConverterFolderIamPolicy()}, "google_folder_iam_binding": {resourcemanager.ResourceConverterFolderIamBinding()}, "google_folder_iam_member": {resourcemanager.ResourceConverterFolderIamMember()}, - "google_folder_organization_policy": {resourceConverterFolderOrgPolicy()}, - "google_kms_crypto_key_iam_policy": {resourceConverterKmsCryptoKeyIamPolicy()}, - "google_kms_crypto_key_iam_binding": {resourceConverterKmsCryptoKeyIamBinding()}, - "google_kms_crypto_key_iam_member": {resourceConverterKmsCryptoKeyIamMember()}, - "google_kms_key_ring_iam_policy": {resourceConverterKmsKeyRingIamPolicy()}, - "google_kms_key_ring_iam_binding": {resourceConverterKmsKeyRingIamBinding()}, - "google_kms_key_ring_iam_member": {resourceConverterKmsKeyRingIamMember()}, + "google_folder_organization_policy": {resourcemanager.ResourceConverterFolderOrgPolicy()}, + "google_kms_crypto_key_iam_policy": {kms.ResourceConverterKmsCryptoKeyIamPolicy()}, + "google_kms_crypto_key_iam_binding": {kms.ResourceConverterKmsCryptoKeyIamBinding()}, + "google_kms_crypto_key_iam_member": {kms.ResourceConverterKmsCryptoKeyIamMember()}, + "google_kms_key_ring_iam_policy": {kms.ResourceConverterKmsKeyRingIamPolicy()}, + "google_kms_key_ring_iam_binding": {kms.ResourceConverterKmsKeyRingIamBinding()}, + "google_kms_key_ring_iam_member": {kms.ResourceConverterKmsKeyRingIamMember()}, "google_project_iam_policy": {resourcemanager.ResourceConverterProjectIamPolicy()}, "google_project_iam_binding": {resourcemanager.ResourceConverterProjectIamBinding()}, "google_project_iam_member": {resourcemanager.ResourceConverterProjectIamMember()}, - "google_project_iam_custom_role": {resourceConverterProjectIAMCustomRole()}, - "google_organization_iam_custom_role": {resourceConverterOrganizationIAMCustomRole()}, + "google_project_iam_custom_role": {resourcemanager.ResourceConverterProjectIAMCustomRole()}, + "google_organization_iam_custom_role": {resourcemanager.ResourceConverterOrganizationIAMCustomRole()}, "google_vpc_access_connector": {vpcaccess.ResourceConverterVPCAccessConnector()}, "google_logging_metric": {logging.ResourceConverterLoggingMetric()}, - "google_service_account": {resourceConverterServiceAccount()}, - "google_service_account_key": {resourceConverterServiceAccountKey()}, + "google_service_account": {resourcemanager.ResourceConverterServiceAccount()}, + "google_service_account_key": {resourcemanager.ResourceConverterServiceAccountKey()}, } } diff --git a/mmv1/third_party/tgc/apikeys_key.go b/mmv1/third_party/tgc/services/apikeys/apikeys_key.go similarity index 98% rename from mmv1/third_party/tgc/apikeys_key.go rename to mmv1/third_party/tgc/services/apikeys/apikeys_key.go index 33fbb101640d..3dad5789dceb 100644 --- a/mmv1/third_party/tgc/apikeys_key.go +++ b/mmv1/third_party/tgc/services/apikeys/apikeys_key.go @@ -1,4 +1,4 @@ -package google +package apikeys import ( "reflect" @@ -10,7 +10,7 @@ import ( const ApikeysKeyAssetType string = "apikeys.googleapis.com/Key" -func resourceConverterApikeysKey() cai.ResourceConverter { +func ResourceConverterApikeysKey() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ApikeysKeyAssetType, Convert: GetApikeysKeyCaiObject, @@ -125,7 +125,7 @@ func expandApikeysKeyDeleteTime(v interface{}, d tpgresource.TerraformResourceDa } func expandApikeysKeyRestrictions(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - + l := v.([]interface{}) if len(l) == 0 || l[0] == nil { return nil, nil @@ -203,7 +203,6 @@ func expandApikeysKeySha1Fingerprint(v interface{}, d tpgresource.TerraformResou return v, nil } - func expandApikeysKeyApiTargets(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { @@ -235,10 +234,9 @@ func expandApikeysKeyService(v interface{}, d tpgresource.TerraformResourceData, } func expandApikeysKeyMethods(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return convertInterfaceToStringArray(v.([]interface{})), nil + return cai.ConvertInterfaceToStringArray(v.([]interface{})), nil } - func expandApikeysKeyDEtag(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/mmv1/third_party/tgc/appengine_application.go b/mmv1/third_party/tgc/services/appengine/appengine_application.go similarity index 96% rename from mmv1/third_party/tgc/appengine_application.go rename to mmv1/third_party/tgc/services/appengine/appengine_application.go index c64f8db8cc98..bdd9ee2c35cb 100644 --- a/mmv1/third_party/tgc/appengine_application.go +++ b/mmv1/third_party/tgc/services/appengine/appengine_application.go @@ -1,4 +1,4 @@ -package google +package appengine import ( "reflect" @@ -10,7 +10,7 @@ import ( const AppEngineApplicationAssetType string = "appengine.googleapis.com/Application" -func resourceConverterAppEngineApplication() cai.ResourceConverter { +func ResourceConverterAppEngineApplication() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: AppEngineApplicationAssetType, Convert: GetAppEngineApplicationCaiObject, @@ -55,7 +55,6 @@ func GetAppEngineApplicationApiObject(d tpgresource.TerraformResourceData, confi obj["location_id"] = locationIdProp } - return obj, nil } @@ -63,7 +62,6 @@ func expandAppEngineApplicationId(v interface{}, d tpgresource.TerraformResource return v, nil } - func expandAppEngineApplicationLocationId(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/mmv1/third_party/tgc/appengine_standard_version.go b/mmv1/third_party/tgc/services/appengine/appengine_standard_version.go similarity index 99% rename from mmv1/third_party/tgc/appengine_standard_version.go rename to mmv1/third_party/tgc/services/appengine/appengine_standard_version.go index a86bfb70e97d..7d9a23685a47 100644 --- a/mmv1/third_party/tgc/appengine_standard_version.go +++ b/mmv1/third_party/tgc/services/appengine/appengine_standard_version.go @@ -1,4 +1,4 @@ -package google +package appengine import ( "reflect" @@ -12,7 +12,7 @@ import ( const AppEngineVersionAssetType string = "appengine.googleapis.com/Version" -func resourceAppEngineStandardAppVersion() cai.ResourceConverter { +func ResourceAppEngineStandardAppVersion() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: AppEngineVersionAssetType, Convert: GetAppEngineVersionCaiObject, diff --git a/mmv1/third_party/tgc/bigquery_dataset_iam.go b/mmv1/third_party/tgc/services/bigquery/bigquery_dataset_iam.go similarity index 100% rename from mmv1/third_party/tgc/bigquery_dataset_iam.go rename to mmv1/third_party/tgc/services/bigquery/bigquery_dataset_iam.go diff --git a/mmv1/third_party/tgc/bigquery_table.go b/mmv1/third_party/tgc/services/bigquery/bigquery_table.go similarity index 99% rename from mmv1/third_party/tgc/bigquery_table.go rename to mmv1/third_party/tgc/services/bigquery/bigquery_table.go index 20ede57cc956..a37f4a1ccf34 100644 --- a/mmv1/third_party/tgc/bigquery_table.go +++ b/mmv1/third_party/tgc/services/bigquery/bigquery_table.go @@ -1,4 +1,4 @@ -package google +package bigquery import ( "reflect" @@ -10,7 +10,7 @@ import ( const BigQueryTableAssetType string = "bigquery.googleapis.com/Table" -func resourceConverterBigQueryTable() cai.ResourceConverter { +func ResourceConverterBigQueryTable() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: BigQueryTableAssetType, Convert: GetBigQueryTableCaiObject, diff --git a/mmv1/third_party/tgc/bigtable_cluster.go b/mmv1/third_party/tgc/services/bigtable/bigtable_cluster.go similarity index 97% rename from mmv1/third_party/tgc/bigtable_cluster.go rename to mmv1/third_party/tgc/services/bigtable/bigtable_cluster.go index 99ce6e523b4b..9f31297843cf 100644 --- a/mmv1/third_party/tgc/bigtable_cluster.go +++ b/mmv1/third_party/tgc/services/bigtable/bigtable_cluster.go @@ -1,4 +1,4 @@ -package google +package bigtable import ( "reflect" @@ -8,7 +8,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterBigtableCluster() cai.ResourceConverter { +func ResourceConverterBigtableCluster() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "bigtableadmin.googleapis.com/Cluster", Convert: GetBigtableClusterCaiObject, diff --git a/mmv1/third_party/tgc/bigtable_instance.go b/mmv1/third_party/tgc/services/bigtable/bigtable_instance.go similarity index 97% rename from mmv1/third_party/tgc/bigtable_instance.go rename to mmv1/third_party/tgc/services/bigtable/bigtable_instance.go index 6403eb378c23..fc63bb53984a 100644 --- a/mmv1/third_party/tgc/bigtable_instance.go +++ b/mmv1/third_party/tgc/services/bigtable/bigtable_instance.go @@ -1,4 +1,4 @@ -package google +package bigtable import ( "reflect" @@ -8,7 +8,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterBigtableInstance() cai.ResourceConverter { +func ResourceConverterBigtableInstance() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "bigtableadmin.googleapis.com/Instance", Convert: GetBigtableInstanceCaiObject, diff --git a/mmv1/third_party/tgc/cloudfunctions_cloud_function.go b/mmv1/third_party/tgc/services/cloudfunctions/cloudfunctions_cloud_function.go similarity index 99% rename from mmv1/third_party/tgc/cloudfunctions_cloud_function.go rename to mmv1/third_party/tgc/services/cloudfunctions/cloudfunctions_cloud_function.go index 7e5fb205cfc8..c54d8ed57bbc 100644 --- a/mmv1/third_party/tgc/cloudfunctions_cloud_function.go +++ b/mmv1/third_party/tgc/services/cloudfunctions/cloudfunctions_cloud_function.go @@ -1,4 +1,4 @@ -package google +package cloudfunctions import ( "reflect" @@ -10,7 +10,7 @@ import ( const CloudFunctionsCloudFunctionAssetType string = "cloudfunctions.googleapis.com/CloudFunction" -func resourceConverterCloudFunctionsCloudFunction() cai.ResourceConverter { +func ResourceConverterCloudFunctionsCloudFunction() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: CloudFunctionsCloudFunctionAssetType, Convert: GetCloudFunctionsCloudFunctionCaiObject, diff --git a/mmv1/third_party/tgc/cloudfunctions_function.go b/mmv1/third_party/tgc/services/cloudfunctions/cloudfunctions_function.go similarity index 99% rename from mmv1/third_party/tgc/cloudfunctions_function.go rename to mmv1/third_party/tgc/services/cloudfunctions/cloudfunctions_function.go index 1f1d917d2739..2ffb16e1d08f 100644 --- a/mmv1/third_party/tgc/cloudfunctions_function.go +++ b/mmv1/third_party/tgc/services/cloudfunctions/cloudfunctions_function.go @@ -1,4 +1,4 @@ -package google +package cloudfunctions import ( "reflect" diff --git a/mmv1/third_party/tgc/composer_environment.go b/mmv1/third_party/tgc/services/composer/composer_environment.go similarity index 99% rename from mmv1/third_party/tgc/composer_environment.go rename to mmv1/third_party/tgc/services/composer/composer_environment.go index fff555854d56..16963eefa237 100644 --- a/mmv1/third_party/tgc/composer_environment.go +++ b/mmv1/third_party/tgc/services/composer/composer_environment.go @@ -1,4 +1,4 @@ -package google +package composer import ( "reflect" @@ -11,7 +11,7 @@ import ( const ComposerEnvironmentAssetType string = "composer.googleapis.com/Environment" -func resourceConverterComposerEnvironment() cai.ResourceConverter { +func ResourceConverterComposerEnvironment() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ComposerEnvironmentAssetType, Convert: GetComposerEnvironmentCaiObject, diff --git a/mmv1/third_party/tgc/commitment.go b/mmv1/third_party/tgc/services/compute/commitment.go similarity index 99% rename from mmv1/third_party/tgc/commitment.go rename to mmv1/third_party/tgc/services/compute/commitment.go index 26bb7d47de5d..a7dc1bff682c 100644 --- a/mmv1/third_party/tgc/commitment.go +++ b/mmv1/third_party/tgc/services/compute/commitment.go @@ -1,4 +1,4 @@ -package google +package compute import ( "reflect" @@ -10,7 +10,7 @@ import ( const commitmentAssetType string = "compute.googleapis.com/Commitment" -func resourceConverterCommitment() cai.ResourceConverter { +func ResourceConverterCommitment() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: commitmentAssetType, Convert: GetCommitmentCaiObject, @@ -152,14 +152,14 @@ func GetCommitmentApiObject(d tpgresource.TerraformResourceData, config *transpo } else if v, ok := d.GetOkExists("start_timestamp"); !tpgresource.IsEmptyValue(reflect.ValueOf(statusMessageProp)) && (ok || !reflect.DeepEqual(v, statusMessageProp)) { obj["startTimestamp"] = startTimestampProp } - + endTimestampProp, err := expandCommitmentEndTimestamp(d.Get("end_timestamp"), d, config) if err != nil { return nil, err } else if v, ok := d.GetOkExists("end_timestamp"); !tpgresource.IsEmptyValue(reflect.ValueOf(endTimestampProp)) && (ok || !reflect.DeepEqual(v, endTimestampProp)) { obj["endTimestamp"] = endTimestampProp } - + selfLinkProp, err := expandCommitmentSelfLink(d.Get("self_link"), d, config) if err != nil { return nil, err @@ -323,4 +323,4 @@ func expandCommitmentPlan(v interface{}, d tpgresource.TerraformResourceData, co func expandCommitmentName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil -} \ No newline at end of file +} diff --git a/mmv1/third_party/tgc/compute_instance.go.tmpl b/mmv1/third_party/tgc/services/compute/compute_instance.go.tmpl similarity index 100% rename from mmv1/third_party/tgc/compute_instance.go.tmpl rename to mmv1/third_party/tgc/services/compute/compute_instance.go.tmpl diff --git a/mmv1/third_party/tgc/compute_instance_group.go b/mmv1/third_party/tgc/services/compute/compute_instance_group.go similarity index 98% rename from mmv1/third_party/tgc/compute_instance_group.go rename to mmv1/third_party/tgc/services/compute/compute_instance_group.go index a7916bc32832..5d6896143ccd 100644 --- a/mmv1/third_party/tgc/compute_instance_group.go +++ b/mmv1/third_party/tgc/services/compute/compute_instance_group.go @@ -1,4 +1,4 @@ -package google +package compute import ( "reflect" @@ -10,7 +10,7 @@ import ( const ComputeInstanceGroupAssetType string = "compute.googleapis.com/InstanceGroup" -func resourceConverterComputeInstanceGroup() cai.ResourceConverter { +func ResourceConverterComputeInstanceGroup() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ComputeInstanceGroupAssetType, Convert: GetComputeInstanceGroupCaiObject, @@ -80,7 +80,7 @@ func GetComputeInstanceGroupApiObject(d tpgresource.TerraformResourceData, confi } url = url + zoneProp.(string) - obj["zone"] = url + obj["zone"] = url } selfLinkProp, err := expandComputeInstanceGroupSelfLink(d.Get("self_link"), d, config) if err != nil { @@ -152,4 +152,4 @@ func expandComputeInstanceGroupRegion(v interface{}, d tpgresource.TerraformReso func expandComputeInstanceGroupSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil -} \ No newline at end of file +} diff --git a/mmv1/third_party/tgc/compute_security_policy.go b/mmv1/third_party/tgc/services/compute/compute_security_policy.go similarity index 99% rename from mmv1/third_party/tgc/compute_security_policy.go rename to mmv1/third_party/tgc/services/compute/compute_security_policy.go index 7107d175c41f..f9a1829cf2c0 100644 --- a/mmv1/third_party/tgc/compute_security_policy.go +++ b/mmv1/third_party/tgc/services/compute/compute_security_policy.go @@ -1,4 +1,4 @@ -package google +package compute import ( "reflect" @@ -11,7 +11,7 @@ import ( const ComputeSecurityPolicyAssetType string = "compute.googleapis.com/SecurityPolicy" -func resourceConverterComputeSecurityPolicy() cai.ResourceConverter { +func ResourceConverterComputeSecurityPolicy() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ComputeSecurityPolicyAssetType, Convert: GetComputeSecurityPolicyCaiObject, diff --git a/mmv1/third_party/tgc/compute_target_pool.go b/mmv1/third_party/tgc/services/compute/compute_target_pool.go similarity index 98% rename from mmv1/third_party/tgc/compute_target_pool.go rename to mmv1/third_party/tgc/services/compute/compute_target_pool.go index 60a5e28b8a8a..0174c0015586 100644 --- a/mmv1/third_party/tgc/compute_target_pool.go +++ b/mmv1/third_party/tgc/services/compute/compute_target_pool.go @@ -1,4 +1,4 @@ -package google +package compute import ( "reflect" @@ -11,7 +11,7 @@ import ( const ComputeTargetPoolAssetType string = "compute.googleapis.com/TargetPool" -func resourceConverterComputeTargetPool() cai.ResourceConverter { +func ResourceConverterComputeTargetPool() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ComputeTargetPoolAssetType, Convert: GetComputeTargetPoolCaiObject, diff --git a/mmv1/third_party/tgc/container.go b/mmv1/third_party/tgc/services/container/container.go similarity index 99% rename from mmv1/third_party/tgc/container.go rename to mmv1/third_party/tgc/services/container/container.go index 4c7caa378740..6da99c3da38f 100644 --- a/mmv1/third_party/tgc/container.go +++ b/mmv1/third_party/tgc/services/container/container.go @@ -4,7 +4,7 @@ // see https://github.com/GoogleCloudPlatform/magic-modules/pull/2485#issuecomment-545680059 // for the discussion. -package google +package container import ( "fmt" @@ -19,14 +19,14 @@ import ( const ContainerClusterAssetType string = "container.googleapis.com/Cluster" const ContainerNodePoolAssetType string = "container.googleapis.com/NodePool" -func resourceConverterContainerCluster() cai.ResourceConverter { +func ResourceConverterContainerCluster() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ContainerClusterAssetType, Convert: GetContainerClusterCaiObject, } } -func resourceConverterContainerNodePool() cai.ResourceConverter { +func ResourceConverterContainerNodePool() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ContainerNodePoolAssetType, Convert: GetContainerNodePoolCaiObject, diff --git a/mmv1/third_party/tgc/job.go b/mmv1/third_party/tgc/services/dataflow/job.go similarity index 99% rename from mmv1/third_party/tgc/job.go rename to mmv1/third_party/tgc/services/dataflow/job.go index 94cac92463cd..4675769fbbc9 100644 --- a/mmv1/third_party/tgc/job.go +++ b/mmv1/third_party/tgc/services/dataflow/job.go @@ -1,4 +1,4 @@ -package google +package dataflow import ( "reflect" @@ -10,7 +10,7 @@ import ( const DataflowJobAssetType string = "dataflow.googleapis.com/Job" -func resourceDataflowJob() cai.ResourceConverter { +func ResourceDataflowJob() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: DataflowJobAssetType, Convert: GetDataflowJobCaiObject, @@ -302,4 +302,4 @@ func expandDataflowRuntimeUpdatableParams(v interface{}, d tpgresource.Terraform func expandDataflowSatisfiesPzi(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil -} \ No newline at end of file +} diff --git a/mmv1/third_party/tgc/dataproc_cluster.go b/mmv1/third_party/tgc/services/dataproc/dataproc_cluster.go similarity index 99% rename from mmv1/third_party/tgc/dataproc_cluster.go rename to mmv1/third_party/tgc/services/dataproc/dataproc_cluster.go index e33b8134617a..5cd634a35ed0 100644 --- a/mmv1/third_party/tgc/dataproc_cluster.go +++ b/mmv1/third_party/tgc/services/dataproc/dataproc_cluster.go @@ -1,4 +1,4 @@ -package google +package dataproc import ( "reflect" @@ -11,7 +11,7 @@ import ( const DataprocClusterAssetType string = "dataproc.googleapis.com/Cluster" -func resourceConverterDataprocCluster() cai.ResourceConverter { +func ResourceConverterDataprocCluster() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: DataprocClusterAssetType, Convert: GetDataprocClusterCaiObject, diff --git a/mmv1/third_party/tgc/firebase_project.go b/mmv1/third_party/tgc/services/firebase/firebase_project.go similarity index 97% rename from mmv1/third_party/tgc/firebase_project.go rename to mmv1/third_party/tgc/services/firebase/firebase_project.go index 28b469278020..7e553f6f0e93 100644 --- a/mmv1/third_party/tgc/firebase_project.go +++ b/mmv1/third_party/tgc/services/firebase/firebase_project.go @@ -1,4 +1,4 @@ -package google +package firebase import ( "reflect" @@ -10,7 +10,7 @@ import ( const firebaseProjectAssetType string = "firebase.googleapis.com/FirebaseProject" -func resourceConverterFirebaseProject() cai.ResourceConverter { +func ResourceConverterFirebaseProject() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: firebaseProjectAssetType, Convert: GetFirebaseProjectCaiObject, @@ -40,7 +40,7 @@ func GetFirebaseProjectCaiObject(d tpgresource.TerraformResourceData, config *tr func GetFirebaseProjectApiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { obj := make(map[string]interface{}) - + nameProp, err := expandFirebaseProjectName(d.Get("name"), d, config) if err != nil { return nil, err @@ -102,4 +102,4 @@ func expandFirebaseProjectProjectId(v interface{}, d tpgresource.TerraformResour func expandFirebaseProjectName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil -} \ No newline at end of file +} diff --git a/mmv1/third_party/tgc/kms_crypto_key_iam.go b/mmv1/third_party/tgc/services/kms/kms_crypto_key_iam.go similarity index 95% rename from mmv1/third_party/tgc/kms_crypto_key_iam.go rename to mmv1/third_party/tgc/services/kms/kms_crypto_key_iam.go index 201cef86cfc5..2690a120e94d 100644 --- a/mmv1/third_party/tgc/kms_crypto_key_iam.go +++ b/mmv1/third_party/tgc/services/kms/kms_crypto_key_iam.go @@ -1,4 +1,4 @@ -package google +package kms import ( "fmt" @@ -10,7 +10,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterKmsCryptoKeyIamPolicy() cai.ResourceConverter { +func ResourceConverterKmsCryptoKeyIamPolicy() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudkms.googleapis.com/CryptoKey", Convert: GetKmsCryptoKeyIamPolicyCaiObject, @@ -18,7 +18,7 @@ func resourceConverterKmsCryptoKeyIamPolicy() cai.ResourceConverter { } } -func resourceConverterKmsCryptoKeyIamBinding() cai.ResourceConverter { +func ResourceConverterKmsCryptoKeyIamBinding() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudkms.googleapis.com/CryptoKey", Convert: GetKmsCryptoKeyIamBindingCaiObject, @@ -28,7 +28,7 @@ func resourceConverterKmsCryptoKeyIamBinding() cai.ResourceConverter { } } -func resourceConverterKmsCryptoKeyIamMember() cai.ResourceConverter { +func ResourceConverterKmsCryptoKeyIamMember() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudkms.googleapis.com/CryptoKey", Convert: GetKmsCryptoKeyIamMemberCaiObject, diff --git a/mmv1/third_party/tgc/kms_key_ring_iam.go b/mmv1/third_party/tgc/services/kms/kms_key_ring_iam.go similarity index 95% rename from mmv1/third_party/tgc/kms_key_ring_iam.go rename to mmv1/third_party/tgc/services/kms/kms_key_ring_iam.go index 57404f81445c..6197ed499a99 100644 --- a/mmv1/third_party/tgc/kms_key_ring_iam.go +++ b/mmv1/third_party/tgc/services/kms/kms_key_ring_iam.go @@ -1,4 +1,4 @@ -package google +package kms import ( "fmt" @@ -10,7 +10,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterKmsKeyRingIamPolicy() cai.ResourceConverter { +func ResourceConverterKmsKeyRingIamPolicy() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudkms.googleapis.com/KeyRing", Convert: GetKmsKeyRingIamPolicyCaiObject, @@ -18,7 +18,7 @@ func resourceConverterKmsKeyRingIamPolicy() cai.ResourceConverter { } } -func resourceConverterKmsKeyRingIamBinding() cai.ResourceConverter { +func ResourceConverterKmsKeyRingIamBinding() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudkms.googleapis.com/KeyRing", Convert: GetKmsKeyRingIamBindingCaiObject, @@ -28,7 +28,7 @@ func resourceConverterKmsKeyRingIamBinding() cai.ResourceConverter { } } -func resourceConverterKmsKeyRingIamMember() cai.ResourceConverter { +func ResourceConverterKmsKeyRingIamMember() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudkms.googleapis.com/KeyRing", Convert: GetKmsKeyRingIamMemberCaiObject, diff --git a/mmv1/third_party/tgc/logging_billing_account_bucket_config.go b/mmv1/third_party/tgc/services/logging/logging_billing_account_bucket_config.go similarity index 98% rename from mmv1/third_party/tgc/logging_billing_account_bucket_config.go rename to mmv1/third_party/tgc/services/logging/logging_billing_account_bucket_config.go index 741e11a59bb5..6a1dae39b162 100644 --- a/mmv1/third_party/tgc/logging_billing_account_bucket_config.go +++ b/mmv1/third_party/tgc/services/logging/logging_billing_account_bucket_config.go @@ -1,4 +1,4 @@ -package google +package logging import ( "reflect" @@ -12,7 +12,7 @@ import ( const logBillingAccountBucketAssetType string = "logging.googleapis.com/LogBucket" -func resourceConverterLogBillingAccountBucket() cai.ResourceConverter { +func ResourceConverterLogBillingAccountBucket() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: logBillingAccountBucketAssetType, Convert: GetLogBillingAccountBucketCaiObject, diff --git a/mmv1/third_party/tgc/logging_folder_bucket_config.go b/mmv1/third_party/tgc/services/logging/logging_folder_bucket_config.go similarity index 98% rename from mmv1/third_party/tgc/logging_folder_bucket_config.go rename to mmv1/third_party/tgc/services/logging/logging_folder_bucket_config.go index 564fc2555c9c..b2c0e2703069 100644 --- a/mmv1/third_party/tgc/logging_folder_bucket_config.go +++ b/mmv1/third_party/tgc/services/logging/logging_folder_bucket_config.go @@ -1,4 +1,4 @@ -package google +package logging import ( "reflect" @@ -12,7 +12,7 @@ import ( const logFolderBucketAssetType string = "logging.googleapis.com/LogBucket" -func resourceConverterLogFolderBucket() cai.ResourceConverter { +func ResourceConverterLogFolderBucket() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: logFolderBucketAssetType, Convert: GetLogFolderBucketCaiObject, diff --git a/mmv1/third_party/tgc/logging_organization_bucket_config.go b/mmv1/third_party/tgc/services/logging/logging_organization_bucket_config.go similarity index 98% rename from mmv1/third_party/tgc/logging_organization_bucket_config.go rename to mmv1/third_party/tgc/services/logging/logging_organization_bucket_config.go index c617d961665d..a4de258d99fe 100644 --- a/mmv1/third_party/tgc/logging_organization_bucket_config.go +++ b/mmv1/third_party/tgc/services/logging/logging_organization_bucket_config.go @@ -1,4 +1,4 @@ -package google +package logging import ( "reflect" @@ -12,7 +12,7 @@ import ( const logOrganizationBucketAssetType string = "logging.googleapis.com/LogBucket" -func resourceConverterLogOrganizationBucket() cai.ResourceConverter { +func ResourceConverterLogOrganizationBucket() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: logOrganizationBucketAssetType, Convert: GetLogOrganizationBucketCaiObject, diff --git a/mmv1/third_party/tgc/logging_project_bucket_config.go b/mmv1/third_party/tgc/services/logging/logging_project_bucket_config.go similarity index 98% rename from mmv1/third_party/tgc/logging_project_bucket_config.go rename to mmv1/third_party/tgc/services/logging/logging_project_bucket_config.go index 77e96884a679..6db9b4fee0d7 100644 --- a/mmv1/third_party/tgc/logging_project_bucket_config.go +++ b/mmv1/third_party/tgc/services/logging/logging_project_bucket_config.go @@ -1,4 +1,4 @@ -package google +package logging import ( "reflect" @@ -12,7 +12,7 @@ import ( const logProjectBucketAssetType string = "logging.googleapis.com/LogBucket" -func resourceConverterLogProjectBucket() cai.ResourceConverter { +func ResourceConverterLogProjectBucket() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: logProjectBucketAssetType, Convert: GetLogProjectBucketCaiObject, diff --git a/mmv1/third_party/tgc/monitoring_slo_helper.go b/mmv1/third_party/tgc/services/monitoring/monitoring_slo_helper.go similarity index 100% rename from mmv1/third_party/tgc/monitoring_slo_helper.go rename to mmv1/third_party/tgc/services/monitoring/monitoring_slo_helper.go diff --git a/mmv1/third_party/tgc/pubsub_subscription_iam.go b/mmv1/third_party/tgc/services/pubsub/pubsub_subscription_iam.go similarity index 100% rename from mmv1/third_party/tgc/pubsub_subscription_iam.go rename to mmv1/third_party/tgc/services/pubsub/pubsub_subscription_iam.go diff --git a/mmv1/third_party/tgc/folder.go b/mmv1/third_party/tgc/services/resourcemanager/folder.go similarity index 95% rename from mmv1/third_party/tgc/folder.go rename to mmv1/third_party/tgc/services/resourcemanager/folder.go index cdcf1b5644ba..3dd43c056b6f 100644 --- a/mmv1/third_party/tgc/folder.go +++ b/mmv1/third_party/tgc/services/resourcemanager/folder.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "time" @@ -8,7 +8,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterFolder() cai.ResourceConverter { +func ResourceConverterFolder() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudresourcemanager.googleapis.com/Folder", Convert: GetFolderCaiObject, diff --git a/mmv1/third_party/tgc/folder_iam.go b/mmv1/third_party/tgc/services/resourcemanager/folder_iam.go similarity index 100% rename from mmv1/third_party/tgc/folder_iam.go rename to mmv1/third_party/tgc/services/resourcemanager/folder_iam.go diff --git a/mmv1/third_party/tgc/folder_organization_policy.go b/mmv1/third_party/tgc/services/resourcemanager/folder_organization_policy.go similarity index 95% rename from mmv1/third_party/tgc/folder_organization_policy.go rename to mmv1/third_party/tgc/services/resourcemanager/folder_organization_policy.go index 275743e35f47..16a50cefe6b4 100644 --- a/mmv1/third_party/tgc/folder_organization_policy.go +++ b/mmv1/third_party/tgc/services/resourcemanager/folder_organization_policy.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" @@ -6,7 +6,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterFolderOrgPolicy() cai.ResourceConverter { +func ResourceConverterFolderOrgPolicy() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudresourcemanager.googleapis.com/Folder", Convert: GetFolderOrgPolicyCaiObject, diff --git a/mmv1/third_party/tgc/org_policy_policy.go b/mmv1/third_party/tgc/services/resourcemanager/org_policy_policy.go similarity index 91% rename from mmv1/third_party/tgc/org_policy_policy.go rename to mmv1/third_party/tgc/services/resourcemanager/org_policy_policy.go index bf14d9a52050..26773f65a4b0 100644 --- a/mmv1/third_party/tgc/org_policy_policy.go +++ b/mmv1/third_party/tgc/services/resourcemanager/org_policy_policy.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "fmt" @@ -9,7 +9,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterOrgPolicyPolicy() cai.ResourceConverter { +func ResourceConverterOrgPolicyPolicy() cai.ResourceConverter { return cai.ResourceConverter{ Convert: GetV2OrgPoliciesCaiObject, MergeCreateUpdate: MergeV2OrgPolicies, @@ -150,8 +150,8 @@ func expandValuesPolicyRule(configured []interface{}) (*cai.StringValues, error) } valuesMap := configured[0].(map[string]interface{}) return &cai.StringValues{ - AllowedValues: convertInterfaceToStringArray(valuesMap["allowed_values"].([]interface{})), - DeniedValues: convertInterfaceToStringArray(valuesMap["denied_values"].([]interface{})), + AllowedValues: cai.ConvertInterfaceToStringArray(valuesMap["allowed_values"].([]interface{})), + DeniedValues: cai.ConvertInterfaceToStringArray(valuesMap["denied_values"].([]interface{})), }, nil } @@ -177,11 +177,3 @@ func convertStringToBool(val string) (bool, error) { return false, fmt.Errorf("Invalid value for a boolean field: %s", val) } - -func convertInterfaceToStringArray(values []interface{}) []string { - stringArray := make([]string, len(values)) - for i, v := range values { - stringArray[i] = v.(string) - } - return stringArray -} diff --git a/mmv1/third_party/tgc/organization_iam.go b/mmv1/third_party/tgc/services/resourcemanager/organization_iam.go similarity index 100% rename from mmv1/third_party/tgc/organization_iam.go rename to mmv1/third_party/tgc/services/resourcemanager/organization_iam.go diff --git a/mmv1/third_party/tgc/organization_iam_custom_role.go b/mmv1/third_party/tgc/services/resourcemanager/organization_iam_custom_role.go similarity index 97% rename from mmv1/third_party/tgc/organization_iam_custom_role.go rename to mmv1/third_party/tgc/services/resourcemanager/organization_iam_custom_role.go index 439975955708..65bab3d118f7 100644 --- a/mmv1/third_party/tgc/organization_iam_custom_role.go +++ b/mmv1/third_party/tgc/services/resourcemanager/organization_iam_custom_role.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "reflect" @@ -11,7 +11,7 @@ import ( const OrganizationIAMCustomRoleAssetType string = "iam.googleapis.com/Role" -func resourceConverterOrganizationIAMCustomRole() cai.ResourceConverter { +func ResourceConverterOrganizationIAMCustomRole() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: OrganizationIAMCustomRoleAssetType, Convert: GetOrganizationIAMCustomRoleCaiObject, diff --git a/mmv1/third_party/tgc/organization_policy.go b/mmv1/third_party/tgc/services/resourcemanager/organization_policy.go similarity index 95% rename from mmv1/third_party/tgc/organization_policy.go rename to mmv1/third_party/tgc/services/resourcemanager/organization_policy.go index 123689001755..0d894cc1367d 100644 --- a/mmv1/third_party/tgc/organization_policy.go +++ b/mmv1/third_party/tgc/services/resourcemanager/organization_policy.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" @@ -6,7 +6,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterOrganizationPolicy() cai.ResourceConverter { +func ResourceConverterOrganizationPolicy() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudresourcemanager.googleapis.com/Organization", Convert: GetOrganizationPolicyCaiObject, diff --git a/mmv1/third_party/tgc/project.go b/mmv1/third_party/tgc/services/resourcemanager/project.go similarity index 96% rename from mmv1/third_party/tgc/project.go rename to mmv1/third_party/tgc/services/resourcemanager/project.go index 9f33a8a95d8d..c43fc4426bd6 100644 --- a/mmv1/third_party/tgc/project.go +++ b/mmv1/third_party/tgc/services/resourcemanager/project.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "fmt" @@ -11,7 +11,7 @@ import ( "google.golang.org/api/cloudresourcemanager/v1" ) -func resourceConverterProject() cai.ResourceConverter { +func ResourceConverterProject() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudresourcemanager.googleapis.com/Project", Convert: GetProjectCaiObject, @@ -19,7 +19,7 @@ func resourceConverterProject() cai.ResourceConverter { } } -func resourceConverterProjectBillingInfo() cai.ResourceConverter { +func ResourceConverterProjectBillingInfo() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudbilling.googleapis.com/ProjectBillingInfo", Convert: GetProjectBillingInfoCaiObject, diff --git a/mmv1/third_party/tgc/project_iam.go b/mmv1/third_party/tgc/services/resourcemanager/project_iam.go similarity index 100% rename from mmv1/third_party/tgc/project_iam.go rename to mmv1/third_party/tgc/services/resourcemanager/project_iam.go diff --git a/mmv1/third_party/tgc/project_iam_custom_role.go b/mmv1/third_party/tgc/services/resourcemanager/project_iam_custom_role.go similarity index 97% rename from mmv1/third_party/tgc/project_iam_custom_role.go rename to mmv1/third_party/tgc/services/resourcemanager/project_iam_custom_role.go index e16bbcc15dc7..21188a195512 100644 --- a/mmv1/third_party/tgc/project_iam_custom_role.go +++ b/mmv1/third_party/tgc/services/resourcemanager/project_iam_custom_role.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "reflect" @@ -11,7 +11,7 @@ import ( const ProjectIAMCustomRoleAssetType string = "iam.googleapis.com/Role" -func resourceConverterProjectIAMCustomRole() cai.ResourceConverter { +func ResourceConverterProjectIAMCustomRole() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ProjectIAMCustomRoleAssetType, Convert: GetProjectIAMCustomRoleCaiObject, diff --git a/mmv1/third_party/tgc/project_organization_policy.go b/mmv1/third_party/tgc/services/resourcemanager/project_organization_policy.go similarity index 97% rename from mmv1/third_party/tgc/project_organization_policy.go rename to mmv1/third_party/tgc/services/resourcemanager/project_organization_policy.go index 16a9b73f7568..a9f14545f7da 100644 --- a/mmv1/third_party/tgc/project_organization_policy.go +++ b/mmv1/third_party/tgc/services/resourcemanager/project_organization_policy.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "fmt" @@ -10,7 +10,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) -func resourceConverterProjectOrgPolicy() cai.ResourceConverter { +func ResourceConverterProjectOrgPolicy() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: "cloudresourcemanager.googleapis.com/Project", Convert: GetProjectOrgPolicyCaiObject, diff --git a/mmv1/third_party/tgc/project_service.go b/mmv1/third_party/tgc/services/resourcemanager/project_service.go similarity index 96% rename from mmv1/third_party/tgc/project_service.go rename to mmv1/third_party/tgc/services/resourcemanager/project_service.go index 50eeae0ba462..8babed065d8f 100644 --- a/mmv1/third_party/tgc/project_service.go +++ b/mmv1/third_party/tgc/services/resourcemanager/project_service.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "fmt" @@ -11,7 +11,7 @@ import ( const ServiceUsageAssetType string = "serviceusage.googleapis.com/Service" -func resourceConverterServiceUsage() cai.ResourceConverter { +func ResourceConverterServiceUsage() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ServiceUsageAssetType, Convert: GetServiceUsageCaiObject, diff --git a/mmv1/third_party/tgc/project_service_test.go b/mmv1/third_party/tgc/services/resourcemanager/project_service_test.go similarity index 99% rename from mmv1/third_party/tgc/project_service_test.go rename to mmv1/third_party/tgc/services/resourcemanager/project_service_test.go index 0b4e9957ae53..4b87b25f78eb 100644 --- a/mmv1/third_party/tgc/project_service_test.go +++ b/mmv1/third_party/tgc/services/resourcemanager/project_service_test.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "testing" diff --git a/mmv1/third_party/tgc/service_account.go b/mmv1/third_party/tgc/services/resourcemanager/service_account.go similarity index 98% rename from mmv1/third_party/tgc/service_account.go rename to mmv1/third_party/tgc/services/resourcemanager/service_account.go index b9cc14038515..d3f7509ee184 100644 --- a/mmv1/third_party/tgc/service_account.go +++ b/mmv1/third_party/tgc/services/resourcemanager/service_account.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "fmt" @@ -11,7 +11,7 @@ import ( const ServiceAccountAssetType string = "iam.googleapis.com/ServiceAccount" -func resourceConverterServiceAccount() cai.ResourceConverter { +func ResourceConverterServiceAccount() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ServiceAccountAssetType, Convert: GetServiceAccountCaiObject, diff --git a/mmv1/third_party/tgc/service_account_key.go b/mmv1/third_party/tgc/services/resourcemanager/service_account_key.go similarity index 99% rename from mmv1/third_party/tgc/service_account_key.go rename to mmv1/third_party/tgc/services/resourcemanager/service_account_key.go index c62b3b14f8a3..7835ea49dcc0 100644 --- a/mmv1/third_party/tgc/service_account_key.go +++ b/mmv1/third_party/tgc/services/resourcemanager/service_account_key.go @@ -1,4 +1,4 @@ -package google +package resourcemanager import ( "reflect" @@ -10,7 +10,7 @@ import ( const ServiceAccountKeyAssetType string = "iam.googleapis.com/ServiceAccountKey" -func resourceConverterServiceAccountKey() cai.ResourceConverter { +func ResourceConverterServiceAccountKey() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: ServiceAccountKeyAssetType, Convert: GetServiceAccountKeyCaiObject, diff --git a/mmv1/third_party/tgc/spanner_database_iam.go b/mmv1/third_party/tgc/services/spanner/spanner_database_iam.go similarity index 100% rename from mmv1/third_party/tgc/spanner_database_iam.go rename to mmv1/third_party/tgc/services/spanner/spanner_database_iam.go diff --git a/mmv1/third_party/tgc/spanner_instance_iam.go b/mmv1/third_party/tgc/services/spanner/spanner_instance_iam.go similarity index 100% rename from mmv1/third_party/tgc/spanner_instance_iam.go rename to mmv1/third_party/tgc/services/spanner/spanner_instance_iam.go diff --git a/mmv1/third_party/tgc/sql_database_instance.go b/mmv1/third_party/tgc/services/sql/sql_database_instance.go similarity index 99% rename from mmv1/third_party/tgc/sql_database_instance.go rename to mmv1/third_party/tgc/services/sql/sql_database_instance.go index 3903b31f2c98..baeccda26768 100644 --- a/mmv1/third_party/tgc/sql_database_instance.go +++ b/mmv1/third_party/tgc/services/sql/sql_database_instance.go @@ -6,7 +6,7 @@ // third_party/terraform/resources/resource_sql_database_instance.go.erb.go // // ---------------------------------------------------------------------------- -package google +package sql import ( "regexp" @@ -22,7 +22,7 @@ import ( const SQLDatabaseInstanceAssetType string = "sqladmin.googleapis.com/Instance" -func resourceConverterSQLDatabaseInstance() cai.ResourceConverter { +func ResourceConverterSQLDatabaseInstance() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: SQLDatabaseInstanceAssetType, Convert: GetSQLDatabaseInstanceCaiObject, diff --git a/mmv1/third_party/tgc/iam_storage_bucket.go b/mmv1/third_party/tgc/services/storage/iam_storage_bucket.go similarity index 99% rename from mmv1/third_party/tgc/iam_storage_bucket.go rename to mmv1/third_party/tgc/services/storage/iam_storage_bucket.go index 44b1ce92a569..57258ff0466d 100644 --- a/mmv1/third_party/tgc/iam_storage_bucket.go +++ b/mmv1/third_party/tgc/services/storage/iam_storage_bucket.go @@ -1,4 +1,4 @@ -package google +package storage import ( "fmt" diff --git a/mmv1/third_party/tgc/storage_bucket.go b/mmv1/third_party/tgc/services/storage/storage_bucket.go similarity index 99% rename from mmv1/third_party/tgc/storage_bucket.go rename to mmv1/third_party/tgc/services/storage/storage_bucket.go index 1bacf205a812..3bd3f4ae4b53 100644 --- a/mmv1/third_party/tgc/storage_bucket.go +++ b/mmv1/third_party/tgc/services/storage/storage_bucket.go @@ -6,7 +6,7 @@ // third_party/terraform/resources/resource_storage_bucket.go // // ---------------------------------------------------------------------------- -package google +package storage import ( "fmt" @@ -21,7 +21,7 @@ import ( const StorageBucketAssetType string = "storage.googleapis.com/Bucket" -func resourceConverterStorageBucket() cai.ResourceConverter { +func ResourceConverterStorageBucket() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: StorageBucketAssetType, Convert: GetStorageBucketCaiObject, diff --git a/mmv1/third_party/tgc/storage_bucket_iam.go b/mmv1/third_party/tgc/services/storage/storage_bucket_iam.go similarity index 94% rename from mmv1/third_party/tgc/storage_bucket_iam.go rename to mmv1/third_party/tgc/services/storage/storage_bucket_iam.go index f88e54c5d908..6ced5b8c67d9 100644 --- a/mmv1/third_party/tgc/storage_bucket_iam.go +++ b/mmv1/third_party/tgc/services/storage/storage_bucket_iam.go @@ -1,4 +1,4 @@ -package google +package storage import ( "fmt" @@ -11,7 +11,7 @@ import ( // Provide a separate asset type constant so we don't have to worry about name conflicts between IAM and non-IAM converter files const StorageBucketIAMAssetType string = "storage.googleapis.com/Bucket" -func resourceConverterStorageBucketIamPolicy() cai.ResourceConverter { +func ResourceConverterStorageBucketIamPolicy() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: StorageBucketIAMAssetType, Convert: GetStorageBucketIamPolicyCaiObject, @@ -19,7 +19,7 @@ func resourceConverterStorageBucketIamPolicy() cai.ResourceConverter { } } -func resourceConverterStorageBucketIamBinding() cai.ResourceConverter { +func ResourceConverterStorageBucketIamBinding() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: StorageBucketIAMAssetType, Convert: GetStorageBucketIamBindingCaiObject, @@ -29,7 +29,7 @@ func resourceConverterStorageBucketIamBinding() cai.ResourceConverter { } } -func resourceConverterStorageBucketIamMember() cai.ResourceConverter { +func ResourceConverterStorageBucketIamMember() cai.ResourceConverter { return cai.ResourceConverter{ AssetType: StorageBucketIAMAssetType, Convert: GetStorageBucketIamMemberCaiObject, diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json index bdc3d1f93e56..2fa16e2aee4f 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json @@ -48,8 +48,9 @@ "pushConfig": { "pushEndpoint": "https://example.com/push" }, + "retryPolicy": null, "topic": "projects/{{.Provider.project}}/topics/example-pubsub-topic" } } } -] \ No newline at end of file +] diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json index dd012c01a7af..7a753fb0f81a 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json @@ -20,6 +20,7 @@ "pushConfig": { "pushEndpoint": "https://example.com/push" }, + "retryPolicy": null, "topic": "projects/{{.Provider.project}}/topics/example-pubsub-topic" } }, @@ -34,4 +35,4 @@ ] } } -] \ No newline at end of file +] diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json index dd012c01a7af..7a753fb0f81a 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json @@ -20,6 +20,7 @@ "pushConfig": { "pushEndpoint": "https://example.com/push" }, + "retryPolicy": null, "topic": "projects/{{.Provider.project}}/topics/example-pubsub-topic" } }, @@ -34,4 +35,4 @@ ] } } -] \ No newline at end of file +] diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json index dd012c01a7af..7a753fb0f81a 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json +++ b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json @@ -20,6 +20,7 @@ "pushConfig": { "pushEndpoint": "https://example.com/push" }, + "retryPolicy": null, "topic": "projects/{{.Provider.project}}/topics/example-pubsub-topic" } }, @@ -34,4 +35,4 @@ ] } } -] \ No newline at end of file +] diff --git a/tpgtools/ignored_handwritten/common_custom_diff.go b/tpgtools/ignored_handwritten/common_custom_diff.go index 6b7130f42bcf..2ef403d0887e 100644 --- a/tpgtools/ignored_handwritten/common_custom_diff.go +++ b/tpgtools/ignored_handwritten/common_custom_diff.go @@ -44,8 +44,8 @@ func resourceComputeSubnetworkSecondaryIpRangeSetStyleDiff(diff *schema.Resource if count < 1 { return nil } - old := make([]interface{}, count) - new := make([]interface{}, count) + old := make([]interface{}, 0, count) + new := make([]interface{}, 0, count) for i := 0; i < count; i++ { o, n := diff.GetChange(fmt.Sprintf("secondary_ip_range.%d", i))