diff --git a/.ci/gcb-generate-diffs-new.yml b/.ci/gcb-generate-diffs-new.yml index f7ce66daa77b..d432871fe8a8 100644 --- a/.ci/gcb-generate-diffs-new.yml +++ b/.ci/gcb-generate-diffs-new.yml @@ -202,45 +202,45 @@ steps: - "17" # Build step # remove after 08/2023 - terraform-google-conversion # remove after 08/2023 - - name: 'gcr.io/graphite-docker-images/go-plus' - id: tgc-test-integration-0.12.31 - entrypoint: '/workspace/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh' - allowFailure: true - secretEnv: ["GITHUB_TOKEN"] - waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] - env: - - TERRAFORM_VERSION=0.12.31 - - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT - - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER - - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY - - TEST_ORG_ID=$_VALIDATOR_TEST_ORG - args: - - $_PR_NUMBER - - $COMMIT_SHA - - $BUILD_ID - - $PROJECT_ID - - "18" # Build step - - terraform-google-conversion + # - name: 'gcr.io/graphite-docker-images/go-plus' + # id: tgc-test-integration-0.12.31 + # entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh' + # allowFailure: true + # secretEnv: ["GITHUB_TOKEN"] + # waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] + # env: + # - TERRAFORM_VERSION=0.12.31 + # - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT + # - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER + # - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY + # - TEST_ORG_ID=$_VALIDATOR_TEST_ORG + # args: + # - $_PR_NUMBER + # - $COMMIT_SHA + # - $BUILD_ID + # - $PROJECT_ID + # - "18" # Build step + # - terraform-google-conversion - - name: 'gcr.io/graphite-docker-images/go-plus' - id: tgc-test-integration-0.13.7 - entrypoint: '/workspace/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh' - allowFailure: true - secretEnv: ["GITHUB_TOKEN"] - waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] - env: - - TERRAFORM_VERSION=0.13.7 - - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT - - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER - - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY - - TEST_ORG_ID=$_VALIDATOR_TEST_ORG - args: - - $_PR_NUMBER - - $COMMIT_SHA - - $BUILD_ID - - $PROJECT_ID - - "19" # Build step - - terraform-google-conversion + # - name: 'gcr.io/graphite-docker-images/go-plus' + # id: tgc-test-integration-0.13.7 + # entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh' + # allowFailure: true + # secretEnv: ["GITHUB_TOKEN"] + # waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] + # env: + # - TERRAFORM_VERSION=0.13.7 + # - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT + # - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER + # - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY + # - TEST_ORG_ID=$_VALIDATOR_TEST_ORG + # args: + # - $_PR_NUMBER + # - $COMMIT_SHA + # - $BUILD_ID + # - $PROJECT_ID + # - "19" # Build step + # - terraform-google-conversion - name: 'gcr.io/graphite-docker-images/go-plus' id: tpgb-test diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index 250738ae5808..b1aec1d4d2d8 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -242,7 +242,6 @@ module "project-services" { "firebasestorage.googleapis.com", "firestore.googleapis.com", "firestorekeyvisualizer.googleapis.com", - "gameservices.googleapis.com", "gkebackup.googleapis.com", "gkeconnect.googleapis.com", "gkehub.googleapis.com", diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 3b975c2bd0c0..f586196428d3 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -201,6 +201,10 @@ module Properties # mmv1/templates/terraform/state_migrations/ # used for maintaining state stability with resources first provisioned on older api versions. attr_reader :schema_version + # From this schema version on, state_upgrader code is generated for the resource. + # When unset, state_upgrade_base_schema_version defauts to 0. + # Normally, it is not needed to be set. + attr_reader :state_upgrade_base_schema_version attr_reader :state_upgraders # This block inserts the named function and its attribute into the # resource schema -- the code for the migrate_state function must @@ -217,6 +221,10 @@ module Properties # public ca external account keys attr_reader :skip_read + # Set to true for resources that wish to disable automatic generation of default provider + # value customdiff functions + attr_reader :skip_default_cdiff + # This enables resources that get their project via a reference to a different resource # instead of a project field to use User Project Overrides attr_reader :supports_indirect_user_project_override @@ -318,10 +326,12 @@ def validate check :error_retry_predicates, type: Array, item_type: String check :error_abort_predicates, type: Array, item_type: String check :schema_version, type: Integer + check :state_upgrade_base_schema_version, type: Integer, default: 0 check :state_upgraders, type: :boolean, default: false check :migrate_state, type: String check :skip_delete, type: :boolean, default: false check :skip_read, type: :boolean, default: false + check :skip_default_cdiff, type: :boolean, default: false check :supports_indirect_user_project_override, type: :boolean, default: false check :legacy_long_form_project, type: :boolean, default: false check :read_error_transform, type: String @@ -342,6 +352,10 @@ def all_properties ((@properties || []) + (@parameters || [])) end + def properties_with_excluded + @properties || [] + end + def properties (@properties || []).reject(&:exclude) end @@ -385,8 +399,13 @@ def all_resourcerefs # At Create, they have no value but they can just be read in anyways, and after a Read # they will need to be set in every Update. def settable_properties - all_user_properties.reject { |v| v.output && !v.is_a?(Api::Type::Fingerprint) } - .reject(&:url_param_only) + props = all_user_properties.reject do |v| + v.output && !v.is_a?(Api::Type::Fingerprint) && !v.is_a?(Api::Type::KeyValueEffectiveLabels) + end + props = props.reject(&:url_param_only) + props.reject do |v| + v.is_a?(Api::Type::KeyValueLabels) || v.is_a?(Api::Type::KeyValueAnnotations) + end end # Properties that will be returned in the API body @@ -439,6 +458,102 @@ def decoder? !@transport&.decoder.nil? end + def add_labels_related_fields(props, parent) + props.each do |p| + if p.is_a? Api::Type::KeyValueLabels + add_labels_fields(props, parent, p) + elsif p.is_a? Api::Type::KeyValueAnnotations + add_annotations_fields(props, parent, p) + elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? + p.properties = add_labels_related_fields(p.all_properties, p) + end + end + props + end + + def add_labels_fields(props, parent, labels) + # The effective_labels field is used to write to API, instead of the labels field. + labels.ignore_write = true + labels.description = "#{labels.description}\n\n#{get_labels_field_note(labels.name)}" + + @custom_diff ||= [] + if parent.nil? || parent.flatten_object + @custom_diff.append('tpgresource.SetLabelsDiff') + elsif parent.name == 'metadata' + @custom_diff.append('tpgresource.SetMetadataLabelsDiff') + end + + props << build_terraform_labels_field('labels', labels.field_min_version) + props << build_effective_labels_field('labels', labels) + end + + def add_annotations_fields(props, parent, annotations) + # The effective_annotations field is used to write to API, + # instead of the annotations field. + annotations.ignore_write = true + + @custom_diff ||= [] + if parent.nil? + @custom_diff.append('tpgresource.SetAnnotationsDiff') + elsif parent.name == 'metadata' + @custom_diff.append('tpgresource.SetMetadataAnnotationsDiff') + end + + props << build_effective_labels_field('annotations', annotations) + end + + def build_effective_labels_field(name, labels) + description = "All of #{name} (key/value pairs)\ + present on the resource in GCP, including the #{name} configured through Terraform,\ + other clients and services." + + Api::Type::KeyValueEffectiveLabels.new( + name: "effective#{name.capitalize}", + output: true, + api_name: name, + description:, + min_version: labels.field_min_version, + update_verb: labels.update_verb, + update_url: labels.update_url, + immutable: labels.immutable + ) + end + + def build_terraform_labels_field(name, min_version) + description = "The combination of #{name} configured directly on the resource + and default #{name} configured on the provider." + + Api::Type::KeyValueTerraformLabels.new( + name: "terraform#{name.capitalize}", + output: true, + api_name: name, + description:, + min_version:, + ignore_write: true + ) + end + + # Return labels fields that should be added to ImportStateVerifyIgnore + def ignore_read_labels_fields(props) + fields = [] + props.each do |p| + if (p.is_a? Api::Type::KeyValueLabels) || + (p.is_a? Api::Type::KeyValueTerraformLabels) || + (p.is_a? Api::Type::KeyValueAnnotations) + fields << p.terraform_lineage + elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? + fields.concat(ignore_read_labels_fields(p.all_properties)) + end + end + fields + end + + def get_labels_field_note(title) + "**Note**: This field is non-authoritative, and will only manage the #{title} present " \ +"in your configuration. +Please refer to the field `effective_#{title}` for all of the #{title} present on the resource." + end + # ==================== # Version-related methods # ==================== diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index 2d0900b1fd7d..130cd2cec617 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -23,7 +23,7 @@ module Fields include Api::Object::Named::Properties attr_reader :default_value - attr_reader :description + attr_accessor :description attr_reader :exclude # Add a deprecation message for a field that's been deprecated in the API @@ -266,6 +266,14 @@ def lineage "#{__parent.lineage}.#{name&.underscore}" end + # Prints the access path of the field in the configration eg: metadata.0.labels + # The only intended purpose is to get the value of the labes field by calling d.Get(). + def terraform_lineage + return name&.underscore if __parent.nil? || __parent.flatten_object + + "#{__parent.terraform_lineage}.0.#{name&.underscore}" + end + def to_json(opts = nil) # ignore fields that will contain references to parent resources and # those which will be added later @@ -728,6 +736,8 @@ def properties @properties.reject(&:exclude) end + attr_writer :properties + def nested_properties properties end @@ -755,6 +765,64 @@ def exclude_if_not_in_version!(version) # simpler property to generate and means we can avoid conditional logic # in Map. class KeyValuePairs < Composite + # Ignore writing the "effective_labels" and "effective_annotations" fields to API. + attr_accessor :ignore_write + + def initialize(name: nil, output: nil, api_name: nil, description: nil, min_version: nil, + ignore_write: nil, update_verb: nil, update_url: nil, immutable: nil) + super() + + @name = name + @output = output + @api_name = api_name + @description = description + @min_version = min_version + @ignore_write = ignore_write + @update_verb = update_verb + @update_url = update_url + @immutable = immutable + end + + def validate + super + check :ignore_write, type: :boolean, default: false + end + + def field_min_version + @min_version + end + end + + # An array of string -> string key -> value pairs used specifically for the "labels" field. + # The field name with this type should be "labels" literally. + class KeyValueLabels < KeyValuePairs + def validate + super + return unless @name != 'labels' + + raise "The field #{name} has the type KeyValueLabels, but the field name is not 'labels'!" + end + end + + # An array of string -> string key -> value pairs used for the "terraform_labels" field. + class KeyValueTerraformLabels < KeyValuePairs + end + + # An array of string -> string key -> value pairs used for the "effective_labels" + # and "effective_annotations" fields. + class KeyValueEffectiveLabels < KeyValuePairs + end + + # An array of string -> string key -> value pairs used specifically for the "annotations" field. + # The field name with this type should be "annotations" literally. + class KeyValueAnnotations < KeyValuePairs + def validate + super + return unless @name != 'annotations' + + raise "The field #{name} has the type KeyValueAnnotations,\ + but the field name is not 'annotations'!" + end end # Map from string keys -> nested object entries diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 6d451cbe7acb..ce996b679641 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -224,6 +224,9 @@ end res_yaml = File.read(file_path) resource = Api::Compiler.new(res_yaml).run + resource.properties = resource.add_labels_related_fields( + resource.properties_with_excluded, nil + ) resource.validate resources.push(resource) end diff --git a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml index 96c2bf0b5b86..dfeb24421dbf 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml @@ -157,6 +157,7 @@ properties: - status.0.access_levels - status.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'accessLevels' description: | @@ -175,6 +176,7 @@ properties: - status.0.access_levels - status.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'restrictedServices' description: | @@ -236,6 +238,7 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' item_type: Api::Type::String + is_set: true description: | A list of identities that are allowed access through this ingress policy. Should be in the format of email address. The email address should represent @@ -275,6 +278,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, protected by this `ServicePerimeter` @@ -348,6 +352,7 @@ properties: A list of identities that are allowed access through this `EgressPolicy`. Should be in the format of email address. The email address should represent individual user or service account only. + is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::NestedObject name: 'egressTo' @@ -357,6 +362,7 @@ properties: properties: - !ruby/object:Api::Type::Array name: 'resources' + is_set: true item_type: Api::Type::String description: | A list of resources, currently only projects in the form @@ -366,6 +372,7 @@ properties: the perimeter. - !ruby/object:Api::Type::Array name: 'externalResources' + is_set: true item_type: Api::Type::String description: | A list of external resources that are allowed to be accessed. A request @@ -423,6 +430,7 @@ properties: - spec.0.access_levels - spec.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'accessLevels' description: | @@ -441,6 +449,7 @@ properties: - spec.0.access_levels - spec.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'restrictedServices' description: | @@ -454,6 +463,7 @@ properties: - spec.0.access_levels - spec.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'vpcAccessibleServices' description: | @@ -471,6 +481,7 @@ properties: The list of APIs usable within the Service Perimeter. Must be empty unless `enableRestriction` is True. item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'ingressPolicies' description: | @@ -500,6 +511,7 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' item_type: Api::Type::String + is_set: true description: | A list of identities that are allowed access through this ingress policy. Should be in the format of email address. The email address should represent @@ -539,6 +551,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, protected by this `ServicePerimeter` @@ -613,6 +626,7 @@ properties: Should be in the format of email address. The email address should represent individual user or service account only. item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'egressTo' description: | @@ -622,6 +636,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, that match this to stanza. A request matches @@ -631,6 +646,7 @@ properties: - !ruby/object:Api::Type::Array name: 'externalResources' item_type: Api::Type::String + is_set: true description: | A list of external resources that are allowed to be accessed. A request matches if it contains an external resource in this list (Example: diff --git a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml index 72a41e289a0d..e4fb6867a3ca 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml @@ -57,7 +57,6 @@ properties: name: 'servicePerimeters' description: | The desired Service Perimeters that should replace all existing Service Perimeters in the Access Policy. - is_set: true item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::String @@ -133,6 +132,7 @@ properties: # - status.0.access_levels # - status.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'accessLevels' description: | @@ -153,6 +153,7 @@ properties: # - status.0.access_levels # - status.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'restrictedServices' description: | @@ -194,6 +195,7 @@ properties: have multiple `IngressPolicies`, each of which is evaluated separately. Access is granted if any `Ingress Policy` grants it. Must be empty for a perimeter bridge. + is_set: true item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::NestedObject @@ -215,6 +217,7 @@ properties: - :ANY_SERVICE_ACCOUNT - !ruby/object:Api::Type::Array name: 'identities' + is_set: true item_type: Api::Type::String description: | A list of identities that are allowed access through this ingress policy. @@ -255,6 +258,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, protected by this `ServicePerimeter` @@ -328,6 +332,7 @@ properties: A list of identities that are allowed access through this `EgressPolicy`. Should be in the format of email address. The email address should represent individual user or service account only. + is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::NestedObject name: 'egressTo' @@ -338,6 +343,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, that match this to stanza. A request matches @@ -347,6 +353,7 @@ properties: - !ruby/object:Api::Type::Array name: 'externalResources' item_type: Api::Type::String + is_set: true description: | A list of external resources that are allowed to be accessed. A request matches if it contains an external resource in this list (Example: @@ -404,9 +411,11 @@ properties: # - spec.0.resources # - spec.0.access_levels # - spec.0.restricted_services + is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::Array name: 'accessLevels' + is_set: true description: | A list of AccessLevel resource names that allow resources within the ServicePerimeter to be accessed from the internet. @@ -440,6 +449,7 @@ properties: # - spec.0.access_levels # - spec.0.restricted_services item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'vpcAccessibleServices' description: | @@ -457,6 +467,7 @@ properties: The list of APIs usable within the Service Perimeter. Must be empty unless `enableRestriction` is True. item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::Array name: 'ingressPolicies' description: | @@ -485,6 +496,7 @@ properties: - :ANY_SERVICE_ACCOUNT - !ruby/object:Api::Type::Array name: 'identities' + is_set: true item_type: Api::Type::String description: | A list of identities that are allowed access through this ingress policy. @@ -525,6 +537,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, protected by this `ServicePerimeter` @@ -599,6 +612,7 @@ properties: Should be in the format of email address. The email address should represent individual user or service account only. item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'egressTo' description: | @@ -608,6 +622,7 @@ properties: - !ruby/object:Api::Type::Array name: 'resources' item_type: Api::Type::String + is_set: true description: | A list of resources, currently only projects in the form `projects/`, that match this to stanza. A request matches @@ -617,6 +632,7 @@ properties: - !ruby/object:Api::Type::Array name: 'externalResources' item_type: Api::Type::String + is_set: true description: | A list of external resources that are allowed to be accessed. A request matches if it contains an external resource in this list (Example: diff --git a/mmv1/products/activedirectory/Domain.yaml b/mmv1/products/activedirectory/Domain.yaml index 8b0cc3e78b33..7ca646ef3565 100644 --- a/mmv1/products/activedirectory/Domain.yaml +++ b/mmv1/products/activedirectory/Domain.yaml @@ -85,7 +85,7 @@ properties: description: 'The unique name of the domain using the format: `projects/{project}/locations/global/domains/{domainName}`.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Resource labels that can contain user-provided metadata' - !ruby/object:Api::Type::Array diff --git a/mmv1/products/activedirectory/Peering.yaml b/mmv1/products/activedirectory/Peering.yaml index b98c94b7ac59..b760bb8ef788 100644 --- a/mmv1/products/activedirectory/Peering.yaml +++ b/mmv1/products/activedirectory/Peering.yaml @@ -73,7 +73,7 @@ properties: output: true description: | Unique name of the peering in this scope including projects and location using the form: projects/{projectId}/locations/global/peerings/{peeringId}. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Resource labels that can contain user-provided metadata' - !ruby/object:Api::Type::String diff --git a/mmv1/products/alloydb/Backup.yaml b/mmv1/products/alloydb/Backup.yaml index ca21f23e49c9..454e5a5c779a 100644 --- a/mmv1/products/alloydb/Backup.yaml +++ b/mmv1/products/alloydb/Backup.yaml @@ -42,8 +42,6 @@ examples: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' network_name: 'alloydb-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-basic")' ignore_read_extra: - 'reconciling' - 'update_time' @@ -55,8 +53,6 @@ examples: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' network_name: 'alloydb-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-full")' ignore_read_extra: - 'reconciling' - 'update_time' diff --git a/mmv1/products/alloydb/Cluster.yaml b/mmv1/products/alloydb/Cluster.yaml index b405a8a765b2..35567507d078 100644 --- a/mmv1/products/alloydb/Cluster.yaml +++ b/mmv1/products/alloydb/Cluster.yaml @@ -106,7 +106,7 @@ properties: output: true description: | The system-generated UID of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the alloydb cluster.' - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/alloydb/Instance.yaml b/mmv1/products/alloydb/Instance.yaml index e3a5ae2a9371..e17e9286b905 100644 --- a/mmv1/products/alloydb/Instance.yaml +++ b/mmv1/products/alloydb/Instance.yaml @@ -57,8 +57,6 @@ examples: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' network_name: 'alloydb-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-instance-basic")' ignore_read_extra: - 'reconciling' - 'update_time' @@ -101,10 +99,10 @@ properties: output: true description: | The system-generated UID of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the alloydb instance.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: 'Annotations to allow client tools to store small amount of arbitrary diff --git a/mmv1/products/apigateway/ApiConfig.yaml b/mmv1/products/apigateway/ApiConfig.yaml index 2c795186cbed..da35b85703d9 100644 --- a/mmv1/products/apigateway/ApiConfig.yaml +++ b/mmv1/products/apigateway/ApiConfig.yaml @@ -120,7 +120,7 @@ properties: output: true description: | The ID of the associated Service Config (https://cloud.google.com/service-infrastructure/docs/glossary#config). - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/apigateway/ApiResource.yaml b/mmv1/products/apigateway/ApiResource.yaml index f295dd636fee..93ae56e5e75b 100644 --- a/mmv1/products/apigateway/ApiResource.yaml +++ b/mmv1/products/apigateway/ApiResource.yaml @@ -87,7 +87,7 @@ properties: name: 'createTime' description: Creation timestamp in RFC3339 text format. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/apigateway/Gateway.yaml b/mmv1/products/apigateway/Gateway.yaml index 5ce68c7f3315..9dc7b3b17b02 100644 --- a/mmv1/products/apigateway/Gateway.yaml +++ b/mmv1/products/apigateway/Gateway.yaml @@ -102,7 +102,7 @@ properties: description: The default API Gateway host name of the form {gatewayId}-{hash}.{region_code}.gateway.dev. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/artifactregistry/Repository.yaml b/mmv1/products/artifactregistry/Repository.yaml index 4af5b1c90516..3d509db50b00 100644 --- a/mmv1/products/artifactregistry/Repository.yaml +++ b/mmv1/products/artifactregistry/Repository.yaml @@ -143,7 +143,7 @@ properties: name: description description: |- The user-provided description of the repository. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels with user-defined metadata. diff --git a/mmv1/products/beyondcorp/AppConnection.yaml b/mmv1/products/beyondcorp/AppConnection.yaml index 215bac419709..1ebf2c7368fb 100644 --- a/mmv1/products/beyondcorp/AppConnection.yaml +++ b/mmv1/products/beyondcorp/AppConnection.yaml @@ -88,7 +88,7 @@ properties: name: 'displayName' description: | An arbitrary user-provided name for the AppConnection. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user provided metadata. diff --git a/mmv1/products/beyondcorp/AppConnector.yaml b/mmv1/products/beyondcorp/AppConnector.yaml index 20a6b3a11bcc..fb8e23bedbf6 100644 --- a/mmv1/products/beyondcorp/AppConnector.yaml +++ b/mmv1/products/beyondcorp/AppConnector.yaml @@ -82,7 +82,7 @@ properties: name: 'displayName' description: | An arbitrary user-provided name for the AppConnector. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user provided metadata. diff --git a/mmv1/products/beyondcorp/AppGateway.yaml b/mmv1/products/beyondcorp/AppGateway.yaml index 1eda5d9eeefe..7d6fc2fc42fe 100644 --- a/mmv1/products/beyondcorp/AppGateway.yaml +++ b/mmv1/products/beyondcorp/AppGateway.yaml @@ -98,7 +98,7 @@ properties: name: 'displayName' description: | An arbitrary user-provided name for the AppGateway. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user provided metadata. diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index 7cd95a4eb7f1..41c0fbf1491d 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -290,12 +290,11 @@ properties: name: 'friendlyName' description: A descriptive name for the dataset send_empty_value: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The labels associated with this dataset. You can use these to - organize and group your datasets - default_from_api: true + organize and group your datasets. - !ruby/object:Api::Type::Integer name: 'lastModifiedTime' description: | diff --git a/mmv1/products/bigquery/Job.yaml b/mmv1/products/bigquery/Job.yaml index cf12ae9fdf3d..016f76d03a72 100644 --- a/mmv1/products/bigquery/Job.yaml +++ b/mmv1/products/bigquery/Job.yaml @@ -168,7 +168,7 @@ properties: name: 'jobTimeoutMs' description: | Job timeout in milliseconds. If this time limit is exceeded, BigQuery may attempt to terminate the job. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The labels associated with this job. You can use these to organize and group your jobs. diff --git a/mmv1/products/bigquery/Routine.yaml b/mmv1/products/bigquery/Routine.yaml index 054100c13ee9..7e57fd7dd1fb 100644 --- a/mmv1/products/bigquery/Routine.yaml +++ b/mmv1/products/bigquery/Routine.yaml @@ -76,6 +76,7 @@ properties: - !ruby/object:Api::Type::Enum name: 'routineType' immutable: true + required: true description: The type of routine. values: - :SCALAR_FUNCTION diff --git a/mmv1/products/bigquery/Table.yaml b/mmv1/products/bigquery/Table.yaml index 5b0d92ec3f9b..6913bf4f2dbc 100644 --- a/mmv1/products/bigquery/Table.yaml +++ b/mmv1/products/bigquery/Table.yaml @@ -88,7 +88,7 @@ properties: name: 'id' description: 'An opaque ID uniquely identifying the table.' output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The labels associated with this dataset. You can use these to diff --git a/mmv1/products/billing/ProjectInfo.yaml b/mmv1/products/billing/ProjectInfo.yaml index b55634709d98..e941f6aaaee7 100644 --- a/mmv1/products/billing/ProjectInfo.yaml +++ b/mmv1/products/billing/ProjectInfo.yaml @@ -28,11 +28,12 @@ custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/billing_project_info.go.erb test_check_destroy: templates/terraform/custom_check_destroy/billing_project_info.go.erb import_format: - ['projects/{{project}}', '{{project}}'] + ['projects/{{%project}}', '{{%project}}'] examples: - !ruby/object:Provider::Terraform::Examples name: 'billing_project_info_basic' primary_resource_id: 'default' + skip_import_test: true test_env_vars: billing_account: :BILLING_ACCT org_id: :ORG_ID diff --git a/mmv1/products/certificatemanager/Certificate.yaml b/mmv1/products/certificatemanager/Certificate.yaml index 552364c08bba..a2cee514e99d 100644 --- a/mmv1/products/certificatemanager/Certificate.yaml +++ b/mmv1/products/certificatemanager/Certificate.yaml @@ -95,7 +95,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the Certificate resource.' - !ruby/object:Api::Type::String diff --git a/mmv1/products/certificatemanager/CertificateIssuanceConfig.yaml b/mmv1/products/certificatemanager/CertificateIssuanceConfig.yaml index 6a994704207a..fa4cec9f21ac 100644 --- a/mmv1/products/certificatemanager/CertificateIssuanceConfig.yaml +++ b/mmv1/products/certificatemanager/CertificateIssuanceConfig.yaml @@ -109,7 +109,7 @@ properties: accurate to nanoseconds with up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | 'Set of label tags associated with the CertificateIssuanceConfig resource. diff --git a/mmv1/products/certificatemanager/CertificateMap.yaml b/mmv1/products/certificatemanager/CertificateMap.yaml index 1342e8344e46..96df010f7666 100644 --- a/mmv1/products/certificatemanager/CertificateMap.yaml +++ b/mmv1/products/certificatemanager/CertificateMap.yaml @@ -76,11 +76,10 @@ properties: accurate to nanoseconds with up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Set of labels associated with a Certificate Map resource. - default_from_api: true - !ruby/object:Api::Type::Array name: 'gclbTargets' description: | diff --git a/mmv1/products/certificatemanager/CertificateMapEntry.yaml b/mmv1/products/certificatemanager/CertificateMapEntry.yaml index 296e342a6920..aa1ac5d57570 100644 --- a/mmv1/products/certificatemanager/CertificateMapEntry.yaml +++ b/mmv1/products/certificatemanager/CertificateMapEntry.yaml @@ -92,13 +92,12 @@ properties: with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Set of labels associated with a Certificate Map Entry. An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. - default_from_api: true - !ruby/object:Api::Type::Array name: 'certificates' required: true diff --git a/mmv1/products/certificatemanager/DnsAuthorization.yaml b/mmv1/products/certificatemanager/DnsAuthorization.yaml index fa6e636e7691..bcb50c60c329 100644 --- a/mmv1/products/certificatemanager/DnsAuthorization.yaml +++ b/mmv1/products/certificatemanager/DnsAuthorization.yaml @@ -63,7 +63,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the DNS Authorization resource.' diff --git a/mmv1/products/certificatemanager/TrustConfig.yaml b/mmv1/products/certificatemanager/TrustConfig.yaml index d4ff25e5256c..d7395fa22948 100644 --- a/mmv1/products/certificatemanager/TrustConfig.yaml +++ b/mmv1/products/certificatemanager/TrustConfig.yaml @@ -84,7 +84,7 @@ properties: A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the trust config.' immutable: true diff --git a/mmv1/products/cloudbuild/BitbucketServerConfig.yaml b/mmv1/products/cloudbuild/BitbucketServerConfig.yaml index d8b2f2763209..bd8bdd316f70 100644 --- a/mmv1/products/cloudbuild/BitbucketServerConfig.yaml +++ b/mmv1/products/cloudbuild/BitbucketServerConfig.yaml @@ -64,8 +64,6 @@ examples: config_id: 'bbs-config' network_name: 'vpc-network' global_address_name: 'private-ip-alloc' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "peered-network")' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/cloudbuild_bitbucketserver_config.go.erb post_create: templates/terraform/post_create/cloudbuild_bitbucketserver_config.go.erb diff --git a/mmv1/products/cloudfunctions/CloudFunction.yaml b/mmv1/products/cloudfunctions/CloudFunction.yaml index ad310f7293ab..6ac2766e6ffe 100644 --- a/mmv1/products/cloudfunctions/CloudFunction.yaml +++ b/mmv1/products/cloudfunctions/CloudFunction.yaml @@ -129,7 +129,7 @@ properties: description: | The version identifier of the Cloud Function. Each deployment attempt results in a new version of a function being created. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs associated with this Cloud Function. diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index 69d5e04907b7..5b0a0ff36b0a 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -251,6 +251,7 @@ parameters: - !ruby/object:Api::Type::String name: 'location' immutable: true + required: true url_param_only: true description: The location of this cloud function. properties: @@ -629,7 +630,7 @@ properties: name: 'updateTime' output: true description: 'The last update timestamp of a Cloud Function.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs associated with this Cloud Function. diff --git a/mmv1/products/cloudiot/Device.yaml b/mmv1/products/cloudiot/Device.yaml deleted file mode 100644 index 6e893b5c3651..000000000000 --- a/mmv1/products/cloudiot/Device.yaml +++ /dev/null @@ -1,243 +0,0 @@ -# Copyright 2023 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. - ---- !ruby/object:Api::Resource -name: 'Device' -base_url: '{{registry}}/devices' -self_link: '{{registry}}/devices/{{name}}' -update_verb: :PATCH -update_mask: true -description: | - A Google Cloud IoT Core device. -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/iot/docs/' - api: 'https://cloud.google.com/iot/docs/reference/cloudiot/rest/' -import_format: ['{{%registry}}/devices/{{name}}'] -deprecation_message: >- - `google_cloudiot_device` is deprecated in the API. This resource will be removed in the next major release of the provider. -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_basic' - primary_resource_id: 'test-device' - vars: - cloudiot_device_name: 'cloudiot-device' - cloudiot_device_registry_name: 'cloudiot-device-registry' - test_env_vars: - project: :PROJECT_NAME - region: :REGION - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_full' - primary_resource_id: 'test-device' - vars: - cloudiot_device_name: 'cloudiot-device' - cloudiot_device_registry_name: 'cloudiot-device-registry' - test_env_vars: - project: :PROJECT_NAME - region: :REGION -parameters: - - !ruby/object:Api::Type::String - name: registry - immutable: true - url_param_only: true - required: true - description: | - The name of the device registry where this device should be created. -properties: - - !ruby/object:Api::Type::String - name: 'name' - immutable: true - required: true - description: | - A unique name for the resource. - api_name: 'id' - - !ruby/object:Api::Type::String - name: 'numId' - output: true - description: | - A server-defined unique numeric ID for the device. - This is a more compact way to identify devices, and it is globally unique. - - !ruby/object:Api::Type::Array - name: 'credentials' - description: | - The credentials used to authenticate this device. - max_size: 3 - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::Time - name: 'expirationTime' - description: | - The time at which this credential becomes invalid. - default_from_api: true - - !ruby/object:Api::Type::NestedObject - name: 'publicKey' - required: true - description: | - A public key used to verify the signature of JSON Web Tokens (JWTs). - properties: - - !ruby/object:Api::Type::Enum - name: 'format' - required: true - description: | - The format of the key. - values: - - :RSA_PEM - - :RSA_X509_PEM - - :ES256_PEM - - :ES256_X509_PEM - - !ruby/object:Api::Type::String - name: 'key' - required: true - description: | - The key data. - - !ruby/object:Api::Type::Time - name: 'lastHeartbeatTime' - output: true - description: | - The last time an MQTT PINGREQ was received. - - !ruby/object:Api::Type::Time - name: 'lastEventTime' - output: true - description: | - The last time a telemetry event was received. - - !ruby/object:Api::Type::Time - name: 'lastStateTime' - output: true - description: | - The last time a state event was received. - - !ruby/object:Api::Type::Time - name: 'lastConfigAckTime' - output: true - description: | - The last time a cloud-to-device config version acknowledgment was received from the device. - - !ruby/object:Api::Type::Time - name: 'lastConfigSendTime' - output: true - description: | - The last time a cloud-to-device config version was sent to the device. - - !ruby/object:Api::Type::Boolean - name: 'blocked' - description: | - If a device is blocked, connections or requests from this device will fail. - - !ruby/object:Api::Type::Time - name: 'lastErrorTime' - output: true - description: | - The time the most recent error occurred, such as a failure to publish to Cloud Pub/Sub. - - !ruby/object:Api::Type::NestedObject - name: 'lastErrorStatus' - output: true - description: | - The error message of the most recent error, such as a failure to publish to Cloud Pub/Sub. - properties: - - !ruby/object:Api::Type::Integer - name: 'number' - description: | - The status code, which should be an enum value of google.rpc.Code. - - !ruby/object:Api::Type::String - name: 'message' - description: | - A developer-facing error message, which should be in English. - - !ruby/object:Api::Type::Array - name: 'details' - description: | - A list of messages that carry the error details. - item_type: Api::Type::KeyValuePairs - - !ruby/object:Api::Type::NestedObject - name: 'config' - output: true - description: | - The most recent device configuration, which is eventually sent from Cloud IoT Core to the device. - properties: - - !ruby/object:Api::Type::String - name: 'version' - output: true - description: | - The version of this update. - - !ruby/object:Api::Type::String - name: 'cloudUpdateTime' - output: true - description: | - The time at which this configuration version was updated in Cloud IoT Core. - - !ruby/object:Api::Type::String - name: 'deviceAckTime' - output: true - description: | - The time at which Cloud IoT Core received the acknowledgment from the device, - indicating that the device has received this configuration version. - - !ruby/object:Api::Type::String - name: 'binaryData' - description: | - The device configuration data. - - !ruby/object:Api::Type::NestedObject - name: 'state' - output: true - description: | - The state most recently received from the device. - properties: - - !ruby/object:Api::Type::Time - name: 'updateTime' - description: | - The time at which this state version was updated in Cloud IoT Core. - - !ruby/object:Api::Type::String - name: 'binaryData' - description: | - The device state data. - - !ruby/object:Api::Type::Enum - name: 'logLevel' - allow_empty_object: true - description: | - The logging verbosity for device activity. - values: - - :NONE - - :ERROR - - :INFO - - :DEBUG - - !ruby/object:Api::Type::KeyValuePairs - name: 'metadata' - description: | - The metadata key-value pairs assigned to the device. - - !ruby/object:Api::Type::NestedObject - name: 'gatewayConfig' - description: | - Gateway-related configuration and state. - update_mask_fields: - - 'gateway_config.gateway_auth_method' - properties: - - !ruby/object:Api::Type::Enum - name: 'gatewayType' - default_value: :NON_GATEWAY - immutable: true - description: | - Indicates whether the device is a gateway. - values: - - :GATEWAY - - :NON_GATEWAY - - !ruby/object:Api::Type::Enum - name: 'gatewayAuthMethod' - description: | - Indicates whether the device is a gateway. - values: - - :ASSOCIATION_ONLY - - :DEVICE_AUTH_TOKEN_ONLY - - :ASSOCIATION_AND_DEVICE_AUTH_TOKEN - - !ruby/object:Api::Type::String - name: 'lastAccessedGatewayId' - output: true - description: | - The ID of the gateway the device accessed most recently. - - !ruby/object:Api::Type::Time - name: 'lastAccessedGatewayTime' - output: true - description: | - The most recent time at which the device accessed the gateway specified in last_accessed_gateway. diff --git a/mmv1/products/cloudiot/DeviceRegistry.yaml b/mmv1/products/cloudiot/DeviceRegistry.yaml deleted file mode 100644 index d879e925304d..000000000000 --- a/mmv1/products/cloudiot/DeviceRegistry.yaml +++ /dev/null @@ -1,174 +0,0 @@ -# Copyright 2023 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. - ---- !ruby/object:Api::Resource -name: 'DeviceRegistry' -base_url: 'projects/{{project}}/locations/{{region}}/registries' -self_link: 'projects/{{project}}/locations/{{region}}/registries/{{name}}' -update_verb: :PATCH -update_mask: true -description: | - A Google Cloud IoT Core device registry. -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/iot/docs/' - api: 'https://cloud.google.com/iot/docs/reference/cloudiot/rest/' -iam_policy: !ruby/object:Api::Resource::IamPolicy - method_name_separator: ':' - fetch_iam_policy_verb: :POST - parent_resource_attribute: 'name' - import_format: - [ - 'projects/{{project}}/locations/{{location}}/registries/{{name}}', - '{{name}}', - ] -legacy_name: 'google_cloudiot_registry' -import_format: ['{{project}}/locations/{{region}}/registries/{{name}}'] -id_format: 'projects/{{project}}/locations/{{region}}/registries/{{name}}' -custom_code: !ruby/object:Provider::Terraform::CustomCode - constants: templates/terraform/constants/cloudiot.go.erb - decoder: templates/terraform/decoders/cloudiot_device_registry.go.erb - encoder: templates/terraform/encoders/cloudiot_device_registry.go.erb - extra_schema_entry: templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb - pre_update: templates/terraform/pre_update/cloudiot_device_registry.go.erb -deprecation_message: >- - `google_cloudiot_registry` is deprecated in the API. This resource will be removed in the next major release of the provider. -docs: !ruby/object:Provider::Terraform::Docs - optional_properties: | - * `state_notification_config` - A PubSub topic to publish device state updates. - The structure is documented below. - - * `mqtt_config` - Activate or deactivate MQTT. - The structure is documented below. - - * `http_config` - Activate or deactivate HTTP. - The structure is documented below. - - * `credentials` - List of public key certificates to authenticate devices. - The structure is documented below. - - The `state_notification_config` block supports: - - * `pubsub_topic_name` - PubSub topic name to publish device state updates. - - The `mqtt_config` block supports: - - * `mqtt_enabled_state` - The field allows `MQTT_ENABLED` or `MQTT_DISABLED`. - - The `http_config` block supports: - - * `http_enabled_state` - The field allows `HTTP_ENABLED` or `HTTP_DISABLED`. - - The `credentials` block supports: - - * `public_key_certificate` - A public key certificate format and data. - - The `public_key_certificate` block supports: - - * `format` - The field allows only `X509_CERTIFICATE_PEM`. - - * `certificate` - The certificate data. -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_registry_basic' - primary_resource_id: 'test-registry' - primary_resource_name: "fmt.Sprintf(\"tf-test-cloudiot-registry%s\", - context[\"\ - random_suffix\"])" - vars: - cloudiot_registry_name: 'cloudiot-registry' - test_env_vars: - project: :PROJECT_NAME - region: :REGION - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_registry_single_event_notification_configs' - primary_resource_id: 'test-registry' - vars: - cloudiot_registry_name: 'cloudiot-registry' - cloudiot_device_telemetry_topic_name: 'default-telemetry' - test_env_vars: - project: :PROJECT_NAME - region: :REGION - - !ruby/object:Provider::Terraform::Examples - name: 'cloudiot_device_registry_full' - primary_resource_id: 'test-registry' - vars: - cloudiot_registry_name: 'cloudiot-registry' - cloudiot_device_status_topic_name: 'default-devicestatus' - cloudiot_device_telemetry_topic_name: 'default-telemetry' - cloudiot_additional_device_telemetry_topic_name: 'additional-telemetry' - cloudiot_subfolder_matches_additional_device_telemetry_topic: 'test/path' - test_env_vars: - project: :PROJECT_NAME - region: :REGION -parameters: - - !ruby/object:Api::Type::String - name: region - immutable: true - url_param_only: true - required: false - description: | - The region in which the created registry should reside. - If it is not provided, the provider region is used. - ignore_read: true - default_from_api: true -properties: - - !ruby/object:Api::Type::String - name: 'name' - immutable: true - required: true - description: | - A unique name for the resource, required by device registry. - api_name: 'id' - validation: !ruby/object:Provider::Terraform::Validation - function: 'ValidateCloudIotDeviceRegistryID' - - !ruby/object:Api::Type::Array - name: 'eventNotificationConfigs' - description: | - List of configurations for event notifications, such as PubSub topics - to publish device events to. - max_size: 10 - default_from_api: true - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'subfolderMatches' - description: | - If the subfolder name matches this string exactly, this - configuration will be used. The string must not include the - leading '/' character. If empty, all strings are matched. Empty - value can only be used for the last `event_notification_configs` - item. - validation: !ruby/object:Provider::Terraform::Validation - function: 'validateCloudIotDeviceRegistrySubfolderMatch' - - !ruby/object:Api::Type::String - name: 'pubsubTopicName' - required: true - description: | - PubSub topic name to publish device events. - diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' - - !ruby/object:Api::Type::Enum - name: 'logLevel' - default_value: :NONE - description: | - The default logging verbosity for activity from devices in this - registry. Specifies which events should be written to logs. For - example, if the LogLevel is ERROR, only events that terminate in - errors will be logged. LogLevel is inclusive; enabling INFO logging - will also enable ERROR logging. - values: - - :NONE - - :ERROR - - :INFO - - :DEBUG - diff_suppress_func: 'tpgresource.EmptyOrDefaultStringSuppress("NONE")' diff --git a/mmv1/products/cloudiot/product.yaml b/mmv1/products/cloudiot/product.yaml deleted file mode 100644 index 2539129f14da..000000000000 --- a/mmv1/products/cloudiot/product.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2020 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. - ---- !ruby/object:Api::Product -name: CloudIot -display_name: Cloud IoT Core -legacy_name: 'cloudiot' -versions: - - !ruby/object:Api::Product::Version - name: ga - base_url: https://cloudiot.googleapis.com/v1/ -scopes: - - https://www.googleapis.com/auth/cloudiot - - https://www.googleapis.com/auth/cloud-platform diff --git a/mmv1/products/cloudrun/DomainMapping.yaml b/mmv1/products/cloudrun/DomainMapping.yaml index 8eb9730a654c..82aa8c386dd3 100644 --- a/mmv1/products/cloudrun/DomainMapping.yaml +++ b/mmv1/products/cloudrun/DomainMapping.yaml @@ -42,6 +42,11 @@ custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: 'templates/terraform/encoders/cloud_run_domain_mapping.go.erb' decoder: 'templates/terraform/decoders/cloud_run.go.erb' constants: templates/terraform/constants/cloud_run_domain_mapping.go.erb +custom_diff: [ + 'hasMetadata', +] +state_upgraders: true +schema_version: 1 parameters: - !ruby/object:Api::Type::String name: location @@ -154,18 +159,16 @@ properties: default_value: :AUTOMATIC - !ruby/object:Api::Type::NestedObject name: metadata - required: true + default_from_api: true description: Metadata associated with this DomainMapping. properties: - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and routes. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels - default_from_api: true - diff_suppress_func: 'DomainMappingLabelDiffSuppress' - !ruby/object:Api::Type::Integer name: generation description: |- @@ -203,8 +206,8 @@ properties: In Cloud Run the namespace must be equal to either the project ID or project number. custom_flatten: templates/terraform/custom_flatten/set_to_project.go.erb - - !ruby/object:Api::Type::KeyValuePairs - name: annotations + - !ruby/object:Api::Type::KeyValueAnnotations + name: 'annotations' description: |- Annotations is a key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. More @@ -213,5 +216,3 @@ properties: **Note**: The Cloud Run API may add additional annotations that were not provided in your config. If terraform plan shows a diff where a server-side annotation is added, you can add it to your config or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field. - default_from_api: true - diff_suppress_func: 'cloudrunAnnotationDiffSuppress' diff --git a/mmv1/products/cloudrun/Service.yaml b/mmv1/products/cloudrun/Service.yaml index 1160362ab594..99dd210064f2 100644 --- a/mmv1/products/cloudrun/Service.yaml +++ b/mmv1/products/cloudrun/Service.yaml @@ -152,7 +152,9 @@ custom_code: !ruby/object:Provider::Terraform::CustomCode custom_diff: [ 'revisionNameCustomizeDiff', ] -schema_version: 1 +state_upgraders: true +state_upgrade_base_schema_version: 1 +schema_version: 2 parameters: - !ruby/object:Api::Type::String name: location @@ -240,7 +242,7 @@ properties: default_from_api: true properties: - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. @@ -279,7 +281,7 @@ properties: default_from_api: true custom_expand: 'templates/terraform/custom_expand/default_to_project.go.erb' - !ruby/object:Api::Type::KeyValuePairs - name: annotations + name: 'annotations' description: |- Annotations is a key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. More @@ -970,14 +972,12 @@ properties: and annotations. default_from_api: true properties: - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: |- Map of string keys and values that can be used to organize and categorize (scope and select) objects. May match selectors of replication controllers and routes. - default_from_api: true - diff_suppress_func: 'cloudrunLabelDiffSuppress' - !ruby/object:Api::Type::Integer name: generation description: |- @@ -1012,8 +1012,8 @@ properties: default_from_api: true custom_flatten: templates/terraform/custom_flatten/set_to_project.go.erb custom_expand: 'templates/terraform/custom_expand/default_to_project.go.erb' - - !ruby/object:Api::Type::KeyValuePairs - name: annotations + - !ruby/object:Api::Type::KeyValueAnnotations + name: 'annotations' description: |- Annotations is a key value map stored with a resource that may be set by external tools to store and retrieve arbitrary metadata. More @@ -1036,5 +1036,3 @@ properties: for the Service. For example, `"run.googleapis.com/ingress" = "all"`. - `run.googleapis.com/launch-stage` sets the [launch stage](https://cloud.google.com/run/docs/troubleshooting#launch-stage-validation) when a preview feature is used. For example, `"run.googleapis.com/launch-stage": "BETA"` - default_from_api: true - diff_suppress_func: 'cloudrunAnnotationDiffSuppress' diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index 64fe831df7e9..dbf6c5eb2708 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -136,7 +136,7 @@ properties: output: true description: | A number that monotonically increases every time the user modifies the desired state. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: |- Unstructured key value map that can be used to organize and categorize objects. User-provided labels are shared with Google's billing system, so they can be used to filter, or break down billing charges by team, component, @@ -144,8 +144,8 @@ properties: Cloud Run API v2 does not support labels with `run.googleapis.com`, `cloud.googleapis.com`, `serving.knative.dev`, or `autoscaling.knative.dev` namespaces, and they will be rejected. All system labels in v1 now have a corresponding field in v2 Job. - - !ruby/object:Api::Type::KeyValuePairs - name: "annotations" + - !ruby/object:Api::Type::KeyValueAnnotations + name: 'annotations' description: |- Unstructured key value map that may be set by external tools to store and arbitrary metadata. They are not queryable and should be preserved when modifying objects. @@ -236,7 +236,7 @@ properties: Cloud Run API v2 does not support labels with `run.googleapis.com`, `cloud.googleapis.com`, `serving.knative.dev`, or `autoscaling.knative.dev` namespaces, and they will be rejected. All system labels in v1 now have a corresponding field in v2 ExecutionTemplate. - !ruby/object:Api::Type::KeyValuePairs - name: "annotations" + name: 'annotations' description: |- Unstructured key value map that may be set by external tools to store and arbitrary metadata. They are not queryable and should be preserved when modifying objects. @@ -374,160 +374,6 @@ properties: name: 'workingDir' description: |- Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. - - !ruby/object:Api::Type::NestedObject - name: 'livenessProbe' - description: |- - Periodic probe of container liveness. Container will be restarted if the probe fails. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - This field is not supported in Cloud Run Job currently. - deprecation_message: >- - `liveness_probe` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API. - properties: - - !ruby/object:Api::Type::Integer - name: 'initialDelaySeconds' - description: |- - Number of seconds after the container has started before the probe is initiated. Defaults to 0 seconds. Minimum value is 0. Maximum value for liveness probe is 3600. Maximum value for startup probe is 240. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - default_value: 0 - - !ruby/object:Api::Type::Integer - name: 'timeoutSeconds' - description: |- - Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. Maximum value is 3600. Must be smaller than periodSeconds. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - default_value: 1 - - !ruby/object:Api::Type::Integer - name: 'periodSeconds' - description: |- - How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. Maximum value for liveness probe is 3600. Maximum value for startup probe is 240. Must be greater or equal than timeoutSeconds - default_value: 10 - - !ruby/object:Api::Type::Integer - name: 'failureThreshold' - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - default_value: 3 - - !ruby/object:Api::Type::NestedObject - name: 'httpGet' - description: |- - HTTPGet specifies the http request to perform. Exactly one of HTTPGet or TCPSocket must be specified. - send_empty_value: true - allow_empty_object: - true - # exactly_one_of: - # - template.0.template.0.containers.0.livenessProbe.0.httpGet - # - template.0.template.0.containers.0.livenessProbe.0.tcpSocket - properties: - - !ruby/object:Api::Type::String - name: 'path' - default_value: '/' - description: |- - Path to access on the HTTP server. Defaults to '/'. - - !ruby/object:Api::Type::Array - name: httpHeaders - description: |- - Custom headers to set in the request. HTTP allows repeated headers. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: name - required: true - description: |- - The header field name - - !ruby/object:Api::Type::String - name: value - description: |- - The header field value - default_value: '' - send_empty_value: true - - !ruby/object:Api::Type::NestedObject - name: 'tcpSocket' - description: |- - TCPSocket specifies an action involving a TCP port. Exactly one of HTTPGet or TCPSocket must be specified. - send_empty_value: true - allow_empty_object: - true - # exactly_one_of: - # - template.0.template.0.containers.0.livenessProbe.0.httpGet - # - template.0.template.0.containers.0.livenessProbe.0.tcpSocket - properties: - - !ruby/object:Api::Type::Integer - name: port - description: |- - Port number to access on the container. Must be in the range 1 to 65535. If not specified, defaults to 8080. - - !ruby/object:Api::Type::NestedObject - name: 'startupProbe' - description: |- - Startup probe of application within the container. All other probes are disabled if a startup probe is provided, until it succeeds. Container will not be added to service endpoints if the probe fails. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - This field is not supported in Cloud Run Job currently. - deprecation_message: >- - `startup_probe` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API. - default_from_api: true - properties: - - !ruby/object:Api::Type::Integer - name: 'initialDelaySeconds' - description: |- - Number of seconds after the container has started before the probe is initiated. Defaults to 0 seconds. Minimum value is 0. Maximum value for liveness probe is 3600. Maximum value for startup probe is 240. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - default_value: 0 - - !ruby/object:Api::Type::Integer - name: 'timeoutSeconds' - description: |- - Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. Maximum value is 3600. Must be smaller than periodSeconds. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes - default_value: 1 - - !ruby/object:Api::Type::Integer - name: 'periodSeconds' - description: |- - How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1. Maximum value for liveness probe is 3600. Maximum value for startup probe is 240. Must be greater or equal than timeoutSeconds - default_value: 10 - - !ruby/object:Api::Type::Integer - name: 'failureThreshold' - description: |- - Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1. - default_value: 3 - - !ruby/object:Api::Type::NestedObject - name: 'httpGet' - description: |- - HTTPGet specifies the http request to perform. Exactly one of HTTPGet or TCPSocket must be specified. - send_empty_value: true - allow_empty_object: - true - # exactly_one_of: - # - template.0.template.0.containers.startupProbe.0.httpGet - # - template.0.template.0.containers.startupProbe.0.tcpSocket - properties: - - !ruby/object:Api::Type::String - name: 'path' - default_value: '/' - description: |- - Path to access on the HTTP server. Defaults to '/'. - - !ruby/object:Api::Type::Array - name: 'httpHeaders' - description: |- - Custom headers to set in the request. HTTP allows repeated headers. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: name - required: true - description: |- - The header field name - - !ruby/object:Api::Type::String - name: value - description: |- - The header field value - default_value: '' - send_empty_value: true - - !ruby/object:Api::Type::NestedObject - name: 'tcpSocket' - description: |- - TCPSocket specifies an action involving a TCP port. Exactly one of HTTPGet or TCPSocket must be specified. - send_empty_value: true - allow_empty_object: - true - # exactly_one_of: - # - template.0.template.0.containers.startupProbe.0.httpGet - # - template.0.template.0.containers.startupProbe.0.tcpSocket - properties: - - !ruby/object:Api::Type::Integer - name: port - description: |- - Port number to access on the container. Must be in the range 1 to 65535. If not specified, defaults to 8080. - default_from_api: true - !ruby/object:Api::Type::Array name: 'volumes' description: |- diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index e51b29c9d7e2..743250b39386 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -152,7 +152,7 @@ properties: output: true description: | A number that monotonically increases every time the user modifies the desired state. Please note that unlike v1, this is an int64 value. As with most Google APIs, its JSON representation will be a string instead of an integer. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: |- Unstructured key value map that can be used to organize and categorize objects. User-provided labels are shared with Google's billing system, so they can be used to filter, or break down billing charges by team, component, @@ -160,7 +160,7 @@ properties: Cloud Run API v2 does not support labels with `run.googleapis.com`, `cloud.googleapis.com`, `serving.knative.dev`, or `autoscaling.knative.dev` namespaces, and they will be rejected. All system labels in v1 now have a corresponding field in v2 Service. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: |- Unstructured key value map that may be set by external tools to store and arbitrary metadata. They are not queryable and should be preserved when modifying objects. @@ -530,19 +530,6 @@ properties: The header field value default_value: '' send_empty_value: true - - !ruby/object:Api::Type::NestedObject - name: 'tcpSocket' - description: |- - TCPSocket specifies an action involving a TCP port. This field is not supported in liveness probe currently. - deprecation_message: >- - `tcp_socket` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API. - send_empty_value: true - allow_empty_object: true - properties: - - !ruby/object:Api::Type::Integer - name: port - description: |- - Port number to access on the container. Must be in the range 1 to 65535. If not specified, defaults to 8080. - !ruby/object:Api::Type::NestedObject name: grpc description: |- @@ -737,6 +724,7 @@ properties: description: |- The Cloud SQL instance connection names, as can be found in https://console.cloud.google.com/sql/instances. Visit https://cloud.google.com/sql/docs/mysql/connect-run for more information on how to connect Cloud SQL and Cloud Run. Format: {project}:{location}:{instance} item_type: Api::Type::String + is_set: true - !ruby/object:Api::Type::NestedObject name: 'emptyDir' description: |- diff --git a/mmv1/products/compute/Address.yaml b/mmv1/products/compute/Address.yaml index e013503a7882..43ac9b0420a6 100644 --- a/mmv1/products/compute/Address.yaml +++ b/mmv1/products/compute/Address.yaml @@ -194,7 +194,7 @@ properties: description: 'The URLs of the resources that are using this address.' item_type: Api::Type::String output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this address. A list of key->value pairs. diff --git a/mmv1/products/compute/Autoscaler.yaml b/mmv1/products/compute/Autoscaler.yaml index 7ac866fc040d..f62d4f9a1b99 100644 --- a/mmv1/products/compute/Autoscaler.yaml +++ b/mmv1/products/compute/Autoscaler.yaml @@ -84,6 +84,7 @@ parameters: URL of the zone where the instance group resides. required: false immutable: true + ignore_read: true default_from_api: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: @@ -363,6 +364,7 @@ properties: TimeSeries are returned upon the query execution, the autoscaler will sum their respective values to obtain its scaling value. min_version: beta + default_value: 'resource.type = gce_instance' - !ruby/object:Api::Type::NestedObject name: 'loadBalancingUtilization' description: | diff --git a/mmv1/products/compute/Disk.yaml b/mmv1/products/compute/Disk.yaml index 58935e9fa227..1a9893cd2d20 100644 --- a/mmv1/products/compute/Disk.yaml +++ b/mmv1/products/compute/Disk.yaml @@ -290,7 +290,7 @@ properties: name: 'lastDetachTimestamp' description: 'Last detach timestamp in RFC3339 text format.' output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this disk. A list of key->value pairs. diff --git a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml index c2cbb0524deb..0926037d8e30 100644 --- a/mmv1/products/compute/DiskResourcePolicyAttachment.yaml +++ b/mmv1/products/compute/DiskResourcePolicyAttachment.yaml @@ -77,6 +77,7 @@ parameters: description: 'A reference to the zone where the disk resides.' required: false url_param_only: true + ignore_read: true default_from_api: true properties: - !ruby/object:Api::Type::String diff --git a/mmv1/products/compute/ExternalVpnGateway.yaml b/mmv1/products/compute/ExternalVpnGateway.yaml index 7fd92d7952f3..271b0f23daee 100644 --- a/mmv1/products/compute/ExternalVpnGateway.yaml +++ b/mmv1/products/compute/ExternalVpnGateway.yaml @@ -63,7 +63,7 @@ properties: - !ruby/object:Api::Type::String name: 'description' description: 'An optional description of this resource.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Labels for the external VPN gateway resource.' update_verb: :POST diff --git a/mmv1/products/compute/ForwardingRule.yaml b/mmv1/products/compute/ForwardingRule.yaml index 138294268651..4c71441df58b 100644 --- a/mmv1/products/compute/ForwardingRule.yaml +++ b/mmv1/products/compute/ForwardingRule.yaml @@ -503,7 +503,7 @@ properties: send_empty_value: true update_verb: :PATCH update_url: projects/{{project}}/regions/{{region}}/forwardingRules/{{name}} - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this forwarding rule. A list of key->value pairs. diff --git a/mmv1/products/compute/GlobalAddress.yaml b/mmv1/products/compute/GlobalAddress.yaml index b5cd3bd89ca5..320460dc8f7f 100644 --- a/mmv1/products/compute/GlobalAddress.yaml +++ b/mmv1/products/compute/GlobalAddress.yaml @@ -86,7 +86,7 @@ properties: characters must be a dash, lowercase letter, or digit, except the last character, which cannot be a dash. required: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this address. A list of key->value pairs. diff --git a/mmv1/products/compute/GlobalForwardingRule.yaml b/mmv1/products/compute/GlobalForwardingRule.yaml index ee6df3585dfd..780dc6e8a562 100644 --- a/mmv1/products/compute/GlobalForwardingRule.yaml +++ b/mmv1/products/compute/GlobalForwardingRule.yaml @@ -296,7 +296,7 @@ properties: values: - :IPV4 - :IPV6 - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this forwarding rule. A list of key->value pairs. diff --git a/mmv1/products/compute/Image.yaml b/mmv1/products/compute/Image.yaml index 2c428d454187..622f1f43d7da 100644 --- a/mmv1/products/compute/Image.yaml +++ b/mmv1/products/compute/Image.yaml @@ -170,7 +170,7 @@ properties: The service account being used for the encryption request for the given KMS key. If absent, the Compute Engine default service account is used. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels to apply to this Image. update_verb: :POST diff --git a/mmv1/products/compute/Instance.yaml b/mmv1/products/compute/Instance.yaml index c8de201d2765..2c8b0c2671fd 100644 --- a/mmv1/products/compute/Instance.yaml +++ b/mmv1/products/compute/Instance.yaml @@ -295,7 +295,7 @@ properties: internally during updates. update_url: 'projects/{{project}}/zones/{{zone}}/instances/{{name}}/setLabels' update_verb: :POST - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this instance. A list of key->value pairs. diff --git a/mmv1/products/compute/InstanceGroupNamedPort.yaml b/mmv1/products/compute/InstanceGroupNamedPort.yaml index 2cc5e2a69e49..be2ae5f63aa8 100644 --- a/mmv1/products/compute/InstanceGroupNamedPort.yaml +++ b/mmv1/products/compute/InstanceGroupNamedPort.yaml @@ -71,6 +71,11 @@ examples: network_name: 'container-network' subnetwork_name: 'container-subnetwork' gke_cluster_name: 'my-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: 'templates/terraform/encoders/normalize_group.go.erb' parameters: diff --git a/mmv1/products/compute/NetworkEndpointGroup.yaml b/mmv1/products/compute/NetworkEndpointGroup.yaml index 9e849d2b3f76..529ebb2fab35 100644 --- a/mmv1/products/compute/NetworkEndpointGroup.yaml +++ b/mmv1/products/compute/NetworkEndpointGroup.yaml @@ -78,6 +78,7 @@ parameters: Zone where the network endpoint group is located. required: false default_from_api: true + ignore_read: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: - !ruby/object:Api::Type::String diff --git a/mmv1/products/compute/NetworkPeeringRoutesConfig.yaml b/mmv1/products/compute/NetworkPeeringRoutesConfig.yaml index b939c63a33c8..bece6c506399 100644 --- a/mmv1/products/compute/NetworkPeeringRoutesConfig.yaml +++ b/mmv1/products/compute/NetworkPeeringRoutesConfig.yaml @@ -74,6 +74,11 @@ examples: network_name: 'container-network' subnetwork_name: 'container-subnetwork' gke_cluster_name: 'private-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: 'templates/terraform/encoders/network_peering_routes_config.go.erb' parameters: diff --git a/mmv1/products/compute/NodeGroup.yaml b/mmv1/products/compute/NodeGroup.yaml index 63e3ab1a8f8d..fbc77e550ea5 100644 --- a/mmv1/products/compute/NodeGroup.yaml +++ b/mmv1/products/compute/NodeGroup.yaml @@ -16,10 +16,11 @@ name: 'NodeGroup' kind: 'compute#NodeGroup' base_url: projects/{{project}}/zones/{{zone}}/nodeGroups create_url: projects/{{project}}/zones/{{zone}}/nodeGroups?initialNodeCount=PRE_CREATE_REPLACE_ME +update_verb: :PATCH +update_mask: true has_self_link: true description: | Represents a NodeGroup resource to manage a group of sole-tenant nodes. -immutable: true references: !ruby/object:Api::Resource::ReferenceLinks guides: 'Sole-Tenant Nodes': 'https://cloud.google.com/compute/docs/nodes/' @@ -43,12 +44,6 @@ async: !ruby/object:Api::OpAsync error: !ruby/object:Api::OpAsync::Error path: 'error/errors' message: 'message' -docs: !ruby/object:Provider::Terraform::Docs - warning: | - Due to limitations of the API, Terraform cannot update the - number of nodes in a node group and changes to node group size either - through Terraform config or through external changes will cause - Terraform to delete and recreate the node group. examples: - !ruby/object:Provider::Terraform::Examples name: 'node_group_basic' @@ -112,21 +107,13 @@ properties: - !ruby/object:Api::Type::Integer name: 'size' description: | - The total number of nodes in the node group. One of `initial_size` or `size` must be specified. - immutable: true - send_empty_value: true - default_from_api: true - exactly_one_of: - - size - - initial_size + The total number of nodes in the node group. + output: true - !ruby/object:Api::Type::Integer name: 'initialSize' description: | - The initial number of nodes in the node group. One of `initial_size` or `size` must be specified. + The initial number of nodes in the node group. One of `initial_size` or `autoscaling_policy` must be configured on resource creation. url_param_only: true - exactly_one_of: - - size - - initial_size - !ruby/object:Api::Type::String name: 'maintenancePolicy' description: | @@ -147,6 +134,8 @@ properties: description: | If you use sole-tenant nodes for your workloads, you can use the node group autoscaler to automatically manage the sizes of your node groups. + + One of `initial_size` or `autoscaling_policy` must be configured on resource creation. default_from_api: true properties: - !ruby/object:Api::Type::Enum diff --git a/mmv1/products/compute/PerInstanceConfig.yaml b/mmv1/products/compute/PerInstanceConfig.yaml index 57c1b8bc3300..5ebfb93a4cfa 100644 --- a/mmv1/products/compute/PerInstanceConfig.yaml +++ b/mmv1/products/compute/PerInstanceConfig.yaml @@ -124,6 +124,7 @@ parameters: url_param_only: true immutable: true ignore_read: true + default_from_api: true - !ruby/object:Api::Type::ResourceRef name: 'instanceGroupManager' resource: 'InstanceGroupManager' diff --git a/mmv1/products/compute/RegionAutoscaler.yaml b/mmv1/products/compute/RegionAutoscaler.yaml index 11bb9bd04466..931e07443408 100644 --- a/mmv1/products/compute/RegionAutoscaler.yaml +++ b/mmv1/products/compute/RegionAutoscaler.yaml @@ -65,6 +65,7 @@ parameters: required: false immutable: true default_from_api: true + ignore_read: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: - !ruby/object:Api::Type::Time diff --git a/mmv1/products/compute/RegionDisk.yaml b/mmv1/products/compute/RegionDisk.yaml index 94424537f21b..d421a950923f 100644 --- a/mmv1/products/compute/RegionDisk.yaml +++ b/mmv1/products/compute/RegionDisk.yaml @@ -218,7 +218,7 @@ properties: name: 'lastDetachTimestamp' description: 'Last detach timestamp in RFC3339 text format.' output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this disk. A list of key->value pairs. diff --git a/mmv1/products/compute/RegionSecurityPolicyRule.yaml b/mmv1/products/compute/RegionSecurityPolicyRule.yaml index 8580b3281d90..fecb3ca06c05 100644 --- a/mmv1/products/compute/RegionSecurityPolicyRule.yaml +++ b/mmv1/products/compute/RegionSecurityPolicyRule.yaml @@ -65,7 +65,7 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'region_security_policy_rule_with_network_match' # it needs to run synchronously because a region can have only one google_compute_network_edge_security_service. - # there is a robust handwritten test which covers this scenario. + # there is a robust handwritten test which covers this scenario. skip_test: true primary_resource_id: 'policy_rule_network_match' min_version: 'beta' diff --git a/mmv1/products/compute/ResourcePolicy.yaml b/mmv1/products/compute/ResourcePolicy.yaml index 2fc5f561273e..8e645187a41e 100644 --- a/mmv1/products/compute/ResourcePolicy.yaml +++ b/mmv1/products/compute/ResourcePolicy.yaml @@ -85,6 +85,7 @@ parameters: description: Region where resource policy resides. immutable: true required: false + ignore_read: true default_from_api: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: diff --git a/mmv1/products/compute/RouterNat.yaml b/mmv1/products/compute/RouterNat.yaml index 794e4046bf44..e260b5c67fea 100644 --- a/mmv1/products/compute/RouterNat.yaml +++ b/mmv1/products/compute/RouterNat.yaml @@ -417,9 +417,9 @@ properties: - !ruby/object:Api::Type::Boolean name: enableEndpointIndependentMapping description: | - Specifies if endpoint independent mapping is enabled. This is enabled by default. For more information - see the [official documentation](https://cloud.google.com/nat/docs/overview#specs-rfcs). - default_value: true + Enable endpoint independent mapping. + For more information see the [official documentation](https://cloud.google.com/nat/docs/overview#specs-rfcs). + default_from_api: true send_empty_value: true - !ruby/object:Api::Type::Enum name: 'type' diff --git a/mmv1/products/compute/ServiceAttachment.yaml b/mmv1/products/compute/ServiceAttachment.yaml index 8531c9ad02d1..f913840817a1 100644 --- a/mmv1/products/compute/ServiceAttachment.yaml +++ b/mmv1/products/compute/ServiceAttachment.yaml @@ -93,6 +93,7 @@ parameters: required: false immutable: true default_from_api: true + ignore_read: true custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' properties: - !ruby/object:Api::Type::String @@ -192,6 +193,7 @@ properties: An array of projects that are allowed to connect to this service attachment. send_empty_value: true + is_set: true item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::String @@ -207,12 +209,10 @@ properties: create. - !ruby/object:Api::Type::Boolean name: reconcileConnections - default_value: true + default_from_api: true send_empty_value: true description: | This flag determines whether a consumer accept/reject list change can reconcile the statuses of existing ACCEPTED or REJECTED PSC endpoints. If false, connection policy update will only affect existing PENDING PSC endpoints. Existing ACCEPTED/REJECTED endpoints will remain untouched regardless how the connection policy is modified . If true, update will affect both PENDING and ACCEPTED/REJECTED PSC endpoints. For example, an ACCEPTED PSC endpoint will be moved to REJECTED if its project is added to the reject list. - - For newly created service attachment, this boolean defaults to true. diff --git a/mmv1/products/compute/Snapshot.yaml b/mmv1/products/compute/Snapshot.yaml index 2f04ab0fb2a1..9d7ad7ffe598 100644 --- a/mmv1/products/compute/Snapshot.yaml +++ b/mmv1/products/compute/Snapshot.yaml @@ -236,7 +236,7 @@ properties: imports: 'selfLink' description: 'A reference to a license associated with this snapshot' custom_expand: 'templates/terraform/custom_expand/array_resourceref_with_validation.go.erb' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels to apply to this Snapshot. update_verb: :POST diff --git a/mmv1/products/compute/VpnTunnel.yaml b/mmv1/products/compute/VpnTunnel.yaml index 3020328720d5..f1724d01ef68 100644 --- a/mmv1/products/compute/VpnTunnel.yaml +++ b/mmv1/products/compute/VpnTunnel.yaml @@ -230,7 +230,7 @@ properties: is_set: true default_from_api: true item_type: Api::Type::String - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels to apply to this VpnTunnel. update_verb: :POST diff --git a/mmv1/products/containerattached/Cluster.yaml b/mmv1/products/containerattached/Cluster.yaml index 082415d82aa0..25e24de25699 100644 --- a/mmv1/products/containerattached/Cluster.yaml +++ b/mmv1/products/containerattached/Cluster.yaml @@ -202,8 +202,8 @@ properties: description: | The Kubernetes version of the cluster. output: true - - !ruby/object:Api::Type::KeyValuePairs - name: annotations + - !ruby/object:Api::Type::KeyValueAnnotations + name: 'annotations' description: | Optional. Annotations on the cluster. This field has the same restrictions as Kubernetes annotations. The total size of all keys and diff --git a/mmv1/products/databasemigrationservice/connectionprofile.yaml b/mmv1/products/databasemigrationservice/connectionprofile.yaml index 3396127ae17b..535cbc4cee92 100644 --- a/mmv1/products/databasemigrationservice/connectionprofile.yaml +++ b/mmv1/products/databasemigrationservice/connectionprofile.yaml @@ -87,8 +87,7 @@ examples: profile: 'my-profileid' global_address_name: 'private-ip-alloc' network_name: 'vpc-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "profile-alloydb")' + skip_test: true parameters: - !ruby/object:Api::Type::String name: 'connectionProfileId' @@ -118,7 +117,7 @@ properties: output: true description: | Output only. The timestamp when the resource was created. A timestamp in RFC3339 UTC 'Zulu' format, accurate to nanoseconds. Example: '2014-10-02T15:01:23.045123456Z'. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The resource labels for connection profile to use to annotate any related underlying resources such as Compute Engine VMs. diff --git a/mmv1/products/datafusion/Instance.yaml b/mmv1/products/datafusion/Instance.yaml index 17f0333f65d8..ccd0efd1c762 100644 --- a/mmv1/products/datafusion/Instance.yaml +++ b/mmv1/products/datafusion/Instance.yaml @@ -141,7 +141,7 @@ properties: name: 'enableRbac' description: | Option to enable granular role-based access control. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The resource labels for instance to use to annotate any related underlying resources, diff --git a/mmv1/products/dataplex/Datascan.yaml b/mmv1/products/dataplex/Datascan.yaml index ee861ea31b5c..c3900509e163 100644 --- a/mmv1/products/dataplex/Datascan.yaml +++ b/mmv1/products/dataplex/Datascan.yaml @@ -126,7 +126,7 @@ properties: name: 'displayName' description: | User friendly display name. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | User-defined labels for the scan. A list of key->value pairs. @@ -489,387 +489,3 @@ properties: Only top-level field names for nested fields are supported. For instance, if 'x' is of nested field type, listing 'x' is supported but 'x.y.z' is not supported. Here 'y' and 'y.z' are nested fields of 'x'. item_type: Api::Type::String - - !ruby/object:Api::Type::NestedObject - name: 'dataQualityResult' - output: true - deprecation_message: "`data_quality_result` is deprecated and will be removed in a future major release." - description: | - The result of the data quality scan. - properties: - - !ruby/object:Api::Type::Boolean - name: 'passed' - output: true - description: | - Overall data quality result -- true if all rules passed. - - !ruby/object:Api::Type::Array - name: 'dimensions' - description: | - A list of results at the dimension level. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::Boolean - name: 'passed' - description: | - Whether the dimension passed or failed. - - !ruby/object:Api::Type::Array - name: 'rules' - output: true - description: | - A list of all the rules in a job, and their results. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::NestedObject - name: 'rule' - output: true - description: | - The rule specified in the DataQualitySpec, as is. - properties: - - !ruby/object:Api::Type::String - name: 'column' - description: | - The unnested column which this rule is evaluated against. - - !ruby/object:Api::Type::Boolean - name: 'ignoreNull' - description: | - Rows with null values will automatically fail a rule, unless ignoreNull is true. In that case, such null rows are trivially considered passing. Only applicable to ColumnMap rules. - - !ruby/object:Api::Type::String - name: 'dimension' - description: | - The dimension a rule belongs to. Results are also aggregated at the dimension level. Supported dimensions are ["COMPLETENESS", "ACCURACY", "CONSISTENCY", "VALIDITY", "UNIQUENESS", "INTEGRITY"] - - !ruby/object:Api::Type::Integer - name: 'threshold' - description: | - The minimum ratio of passing_rows / total_rows required to pass this rule, with a range of [0.0, 1.0]. 0 indicates default value (i.e. 1.0). - - !ruby/object:Api::Type::NestedObject - name: 'rangeExpectation' - output: true - description: | - ColumnMap rule which evaluates whether each column value lies between a specified range. - properties: - - !ruby/object:Api::Type::String - name: 'minValue' - description: | - The minimum column value allowed for a row to pass this validation. At least one of minValue and maxValue need to be provided. - - !ruby/object:Api::Type::String - name: maxValue - description: | - The maximum column value allowed for a row to pass this validation. At least one of minValue and maxValue need to be provided. - - !ruby/object:Api::Type::Boolean - name: 'strictMinEnabled' - default_value: false - description: | - Whether each value needs to be strictly greater than ('>') the minimum, or if equality is allowed. - Only relevant if a minValue has been defined. Default = false. - - !ruby/object:Api::Type::Boolean - name: 'strictMaxEnabled' - default_value: false - description: | - Whether each value needs to be strictly lesser than ('<') the maximum, or if equality is allowed. - Only relevant if a maxValue has been defined. Default = false. - - !ruby/object:Api::Type::NestedObject - name: 'nonNullExpectation' - output: true - allow_empty_object: true - description: | - ColumnMap rule which evaluates whether each column value is null. - properties: [] - - !ruby/object:Api::Type::NestedObject - name: 'setExpectation' - output: true - description: | - ColumnMap rule which evaluates whether each column value is contained by a specified set. - properties: - - !ruby/object:Api::Type::Array - name: 'values' - description: | - Expected values for the column value. - item_type: Api::Type::String - - !ruby/object:Api::Type::NestedObject - name: 'regexExpectation' - output: true - description: | - ColumnMap rule which evaluates whether each column value matches a specified regex. - properties: - - !ruby/object:Api::Type::String - name: 'regex' - description: | - A regular expression the column value is expected to match. - - !ruby/object:Api::Type::NestedObject - name: 'uniquenessExpectation' - output: true - allow_empty_object: true - description: | - ColumnAggregate rule which evaluates whether the column has duplicates. - properties: [] - - !ruby/object:Api::Type::NestedObject - name: 'statisticRangeExpectation' - output: true - description: | - ColumnAggregate rule which evaluates whether the column aggregate statistic lies between a specified range. - properties: - - !ruby/object:Api::Type::Enum - name: 'statistic' - description: | - column statistics. - values: - - :STATISTIC_UNDEFINED - - :MEAN - - :MIN - - :MAX - - !ruby/object:Api::Type::String - name: 'minValue' - description: | - The minimum column statistic value allowed for a row to pass this validation. - At least one of minValue and maxValue need to be provided. - - !ruby/object:Api::Type::String - name: 'maxValue' - description: | - The maximum column statistic value allowed for a row to pass this validation. - At least one of minValue and maxValue need to be provided. - - !ruby/object:Api::Type::Boolean - name: 'strictMinEnabled' - description: | - Whether column statistic needs to be strictly greater than ('>') the minimum, or if equality is allowed. - Only relevant if a minValue has been defined. Default = false. - - !ruby/object:Api::Type::Boolean - name: 'strictMaxEnabled' - description: | - Whether column statistic needs to be strictly lesser than ('<') the maximum, or if equality is allowed. - Only relevant if a maxValue has been defined. Default = false. - - !ruby/object:Api::Type::NestedObject - name: 'rowConditionExpectation' - output: true - description: | - Table rule which evaluates whether each row passes the specified condition. - properties: - - !ruby/object:Api::Type::String - name: 'sqlExpression' - description: | - The SQL expression. - - !ruby/object:Api::Type::NestedObject - name: 'tableConditionExpectation' - output: true - description: | - Table rule which evaluates whether the provided expression is true. - properties: - - !ruby/object:Api::Type::String - name: 'sqlExpression' - description: | - The SQL expression. - - !ruby/object:Api::Type::Boolean - name: 'passed' - output: true - description: | - Whether the rule passed or failed. - - !ruby/object:Api::Type::String - name: 'evaluatedCount' - output: true - description: | - The number of rows a rule was evaluated against. This field is only valid for ColumnMap type rules. - Evaluated count can be configured to either - 1. include all rows (default) - with null rows automatically failing rule evaluation, or - 2. exclude null rows from the evaluatedCount, by setting ignore_nulls = true. - - !ruby/object:Api::Type::String - name: 'passedCount' - output: true - description: | - The number of rows which passed a rule evaluation. This field is only valid for ColumnMap type rules. - - !ruby/object:Api::Type::String - name: 'nullCount' - output: true - description: | - The number of rows with null values in the specified column. - - !ruby/object:Api::Type::Integer - name: 'passRatio' - output: true - description: | - The ratio of passedCount / evaluatedCount. This field is only valid for ColumnMap type rules. - - !ruby/object:Api::Type::String - name: 'failingRowsQuery' - output: true - description: | - The query to find rows that did not pass this rule. Only applies to ColumnMap and RowCondition rules. - - !ruby/object:Api::Type::String - name: 'rowCount' - output: true - description: | - The count of rows processed. - - !ruby/object:Api::Type::NestedObject - name: 'scannedData' - output: true - description: | - The data scanned for this result. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'incrementalField' - description: | - The range denoted by values of an incremental field - properties: - - !ruby/object:Api::Type::String - name: 'field' - description: | - The field that contains values which monotonically increases over time (e.g. a timestamp column). - - !ruby/object:Api::Type::String - name: 'start' - description: | - Value that marks the start of the range. - - !ruby/object:Api::Type::String - name: 'end' - description: Value that marks the end of the range. - - !ruby/object:Api::Type::NestedObject - name: 'dataProfileResult' - output: true - deprecation_message: "`data_profile_result` is deprecated and will be removed in a future major release." - custom_flatten: templates/terraform/custom_flatten/dataplex_datascan_ignore_profile_result.go.erb - description: | - The result of the data profile scan. - properties: - - !ruby/object:Api::Type::String - name: 'rowCount' - description: | - The count of rows scanned. - - !ruby/object:Api::Type::NestedObject - name: 'profile' - output: true - description: | - The profile information per field. - properties: - - !ruby/object:Api::Type::Array - name: 'fields' - description: | - List of fields with structural and profile information for each field. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'name' - description: | - The name of the field. - - !ruby/object:Api::Type::String - name: 'type' - description: | - The field data type. - - !ruby/object:Api::Type::String - name: 'mode' - description: | - The mode of the field. Possible values include: - 1. REQUIRED, if it is a required field. - 2. NULLABLE, if it is an optional field. - 3. REPEATED, if it is a repeated field. - - !ruby/object:Api::Type::NestedObject - name: 'profile' - description: | - Profile information for the corresponding field. - properties: - - !ruby/object:Api::Type::Integer - name: 'nullRatio' - output: true - description: | - Ratio of rows with null value against total scanned rows. - - !ruby/object:Api::Type::Integer - name: 'distinctRatio' - description: | - Ratio of rows with distinct values against total scanned rows. Not available for complex non-groupable field type RECORD and fields with REPEATABLE mode. - - !ruby/object:Api::Type::NestedObject - name: 'topNValues' - description: | - The list of top N non-null values and number of times they occur in the scanned data. N is 10 or equal to the number of distinct values in the field, whichever is smaller. Not available for complex non-groupable field type RECORD and fields with REPEATABLE mode. - properties: - - !ruby/object:Api::Type::String - name: 'value' - description: | - String value of a top N non-null value. - - !ruby/object:Api::Type::String - name: 'count' - description: | - Count of the corresponding value in the scanned data. - - !ruby/object:Api::Type::NestedObject - name: 'stringProfile' - output: true - description: | - String type field information. - properties: - - !ruby/object:Api::Type::String - name: 'minLength' - description: | - Minimum length of non-null values in the scanned data. - - !ruby/object:Api::Type::String - name: 'maxLength' - description: | - Maximum length of non-null values in the scanned data. - - !ruby/object:Api::Type::Integer - name: 'averageLength' - description: | - Average length of non-null values in the scanned data. - - !ruby/object:Api::Type::NestedObject - name: 'integerProfile' - output: true - description: | - Integer type field information. - properties: - - !ruby/object:Api::Type::Integer - name: 'average' - description: | - Average of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::Integer - name: 'standardDeviation' - description: | - Standard deviation of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::String - name: 'min' - description: | - Minimum of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::String - name: 'quartiles' - description: | - A quartile divides the number of data points into four parts, or quarters, of more-or-less equal size. Three main quartiles used are: The first quartile (Q1) splits off the lowest 25% of data from the highest 75%. It is also known as the lower or 25th empirical quartile, as 25% of the data is below this point. The second quartile (Q2) is the median of a data set. So, 50% of the data lies below this point. The third quartile (Q3) splits off the highest 25% of data from the lowest 75%. It is known as the upper or 75th empirical quartile, as 75% of the data lies below this point. Here, the quartiles is provided as an ordered list of quartile values for the scanned data, occurring in order Q1, median, Q3. - - !ruby/object:Api::Type::String - name: 'max' - description: | - Maximum of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::NestedObject - name: 'doubleProfile' - output: true - description: | - Double type field information. - properties: - - !ruby/object:Api::Type::Integer - name: 'average' - description: | - Average of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::Integer - name: 'standardDeviation' - description: | - Standard deviation of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::String - name: 'min' - description: | - Minimum of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::String - name: 'quartiles' - description: | - A quartile divides the number of data points into four parts, or quarters, of more-or-less equal size. Three main quartiles used are: The first quartile (Q1) splits off the lowest 25% of data from the highest 75%. It is also known as the lower or 25th empirical quartile, as 25% of the data is below this point. The second quartile (Q2) is the median of a data set. So, 50% of the data lies below this point. The third quartile (Q3) splits off the highest 25% of data from the lowest 75%. It is known as the upper or 75th empirical quartile, as 75% of the data lies below this point. Here, the quartiles is provided as an ordered list of quartile values for the scanned data, occurring in order Q1, median, Q3. - - !ruby/object:Api::Type::String - name: 'max' - description: | - Maximum of non-null values in the scanned data. NaN, if the field has a NaN. - - !ruby/object:Api::Type::NestedObject - name: 'scannedData' - output: true - description: The data scanned for this result. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'incrementalField' - description: | - The range denoted by values of an incremental field - properties: - - !ruby/object:Api::Type::String - name: 'field' - description: | - The field that contains values which monotonically increases over time (e.g. a timestamp column). - - !ruby/object:Api::Type::String - name: 'start' - description: | - Value that marks the start of the range. - - !ruby/object:Api::Type::String - name: 'end' - description: Value that marks the end of the range. diff --git a/mmv1/products/dataplex/Task.yaml b/mmv1/products/dataplex/Task.yaml index 3a4095794264..66ed12c16dbb 100644 --- a/mmv1/products/dataplex/Task.yaml +++ b/mmv1/products/dataplex/Task.yaml @@ -116,7 +116,7 @@ properties: - :CREATING - :DELETING - :ACTION_REQUIRED - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | User-defined labels for the task. diff --git a/mmv1/products/datastream/ConnectionProfile.yaml b/mmv1/products/datastream/ConnectionProfile.yaml index 5e5258e765b6..3a8a4d94879f 100644 --- a/mmv1/products/datastream/ConnectionProfile.yaml +++ b/mmv1/products/datastream/ConnectionProfile.yaml @@ -81,7 +81,7 @@ properties: name: 'name' output: true description: The resource's name. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels. - !ruby/object:Api::Type::String diff --git a/mmv1/products/datastream/PrivateConnection.yaml b/mmv1/products/datastream/PrivateConnection.yaml index dcd9a6da8d71..c2a10d6c8bce 100644 --- a/mmv1/products/datastream/PrivateConnection.yaml +++ b/mmv1/products/datastream/PrivateConnection.yaml @@ -59,7 +59,7 @@ properties: name: 'name' output: true description: The resource's name. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels. - !ruby/object:Api::Type::String diff --git a/mmv1/products/datastream/Stream.yaml b/mmv1/products/datastream/Stream.yaml index 039b51a75457..a88ed1eeb73c 100644 --- a/mmv1/products/datastream/Stream.yaml +++ b/mmv1/products/datastream/Stream.yaml @@ -157,7 +157,7 @@ properties: name: 'name' output: true description: The stream's name. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Labels. - !ruby/object:Api::Type::String diff --git a/mmv1/products/dialogflowcx/Intent.yaml b/mmv1/products/dialogflowcx/Intent.yaml index caf8c2dd32d7..479e7756756e 100644 --- a/mmv1/products/dialogflowcx/Intent.yaml +++ b/mmv1/products/dialogflowcx/Intent.yaml @@ -144,7 +144,7 @@ properties: description: | Indicates whether this is a fallback intent. Currently only default fallback intent is allowed in the agent, which is added upon agent creation. Adding training phrases to fallback intent is useful in the case of requests that are mistakenly matched, since training phrases assigned to fallback intents act as negative examples that triggers no-match event. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The key/value metadata to label an intent. Labels can contain lowercase letters, digits and the symbols '-' and '_'. International characters are allowed, including letters from unicase alphabets. Keys must start with a letter. Keys and values can be no longer than 63 characters and no more than 128 bytes. diff --git a/mmv1/products/dns/ManagedZone.yaml b/mmv1/products/dns/ManagedZone.yaml index 62565124dfad..4498bf699485 100644 --- a/mmv1/products/dns/ManagedZone.yaml +++ b/mmv1/products/dns/ManagedZone.yaml @@ -97,6 +97,11 @@ examples: zone_name: 'private-zone' network_1_name: 'network-1' cluster_1_name: 'cluster-1' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'dns_managed_zone_private_peering' primary_resource_id: 'peering-zone' @@ -247,7 +252,7 @@ properties: The time that this resource was created on the server. This is in RFC3339 text format. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this ManagedZone. diff --git a/mmv1/products/dns/ResponsePolicy.yaml b/mmv1/products/dns/ResponsePolicy.yaml index cf2d2a7681fb..9f14ffdd65e3 100644 --- a/mmv1/products/dns/ResponsePolicy.yaml +++ b/mmv1/products/dns/ResponsePolicy.yaml @@ -31,6 +31,11 @@ examples: network_1_name: 'network-1' network_2_name: 'network-2' cluster_1_name: 'cluster-1' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' custom_code: !ruby/object:Provider::Terraform::CustomCode pre_delete: templates/terraform/pre_delete/response_policy_detach_network_gke.erb properties: diff --git a/mmv1/products/filestore/Backup.yaml b/mmv1/products/filestore/Backup.yaml index de9f8c3359ea..aaa18af7ecf4 100644 --- a/mmv1/products/filestore/Backup.yaml +++ b/mmv1/products/filestore/Backup.yaml @@ -78,7 +78,7 @@ properties: description: | The time when the snapshot was created in RFC3339 text format. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/filestore/Instance.yaml b/mmv1/products/filestore/Instance.yaml index e2b7f6ef054f..5292b7a197db 100644 --- a/mmv1/products/filestore/Instance.yaml +++ b/mmv1/products/filestore/Instance.yaml @@ -44,7 +44,8 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'filestore_instance_enterprise' primary_resource_id: 'instance' - skip_test: true # https://github.com/GoogleCloudPlatform/magic-modules/pull/5875#discussion_r844285335 + # https://github.com/GoogleCloudPlatform/magic-modules/pull/5875#discussion_r844285335 + skip_test: true vars: instance_name: 'test-instance' custom_code: !ruby/object:Provider::Terraform::CustomCode @@ -98,7 +99,7 @@ properties: Possible values include: STANDARD, PREMIUM, BASIC_HDD, BASIC_SSD, HIGH_SCALE_SSD, ZONAL and ENTERPRISE required: true immutable: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/filestore/Snapshot.yaml b/mmv1/products/filestore/Snapshot.yaml index e5390f5445ae..1ce5ea76bb50 100644 --- a/mmv1/products/filestore/Snapshot.yaml +++ b/mmv1/products/filestore/Snapshot.yaml @@ -89,7 +89,7 @@ properties: description: | The time when the snapshot was created in RFC3339 text format. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/firebase/AndroidApp.yaml b/mmv1/products/firebase/AndroidApp.yaml index 5a0bb9027a22..8cd21b2db2ba 100644 --- a/mmv1/products/firebase/AndroidApp.yaml +++ b/mmv1/products/firebase/AndroidApp.yaml @@ -89,14 +89,16 @@ examples: - project - deletion_policy virtual_fields: - # TODO: make this an enum in a future major version. If using this field as a reference, look at PerInstanceConfig's minimal_action field for enum configuration. - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Enum name: 'deletion_policy' description: | (Optional) Set to `ABANDON` to allow the AndroidApp to be untracked from terraform state rather than deleted upon `terraform destroy`. This is useful because the AndroidApp may be serving traffic. Set to `DELETE` to delete the AndroidApp. Defaults to `DELETE`. - default_value: DELETE + default_value: :DELETE + values: + - :DELETE + - :ABANDON custom_code: !ruby/object:Provider::Terraform::CustomCode custom_delete: templates/terraform/custom_delete/firebase_app_deletion_policy.erb properties: diff --git a/mmv1/products/firebase/AppleApp.yaml b/mmv1/products/firebase/AppleApp.yaml index ac62a91975ee..7c9ab93c8258 100644 --- a/mmv1/products/firebase/AppleApp.yaml +++ b/mmv1/products/firebase/AppleApp.yaml @@ -65,7 +65,6 @@ examples: display_name: 'Display Name Basic' bundle_id: 'apple.app.12345' test_env_vars: - org_id: :ORG_ID project_id: :PROJECT_NAME test_vars_overrides: display_name: '"tf-test Display Name Basic"' @@ -80,7 +79,6 @@ examples: team_id: '9987654321' # Has to be a 10-digit number. api_key_name: 'api-key' test_env_vars: - org_id: :ORG_ID project_id: :PROJECT_NAME test_vars_overrides: app_store_id: '12345' @@ -90,14 +88,16 @@ examples: - project - deletion_policy virtual_fields: - # TODO: make this an enum in a future major version. If using this field as a reference, look at PerInstanceConfig's minimal_action field for enum configuration. - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Enum name: 'deletion_policy' description: | (Optional) Set to `ABANDON` to allow the Apple to be untracked from terraform state rather than deleted upon `terraform destroy`. This is useful because the Apple may be serving traffic. Set to `DELETE` to delete the Apple. Defaults to `DELETE`. - default_value: DELETE + default_value: :DELETE + values: + - :DELETE + - :ABANDON custom_code: !ruby/object:Provider::Terraform::CustomCode custom_delete: templates/terraform/custom_delete/firebase_app_deletion_policy.erb properties: diff --git a/mmv1/products/firebase/ProjectLocation.yaml b/mmv1/products/firebase/ProjectLocation.yaml deleted file mode 100644 index e1957694e954..000000000000 --- a/mmv1/products/firebase/ProjectLocation.yaml +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2023 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. - ---- !ruby/object:Api::Resource -name: 'ProjectLocation' -min_version: beta -base_url: projects/{{project}} -self_link: projects/{{project}} -create_url: projects/{{project}}/defaultLocation:finalize -nested_query: !ruby/object:Api::Resource::NestedQuery - keys: - - resources -immutable: true -description: | - Sets the default Google Cloud Platform (GCP) resource location for the specified FirebaseProject. - This method creates an App Engine application with a default Cloud Storage bucket, located in the specified - locationId. This location must be one of the available GCP resource locations. - After the default GCP resource location is finalized, or if it was already set, it cannot be changed. - The default GCP resource location for the specified FirebaseProject might already be set because either the - GCP Project already has an App Engine application or defaultLocation.finalize was previously called with a - specified locationId. Any new calls to defaultLocation.finalize with a different specified locationId will - return a 409 error. -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://firebase.google.com/' - api: 'https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.defaultLocation/finalize' -import_format: ['projects/{{project}}', '{{project}}'] -skip_delete: true -skip_sweeper: true -deprecation_message: >- - `google_firebase_project_location` is deprecated in favor of explicitly configuring `google_app_engine_application` - and `google_firestore_database`. This resource will be removed in the next major release of the provider. -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'firebase_project_location_basic' - min_version: 'beta' - primary_resource_id: 'basic' - test_env_vars: - org_id: :ORG_ID - vars: - project_name: "my-project" -properties: - - !ruby/object:Api::Type::String - name: locationId - required: true - description: | - The ID of the default GCP resource location for the Project. The location must be one of the available GCP - resource locations. diff --git a/mmv1/products/firebase/WebApp.yaml b/mmv1/products/firebase/WebApp.yaml index 6c7a9eb5ba57..e6682fdb76df 100644 --- a/mmv1/products/firebase/WebApp.yaml +++ b/mmv1/products/firebase/WebApp.yaml @@ -65,9 +65,8 @@ examples: vars: display_name: 'Display Name Basic' bucket_name: 'fb-webapp-' - project_name: "my-project" test_env_vars: - org_id: :ORG_ID + project_id: :PROJECT_NAME test_vars_overrides: display_name: '"tf-test Display Name Basic"' ignore_read_extra: @@ -86,14 +85,16 @@ examples: - project - deletion_policy virtual_fields: - # TODO: make this an enum in a future major version. If using this field as a reference, look at PerInstanceConfig's minimal_action field for enum configuration. - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Enum name: 'deletion_policy' description: | Set to `ABANDON` to allow the WebApp to be untracked from terraform state rather than deleted upon `terraform destroy`. This is useful becaue the WebApp may be - serving traffic. Set to `DELETE` to delete the WebApp. Default to `ABANDON` - default_value: ABANDON + serving traffic. Set to `DELETE` to delete the WebApp. Default to `DELETE` + default_value: :DELETE + values: + - :DELETE + - :ABANDON custom_code: !ruby/object:Provider::Terraform::CustomCode custom_delete: templates/terraform/custom_delete/firebase_app_deletion_policy.erb properties: diff --git a/mmv1/products/firebasehosting/Channel.yaml b/mmv1/products/firebasehosting/Channel.yaml index d94e4bef481b..5a1cc9648230 100644 --- a/mmv1/products/firebasehosting/Channel.yaml +++ b/mmv1/products/firebasehosting/Channel.yaml @@ -76,8 +76,8 @@ properties: The number of previous releases to retain on the channel for rollback or other purposes. Must be a number between 1-100. Defaults to 10 for new channels. default_from_api: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: Text labels used for extra metadata and/or filtering - !ruby/object:Api::Type::Time name: expireTime diff --git a/mmv1/products/gameservices/GameServerCluster.yaml b/mmv1/products/gameservices/GameServerCluster.yaml deleted file mode 100644 index 8f768c02bfa6..000000000000 --- a/mmv1/products/gameservices/GameServerCluster.yaml +++ /dev/null @@ -1,137 +0,0 @@ -# Copyright 2023 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. - ---- !ruby/object:Api::Resource -name: GameServerCluster -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/projects.locations.realms.gameServerClusters' -update_verb: :PATCH -update_mask: true -base_url: projects/{{project}}/locations/{{location}}/realms/{{realm_id}}/gameServerClusters -create_url: projects/{{project}}/locations/{{location}}/realms/{{realm_id}}/gameServerClusters?gameServerClusterId={{cluster_id}} -self_link: projects/{{project}}/locations/{{location}}/realms/{{realm_id}}/gameServerClusters/{{cluster_id}} -description: A game server cluster resource. -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - result: !ruby/object:Api::OpAsync::Result - path: 'response' - resource_inside_response: true - status: !ruby/object:Api::OpAsync::Status - path: 'done' - complete: true - allowed: - - true - - false - error: !ruby/object:Api::OpAsync::Error - path: 'error/errors' - message: 'message' -import_format: - [ - 'projects/{{project}}/locations/{{location}}/realms/{{realm_id}}/gameServerClusters/{{cluster_id}}', - ] -# Skipping the sweeper due to the non-standard base_url -skip_sweeper: true -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_cluster_basic' - primary_resource_id: - 'default' - skip_test: true - vars: - realm_id: 'realm' - test_vars_overrides: - agones_cluster: '"bootstrapped-agones-cluster"' -custom_code: !ruby/object:Provider::Terraform::CustomCode - constants: 'templates/terraform/constants/gameserver_cluster_custom_diff.go' -properties: - - !ruby/object:Api::Type::String - immutable: true - name: clusterId - required: true - url_param_only: true - description: |- - Required. The resource name of the game server cluster - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource id of the game server cluster, eg: - - `projects/{project_id}/locations/{location}/realms/{realm_id}/gameServerClusters/{cluster_id}`. - For example, - - `projects/my-project/locations/{location}/realms/zanzibar/gameServerClusters/my-onprem-cluster`. - - !ruby/object:Api::Type::ResourceRef - name: realmId - url_param_only: true - resource: Realm - imports: name - required: true - description: |- - The realm id of the game server realm. - - !ruby/object:Api::Type::String - name: location - url_param_only: true - default_value: global - description: Location of the Cluster. - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: |- - The labels associated with this game server cluster. Each label is a - key-value pair. - - !ruby/object:Api::Type::NestedObject - name: connectionInfo - required: true - immutable: true - description: |- - Game server cluster connection information. This information is used to - manage game server clusters. - properties: - - !ruby/object:Api::Type::NestedObject - name: gkeClusterReference - required: true - immutable: true - description: - Reference of the GKE cluster where the game servers are installed. - properties: - - !ruby/object:Api::Type::String - name: cluster - required: true - immutable: true - description: |- - The full or partial name of a GKE cluster, using one of the following - forms: - - * `projects/{project_id}/locations/{location}/clusters/{cluster_id}` - * `locations/{location}/clusters/{cluster_id}` - * `{cluster_id}` - - If project and location are not specified, the project and location of the - GameServerCluster resource are used to generate the full name of the - GKE cluster. - diff_suppress_func: suppressSuffixDiff - - !ruby/object:Api::Type::String - name: namespace - required: true - description: |- - Namespace designated on the game server cluster where the game server - instances will be created. The namespace existence will be validated - during creation. - - !ruby/object:Api::Type::String - name: description - description: Human readable description of the cluster. diff --git a/mmv1/products/gameservices/GameServerConfig.yaml b/mmv1/products/gameservices/GameServerConfig.yaml deleted file mode 100644 index 75de43ab2eb0..000000000000 --- a/mmv1/products/gameservices/GameServerConfig.yaml +++ /dev/null @@ -1,176 +0,0 @@ -# Copyright 2023 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. - ---- !ruby/object:Api::Resource -name: GameServerConfig -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/projects.locations.gameServerDeployments.configs' -create_url: projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}/configs?configId={{config_id}} -base_url: projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}/configs -self_link: projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}/configs/{{config_id}} -immutable: true -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - result: !ruby/object:Api::OpAsync::Result - path: 'response' - resource_inside_response: true - status: !ruby/object:Api::OpAsync::Status - path: 'done' - complete: true - allowed: - - true - - false - error: !ruby/object:Api::OpAsync::Error - path: 'error/errors' - message: 'message' -description: A game server config resource. Configs are global and immutable. -autogen_async: true -import_format: - [ - 'projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}/configs/{{config_id}}', - ] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_config_basic' - primary_resource_id: 'default' - skip_test: true - vars: - deployment_id: 'tf-test-deployment' - config_id: 'tf-test-config' -properties: - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource name of the game server config, in the form: - - `projects/{project_id}/locations/{location}/gameServerDeployments/{deployment_id}/configs/{config_id}`. - - !ruby/object:Api::Type::String - name: configId - immutable: true - required: true - url_param_only: true - description: | - A unique id for the deployment config. - - !ruby/object:Api::Type::String - name: location - # The only acceptable location currently is 'global' - # TODO - either hard code or set as computed - url_param_only: true - default_value: global - description: Location of the Deployment. - - !ruby/object:Api::Type::ResourceRef - name: deploymentId - resource: 'GameServerDeployment' - imports: 'deploymentId' - immutable: true - required: true - url_param_only: true - description: | - A unique id for the deployment. - - !ruby/object:Api::Type::String - name: description - description: The description of the game server config. - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: |- - The labels associated with this game server config. Each label is a - key-value pair. - - !ruby/object:Api::Type::Array - name: fleetConfigs - required: true - description: |- - The fleet config contains list of fleet specs. In the Single Cloud, there - will be only one. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - required: true - name: fleetSpec - description: | - The fleet spec, which is sent to Agones to configure fleet. - The spec can be passed as inline json but it is recommended to use a file reference - instead. File references can contain the json or yaml format of the fleet spec. Eg: - - * fleet_spec = jsonencode(yamldecode(file("fleet_configs.yaml"))) - * fleet_spec = file("fleet_configs.json") - - The format of the spec can be found : - `https://agones.dev/site/docs/reference/fleet/`. - - !ruby/object:Api::Type::String - name: name - required: true - description: The name of the FleetConfig. - default_from_api: true - - !ruby/object:Api::Type::Array - name: scalingConfigs - description: Optional. This contains the autoscaling settings. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: name - required: true - description: The name of the ScalingConfig - - !ruby/object:Api::Type::String - required: true - name: fleetAutoscalerSpec - description: |- - Fleet autoscaler spec, which is sent to Agones. - Example spec can be found : - https://agones.dev/site/docs/reference/fleetautoscaler/ - - !ruby/object:Api::Type::Array - name: selectors - description: |- - Labels used to identify the clusters to which this scaling config - applies. A cluster is subject to this scaling config if its labels match - any of the selector entries. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: Set of labels to group by. - - !ruby/object:Api::Type::Array - name: schedules - description: The schedules to which this scaling config applies. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: startTime - description: |- - The start time of the event. - - A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z". - - !ruby/object:Api::Type::String - name: endTime - description: |- - The end time of the event. - - A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z". - - !ruby/object:Api::Type::String - name: cronJobDuration - description: |- - The duration for the cron job event. The duration of the event is effective - after the cron job's start time. - - A duration in seconds with up to nine fractional digits, terminated by 's'. Example: "3.5s". - - !ruby/object:Api::Type::String - name: cronSpec - description: |- - The cron definition of the scheduled event. See - https://en.wikipedia.org/wiki/Cron. Cron spec specifies the local time as - defined by the realm. diff --git a/mmv1/products/gameservices/GameServerDeployment.yaml b/mmv1/products/gameservices/GameServerDeployment.yaml deleted file mode 100644 index 041d44def02e..000000000000 --- a/mmv1/products/gameservices/GameServerDeployment.yaml +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2023 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. - ---- !ruby/object:Api::Resource -name: GameServerDeployment -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/projects.locations.gameServerDeployments' -base_url: projects/{{project}}/locations/{{location}}/gameServerDeployments -create_url: projects/{{project}}/locations/{{location}}/gameServerDeployments?deploymentId={{deployment_id}} -self_link: projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}} -update_mask: true -update_verb: :PATCH -description: A game server deployment resource. -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - result: !ruby/object:Api::OpAsync::Result - path: 'response' - resource_inside_response: true - status: !ruby/object:Api::OpAsync::Status - path: 'done' - complete: true - allowed: - - true - - false - error: !ruby/object:Api::OpAsync::Error - path: 'error/errors' - message: 'message' -autogen_async: true -import_format: - [ - 'projects/{{project}}/locations/{{location}}/gameServerDeployments/{{deployment_id}}', - ] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_deployment_basic' - primary_resource_id: 'default' - skip_test: true - vars: - deployment_id: 'tf-test-deployment' -properties: - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource id of the game server deployment, eg: - - `projects/{project_id}/locations/{location}/gameServerDeployments/{deployment_id}`. - For example, - - `projects/my-project/locations/{location}/gameServerDeployments/my-deployment`. - - !ruby/object:Api::Type::String - name: description - description: Human readable description of the game server deployment. - - !ruby/object:Api::Type::String - name: deploymentId - immutable: true - required: true - url_param_only: true - description: | - A unique id for the deployment. - - !ruby/object:Api::Type::String - name: location - # The only acceptable location currently is 'global' - # TODO - either hard code or set as computed - url_param_only: true - default_value: global - description: Location of the Deployment. - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: |- - The labels associated with this game server deployment. Each label is a - key-value pair. diff --git a/mmv1/products/gameservices/GameServerDeploymentRollout.yaml b/mmv1/products/gameservices/GameServerDeploymentRollout.yaml deleted file mode 100644 index 3b9cad5296de..000000000000 --- a/mmv1/products/gameservices/GameServerDeploymentRollout.yaml +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright 2023 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. - ---- !ruby/object:Api::Resource -name: GameServerDeploymentRollout -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/GameServerDeploymentRollout' -create_url: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout -base_url: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout -update_url: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout -# Deleting a rollout is synonymous with removing the default game server config -delete_url: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout?updateMask=defaultGameServerConfig -update_verb: :PATCH -delete_verb: :PATCH -update_mask: true -self_link: projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - result: !ruby/object:Api::OpAsync::Result - path: 'response' - resource_inside_response: true - status: !ruby/object:Api::OpAsync::Status - path: 'done' - complete: true - allowed: - - true - - false - error: !ruby/object:Api::OpAsync::Error - path: 'error/errors' - message: 'message' -description: |- - This represents the rollout state. This is part of the game server - deployment. -import_format: - [ - 'projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout', - ] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_deployment_rollout_basic' - primary_resource_id: 'default' - skip_test: true - vars: - deployment_id: 'tf-test-deployment' - config_id: 'tf-test-config' -custom_code: !ruby/object:Provider::Terraform::CustomCode - custom_create: 'templates/terraform/custom_create/gameservice_rollout_create.go' -properties: - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource id of the game server deployment - - eg: `projects/my-project/locations/global/gameServerDeployments/my-deployment/rollout`. - - !ruby/object:Api::Type::ResourceRef - name: deploymentId - resource: GameServerDeployment - url_param_only: true - required: true - imports: name - description: | - The deployment to rollout the new config to. Only 1 rollout must be associated with each deployment. - - !ruby/object:Api::Type::String - name: defaultGameServerConfig - required: true - description: |- - This field points to the game server config that is - applied by default to all realms and clusters. For example, - - `projects/my-project/locations/global/gameServerDeployments/my-game/configs/my-config`. - - !ruby/object:Api::Type::Array - name: gameServerConfigOverrides - description: |- - The game_server_config_overrides contains the per game server config - overrides. The overrides are processed in the order they are listed. As - soon as a match is found for a cluster, the rest of the list is not - processed. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::NestedObject - name: realmsSelector - description: Selection by realms. - properties: - - !ruby/object:Api::Type::Array - name: realms - description: List of realms to match against. - item_type: Api::Type::String - - !ruby/object:Api::Type::String - name: configVersion - description: Version of the configuration. diff --git a/mmv1/products/gameservices/Realm.yaml b/mmv1/products/gameservices/Realm.yaml deleted file mode 100644 index 07a0f6f2c650..000000000000 --- a/mmv1/products/gameservices/Realm.yaml +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright 2023 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. - ---- !ruby/object:Api::Resource -name: Realm -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': 'https://cloud.google.com/game-servers/docs' - api: 'https://cloud.google.com/game-servers/docs/reference/rest/v1beta/projects.locations.realms' -create_url: projects/{{project}}/locations/{{location}}/realms?realmId={{realm_id}} -base_url: projects/{{project}}/locations/{{location}}/realms -self_link: projects/{{project}}/locations/{{location}}/realms/{{realm_id}} -update_verb: :PATCH -update_mask: true -description: A Realm resource. -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' - wait_ms: 1000 - result: !ruby/object:Api::OpAsync::Result - path: 'response' - resource_inside_response: true - status: !ruby/object:Api::OpAsync::Status - path: 'done' - complete: true - allowed: - - true - - false - error: !ruby/object:Api::OpAsync::Error - path: 'error/errors' - message: 'message' -autogen_async: true -import_format: - ['projects/{{project}}/locations/{{location}}/realms/{{realm_id}}'] -examples: - - !ruby/object:Provider::Terraform::Examples - name: 'game_service_realm_basic' - primary_resource_id: 'default' - skip_test: true - vars: - realm_id: 'tf-test-realm' -parameters: - - !ruby/object:Api::Type::String - name: location - url_param_only: true - default_value: global - description: Location of the Realm. - - !ruby/object:Api::Type::String - name: realmId - immutable: true - url_param_only: true - required: true - description: GCP region of the Realm. -properties: - - !ruby/object:Api::Type::String - name: name - output: true - description: |- - The resource id of the realm, of the form: - `projects/{project_id}/locations/{location}/realms/{realm_id}`. For - example, `projects/my-project/locations/{location}/realms/my-realm`. - - !ruby/object:Api::Type::KeyValuePairs - name: labels - description: - The labels associated with this realm. Each label is a key-value pair. - - !ruby/object:Api::Type::String - name: timeZone - required: true - description: |- - Required. Time zone where all realm-specific policies are evaluated. The value of - this field must be from the IANA time zone database: - https://www.iana.org/time-zones. - - !ruby/object:Api::Type::String - name: etag - output: true - description: ETag of the resource. - - !ruby/object:Api::Type::String - name: description - description: Human readable description of the realm. diff --git a/mmv1/products/gameservices/product.yaml b/mmv1/products/gameservices/product.yaml deleted file mode 100644 index 45ddaf0b3d6d..000000000000 --- a/mmv1/products/gameservices/product.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2019 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. - ---- !ruby/object:Api::Product -name: GameServices -display_name: Game Servers -scopes: - - https://www.googleapis.com/auth/compute -versions: - - !ruby/object:Api::Product::Version - name: ga - base_url: https://gameservices.googleapis.com/v1/ - - !ruby/object:Api::Product::Version - name: beta - base_url: https://gameservices.googleapis.com/v1beta/ diff --git a/mmv1/products/gkebackup/BackupPlan.yaml b/mmv1/products/gkebackup/BackupPlan.yaml index 28172b41460f..0f66592368ff 100644 --- a/mmv1/products/gkebackup/BackupPlan.yaml +++ b/mmv1/products/gkebackup/BackupPlan.yaml @@ -44,6 +44,11 @@ examples: vars: name: 'basic-plan' cluster_name: 'basic-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME - !ruby/object:Provider::Terraform::Examples @@ -52,6 +57,11 @@ examples: vars: name: 'autopilot-plan' cluster_name: 'autopilot-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_backupplan_cmek' primary_resource_id: 'cmek' @@ -59,6 +69,11 @@ examples: name: 'cmek-plan' cluster_name: 'cmek-cluster' key_name: 'backup-key' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME - !ruby/object:Provider::Terraform::Examples @@ -67,6 +82,11 @@ examples: vars: name: 'full-plan' cluster_name: 'full-cluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME skip_sweeper: true @@ -138,8 +158,8 @@ properties: If set to True, no further update is allowed on this policy, including the locked field itself. default_from_api: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | Description: A set of custom labels supplied by the user. A list of key->value pairs. diff --git a/mmv1/products/gkebackup/RestorePlan.yaml b/mmv1/products/gkebackup/RestorePlan.yaml index b457a450fcb2..c70bda73c22d 100644 --- a/mmv1/products/gkebackup/RestorePlan.yaml +++ b/mmv1/products/gkebackup/RestorePlan.yaml @@ -45,6 +45,11 @@ examples: name: 'restore-all-ns' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_rollback_namespace' primary_resource_id: 'rollback_ns' @@ -52,6 +57,11 @@ examples: name: 'rollback-ns' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_protected_application' primary_resource_id: 'rollback_app' @@ -59,6 +69,11 @@ examples: name: 'rollback-app' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_all_cluster_resources' primary_resource_id: 'all_cluster_resources' @@ -66,6 +81,11 @@ examples: name: 'all-groupkinds' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_rename_namespace' primary_resource_id: 'rename_ns' @@ -73,6 +93,11 @@ examples: name: 'rename-ns' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkebackup_restoreplan_second_transformation' primary_resource_id: 'transform_rule' @@ -80,6 +105,11 @@ examples: name: 'transform-rule' test_env_vars: project: :PROJECT_NAME + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' skip_sweeper: true parameters: - !ruby/object:Api::Type::String @@ -107,7 +137,7 @@ properties: name: description description: | User specified descriptive string for this RestorePlan. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: labels description: | Description: A set of custom labels supplied by the user. diff --git a/mmv1/products/gkehub/Membership.yaml b/mmv1/products/gkehub/Membership.yaml index a73d65715fd6..8d235c069c1b 100644 --- a/mmv1/products/gkehub/Membership.yaml +++ b/mmv1/products/gkehub/Membership.yaml @@ -60,12 +60,22 @@ examples: vars: name: 'basic' cluster_name: 'basiccluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'gkehub_membership_issuer' primary_resource_id: 'membership' vars: name: 'basic' cluster_name: 'basiccluster' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME # Skip sweeper gen since this is a child resource. @@ -95,7 +105,7 @@ properties: min_version: beta description: | The name of this entity type to be displayed on the console. This field is unavailable in v1 of the API. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this membership. diff --git a/mmv1/products/gkehub2/Feature.yaml b/mmv1/products/gkehub2/Feature.yaml index e2621d30a24c..89bdd43b671d 100644 --- a/mmv1/products/gkehub2/Feature.yaml +++ b/mmv1/products/gkehub2/Feature.yaml @@ -105,8 +105,8 @@ properties: diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: GCP labels for this Feature. - !ruby/object:Api::Type::NestedObject name: resourceState diff --git a/mmv1/products/gkehub2/MembershipBinding.yaml b/mmv1/products/gkehub2/MembershipBinding.yaml index b3ff846f787f..e2d76ec60865 100644 --- a/mmv1/products/gkehub2/MembershipBinding.yaml +++ b/mmv1/products/gkehub2/MembershipBinding.yaml @@ -51,6 +51,11 @@ examples: primary_resource_id: "example" vars: cluster_name: "basiccluster" + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME location: :REGION @@ -132,7 +137,7 @@ properties: - :READY - :DELETING - :UPDATING - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels for this Membership binding. diff --git a/mmv1/products/gkehub2/MembershipRBACRoleBinding.yaml b/mmv1/products/gkehub2/MembershipRBACRoleBinding.yaml index 53d8d3d52c5b..2301d208bc6d 100644 --- a/mmv1/products/gkehub2/MembershipRBACRoleBinding.yaml +++ b/mmv1/products/gkehub2/MembershipRBACRoleBinding.yaml @@ -51,6 +51,11 @@ examples: min_version: beta vars: cluster_name: "basiccluster" + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME location: 'global' diff --git a/mmv1/products/gkehub2/Namespace.yaml b/mmv1/products/gkehub2/Namespace.yaml index 8b1901bbbe5e..b96e5e4e65e8 100644 --- a/mmv1/products/gkehub2/Namespace.yaml +++ b/mmv1/products/gkehub2/Namespace.yaml @@ -133,7 +133,7 @@ properties: Scope. Scope-level labels (`namespace_labels` in the Fleet Scope resource) take precedence over Namespace-level labels if they share a key. Keys and values must be Kubernetes-conformant. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels for this Namespace. diff --git a/mmv1/products/gkehub2/Scope.yaml b/mmv1/products/gkehub2/Scope.yaml index 86e1a806ac47..70ffbabfdaac 100644 --- a/mmv1/products/gkehub2/Scope.yaml +++ b/mmv1/products/gkehub2/Scope.yaml @@ -115,7 +115,7 @@ properties: - :READY - :DELETING - :UPDATING - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels for this Scope. diff --git a/mmv1/products/gkehub2/ScopeRBACRoleBinding.yaml b/mmv1/products/gkehub2/ScopeRBACRoleBinding.yaml index 850df3f36c3e..392699d1024e 100644 --- a/mmv1/products/gkehub2/ScopeRBACRoleBinding.yaml +++ b/mmv1/products/gkehub2/ScopeRBACRoleBinding.yaml @@ -148,7 +148,7 @@ properties: - :ADMIN - :EDIT - :VIEW - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels for this ScopeRBACRoleBinding. diff --git a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml index e14dcc81ce9d..38df22b5972e 100644 --- a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml @@ -16,17 +16,16 @@ min_version: beta base_url: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters" create_url: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters?bare_metal_admin_cluster_id={{name}}" update_url: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}" -delete_url: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}:unenroll?ignore_errors=true" self_link: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}" update_verb: :PATCH update_mask: true autogen_async: false id_format: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}" import_format: ["projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}"] +skip_delete: true taint_resource_on_failed_create: true timeouts: !ruby/object:Api::Timeouts insert_minutes: 60 - delete_minutes: 60 update_minutes: 60 description: "A Google Bare Metal Admin Cluster." examples: @@ -133,8 +132,8 @@ properties: Allows clients to perform consistent read-modify-writes through optimistic concurrency control. output: true - - !ruby/object:Api::Type::KeyValuePairs - name: "annotations" + - !ruby/object:Api::Type::KeyValueAnnotations + name: 'annotations' description: | Annotations on the Bare Metal Admin Cluster. This field has the same restrictions as Kubernetes annotations. @@ -194,7 +193,7 @@ properties: The default IPv4 address for SSH access and Kubernetes node. Example: 192.168.0.1 - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -233,7 +232,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) diff --git a/mmv1/products/gkeonprem/BareMetalCluster.yaml b/mmv1/products/gkeonprem/BareMetalCluster.yaml index 0f4bf81e2bf4..4aecba4e9b2d 100644 --- a/mmv1/products/gkeonprem/BareMetalCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalCluster.yaml @@ -85,8 +85,8 @@ properties: required: true description: | A human readable description of this Bare Metal User Cluster. - - !ruby/object:Api::Type::KeyValuePairs - name: "annotations" + - !ruby/object:Api::Type::KeyValueAnnotations + name: 'annotations' description: | Annotations on the Bare Metal User Cluster. This field has the same restrictions as Kubernetes annotations. @@ -96,7 +96,6 @@ properties: Prefix must be a DNS subdomain. Name must be 63 characters or less, begin and end with alphanumerics, with dashes (-), underscores (_), dots (.), and alphanumerics between. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: "networkConfig" description: | @@ -177,7 +176,7 @@ properties: The default IPv4 address for SSH access and Kubernetes node. Example: 192.168.0.1 - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -218,7 +217,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -341,7 +340,7 @@ properties: The default IPv4 address for SSH access and Kubernetes node. Example: 192.168.0.1 - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -382,7 +381,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -505,7 +504,7 @@ properties: The default IPv4 address for SSH access and Kubernetes node. Example: 192.168.0.1 - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) @@ -544,7 +543,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) diff --git a/mmv1/products/gkeonprem/BareMetalNodePool.yaml b/mmv1/products/gkeonprem/BareMetalNodePool.yaml index 42d8ac17f5d1..8060fafcf655 100644 --- a/mmv1/products/gkeonprem/BareMetalNodePool.yaml +++ b/mmv1/products/gkeonprem/BareMetalNodePool.yaml @@ -74,7 +74,7 @@ properties: name: 'displayName' description: | The display name for the Bare Metal Node Pool. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: | Annotations on the Bare Metal Node Pool. @@ -85,7 +85,6 @@ properties: Prefix must be a DNS subdomain. Name must be 63 characters or less, begin and end with alphanumerics, with dashes (-), underscores (_), dots (.), and alphanumerics between. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: 'nodePoolConfig' required: true diff --git a/mmv1/products/gkeonprem/VmwareCluster.yaml b/mmv1/products/gkeonprem/VmwareCluster.yaml index f460b42f42bd..c2ccf1c6b2b3 100644 --- a/mmv1/products/gkeonprem/VmwareCluster.yaml +++ b/mmv1/products/gkeonprem/VmwareCluster.yaml @@ -89,7 +89,7 @@ properties: required: true description: | The Anthos clusters on the VMware version for your user cluster. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: | Annotations on the VMware User Cluster. @@ -100,7 +100,6 @@ properties: Prefix must be a DNS subdomain. Name must be 63 characters or less, begin and end with alphanumerics, with dashes (-), underscores (_), dots (.), and alphanumerics between. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: 'controlPlaneNode' description: | diff --git a/mmv1/products/gkeonprem/VmwareNodePool.yaml b/mmv1/products/gkeonprem/VmwareNodePool.yaml index bfaf50cdb0ee..5afe0bb7859e 100644 --- a/mmv1/products/gkeonprem/VmwareNodePool.yaml +++ b/mmv1/products/gkeonprem/VmwareNodePool.yaml @@ -71,8 +71,8 @@ properties: - !ruby/object:Api::Type::String name: "displayName" description: The display name for the node pool. - - !ruby/object:Api::Type::KeyValuePairs - name: "annotations" + - !ruby/object:Api::Type::KeyValueAnnotations + name: 'annotations' description: | Annotations on the node Pool. This field has the same restrictions as Kubernetes annotations. @@ -82,7 +82,6 @@ properties: Prefix must be a DNS subdomain. Name must be 63 characters or less, begin and end with alphanumerics, with dashes (-), underscores (_), dots (.), and alphanumerics between. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: "nodePoolAutoscaling" description: Node Pool autoscaling config for the node pool. @@ -149,7 +148,7 @@ properties: - PREFER_NO_SCHEDULE - NO_EXECUTE - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + name: 'labels' description: | The map of Kubernetes labels (key/value pairs) to be applied to each node. These will added in addition to any default label(s) that diff --git a/mmv1/products/healthcare/ConsentStore.yaml b/mmv1/products/healthcare/ConsentStore.yaml index 7db49d2bcf38..75a56824809b 100644 --- a/mmv1/products/healthcare/ConsentStore.yaml +++ b/mmv1/products/healthcare/ConsentStore.yaml @@ -93,8 +93,8 @@ properties: required: false description: | If true, [consents.patch] [google.cloud.healthcare.v1.consent.UpdateConsent] creates the consent if it does not already exist. - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' required: false description: | User-supplied key-value pairs used to organize Consent stores. diff --git a/mmv1/products/healthcare/DicomStore.yaml b/mmv1/products/healthcare/DicomStore.yaml index 90ab6b2cbd86..98378ff2998e 100644 --- a/mmv1/products/healthcare/DicomStore.yaml +++ b/mmv1/products/healthcare/DicomStore.yaml @@ -73,8 +73,8 @@ properties: ** Changing this property may recreate the Dicom store (removing all data) ** required: true immutable: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' required: false description: | User-supplied key-value pairs used to organize DICOM stores. diff --git a/mmv1/products/healthcare/FhirStore.yaml b/mmv1/products/healthcare/FhirStore.yaml index d9bebcee2dbc..dc9100591bd7 100644 --- a/mmv1/products/healthcare/FhirStore.yaml +++ b/mmv1/products/healthcare/FhirStore.yaml @@ -166,8 +166,8 @@ properties: ** This property can be changed manually in the Google Cloud Healthcare admin console without recreating the FHIR store ** required: false immutable: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' required: false description: | User-supplied key-value pairs used to organize FHIR stores. diff --git a/mmv1/products/healthcare/Hl7V2Store.yaml b/mmv1/products/healthcare/Hl7V2Store.yaml index 931730c5e672..2c395e9a1338 100644 --- a/mmv1/products/healthcare/Hl7V2Store.yaml +++ b/mmv1/products/healthcare/Hl7V2Store.yaml @@ -129,8 +129,8 @@ properties: - :V1 - :V2 - :V3 - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' required: false description: | User-supplied key-value pairs used to organize HL7v2 stores. diff --git a/mmv1/products/kms/CryptoKey.yaml b/mmv1/products/kms/CryptoKey.yaml index bbfc7551db90..efa270a82173 100644 --- a/mmv1/products/kms/CryptoKey.yaml +++ b/mmv1/products/kms/CryptoKey.yaml @@ -80,7 +80,7 @@ properties: immutable: true url_param_only: true ignore_read: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels with user-defined metadata to apply to this resource. diff --git a/mmv1/products/logging/Metric.yaml b/mmv1/products/logging/Metric.yaml index 030758a8465d..5bcf2eae51bb 100644 --- a/mmv1/products/logging/Metric.yaml +++ b/mmv1/products/logging/Metric.yaml @@ -132,7 +132,7 @@ properties: - :CUMULATIVE required: true - !ruby/object:Api::Type::Array - name: labels + name: 'labels' description: | The set of labels that can be used to describe a specific instance of this metric type. For example, the appengine.googleapis.com/http/server/response_latencies metric type has a label @@ -206,28 +206,19 @@ properties: properties: - !ruby/object:Api::Type::Integer name: numFiniteBuckets - at_least_one_of: - - bucket_options.0.linear_buckets.0.num_finite_buckets - - bucket_options.0.linear_buckets.0.width - - bucket_options.0.linear_buckets.0.offset description: | Must be greater than 0. + required: true - !ruby/object:Api::Type::Double name: width - at_least_one_of: - - bucket_options.0.linear_buckets.0.num_finite_buckets - - bucket_options.0.linear_buckets.0.width - - bucket_options.0.linear_buckets.0.offset description: | Must be greater than 0. + required: true - !ruby/object:Api::Type::Double name: offset - at_least_one_of: - - bucket_options.0.linear_buckets.0.num_finite_buckets - - bucket_options.0.linear_buckets.0.width - - bucket_options.0.linear_buckets.0.offset description: | Lower bound of the first bucket. + required: true - !ruby/object:Api::Type::NestedObject name: exponentialBuckets at_least_one_of: @@ -240,28 +231,19 @@ properties: properties: - !ruby/object:Api::Type::Integer name: numFiniteBuckets - at_least_one_of: - - bucket_options.0.exponential_buckets.0.num_finite_buckets - - bucket_options.0.exponential_buckets.0.growth_factor - - bucket_options.0.exponential_buckets.0.scale description: | Must be greater than 0. + required: true - !ruby/object:Api::Type::Double name: growthFactor - at_least_one_of: - - bucket_options.0.exponential_buckets.0.num_finite_buckets - - bucket_options.0.exponential_buckets.0.growth_factor - - bucket_options.0.exponential_buckets.0.scale description: | Must be greater than 1. + required: true - !ruby/object:Api::Type::Double name: scale - at_least_one_of: - - bucket_options.0.exponential_buckets.0.num_finite_buckets - - bucket_options.0.exponential_buckets.0.growth_factor - - bucket_options.0.exponential_buckets.0.scale description: | Must be greater than 0. + required: true - !ruby/object:Api::Type::NestedObject name: explicitBuckets at_least_one_of: diff --git a/mmv1/products/looker/Instance.yaml b/mmv1/products/looker/Instance.yaml index 7e645702f776..5aa64984ab7e 100644 --- a/mmv1/products/looker/Instance.yaml +++ b/mmv1/products/looker/Instance.yaml @@ -57,7 +57,6 @@ examples: client_id: 'my-client-id' client_secret: 'my-client-secret' test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "looker-instance-enterprise")' kms_key_name: 'acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' parameters: - !ruby/object:Api::Type::String @@ -345,14 +344,12 @@ properties: - LOOKER_CORE_STANDARD_ANNUAL: subscription standard instance - LOOKER_CORE_ENTERPRISE_ANNUAL: subscription enterprise instance - LOOKER_CORE_EMBED_ANNUAL: subscription embed instance - - LOOKER_MODELER: standalone modeling service values: - :LOOKER_CORE_TRIAL - :LOOKER_CORE_STANDARD - :LOOKER_CORE_STANDARD_ANNUAL - :LOOKER_CORE_ENTERPRISE_ANNUAL - :LOOKER_CORE_EMBED_ANNUAL - - :LOOKER_MODELER default_value: :LOOKER_CORE_TRIAL immutable: true - !ruby/object:Api::Type::Boolean diff --git a/mmv1/products/memcache/Instance.yaml b/mmv1/products/memcache/Instance.yaml index 11637e7d1cd4..fc24167d1212 100644 --- a/mmv1/products/memcache/Instance.yaml +++ b/mmv1/products/memcache/Instance.yaml @@ -37,8 +37,6 @@ examples: instance_name: 'test-instance' network_name: 'test-network' address_name: 'address' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "memcache-instance-basic")' parameters: - !ruby/object:Api::Type::String name: 'region' @@ -101,7 +99,7 @@ properties: name: 'discoveryEndpoint' description: Endpoint for Discovery API output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/metastore/Federation.yaml b/mmv1/products/metastore/Federation.yaml index b4fadf816107..565f0d9f8077 100644 --- a/mmv1/products/metastore/Federation.yaml +++ b/mmv1/products/metastore/Federation.yaml @@ -92,7 +92,7 @@ properties: output: true description: | The relative resource name of the metastore federation. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the metastore federation.' - !ruby/object:Api::Type::String diff --git a/mmv1/products/metastore/Service.yaml b/mmv1/products/metastore/Service.yaml index b4097033db09..ec54fa3e782b 100644 --- a/mmv1/products/metastore/Service.yaml +++ b/mmv1/products/metastore/Service.yaml @@ -155,7 +155,7 @@ properties: output: true description: | The relative resource name of the metastore service. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'User-defined labels for the metastore service.' # This is an x-product resource reference. diff --git a/mmv1/products/mlengine/Model.yaml b/mmv1/products/mlengine/Model.yaml index 9ea33d2aa9f9..281cc3665f2e 100644 --- a/mmv1/products/mlengine/Model.yaml +++ b/mmv1/products/mlengine/Model.yaml @@ -96,6 +96,6 @@ properties: description: If true, online prediction nodes send stderr and stdout streams to Stackdriver Logging - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: One or more labels that you can add, to organize your models. diff --git a/mmv1/products/monitoring/AlertPolicy.yaml b/mmv1/products/monitoring/AlertPolicy.yaml index 6ec4e791e16f..d33ba8bd9764 100644 --- a/mmv1/products/monitoring/AlertPolicy.yaml +++ b/mmv1/products/monitoring/AlertPolicy.yaml @@ -859,7 +859,7 @@ properties: alerting rule, then this value should be taken from the enclosing rule group. - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' description: | Labels to add to or overwrite in the PromQL query result. Label names must be valid. diff --git a/mmv1/products/monitoring/MetricDescriptor.yaml b/mmv1/products/monitoring/MetricDescriptor.yaml index d83d04bc820b..721677e7eba7 100644 --- a/mmv1/products/monitoring/MetricDescriptor.yaml +++ b/mmv1/products/monitoring/MetricDescriptor.yaml @@ -69,11 +69,12 @@ properties: the DNS name custom.googleapis.com, external.googleapis.com, or logging.googleapis.com/user/. - !ruby/object:Api::Type::Array - name: labels + name: 'labels' description: The set of labels that can be used to describe a specific instance of this metric type. In order to delete a label, the entire resource must be deleted, then created with the desired labels. + immutable: true is_set: true item_type: !ruby/object:Api::Type::NestedObject properties: @@ -161,7 +162,6 @@ properties: Use sentence case without an ending period, for example "Request count". - !ruby/object:Api::Type::NestedObject name: metadata - immutable: true description: Metadata which can be used to guide usage of the metric. ignore_read: true properties: diff --git a/mmv1/products/monitoring/NotificationChannel.yaml b/mmv1/products/monitoring/NotificationChannel.yaml index 7c67e49d806d..0efb110aef66 100644 --- a/mmv1/products/monitoring/NotificationChannel.yaml +++ b/mmv1/products/monitoring/NotificationChannel.yaml @@ -79,7 +79,7 @@ custom_diff: [ ] properties: - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' description: | Configuration fields that define the channel and its behavior. The permissible and required labels are specified in the diff --git a/mmv1/products/monitoring/UptimeCheckConfig.yaml b/mmv1/products/monitoring/UptimeCheckConfig.yaml index b1d923680ebc..3af431687199 100644 --- a/mmv1/products/monitoring/UptimeCheckConfig.yaml +++ b/mmv1/products/monitoring/UptimeCheckConfig.yaml @@ -402,7 +402,7 @@ properties: resource types (https://cloud.google.com/logging/docs/api/v2/resource-list). - !ruby/object:Api::Type::KeyValuePairs - name: labels + name: 'labels' immutable: true required: true description: diff --git a/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml b/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml index 174943e84a94..89551984b665 100644 --- a/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml +++ b/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml @@ -205,7 +205,7 @@ properties: output: true description: | The type of underlying resources used to create the connection. - - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | User-defined labels. diff --git a/mmv1/products/networkmanagement/ConnectivityTest.yaml b/mmv1/products/networkmanagement/ConnectivityTest.yaml index b68d0d350f43..35264ff07a99 100644 --- a/mmv1/products/networkmanagement/ConnectivityTest.yaml +++ b/mmv1/products/networkmanagement/ConnectivityTest.yaml @@ -204,7 +204,7 @@ properties: This is applicable to scenarios where a test can cross project boundaries. item_type: Api::Type::String - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels to represent user-provided metadata. diff --git a/mmv1/products/networksecurity/AddressGroup.yaml b/mmv1/products/networksecurity/AddressGroup.yaml index 09177a4a472b..87d2b9a19951 100644 --- a/mmv1/products/networksecurity/AddressGroup.yaml +++ b/mmv1/products/networksecurity/AddressGroup.yaml @@ -95,8 +95,8 @@ properties: A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | Set of label tags associated with the AddressGroup resource. An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. diff --git a/mmv1/products/networksecurity/AuthorizationPolicy.yaml b/mmv1/products/networksecurity/AuthorizationPolicy.yaml index f4af9f533eee..daa0dda1a7fe 100644 --- a/mmv1/products/networksecurity/AuthorizationPolicy.yaml +++ b/mmv1/products/networksecurity/AuthorizationPolicy.yaml @@ -84,7 +84,7 @@ properties: description: | Time the AuthorizationPolicy was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the AuthorizationPolicy resource. diff --git a/mmv1/products/networksecurity/ClientTlsPolicy.yaml b/mmv1/products/networksecurity/ClientTlsPolicy.yaml index 7773d5354768..0f87404c7b78 100644 --- a/mmv1/products/networksecurity/ClientTlsPolicy.yaml +++ b/mmv1/products/networksecurity/ClientTlsPolicy.yaml @@ -86,7 +86,7 @@ properties: description: | Time the ClientTlsPolicy was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the ClientTlsPolicy resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networksecurity/ServerTlsPolicy.yaml b/mmv1/products/networksecurity/ServerTlsPolicy.yaml index c300f03f5e12..556af18eb7ef 100644 --- a/mmv1/products/networksecurity/ServerTlsPolicy.yaml +++ b/mmv1/products/networksecurity/ServerTlsPolicy.yaml @@ -90,7 +90,7 @@ properties: description: | Time the ServerTlsPolicy was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the ServerTlsPolicy resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/EdgeCacheKeyset.yaml b/mmv1/products/networkservices/EdgeCacheKeyset.yaml index d8b79ef24b28..b1ec5986023d 100644 --- a/mmv1/products/networkservices/EdgeCacheKeyset.yaml +++ b/mmv1/products/networkservices/EdgeCacheKeyset.yaml @@ -74,7 +74,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the EdgeCache resource.' - !ruby/object:Api::Type::Array diff --git a/mmv1/products/networkservices/EdgeCacheOrigin.yaml b/mmv1/products/networkservices/EdgeCacheOrigin.yaml index 3f2205323602..4b97a7a51c82 100644 --- a/mmv1/products/networkservices/EdgeCacheOrigin.yaml +++ b/mmv1/products/networkservices/EdgeCacheOrigin.yaml @@ -84,7 +84,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the EdgeCache resource.' - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/EdgeCacheService.yaml b/mmv1/products/networkservices/EdgeCacheService.yaml index ac6c6960246a..c64160154345 100644 --- a/mmv1/products/networkservices/EdgeCacheService.yaml +++ b/mmv1/products/networkservices/EdgeCacheService.yaml @@ -85,7 +85,7 @@ properties: name: 'description' description: | A human-readable description of the resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Set of label tags associated with the EdgeCache resource.' - !ruby/object:Api::Type::Boolean diff --git a/mmv1/products/networkservices/EndpointPolicy.yaml b/mmv1/products/networkservices/EndpointPolicy.yaml index ff3effffd4cf..8a2088f5a227 100644 --- a/mmv1/products/networkservices/EndpointPolicy.yaml +++ b/mmv1/products/networkservices/EndpointPolicy.yaml @@ -76,7 +76,7 @@ properties: description: | Time the TcpRoute was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the TcpRoute resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/Gateway.yaml b/mmv1/products/networkservices/Gateway.yaml index 49843a39241c..c04a69be5f5e 100644 --- a/mmv1/products/networkservices/Gateway.yaml +++ b/mmv1/products/networkservices/Gateway.yaml @@ -128,7 +128,7 @@ properties: description: | Time the AccessPolicy was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the Gateway resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/GrpcRoute.yaml b/mmv1/products/networkservices/GrpcRoute.yaml index c8bd32e506c9..14efbe9ecf17 100644 --- a/mmv1/products/networkservices/GrpcRoute.yaml +++ b/mmv1/products/networkservices/GrpcRoute.yaml @@ -88,7 +88,7 @@ properties: description: | Time the GrpcRoute was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the GrpcRoute resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/HttpRoute.yaml b/mmv1/products/networkservices/HttpRoute.yaml index 77575f4dcb0f..cb60ad50e730 100644 --- a/mmv1/products/networkservices/HttpRoute.yaml +++ b/mmv1/products/networkservices/HttpRoute.yaml @@ -97,7 +97,7 @@ properties: description: | Time the HttpRoute was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the HttpRoute resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/Mesh.yaml b/mmv1/products/networkservices/Mesh.yaml index cc61b1d1b7c5..deb7437b985a 100644 --- a/mmv1/products/networkservices/Mesh.yaml +++ b/mmv1/products/networkservices/Mesh.yaml @@ -83,7 +83,7 @@ properties: description: | Time the Mesh was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the Mesh resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/ServiceBinding.yaml b/mmv1/products/networkservices/ServiceBinding.yaml index ffda6f36d650..c13d23a7c94c 100644 --- a/mmv1/products/networkservices/ServiceBinding.yaml +++ b/mmv1/products/networkservices/ServiceBinding.yaml @@ -72,7 +72,7 @@ properties: description: | Time the ServiceBinding was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the ServiceBinding resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/networkservices/TcpRoute.yaml b/mmv1/products/networkservices/TcpRoute.yaml index 27be31a1b54f..7fae44f3f0bc 100644 --- a/mmv1/products/networkservices/TcpRoute.yaml +++ b/mmv1/products/networkservices/TcpRoute.yaml @@ -104,7 +104,7 @@ properties: description: | Time the TcpRoute was updated in UTC. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Set of label tags associated with the TcpRoute resource. - !ruby/object:Api::Type::String diff --git a/mmv1/products/notebooks/Instance.yaml b/mmv1/products/notebooks/Instance.yaml index 6986b560e77e..c6fc8de89d4c 100644 --- a/mmv1/products/notebooks/Instance.yaml +++ b/mmv1/products/notebooks/Instance.yaml @@ -80,8 +80,9 @@ examples: test_env_vars: service_account: :SERVICE_ACCT custom_code: !ruby/object:Provider::Terraform::CustomCode - constants: templates/terraform/constants/notebooks_instance.go update_encoder: templates/terraform/update_encoder/notebooks_instance.go +state_upgraders: true +schema_version: 1 parameters: - !ruby/object:Api::Type::ResourceRef name: 'location' @@ -344,15 +345,13 @@ properties: Format: projects/{project_id}/regions/{region}/subnetworks/{subnetwork_id} diff_suppress_func: tpgresource.CompareSelfLinkOrResourceName default_from_api: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels to apply to this instance. These can be later modified by the setLabels method. An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. update_verb: :PATCH update_url: 'projects/{{project}}/locations/{{location}}/instances/{{name}}:setLabels' - default_from_api: true - diff_suppress_func: NotebooksInstanceLabelDiffSuppress - !ruby/object:Api::Type::Array name: 'tags' description: | diff --git a/mmv1/products/privateca/CaPool.yaml b/mmv1/products/privateca/CaPool.yaml index 6886aef18c94..5ffda3b7cacc 100644 --- a/mmv1/products/privateca/CaPool.yaml +++ b/mmv1/products/privateca/CaPool.yaml @@ -480,8 +480,8 @@ properties: values: - :PEM - :DER - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | Labels with user-defined metadata. diff --git a/mmv1/products/privateca/Certificate.yaml b/mmv1/products/privateca/Certificate.yaml index 86337ac8eb32..aed9215977fb 100644 --- a/mmv1/products/privateca/Certificate.yaml +++ b/mmv1/products/privateca/Certificate.yaml @@ -544,132 +544,6 @@ properties: leading period (like `.example.com`) output: true item_type: Api::Type::String - - !ruby/object:Api::Type::NestedObject - name: 'configValues' - deprecation_message: >- - `config_values` is deprecated and will be removed in a future release. Use `x509_description` instead. - output: true - description: | - Describes some of the technical fields in a certificate. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'keyUsage' - output: true - description: | - Indicates the intended use for keys that correspond to a certificate. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'baseKeyUsage' - output: true - description: | - Describes high-level ways in which a key may be used. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'keyUsageOptions' - output: true - description: | - Describes high-level ways in which a key may be used. - properties: - - !ruby/object:Api::Type::Boolean - name: 'digitalSignature' - output: true - description: | - The key may be used for digital signatures. - - !ruby/object:Api::Type::Boolean - name: 'contentCommitment' - output: true - description: | - The key may be used for cryptographic commitments. Note that this may also be referred to as "non-repudiation". - - !ruby/object:Api::Type::Boolean - name: 'keyEncipherment' - output: true - description: | - The key may be used to encipher other keys. - - !ruby/object:Api::Type::Boolean - name: 'dataEncipherment' - output: true - description: | - The key may be used to encipher data. - - !ruby/object:Api::Type::Boolean - name: 'keyAgreement' - output: true - description: | - The key may be used in a key agreement protocol. - - !ruby/object:Api::Type::Boolean - name: 'certSign' - output: true - description: | - The key may be used to sign certificates. - - !ruby/object:Api::Type::Boolean - name: 'crlSign' - output: true - description: | - The key may be used sign certificate revocation lists. - - !ruby/object:Api::Type::Boolean - name: 'encipherOnly' - output: true - description: | - The key may be used to encipher only. - - !ruby/object:Api::Type::Boolean - name: 'decipherOnly' - output: true - description: | - The key may be used to decipher only. - - !ruby/object:Api::Type::NestedObject - name: 'extendedKeyUsage' - output: true - description: | - Describes high-level ways in which a key may be used. - properties: - - !ruby/object:Api::Type::Boolean - name: 'serverAuth' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.1. Officially described as "TLS WWW server authentication", though regularly used for non-WWW TLS. - - !ruby/object:Api::Type::Boolean - name: 'clientAuth' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.2. Officially described as "TLS WWW client authentication", though regularly used for non-WWW TLS. - - !ruby/object:Api::Type::Boolean - name: 'codeSigning' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.3. Officially described as "Signing of downloadable executable code client authentication". - - !ruby/object:Api::Type::Boolean - name: 'emailProtection' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.4. Officially described as "Email protection". - - !ruby/object:Api::Type::Boolean - name: 'timeStamping' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.8. Officially described as "Binding the hash of an object to a time". - - !ruby/object:Api::Type::Boolean - name: 'ocspSigning' - output: true - description: | - Corresponds to OID 1.3.6.1.5.5.7.3.9. Officially described as "Signing OCSP responses". - - !ruby/object:Api::Type::Array - name: 'unknownExtendedKeyUsages' - output: true - description: | - An ObjectId specifies an object identifier (OID). These provide context and describe types in ASN.1 messages. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::NestedObject - name: 'obectId' - output: true - description: | - Required. Describes how some of the technical fields in a certificate should be populated. - properties: - - !ruby/object:Api::Type::Array - name: 'objectIdPath' - output: true - item_type: Api::Type::Integer - description: | - An ObjectId specifies an object identifier (OID). These provide context and describe types in ASN.1 messages. - !ruby/object:Api::Type::NestedObject name: 'publicKey' output: true @@ -740,14 +614,6 @@ properties: description: | The chain that may be used to verify the X.509 certificate. Expected to be in issuer-to-root order according to RFC 5246. item_type: Api::Type::String - - !ruby/object:Api::Type::Array - name: 'pemCertificates' - deprecation_message: >- - `pem_certificates` is deprecated and will be removed in a future major release. Use `pem_certificate_chain` instead. - output: true - description: | - Required. Expected to be in leaf-to-root order according to RFC 5246. - item_type: Api::Type::String - !ruby/object:Api::Type::Time name: 'createTime' description: | @@ -772,7 +638,7 @@ properties: omitted, no template will be used. This template must be in the same location as the Certificate. diff_suppress_func: 'tpgresource.CompareResourceNames' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels with user-defined metadata to apply to this resource. diff --git a/mmv1/products/privateca/CertificateAuthority.yaml b/mmv1/products/privateca/CertificateAuthority.yaml index 99d9e118c14f..85e8d98598c2 100644 --- a/mmv1/products/privateca/CertificateAuthority.yaml +++ b/mmv1/products/privateca/CertificateAuthority.yaml @@ -735,8 +735,8 @@ properties: A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: | Labels with user-defined metadata. diff --git a/mmv1/products/pubsub/Subscription.yaml b/mmv1/products/pubsub/Subscription.yaml index 2f40689d689c..1def915ef94c 100644 --- a/mmv1/products/pubsub/Subscription.yaml +++ b/mmv1/products/pubsub/Subscription.yaml @@ -107,7 +107,7 @@ properties: pattern: 'projects/{{project}}/topics/{{topic}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/computed_subscription_topic.erb - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Subscription. diff --git a/mmv1/products/pubsub/Topic.yaml b/mmv1/products/pubsub/Topic.yaml index 6bb9290a058f..16f25f459596 100644 --- a/mmv1/products/pubsub/Topic.yaml +++ b/mmv1/products/pubsub/Topic.yaml @@ -93,7 +93,7 @@ properties: (`service-{{PROJECT_NUMBER}}@gcp-sa-pubsub.iam.gserviceaccount.com`) must have `roles/cloudkms.cryptoKeyEncrypterDecrypter` to use this feature. The expected format is `projects/*/locations/*/keyRings/*/cryptoKeys/*` - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Topic. diff --git a/mmv1/products/redis/Instance.yaml b/mmv1/products/redis/Instance.yaml index eaab27ffdb55..3aa6a3a8d434 100644 --- a/mmv1/products/redis/Instance.yaml +++ b/mmv1/products/redis/Instance.yaml @@ -28,6 +28,7 @@ timeouts: !ruby/object:Api::Timeouts update_minutes: 20 delete_minutes: 20 autogen_async: true +skip_default_cdiff: true custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/redis_location_id_for_fallback_zone.go.erb decoder: templates/terraform/decoders/redis_instance.go.erb @@ -35,6 +36,7 @@ custom_code: !ruby/object:Provider::Terraform::CustomCode constants: templates/terraform/constants/redis_instance.go custom_diff: [ 'customdiff.ForceNewIfChange("redis_version", isRedisVersionDecreasing)', + 'tpgresource.DefaultProviderProject', ] examples: - !ruby/object:Provider::Terraform::Examples @@ -65,8 +67,6 @@ examples: instance_name: 'private-cache' address_name: 'address' network_name: 'redis-test-network' - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "redis-private-service")' - !ruby/object:Provider::Terraform::Examples name: 'redis_instance_mrr' primary_resource_id: 'cache' @@ -156,7 +156,7 @@ properties: Hostname or IP address of the exposed Redis endpoint used by clients to connect to the service. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: Resource labels to represent user provided metadata. - !ruby/object:Api::Type::KeyValuePairs diff --git a/mmv1/products/secretmanager/Secret.yaml b/mmv1/products/secretmanager/Secret.yaml index cd6ba56029b8..ce86d7c0b347 100644 --- a/mmv1/products/secretmanager/Secret.yaml +++ b/mmv1/products/secretmanager/Secret.yaml @@ -71,7 +71,7 @@ properties: output: true description: | The time at which the Secret was created. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: labels description: | The labels assigned to this Secret. @@ -86,7 +86,7 @@ properties: An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: annotations description: | Custom metadata about the secret. @@ -119,31 +119,17 @@ properties: name: replication required: true immutable: true - custom_expand: templates/terraform/custom_expand/secret_manager_replication.go.erb - custom_flatten: templates/terraform/custom_flatten/secret_manager_replication.go.erb description: | The replication policy of the secret data attached to the Secret. It cannot be changed after the Secret has been created. properties: - - !ruby/object:Api::Type::Boolean - name: automatic - # Immutability is handled by the custom diff function until "automatic" is removed - # immutable: true - exactly_one_of: - - replication.0.automatic - - replication.0.user_managed - - replication.0.auto - deprecation_message: >- - `automatic` is deprecated and will be removed in a future major release. Use `auto` instead. - description: | - The Secret will automatically be replicated without any restrictions. - !ruby/object:Api::Type::NestedObject name: auto api_name: automatic - # Immutability is handled by the custom diff function until "automatic" is removed - # immutable: true + immutable: true + allow_empty_object: true + send_empty_value: true exactly_one_of: - - replication.0.automatic - replication.0.user_managed - replication.0.auto description: | @@ -165,7 +151,6 @@ properties: name: userManaged immutable: true exactly_one_of: - - replication.0.automatic - replication.0.user_managed - replication.0.auto description: | diff --git a/mmv1/products/servicedirectory/Namespace.yaml b/mmv1/products/servicedirectory/Namespace.yaml index 8224784f9dd1..8d76947730ef 100644 --- a/mmv1/products/servicedirectory/Namespace.yaml +++ b/mmv1/products/servicedirectory/Namespace.yaml @@ -72,7 +72,7 @@ properties: The resource name for the namespace in the format `projects/*/locations/*/namespaces/*`. output: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Resource labels associated with this Namespace. No more than 64 user diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index bbc63c307ff6..6903c10a4416 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -143,7 +143,7 @@ properties: - num_nodes - processing_units default_from_api: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | An object containing a list of "key": value pairs. diff --git a/mmv1/products/storage/Bucket.yaml b/mmv1/products/storage/Bucket.yaml index bbf776e2f8df..979c5716bd58 100644 --- a/mmv1/products/storage/Bucket.yaml +++ b/mmv1/products/storage/Bucket.yaml @@ -464,7 +464,7 @@ properties: object is missing, if applicable, the service will return the named object from this bucket as the content for a 404 Not Found result. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | Labels applied to this bucket. A list of key->value pairs. diff --git a/mmv1/products/tpu/Node.yaml b/mmv1/products/tpu/Node.yaml index e3d1ac84fdc5..cd8e4a1136f7 100644 --- a/mmv1/products/tpu/Node.yaml +++ b/mmv1/products/tpu/Node.yaml @@ -36,6 +36,7 @@ examples: vars: node_name: 'test-tpu' global_address_name: 'my-global-address' + network_name: 'tpu-node-network' custom_code: !ruby/object:Provider::Terraform::CustomCode constants: 'templates/terraform/constants/tpu_node.erb' custom_diff: [ @@ -153,7 +154,7 @@ properties: output: true description: | The port of this network endpoint. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' immutable: true description: Resource labels to represent user provided metadata. diff --git a/mmv1/products/vertexai/Dataset.yaml b/mmv1/products/vertexai/Dataset.yaml index 6f27a6d908e7..71f4bfad9ad3 100644 --- a/mmv1/products/vertexai/Dataset.yaml +++ b/mmv1/products/vertexai/Dataset.yaml @@ -81,11 +81,10 @@ properties: output: true description: | The timestamp of when the dataset was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Workflow. - default_from_api: true - !ruby/object:Api::Type::NestedObject name: 'encryptionSpec' immutable: true diff --git a/mmv1/products/vertexai/Endpoint.yaml b/mmv1/products/vertexai/Endpoint.yaml index 900fd90ee5df..9bd52067d4e2 100644 --- a/mmv1/products/vertexai/Endpoint.yaml +++ b/mmv1/products/vertexai/Endpoint.yaml @@ -359,8 +359,8 @@ properties: "overwrite" update happens. output: true ignore_read: true - - !ruby/object:Api::Type::KeyValuePairs - name: labels + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: The labels with user-defined metadata to organize your Endpoints. Label keys and values can be no longer than 64 characters (Unicode codepoints), diff --git a/mmv1/products/vertexai/Featurestore.yaml b/mmv1/products/vertexai/Featurestore.yaml index d8ce854c04d3..40bb998ec75f 100644 --- a/mmv1/products/vertexai/Featurestore.yaml +++ b/mmv1/products/vertexai/Featurestore.yaml @@ -145,7 +145,7 @@ properties: output: true description: | The timestamp of when the featurestore was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Featurestore. diff --git a/mmv1/products/vertexai/FeaturestoreEntitytype.yaml b/mmv1/products/vertexai/FeaturestoreEntitytype.yaml index c7f097d95a1b..53fefc21ecfa 100644 --- a/mmv1/products/vertexai/FeaturestoreEntitytype.yaml +++ b/mmv1/products/vertexai/FeaturestoreEntitytype.yaml @@ -132,7 +132,7 @@ properties: output: true description: | The timestamp of when the featurestore was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this EntityType. diff --git a/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml b/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml index 4152ab0e6327..b2379118329e 100644 --- a/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml +++ b/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml @@ -105,7 +105,7 @@ properties: output: true description: | The timestamp when the entity type was most recently updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to the feature. diff --git a/mmv1/products/vertexai/Index.yaml b/mmv1/products/vertexai/Index.yaml index 30afd0d49c9b..28efea9b6e76 100644 --- a/mmv1/products/vertexai/Index.yaml +++ b/mmv1/products/vertexai/Index.yaml @@ -223,7 +223,7 @@ properties: description: Used to perform consistent read-modify-write updates. output: true ignore_read: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: The labels with user-defined metadata to organize your Indexes. - !ruby/object:Api::Type::String diff --git a/mmv1/products/vertexai/IndexEndpoint.yaml b/mmv1/products/vertexai/IndexEndpoint.yaml index 465147a362ed..1fd415896a8e 100644 --- a/mmv1/products/vertexai/IndexEndpoint.yaml +++ b/mmv1/products/vertexai/IndexEndpoint.yaml @@ -51,8 +51,6 @@ examples: vars: address_name: "address-name" network_name: "network-name" - test_vars_overrides: - network_name: 'acctest.BootstrapSharedTestNetwork(t, "vertex-ai-index-endpoint")' - !ruby/object:Provider::Terraform::Examples name: "vertex_ai_index_endpoint_with_public_endpoint" primary_resource_id: "index_endpoint" @@ -83,7 +81,7 @@ properties: description: Used to perform consistent read-modify-write updates. output: true ignore_read: true - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: The labels with user-defined metadata to organize your Indexes. - !ruby/object:Api::Type::String diff --git a/mmv1/products/vertexai/Tensorboard.yaml b/mmv1/products/vertexai/Tensorboard.yaml index 99c2895a1e1c..3d341ba2328e 100644 --- a/mmv1/products/vertexai/Tensorboard.yaml +++ b/mmv1/products/vertexai/Tensorboard.yaml @@ -113,7 +113,7 @@ properties: output: true description: | The timestamp of when the Tensorboard was last updated in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | The labels with user-defined metadata to organize your Tensorboards. diff --git a/mmv1/products/workflows/Workflow.yaml b/mmv1/products/workflows/Workflow.yaml index 80d80a05e276..3c7a4baad876 100644 --- a/mmv1/products/workflows/Workflow.yaml +++ b/mmv1/products/workflows/Workflow.yaml @@ -77,7 +77,7 @@ properties: name: 'state' output: true description: State of the workflow deployment. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | A set of key/value label pairs to assign to this Workflow. diff --git a/mmv1/products/workstations/Workstation.yaml b/mmv1/products/workstations/Workstation.yaml index 39608a4ba043..9bac34f941aa 100644 --- a/mmv1/products/workstations/Workstation.yaml +++ b/mmv1/products/workstations/Workstation.yaml @@ -117,12 +117,12 @@ properties: name: 'displayName' description: | Human-readable name for this resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Client-specified labels that are applied to the resource and that are also propagated to the underlying Compute Engine resources.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: 'Client-specified annotations. This is distinct from labels.' - !ruby/object:Api::Type::KeyValuePairs diff --git a/mmv1/products/workstations/WorkstationCluster.yaml b/mmv1/products/workstations/WorkstationCluster.yaml index ed0f940c896d..f06be329f74e 100644 --- a/mmv1/products/workstations/WorkstationCluster.yaml +++ b/mmv1/products/workstations/WorkstationCluster.yaml @@ -89,8 +89,8 @@ properties: output: true description: | The system-generated UID of the resource. - - !ruby/object:Api::Type::KeyValuePairs - name: "labels" + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' description: "Client-specified labels that are applied to the resource and that are also propagated to the underlying Compute Engine resources." @@ -118,8 +118,8 @@ properties: Whether this resource is in degraded mode, in which case it may require user action to restore full functionality. Details can be found in the conditions field. output: true - - !ruby/object:Api::Type::KeyValuePairs - name: "annotations" + - !ruby/object:Api::Type::KeyValueAnnotations + name: 'annotations' description: "Client-specified annotations. This is distinct from labels." - !ruby/object:Api::Type::Fingerprint name: "etag" diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index d41c39ffd811..ea500032c3d6 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -153,12 +153,12 @@ properties: name: 'displayName' description: | Human-readable name for this resource. - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: 'Client-specified labels that are applied to the resource and that are also propagated to the underlying Compute Engine resources.' - - !ruby/object:Api::Type::KeyValuePairs + - !ruby/object:Api::Type::KeyValueAnnotations name: 'annotations' description: 'Client-specified annotations. This is distinct from labels.' - !ruby/object:Api::Type::Fingerprint diff --git a/mmv1/provider/core.rb b/mmv1/provider/core.rb index fb66cbbc4377..0cdf06f8c4e9 100644 --- a/mmv1/provider/core.rb +++ b/mmv1/provider/core.rb @@ -401,7 +401,8 @@ def field_specific_update_methods(properties) # method and group them by update url & verb. def properties_by_custom_update(properties) update_props = properties.reject do |p| - p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP + p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP || + p.is_a?(Api::Type::KeyValueLabels) # effective_labels is used for update end update_props.group_by do |p| diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 3d2e9b2e1aa6..512a26b353bf 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -91,6 +91,10 @@ def tf_types Api::Type::NestedObject => 'schema.TypeList', Api::Type::Array => 'schema.TypeList', Api::Type::KeyValuePairs => 'schema.TypeMap', + Api::Type::KeyValueLabels => 'schema.TypeMap', + Api::Type::KeyValueTerraformLabels => 'schema.TypeMap', + Api::Type::KeyValueEffectiveLabels => 'schema.TypeMap', + Api::Type::KeyValueAnnotations => 'schema.TypeMap', Api::Type::Map => 'schema.TypeSet', Api::Type::Fingerprint => 'schema.TypeString' } @@ -101,7 +105,7 @@ def updatable?(resource, properties) end def force_new?(property, resource) - !property.output && + (!property.output || property.is_a?(Api::Type::KeyValueEffectiveLabels)) && (property.immutable || (resource.immutable && property.update_url.nil? && property.immutable.nil? && (property.parent.nil? || diff --git a/mmv1/templates/terraform/constants/cloud_run_domain_mapping.go.erb b/mmv1/templates/terraform/constants/cloud_run_domain_mapping.go.erb index 7ae3d75f1a55..eacab2177f96 100644 --- a/mmv1/templates/terraform/constants/cloud_run_domain_mapping.go.erb +++ b/mmv1/templates/terraform/constants/cloud_run_domain_mapping.go.erb @@ -1,21 +1,9 @@ -var domainMappingGoogleProvidedLabels = []string{ - "cloud.googleapis.com/location", - "run.googleapis.com/overrideAt", -} +func hasMetadata(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + newCount := diff.Get("metadata.#") -func DomainMappingLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - // Suppress diffs for the labels provided by Google - for _, label := range domainMappingGoogleProvidedLabels { - if strings.Contains(k, label) && new == "" { - return true - } + if newCount.(int) < 1 { + return fmt.Errorf("Insufficient \"metadata\" blocks. 1 \"metadata\" block is required.") } - // Let diff be determined by labels (above) - if strings.Contains(k, "labels.%") { - return true - } - - // For other keys, don't suppress diff. - return false -} + return nil +} \ No newline at end of file diff --git a/mmv1/templates/terraform/constants/cloud_run_service.go.erb b/mmv1/templates/terraform/constants/cloud_run_service.go.erb index eb4bd8e2c22b..0b748a4b3ba6 100644 --- a/mmv1/templates/terraform/constants/cloud_run_service.go.erb +++ b/mmv1/templates/terraform/constants/cloud_run_service.go.erb @@ -7,27 +7,6 @@ func revisionNameCustomizeDiff(_ context.Context, diff *schema.ResourceDiff, v i return nil } -var cloudRunGoogleProvidedAnnotations = regexp.MustCompile(`serving\.knative\.dev/(?:(?:creator)|(?:lastModifier))$|run\.googleapis\.com/(?:(?:ingress-status)|(?:operation-id))$|cloud\.googleapis\.com/(?:(?:location))`) - -func cloudrunAnnotationDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - // Suppress diffs for the annotations provided by Google - if cloudRunGoogleProvidedAnnotations.MatchString(k) && new == "" { - return true - } - - if strings.HasSuffix(k, "run.googleapis.com/ingress") { - return old == "all" && new == "" - } - - // Let diff be determined by annotations (above) - if strings.Contains(k, "annotations.%") { - return true - } - - // For other keys, don't suppress diff. - return false -} - var cloudRunGoogleProvidedTemplateAnnotations = regexp.MustCompile(`template\.0\.metadata\.0\.annotations\.run\.googleapis\.com/sandbox`) var cloudRunGoogleProvidedTemplateAnnotations_autoscaling_maxscale = regexp.MustCompile(`template\.0\.metadata\.0\.annotations\.autoscaling\.knative\.dev/maxScale`) @@ -46,23 +25,6 @@ func cloudrunTemplateAnnotationDiffSuppress(k, old, new string, d *schema.Resour return false } -var cloudRunGoogleProvidedLabels = regexp.MustCompile(`cloud\.googleapis\.com/(?:(?:location))`) - -func cloudrunLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - // Suppress diffs for the labels provided by Google - if cloudRunGoogleProvidedLabels.MatchString(k) && new == "" { - return true - } - - // Let diff be determined by labels (above) - if strings.Contains(k, "labels.%") { - return true - } - - // For other keys, don't suppress diff. - return false -} - var cloudRunGoogleProvidedTemplateLabels = []string{ "run.googleapis.com/startupProbeType", } diff --git a/mmv1/templates/terraform/constants/cloudiot.go.erb b/mmv1/templates/terraform/constants/cloudiot.go.erb deleted file mode 100644 index 03905061d6ef..000000000000 --- a/mmv1/templates/terraform/constants/cloudiot.go.erb +++ /dev/null @@ -1,241 +0,0 @@ -func expandCloudIotDeviceRegistryHTTPConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedHTTPEnabledState, err := expandCloudIotDeviceRegistryHTTPEnabledState(original["http_enabled_state"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedHTTPEnabledState); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["httpEnabledState"] = transformedHTTPEnabledState - } - - return transformed, nil -} - -func expandCloudIotDeviceRegistryHTTPEnabledState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandCloudIotDeviceRegistryMqttConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedMqttEnabledState, err := expandCloudIotDeviceRegistryMqttEnabledState(original["mqtt_enabled_state"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedMqttEnabledState); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["mqttEnabledState"] = transformedMqttEnabledState - } - - return transformed, nil -} - -func expandCloudIotDeviceRegistryMqttEnabledState(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandCloudIotDeviceRegistryStateNotificationConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedPubsubTopicName, err := expandCloudIotDeviceRegistryStateNotificationConfigPubsubTopicName(original["pubsub_topic_name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedPubsubTopicName); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["pubsubTopicName"] = transformedPubsubTopicName - } - - return transformed, nil -} - -func expandCloudIotDeviceRegistryStateNotificationConfigPubsubTopicName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandCloudIotDeviceRegistryCredentials(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedPublicKeyCertificate, err := expandCloudIotDeviceRegistryCredentialsPublicKeyCertificate(original["public_key_certificate"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedPublicKeyCertificate); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["publicKeyCertificate"] = transformedPublicKeyCertificate - } - - req = append(req, transformed) - } - - return req, nil -} - -func expandCloudIotDeviceRegistryCredentialsPublicKeyCertificate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedFormat, err := expandCloudIotDeviceRegistryPublicKeyCertificateFormat(original["format"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedFormat); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["format"] = transformedFormat - } - - transformedCertificate, err := expandCloudIotDeviceRegistryPublicKeyCertificateCertificate(original["certificate"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedCertificate); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["certificate"] = transformedCertificate - } - - return transformed, nil -} - -func expandCloudIotDeviceRegistryPublicKeyCertificateFormat(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandCloudIotDeviceRegistryPublicKeyCertificateCertificate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func flattenCloudIotDeviceRegistryCredentials(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - log.Printf("[DEBUG] Flattening device resitry credentials: %q", d.Id()) - if v == nil { - log.Printf("[DEBUG] The credentials array is nil: %q", d.Id()) - return v - } - l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) - for _, raw := range l { - original := raw.(map[string]interface{}) - log.Printf("[DEBUG] Original credential: %+v", original) - if len(original) < 1 { - log.Printf("[DEBUG] Excluding empty credential that the API returned. %q", d.Id()) - continue - } - log.Printf("[DEBUG] Credentials array before appending a new credential: %+v", transformed) - transformed = append(transformed, map[string]interface{}{ - "public_key_certificate": flattenCloudIotDeviceRegistryCredentialsPublicKeyCertificate(original["publicKeyCertificate"], d, config), - }) - log.Printf("[DEBUG] Credentials array after appending a new credential: %+v", transformed) - } - return transformed -} - -func flattenCloudIotDeviceRegistryCredentialsPublicKeyCertificate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - log.Printf("[DEBUG] Flattening device resitry credentials public key certificate: %q", d.Id()) - if v == nil { - log.Printf("[DEBUG] The public key certificate is nil: %q", d.Id()) - return v - } - - original := v.(map[string]interface{}) - log.Printf("[DEBUG] Original public key certificate: %+v", original) - transformed := make(map[string]interface{}) - - transformedPublicKeyCertificateFormat := flattenCloudIotDeviceRegistryPublicKeyCertificateFormat(original["format"], d, config) - transformed["format"] = transformedPublicKeyCertificateFormat - - transformedPublicKeyCertificateCertificate := flattenCloudIotDeviceRegistryPublicKeyCertificateCertificate(original["certificate"], d, config) - transformed["certificate"] = transformedPublicKeyCertificateCertificate - - log.Printf("[DEBUG] Transformed public key certificate: %+v", transformed) - - return transformed -} - -func flattenCloudIotDeviceRegistryPublicKeyCertificateFormat(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenCloudIotDeviceRegistryPublicKeyCertificateCertificate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenCloudIotDeviceRegistryHTTPConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - if v == nil { - return v - } - - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedHTTPEnabledState := flattenCloudIotDeviceRegistryHTTPConfigHTTPEnabledState(original["httpEnabledState"], d, config) - transformed["http_enabled_state"] = transformedHTTPEnabledState - - return transformed -} - -func flattenCloudIotDeviceRegistryHTTPConfigHTTPEnabledState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenCloudIotDeviceRegistryMqttConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - if v == nil { - return v - } - - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedMqttEnabledState := flattenCloudIotDeviceRegistryMqttConfigMqttEnabledState(original["mqttEnabledState"], d, config) - transformed["mqtt_enabled_state"] = transformedMqttEnabledState - - return transformed -} - -func flattenCloudIotDeviceRegistryMqttConfigMqttEnabledState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenCloudIotDeviceRegistryStateNotificationConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - log.Printf("[DEBUG] Flattening state notification config: %+v", v) - if v == nil { - return v - } - - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedPubsubTopicName := flattenCloudIotDeviceRegistryStateNotificationConfigPubsubTopicName(original["pubsubTopicName"], d, config) - if val := reflect.ValueOf(transformedPubsubTopicName); val.IsValid() && !tpgresource.IsEmptyValue(val) { - log.Printf("[DEBUG] pubsub topic name is not null: %v", d.Get("pubsub_topic_name")) - transformed["pubsub_topic_name"] = transformedPubsubTopicName - } - - - return transformed -} - -func flattenCloudIotDeviceRegistryStateNotificationConfigPubsubTopicName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func ValidateCloudIotDeviceRegistryID(v interface{}, k string) (warnings []string, errors []error) { - value := v.(string) - if strings.HasPrefix(value, "goog") { - errors = append(errors, fmt.Errorf( - "%q (%q) can not start with \"goog\"", k, value)) - } - if !regexp.MustCompile(verify.CloudIoTIdRegex).MatchString(value) { - errors = append(errors, fmt.Errorf( - "%q (%q) doesn't match regexp %q", k, value, verify.CloudIoTIdRegex)) - } - return -} - -func validateCloudIotDeviceRegistrySubfolderMatch(v interface{}, k string) (warnings []string, errors []error) { - value := v.(string) - if strings.HasPrefix(value, "/") { - errors = append(errors, fmt.Errorf( - "%q (%q) can not start with '/'", k, value)) - } - return -} diff --git a/mmv1/templates/terraform/constants/notebooks_instance.go b/mmv1/templates/terraform/constants/notebooks_instance.go deleted file mode 100644 index 11fc19272311..000000000000 --- a/mmv1/templates/terraform/constants/notebooks_instance.go +++ /dev/null @@ -1,16 +0,0 @@ -const notebooksInstanceGoogleProvidedLabel = "goog-caip-notebook" - -func NotebooksInstanceLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - // Suppress diffs for the label provided by Google - if strings.Contains(k, notebooksInstanceGoogleProvidedLabel) && new == "" { - return true - } - - // Let diff be determined by labels (above) - if strings.Contains(k, "labels.%") { - return true - } - - // For other keys, don't suppress diff. - return false -} diff --git a/mmv1/templates/terraform/custom_create/gameservice_rollout_create.go b/mmv1/templates/terraform/custom_create/gameservice_rollout_create.go deleted file mode 100644 index 85da871cd049..000000000000 --- a/mmv1/templates/terraform/custom_create/gameservice_rollout_create.go +++ /dev/null @@ -1,16 +0,0 @@ -// Store the ID now -id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout") -if err != nil { - return fmt.Errorf("Error constructing id: %s", err) -} -d.SetId(id) - -log.Printf("[DEBUG] Creating GameServerDeploymentRollout %q: ", d.Id()) - -err = resourceGameServicesGameServerDeploymentRolloutUpdate(d, meta) -if err != nil { - d.SetId("") - return fmt.Errorf("Error trying to create GameServerDeploymentRollout: %s", err) -} - -return nil diff --git a/mmv1/templates/terraform/custom_expand/secret_manager_replication.go.erb b/mmv1/templates/terraform/custom_expand/secret_manager_replication.go.erb deleted file mode 100644 index af13a17e9002..000000000000 --- a/mmv1/templates/terraform/custom_expand/secret_manager_replication.go.erb +++ /dev/null @@ -1,180 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 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. --%> -func expandSecretManagerSecretReplication(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - if _, ok := d.GetOk("replication.0.automatic"); ok{ - transformedAutomatic, err := expandSecretManagerSecretReplicationAutomatic(original["automatic"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedAutomatic); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["automatic"] = transformedAutomatic - } - } - - if _, ok := d.GetOk("replication.0.auto"); ok{ - transformedAuto, err := expandSecretManagerSecretReplicationAuto(original["auto"], d, config) - if err != nil { - return nil, err - } else { - transformed["automatic"] = transformedAuto - } - } - - transformedUserManaged, err := expandSecretManagerSecretReplicationUserManaged(original["user_managed"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedUserManaged); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["userManaged"] = transformedUserManaged - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationAutomatic(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - if v == nil || !v.(bool) { - return nil, nil - } - - return struct{}{}, nil -} - -func expandSecretManagerSecretReplicationAuto(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 { - return nil, nil - } - - if l[0] == nil { - transformed := make(map[string]interface{}) - return transformed, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedCustomerManagedEncryption, err := expandSecretManagerSecretReplicationAutoCustomerManagedEncryption(original["customer_managed_encryption"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedCustomerManagedEncryption); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["customerManagedEncryption"] = transformedCustomerManagedEncryption - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationAutoCustomerManagedEncryption(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedKmsKeyName, err := expandSecretManagerSecretReplicationAutoCustomerManagedEncryptionKmsKeyName(original["kms_key_name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["kmsKeyName"] = transformedKmsKeyName - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationAutoCustomerManagedEncryptionKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandSecretManagerSecretReplicationUserManaged(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedReplicas, err := expandSecretManagerSecretReplicationUserManagedReplicas(original["replicas"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedReplicas); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["replicas"] = transformedReplicas - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationUserManagedReplicas(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - req := make([]interface{}, 0, len(l)) - for _, raw := range l { - if raw == nil { - continue - } - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedLocation, err := expandSecretManagerSecretReplicationUserManagedReplicasLocation(original["location"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedLocation); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["location"] = transformedLocation - } - - transformedCustomerManagedEncryption, err := expandSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryption(original["customer_managed_encryption"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedCustomerManagedEncryption); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["customerManagedEncryption"] = transformedCustomerManagedEncryption - } - - req = append(req, transformed) - } - return req, nil -} - -func expandSecretManagerSecretReplicationUserManagedReplicasLocation(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} - -func expandSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryption(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - l := v.([]interface{}) - if len(l) == 0 || l[0] == nil { - return nil, nil - } - raw := l[0] - original := raw.(map[string]interface{}) - transformed := make(map[string]interface{}) - - transformedKmsKeyName, err := expandSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryptionKmsKeyName(original["kms_key_name"], d, config) - if err != nil { - return nil, err - } else if val := reflect.ValueOf(transformedKmsKeyName); val.IsValid() && !tpgresource.IsEmptyValue(val) { - transformed["kmsKeyName"] = transformedKmsKeyName - } - - return transformed, nil -} - -func expandSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryptionKmsKeyName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return v, nil -} diff --git a/mmv1/templates/terraform/custom_flatten/secret_manager_replication.go.erb b/mmv1/templates/terraform/custom_flatten/secret_manager_replication.go.erb deleted file mode 100644 index 76f56f85396d..000000000000 --- a/mmv1/templates/terraform/custom_flatten/secret_manager_replication.go.erb +++ /dev/null @@ -1,118 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 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. --%> -func flattenSecretManagerSecretReplication(v interface{}, d *schema.ResourceData, 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{}) - _, ok := d.GetOk("replication.0.automatic") - if ok { - transformed["automatic"] = - flattenSecretManagerSecretReplicationAutomatic(original["automatic"], d, config) - } else { - transformed["auto"] = - flattenSecretManagerSecretReplicationAuto(original["automatic"], d, config) - } - transformed["user_managed"] = - flattenSecretManagerSecretReplicationUserManaged(original["userManaged"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationAutomatic(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v != nil -} - -func flattenSecretManagerSecretReplicationAuto(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - if v == nil { - return nil - } - original := v.(map[string]interface{}) - transformed := make(map[string]interface{}) - transformed["customer_managed_encryption"] = - flattenSecretManagerSecretReplicationAutoCustomerManagedEncryption(original["customerManagedEncryption"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationAutoCustomerManagedEncryption(v interface{}, d *schema.ResourceData, 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["kms_key_name"] = - flattenSecretManagerSecretReplicationAutoCustomerManagedEncryptionKmsKeyName(original["kmsKeyName"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationAutoCustomerManagedEncryptionKmsKeyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenSecretManagerSecretReplicationUserManaged(v interface{}, d *schema.ResourceData, 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["replicas"] = - flattenSecretManagerSecretReplicationUserManagedReplicas(original["replicas"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationUserManagedReplicas(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - if v == nil { - return v - } - l := v.([]interface{}) - transformed := make([]interface{}, 0, len(l)) - for _, raw := range l { - original := raw.(map[string]interface{}) - if len(original) < 1 { - // Do not include empty json objects coming back from the api - continue - } - transformed = append(transformed, map[string]interface{}{ - "location": flattenSecretManagerSecretReplicationUserManagedReplicasLocation(original["location"], d, config), - "customer_managed_encryption": flattenSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryption(original["customerManagedEncryption"], d, config), - }) - } - return transformed -} -func flattenSecretManagerSecretReplicationUserManagedReplicasLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} - -func flattenSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryption(v interface{}, d *schema.ResourceData, 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["kms_key_name"] = - flattenSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryptionKmsKeyName(original["kmsKeyName"], d, config) - return []interface{}{transformed} -} -func flattenSecretManagerSecretReplicationUserManagedReplicasCustomerManagedEncryptionKmsKeyName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { - return v -} diff --git a/mmv1/templates/terraform/decoders/cloudiot_device_registry.go.erb b/mmv1/templates/terraform/decoders/cloudiot_device_registry.go.erb deleted file mode 100644 index b5652175ebee..000000000000 --- a/mmv1/templates/terraform/decoders/cloudiot_device_registry.go.erb +++ /dev/null @@ -1,31 +0,0 @@ -config := meta.(*transport_tpg.Config) - -log.Printf("[DEBUG] Decoding state notification config: %q", d.Id()) -log.Printf("[DEBUG] State notification config before decoding: %v", d.Get("state_notification_config")) -if err := d.Set("state_notification_config", flattenCloudIotDeviceRegistryStateNotificationConfig(res["stateNotificationConfig"], d, config)); err != nil { - return nil, fmt.Errorf("Error reading DeviceRegistry: %s", err) -} -log.Printf("[DEBUG] State notification config after decoding: %v", d.Get("state_notification_config")) - -log.Printf("[DEBUG] Decoding HTTP config: %q", d.Id()) -log.Printf("[DEBUG] HTTP config before decoding: %v", d.Get("http_config")) -if err := d.Set("http_config", flattenCloudIotDeviceRegistryHTTPConfig(res["httpConfig"], d, config)); err != nil { - return nil, fmt.Errorf("Error reading DeviceRegistry: %s", err) -} -log.Printf("[DEBUG] HTTP config after decoding: %v", d.Get("http_config")) - -log.Printf("[DEBUG] Decoding MQTT config: %q", d.Id()) -log.Printf("[DEBUG] MQTT config before decoding: %v", d.Get("mqtt_config")) -if err := d.Set("mqtt_config", flattenCloudIotDeviceRegistryMqttConfig(res["mqttConfig"], d, config)); err != nil { - return nil, fmt.Errorf("Error reading DeviceRegistry: %s", err) -} -log.Printf("[DEBUG] MQTT config after decoding: %v", d.Get("mqtt_config")) - -log.Printf("[DEBUG] Decoding credentials: %q", d.Id()) -log.Printf("[DEBUG] credentials before decoding: %v", d.Get("credentials")) -if err := d.Set("credentials", flattenCloudIotDeviceRegistryCredentials(res["credentials"], d, config)); err != nil { - return nil, fmt.Errorf("Error reading DeviceRegistry: %s", err) -} -log.Printf("[DEBUG] credentials after decoding: %v", d.Get("credentials")) - -return res, nil diff --git a/mmv1/templates/terraform/encoders/cloudiot_device_registry.go.erb b/mmv1/templates/terraform/encoders/cloudiot_device_registry.go.erb deleted file mode 100644 index 37794ff71630..000000000000 --- a/mmv1/templates/terraform/encoders/cloudiot_device_registry.go.erb +++ /dev/null @@ -1,43 +0,0 @@ -config := meta.(*transport_tpg.Config) - -log.Printf("[DEBUG] Resource data before encoding extra schema entries %q: %#v", d.Id(), obj) - -log.Printf("[DEBUG] Encoding state notification config: %q", d.Id()) -stateNotificationConfigProp, err := expandCloudIotDeviceRegistryStateNotificationConfig(d.Get("state_notification_config"), d, config) -if err != nil { - return nil, err -} else if v, ok := d.GetOkExists("state_notification_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(stateNotificationConfigProp)) && (ok || !reflect.DeepEqual(v, stateNotificationConfigProp)) { - log.Printf("[DEBUG] Encoding %q. Setting stateNotificationConfig: %#v", d.Id(), stateNotificationConfigProp) - obj["stateNotificationConfig"] = stateNotificationConfigProp -} - -log.Printf("[DEBUG] Encoding HTTP config: %q", d.Id()) -httpConfigProp, err := expandCloudIotDeviceRegistryHTTPConfig(d.Get("http_config"), d, config) -if err != nil { - return nil, err -} else if v, ok := d.GetOkExists("http_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(httpConfigProp)) && (ok || !reflect.DeepEqual(v, httpConfigProp)) { - log.Printf("[DEBUG] Encoding %q. Setting httpConfig: %#v", d.Id(), httpConfigProp) - obj["httpConfig"] = httpConfigProp -} - -log.Printf("[DEBUG] Encoding MQTT config: %q", d.Id()) -mqttConfigProp, err := expandCloudIotDeviceRegistryMqttConfig(d.Get("mqtt_config"), d, config) -if err != nil { - return nil, err -} else if v, ok := d.GetOkExists("mqtt_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(mqttConfigProp)) && (ok || !reflect.DeepEqual(v, mqttConfigProp)) { - log.Printf("[DEBUG] Encoding %q. Setting mqttConfig: %#v", d.Id(), mqttConfigProp) - obj["mqttConfig"] = mqttConfigProp -} - -log.Printf("[DEBUG] Encoding credentials: %q", d.Id()) -credentialsProp, err := expandCloudIotDeviceRegistryCredentials(d.Get("credentials"), d, config) -if err != nil { - return nil, err -} else if v, ok := d.GetOkExists("credentials"); !tpgresource.IsEmptyValue(reflect.ValueOf(credentialsProp)) && (ok || !reflect.DeepEqual(v, credentialsProp)) { - log.Printf("[DEBUG] Encoding %q. Setting credentials: %#v", d.Id(), credentialsProp) - obj["credentials"] = credentialsProp -} - -log.Printf("[DEBUG] Resource data after encoding extra schema entries %q: %#v", d.Id(), obj) - -return obj, nil diff --git a/mmv1/templates/terraform/examples/alloydb_backup_basic.tf.erb b/mmv1/templates/terraform/examples/alloydb_backup_basic.tf.erb index 418ccb67c8ed..41521891bfec 100644 --- a/mmv1/templates/terraform/examples/alloydb_backup_basic.tf.erb +++ b/mmv1/templates/terraform/examples/alloydb_backup_basic.tf.erb @@ -9,7 +9,7 @@ resource "google_alloydb_backup" "<%= ctx[:primary_resource_id] %>" { resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { cluster_id = "<%= ctx[:vars]['alloydb_cluster_name'] %>" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" { @@ -25,15 +25,15 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } diff --git a/mmv1/templates/terraform/examples/alloydb_backup_full.tf.erb b/mmv1/templates/terraform/examples/alloydb_backup_full.tf.erb index f64733a1ae95..dd891fb49d30 100644 --- a/mmv1/templates/terraform/examples/alloydb_backup_full.tf.erb +++ b/mmv1/templates/terraform/examples/alloydb_backup_full.tf.erb @@ -14,7 +14,7 @@ resource "google_alloydb_backup" "<%= ctx[:primary_resource_id] %>" { resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { cluster_id = "<%= ctx[:vars]['alloydb_cluster_name'] %>" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" { @@ -30,15 +30,15 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } diff --git a/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb b/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb index f6907cd44237..479245a01cb2 100644 --- a/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb +++ b/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb @@ -13,7 +13,7 @@ resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" { resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { cluster_id = "<%= ctx[:vars]['alloydb_cluster_name'] %>" location = "us-central1" - network = data.google_compute_network.default.id + network = google_compute_network.default.id initial_user { password = "<%= ctx[:vars]['alloydb_cluster_name'] %>" @@ -22,7 +22,7 @@ resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { data "google_project" "project" {} -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -31,11 +31,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/base_configs/test_file.go.erb b/mmv1/templates/terraform/examples/base_configs/test_file.go.erb index b374fda44db4..64aa47337ddd 100644 --- a/mmv1/templates/terraform/examples/base_configs/test_file.go.erb +++ b/mmv1/templates/terraform/examples/base_configs/test_file.go.erb @@ -44,9 +44,10 @@ object.examples test_slug = "#{resource_name}_#{example.name.camelize(:lower)}Example" ignore_read = object.all_user_properties - .select{|p| p.url_param_only || p.ignore_read || p.is_a?(Api::Type::ResourceRef) } + .select{|p| p.url_param_only || p.ignore_read || p.is_a?(Api::Type::ResourceRef)} .map { |p| p.name.underscore } .concat(example.ignore_read_extra) + .concat(object.ignore_read_labels_fields(object.properties_with_excluded)) # Use explicit version for the example if given. # Otherwise, use object version. diff --git a/mmv1/templates/terraform/examples/certificate_manager_google_managed_certificate_dns.tf.erb b/mmv1/templates/terraform/examples/certificate_manager_google_managed_certificate_dns.tf.erb index 48d499afeff7..6e457875fbd2 100644 --- a/mmv1/templates/terraform/examples/certificate_manager_google_managed_certificate_dns.tf.erb +++ b/mmv1/templates/terraform/examples/certificate_manager_google_managed_certificate_dns.tf.erb @@ -2,6 +2,9 @@ resource "google_certificate_manager_certificate" "<%= ctx[:primary_resource_id] name = "<%= ctx[:vars]['cert_name'] %>" description = "The default cert" scope = "EDGE_CACHE" + labels = { + env = "test" + } managed { domains = [ google_certificate_manager_dns_authorization.instance.domain, diff --git a/mmv1/templates/terraform/examples/cloudbuild_bitbucket_server_config_peered_network.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_bitbucket_server_config_peered_network.tf.erb index f59bc3278d77..bedb109901ee 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_bitbucket_server_config_peered_network.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_bitbucket_server_config_peered_network.tf.erb @@ -4,8 +4,8 @@ resource "google_project_service" "servicenetworking" { service = "servicenetworking.googleapis.com" disable_on_destroy = false } - -data "google_compute_network" "vpc_network" { + +resource "google_compute_network" "vpc_network" { name = "<%= ctx[:vars]['network_name'] %>" depends_on = [google_project_service.servicenetworking] } @@ -15,11 +15,11 @@ resource "google_compute_global_address" "private_ip_alloc" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.vpc_network.id + network = google_compute_network.vpc_network.id } resource "google_service_networking_connection" "default" { - network = data.google_compute_network.vpc_network.id + network = google_compute_network.vpc_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] depends_on = [google_project_service.servicenetworking] @@ -36,7 +36,7 @@ resource "google_cloudbuild_bitbucket_server_config" "<%= ctx[:primary_resource_ } username = "test" api_key = "" - peered_network = replace(data.google_compute_network.vpc_network.id, data.google_project.project.name, data.google_project.project.number) + peered_network = replace(google_compute_network.vpc_network.id, data.google_project.project.name, data.google_project.project.number) ssl_ca = "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----\n" depends_on = [google_service_networking_connection.default] } diff --git a/mmv1/templates/terraform/examples/cloudiot_device_basic.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_basic.tf.erb deleted file mode 100644 index dbfd02b17e4d..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_basic.tf.erb +++ /dev/null @@ -1,8 +0,0 @@ -resource "google_cloudiot_registry" "registry" { - name = "<%= ctx[:vars]['cloudiot_device_registry_name'] %>" -} - -resource "google_cloudiot_device" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_device_name'] %>" - registry = google_cloudiot_registry.registry.id -} diff --git a/mmv1/templates/terraform/examples/cloudiot_device_full.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_full.tf.erb deleted file mode 100644 index 0c3457d4029c..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_full.tf.erb +++ /dev/null @@ -1,27 +0,0 @@ -resource "google_cloudiot_registry" "registry" { - name = "<%= ctx[:vars]['cloudiot_device_registry_name'] %>" -} - -resource "google_cloudiot_device" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_device_name'] %>" - registry = google_cloudiot_registry.registry.id - - credentials { - public_key { - format = "RSA_PEM" - key = file("test-fixtures/rsa_public.pem") - } - } - - blocked = false - - log_level = "INFO" - - metadata = { - test_key_1 = "test_value_1" - } - - gateway_config { - gateway_type = "NON_GATEWAY" - } -} diff --git a/mmv1/templates/terraform/examples/cloudiot_device_registry_basic.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_registry_basic.tf.erb deleted file mode 100644 index 67bf5e108304..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_registry_basic.tf.erb +++ /dev/null @@ -1,3 +0,0 @@ -resource "google_cloudiot_registry" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_registry_name'] %>" -} diff --git a/mmv1/templates/terraform/examples/cloudiot_device_registry_full.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_registry_full.tf.erb deleted file mode 100644 index f5c11d9abdcc..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_registry_full.tf.erb +++ /dev/null @@ -1,46 +0,0 @@ -resource "google_pubsub_topic" "default-devicestatus" { - name = "<%= ctx[:vars]['cloudiot_device_status_topic_name'] %>" -} - -resource "google_pubsub_topic" "default-telemetry" { - name = "<%= ctx[:vars]['cloudiot_device_telemetry_topic_name'] %>" -} - -resource "google_pubsub_topic" "additional-telemetry" { - name = "<%= ctx[:vars]['cloudiot_additional_device_telemetry_topic_name'] %>" -} - -resource "google_cloudiot_registry" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_registry_name'] %>" - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.additional-telemetry.id - subfolder_matches = "<%= ctx[:vars]['cloudiot_subfolder_matches_additional_device_telemetry_topic'] %>" - } - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.default-telemetry.id - subfolder_matches = "" - } - - state_notification_config = { - pubsub_topic_name = google_pubsub_topic.default-devicestatus.id - } - - mqtt_config = { - mqtt_enabled_state = "MQTT_ENABLED" - } - - http_config = { - http_enabled_state = "HTTP_ENABLED" - } - - log_level = "INFO" - - credentials { - public_key_certificate = { - format = "X509_CERTIFICATE_PEM" - certificate = file("test-fixtures/rsa_cert.pem") - } - } -} diff --git a/mmv1/templates/terraform/examples/cloudiot_device_registry_single_event_notification_configs.tf.erb b/mmv1/templates/terraform/examples/cloudiot_device_registry_single_event_notification_configs.tf.erb deleted file mode 100644 index 45139229a27c..000000000000 --- a/mmv1/templates/terraform/examples/cloudiot_device_registry_single_event_notification_configs.tf.erb +++ /dev/null @@ -1,13 +0,0 @@ -resource "google_pubsub_topic" "default-telemetry" { - name = "<%= ctx[:vars]['cloudiot_device_telemetry_topic_name'] %>" -} - -resource "google_cloudiot_registry" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['cloudiot_registry_name'] %>" - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.default-telemetry.id - subfolder_matches = "" - } - -} diff --git a/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb b/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb index 68a6ea686b57..96384e6e4b58 100644 --- a/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb +++ b/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb @@ -1,7 +1,7 @@ data "google_project" "project" { } -data "google_compute_network" "default" { +resource "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -10,11 +10,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = data.google_compute_network.default.id + network = google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id + network = google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -34,7 +34,7 @@ resource "google_database_migration_service_connection_profile" "<%= ctx[:primar user = "alloyuser%{random_suffix}" password = "alloypass%{random_suffix}" } - vpc_network = data.google_compute_network.default.id + vpc_network = google_compute_network.default.id labels = { alloyfoo = "alloybar" } diff --git a/mmv1/templates/terraform/examples/dataproc_metastore_service_basic.tf.erb b/mmv1/templates/terraform/examples/dataproc_metastore_service_basic.tf.erb index a95e7607e470..368e76e15bd1 100644 --- a/mmv1/templates/terraform/examples/dataproc_metastore_service_basic.tf.erb +++ b/mmv1/templates/terraform/examples/dataproc_metastore_service_basic.tf.erb @@ -12,4 +12,8 @@ resource "google_dataproc_metastore_service" "<%= ctx[:primary_resource_id] %>" hive_metastore_config { version = "2.3.6" } + + labels = { + env = "test" + } } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/dns_managed_zone_private_gke.tf.erb b/mmv1/templates/terraform/examples/dns_managed_zone_private_gke.tf.erb index 667677b48b57..5c58fb5e6b71 100644 --- a/mmv1/templates/terraform/examples/dns_managed_zone_private_gke.tf.erb +++ b/mmv1/templates/terraform/examples/dns_managed_zone_private_gke.tf.erb @@ -65,5 +65,6 @@ resource "google_container_cluster" "cluster-1" { cluster_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[1].range_name } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } # [END dns_managed_zone_private_gke] \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/dns_response_policy_basic.tf.erb b/mmv1/templates/terraform/examples/dns_response_policy_basic.tf.erb index 6bfde1fe8964..767f8706638c 100644 --- a/mmv1/templates/terraform/examples/dns_response_policy_basic.tf.erb +++ b/mmv1/templates/terraform/examples/dns_response_policy_basic.tf.erb @@ -53,6 +53,7 @@ resource "google_container_cluster" "cluster-1" { cluster_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[1].range_name } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_dns_response_policy" "<%= ctx[:primary_resource_id] %>" { diff --git a/mmv1/templates/terraform/examples/firebase_project_location_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_project_location_basic.tf.erb deleted file mode 100644 index 4cdebbe83a21..000000000000 --- a/mmv1/templates/terraform/examples/firebase_project_location_basic.tf.erb +++ /dev/null @@ -1,23 +0,0 @@ -resource "google_project" "default" { - provider = google-beta - - project_id = "<%= ctx[:vars]['project_name'] %>" - name = "<%= ctx[:vars]['project_name'] %>" - org_id = "<%= ctx[:test_env_vars]['org_id'] %>" - - labels = { - "firebase" = "enabled" - } -} - -resource "google_firebase_project" "default" { - provider = google-beta - project = google_project.default.project_id -} - -resource "google_firebase_project_location" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta - project = google_firebase_project.default.project - - location_id = "us-central" -} diff --git a/mmv1/templates/terraform/examples/firebase_web_app_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_web_app_basic.tf.erb index c75c49c821d6..46d98f831900 100644 --- a/mmv1/templates/terraform/examples/firebase_web_app_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_web_app_basic.tf.erb @@ -1,27 +1,7 @@ -resource "google_project" "default" { - provider = google-beta - - project_id = "<%= ctx[:vars]['project_name'] %>" - name = "<%= ctx[:vars]['project_name'] %>" - org_id = "<%= ctx[:test_env_vars]['org_id'] %>" - - labels = { - "firebase" = "enabled" - } -} - -resource "google_firebase_project" "default" { - provider = google-beta - project = google_project.default.project_id -} - resource "google_firebase_web_app" "<%= ctx[:primary_resource_id] %>" { provider = google-beta - project = google_project.default.project_id + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "<%= ctx[:vars]['display_name'] %>" - deletion_policy = "DELETE" - - depends_on = [google_firebase_project.default] } data "google_firebase_web_app_config" "basic" { diff --git a/mmv1/templates/terraform/examples/firebasehosting_site_full.tf.erb b/mmv1/templates/terraform/examples/firebasehosting_site_full.tf.erb index 57c88044615e..f436a7264428 100644 --- a/mmv1/templates/terraform/examples/firebasehosting_site_full.tf.erb +++ b/mmv1/templates/terraform/examples/firebasehosting_site_full.tf.erb @@ -2,7 +2,6 @@ resource "google_firebase_web_app" "default" { provider = google-beta project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "<%= ctx[:vars]['display_name'] %>" - deletion_policy = "DELETE" } resource "google_firebase_hosting_site" "full" { diff --git a/mmv1/templates/terraform/examples/game_service_cluster_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_cluster_basic.tf.erb deleted file mode 100644 index 19eb85571952..000000000000 --- a/mmv1/templates/terraform/examples/game_service_cluster_basic.tf.erb +++ /dev/null @@ -1,62 +0,0 @@ -resource "google_game_services_game_server_cluster" "<%= ctx[:primary_resource_id] %>" { - <%# depends_on = [google_project_iam_member.kubernetes_developer] -%> - <%# depends_on = [module.agones_cluster, module.helm_agones] -%> - - cluster_id = "<%= ctx[:vars]['agones_cluster'] %>" - realm_id = google_game_services_realm.default.realm_id - - connection_info { - gke_cluster_reference { - cluster = "locations/us-west1/clusters/%{agones_cluster}" - } - namespace = "default" - } -} - -resource "google_game_services_realm" "default" { - realm_id = "<%= ctx[:vars]["realm_id"] %>" - time_zone = "PST8PDT" - - description = "Test Game Realm" -} - - -<%# -This resource requires that a GKE cluster is already created with Agones provisioned -and configured correctly for this test to succeed. Since this setup requires a fair amount -of bootstrapping that is non-essential to testing that the resource works we've decided to -set up the cluster in advance and run the tests against it. The following Terraform config -was used to provision the cluster. Since it is a manual set up this config not guaranteed to -work out of the box. - -module "agones_cluster" { - source = "git::https://github.com/googleforgames/agones.git//install/terraform/modules/gke/?ref=release-1.4.0" - - cluster = { - "name" = var.name - "zone" = "us-west1" - "machineType" = "e2-standard-4" - "initialNodeCount" = 1 - "project" = "" - "network" = "default" - } -} - -// Install Agones via Helm -module "helm_agones" { - source = "git::https://github.com/googleforgames/agones.git//install/terraform/modules/helm/?ref=release-1.4.0" - - agones_version = "1.4.0" - values_file = "" - chart = "agones" - host = module.agones_cluster.host - token = module.agones_cluster.token - cluster_ca_certificate = module.agones_cluster.cluster_ca_certificate -} - -resource "google_project_iam_member" "agent_create" { - project = var.project - role = "roles/container.developer" - member = "serviceAccount:service-@gcp-sa-gameservices.iam.gserviceaccount.com" -} --%> \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/game_service_config_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_config_basic.tf.erb deleted file mode 100644 index 6c89cbcf8f7c..000000000000 --- a/mmv1/templates/terraform/examples/game_service_config_basic.tf.erb +++ /dev/null @@ -1,30 +0,0 @@ -resource "google_game_services_game_server_deployment" "default" { - deployment_id = "<%= ctx[:vars]["deployment_id"] %>" - description = "a deployment description" -} - -resource "google_game_services_game_server_config" "<%= ctx[:primary_resource_id] %>" { - config_id = "<%= ctx[:vars]["config_id"] %>" - deployment_id = google_game_services_game_server_deployment.default.deployment_id - description = "a config description" - - fleet_configs { - name = "something-unique" - fleet_spec = jsonencode({ "replicas" : 1, "scheduling" : "Packed", "template" : { "metadata" : { "name" : "tf-test-game-server-template" }, "spec" : { "ports": [{"name": "default", "portPolicy": "Dynamic", "containerPort": 7654, "protocol": "UDP"}], "template" : { "spec" : { "containers" : [{ "name" : "simple-udp-server", "image" : "gcr.io/agones-images/udp-server:0.14" }] } } } } }) - } - - scaling_configs { - name = "scaling-config-name" - fleet_autoscaler_spec = jsonencode({"policy": {"type": "Webhook","webhook": {"service": {"name": "autoscaler-webhook-service","namespace": "default","path": "scale"}}}}) - selectors { - labels = { - "one" : "two" - } - } - - schedules { - cron_job_duration = "3.500s" - cron_spec = "0 0 * * 0" - } - } -} diff --git a/mmv1/templates/terraform/examples/game_service_deployment_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_deployment_basic.tf.erb deleted file mode 100644 index 10e00ebc6ace..000000000000 --- a/mmv1/templates/terraform/examples/game_service_deployment_basic.tf.erb +++ /dev/null @@ -1,5 +0,0 @@ -resource "google_game_services_game_server_deployment" "<%= ctx[:primary_resource_id] %>" { - deployment_id = "<%= ctx[:vars]["deployment_id"] %>" - description = "a deployment description" -} - diff --git a/mmv1/templates/terraform/examples/game_service_deployment_rollout_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_deployment_rollout_basic.tf.erb deleted file mode 100644 index 8d41a0ddd382..000000000000 --- a/mmv1/templates/terraform/examples/game_service_deployment_rollout_basic.tf.erb +++ /dev/null @@ -1,23 +0,0 @@ -resource "google_game_services_game_server_deployment" "default" { - deployment_id = "<%= ctx[:vars]["deployment_id"] %>" - description = "a deployment description" -} - -resource "google_game_services_game_server_config" "default" { - config_id = "<%= ctx[:vars]["config_id"] %>" - deployment_id = google_game_services_game_server_deployment.default.deployment_id - description = "a config description" - - fleet_configs { - name = "some-non-guid" - fleet_spec = jsonencode({ "replicas" : 1, "scheduling" : "Packed", "template" : { "metadata" : { "name" : "tf-test-game-server-template" }, "spec" : { "ports": [{"name": "default", "portPolicy": "Dynamic", "containerPort": 7654, "protocol": "UDP"}], "template" : { "spec" : { "containers" : [{ "name" : "simple-udp-server", "image" : "gcr.io/agones-images/udp-server:0.14" }] } } } } }) - - // Alternate usage: - // fleet_spec = file(fleet_configs.json) - } -} - -resource "google_game_services_game_server_deployment_rollout" "<%= ctx[:primary_resource_id] %>" { - deployment_id = google_game_services_game_server_deployment.default.deployment_id - default_game_server_config = google_game_services_game_server_config.default.name -} diff --git a/mmv1/templates/terraform/examples/game_service_realm_basic.tf.erb b/mmv1/templates/terraform/examples/game_service_realm_basic.tf.erb deleted file mode 100644 index 0385c37a6f2c..000000000000 --- a/mmv1/templates/terraform/examples/game_service_realm_basic.tf.erb +++ /dev/null @@ -1,8 +0,0 @@ -resource "google_game_services_realm" "<%= ctx[:primary_resource_id] %>" { - realm_id = "<%= ctx[:vars]["realm_id"] %>" - time_zone = "EST" - location = "global" - - description = "one of the nine" -} - diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_autopilot.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_autopilot.tf.erb index 333a6cfc9863..cd0bd7803090 100644 --- a/mmv1/templates/terraform/examples/gkebackup_backupplan_autopilot.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_autopilot.tf.erb @@ -12,6 +12,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "autopilot" { diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_basic.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_basic.tf.erb index e3f834662ab7..1377aca5ed77 100644 --- a/mmv1/templates/terraform/examples/gkebackup_backupplan_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_basic.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_cmek.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_cmek.tf.erb index 6f2a715b7901..d9ed2a434a39 100644 --- a/mmv1/templates/terraform/examples/gkebackup_backupplan_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_cmek.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "cmek" { diff --git a/mmv1/templates/terraform/examples/gkebackup_backupplan_full.tf.erb b/mmv1/templates/terraform/examples/gkebackup_backupplan_full.tf.erb index 231727fabb35..cce561f53bad 100644 --- a/mmv1/templates/terraform/examples/gkebackup_backupplan_full.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_backupplan_full.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "full" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_cluster_resources.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_cluster_resources.tf.erb index 4578aba10489..4f633dcada2e 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_cluster_resources.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_cluster_resources.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_namespaces.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_namespaces.tf.erb index 94c5d25f55ba..f431cda66270 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_namespaces.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_all_namespaces.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_protected_application.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_protected_application.tf.erb index 64585c3f89a0..25b7a878e78a 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_protected_application.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_protected_application.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_rename_namespace.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_rename_namespace.tf.erb index 11179e2afee6..7a3496f87c85 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_rename_namespace.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_rename_namespace.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_rollback_namespace.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_rollback_namespace.tf.erb index e2b76bae6d28..61081b246b51 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_rollback_namespace.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_rollback_namespace.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkebackup_restoreplan_second_transformation.tf.erb b/mmv1/templates/terraform/examples/gkebackup_restoreplan_second_transformation.tf.erb index 1392a5997f74..e0dbd69e4f73 100644 --- a/mmv1/templates/terraform/examples/gkebackup_restoreplan_second_transformation.tf.erb +++ b/mmv1/templates/terraform/examples/gkebackup_restoreplan_second_transformation.tf.erb @@ -10,6 +10,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_backup_backup_plan" "basic" { diff --git a/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb index 0cd1916c20eb..61478e731374 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_basic.tf.erb @@ -2,6 +2,7 @@ resource "google_container_cluster" "primary" { name = "<%= ctx[:vars]['cluster_name'] %>" location = "us-central1-a" initial_node_count = 1 + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_hub_membership" "membership" { @@ -11,4 +12,8 @@ resource "google_gke_hub_membership" "membership" { resource_link = "//container.googleapis.com/${google_container_cluster.primary.id}" } } + + labels = { + env = "test" + } } diff --git a/mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb index e99bb4ec5577..f7899210e7bb 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb @@ -2,6 +2,7 @@ resource "google_container_cluster" "primary" { name = "<%= ctx[:vars]['cluster_name'] %>" location = "us-central1-a" initial_node_count = 1 + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_hub_membership" "<%= ctx[:primary_resource_id] %>" { diff --git a/mmv1/templates/terraform/examples/gkehub_membership_issuer.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_issuer.tf.erb index 159ae9de7067..a6b6c55c682b 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_issuer.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_issuer.tf.erb @@ -5,6 +5,7 @@ resource "google_container_cluster" "primary" { workload_identity_config { workload_pool = "<%= ctx[:test_env_vars]['project'] %>.svc.id.goog" } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_hub_membership" "membership" { diff --git a/mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb index 7c117e3f2426..eddcf586da05 100644 --- a/mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb @@ -3,6 +3,7 @@ resource "google_container_cluster" "primary" { name = "<%= ctx[:vars]['cluster_name'] %>" location = "us-central1-a" initial_node_count = 1 + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } resource "google_gke_hub_membership" "<%= ctx[:primary_resource_id] %>" { diff --git a/mmv1/templates/terraform/examples/gkeonprem_bare_metal_admin_cluster_full.tf.erb b/mmv1/templates/terraform/examples/gkeonprem_bare_metal_admin_cluster_full.tf.erb index 58046c4f55cc..327d91fd302d 100644 --- a/mmv1/templates/terraform/examples/gkeonprem_bare_metal_admin_cluster_full.tf.erb +++ b/mmv1/templates/terraform/examples/gkeonprem_bare_metal_admin_cluster_full.tf.erb @@ -4,7 +4,9 @@ resource "google_gkeonprem_bare_metal_admin_cluster" "<%= ctx[:primary_resource_ location = "us-west1" description = "test description" bare_metal_version = "1.13.4" - annotations = {} + annotations = { + env = "test" + } network_config { island_mode_cidr { service_address_cidr_blocks = ["172.26.0.0/16"] diff --git a/mmv1/templates/terraform/examples/instance_group_named_port_gke.tf.erb b/mmv1/templates/terraform/examples/instance_group_named_port_gke.tf.erb index 3a4b492eca8a..32d2d23c876e 100644 --- a/mmv1/templates/terraform/examples/instance_group_named_port_gke.tf.erb +++ b/mmv1/templates/terraform/examples/instance_group_named_port_gke.tf.erb @@ -38,4 +38,5 @@ resource "google_container_cluster" "my_cluster" { cluster_ipv4_cidr_block = "/19" services_ipv4_cidr_block = "/22" } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } diff --git a/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb b/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb index 5a223f1e21db..54d74ad63d8e 100644 --- a/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb +++ b/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb @@ -5,7 +5,7 @@ resource "google_looker_instance" "<%= ctx[:primary_resource_id] %>" { private_ip_enabled = true public_ip_enabled = false reserved_range = "${google_compute_global_address.looker_range.name}" - consumer_network = data.google_compute_network.looker_network.id + consumer_network = google_compute_network.looker_network.id admin_settings { allowed_email_domains = ["google.com"] } @@ -49,7 +49,7 @@ resource "google_looker_instance" "<%= ctx[:primary_resource_id] %>" { } resource "google_service_networking_connection" "looker_vpc_connection" { - network = data.google_compute_network.looker_network.id + network = google_compute_network.looker_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.looker_range.name] } @@ -59,12 +59,12 @@ resource "google_compute_global_address" "looker_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 20 - network = data.google_compute_network.looker_network.id + network = google_compute_network.looker_network.id } data "google_project" "project" {} -data "google_compute_network" "looker_network" { +resource "google_compute_network" "looker_network" { name = "<%= ctx[:vars]["network_name"] %>" } diff --git a/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb b/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb index e021bacf3d63..2744c21f85b4 100644 --- a/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb +++ b/mmv1/templates/terraform/examples/memcache_instance_basic.tf.erb @@ -6,7 +6,7 @@ // If this network hasn't been created and you are using this example in your // config, add an additional network resource or change // this from "data"to "resource" -data "google_compute_network" "memcache_network" { +resource "google_compute_network" "memcache_network" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -15,11 +15,11 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.memcache_network.id + network = google_compute_network.memcache_network.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.memcache_network.id + network = google_compute_network.memcache_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } @@ -28,6 +28,10 @@ resource "google_memcache_instance" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]["instance_name"] %>" authorized_network = google_service_networking_connection.private_service_connection.network + labels = { + env = "test" + } + node_config { cpu_count = 1 memory_size_mb = 1024 diff --git a/mmv1/templates/terraform/examples/network_management_connectivity_test_instances.tf.erb b/mmv1/templates/terraform/examples/network_management_connectivity_test_instances.tf.erb index 09a5dc0f7c6a..190c4fc40b1e 100644 --- a/mmv1/templates/terraform/examples/network_management_connectivity_test_instances.tf.erb +++ b/mmv1/templates/terraform/examples/network_management_connectivity_test_instances.tf.erb @@ -10,6 +10,9 @@ resource "google_network_management_connectivity_test" "<%= ctx[:primary_resourc } protocol = "TCP" + labels = { + env = "test" + } } resource "google_compute_instance" "source" { diff --git a/mmv1/templates/terraform/examples/network_peering_routes_config_gke.tf.erb b/mmv1/templates/terraform/examples/network_peering_routes_config_gke.tf.erb index bd6ef2cd8a7b..a75f44cafcb9 100644 --- a/mmv1/templates/terraform/examples/network_peering_routes_config_gke.tf.erb +++ b/mmv1/templates/terraform/examples/network_peering_routes_config_gke.tf.erb @@ -49,4 +49,5 @@ resource "google_container_cluster" "private_cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" } diff --git a/mmv1/templates/terraform/examples/node_group_basic.tf.erb b/mmv1/templates/terraform/examples/node_group_basic.tf.erb index 39b32a385c4d..3ed5b02dd02b 100644 --- a/mmv1/templates/terraform/examples/node_group_basic.tf.erb +++ b/mmv1/templates/terraform/examples/node_group_basic.tf.erb @@ -9,6 +9,6 @@ resource "google_compute_node_group" "<%= ctx[:primary_resource_id] %>" { zone = "us-central1-f" description = "example google_compute_node_group for Terraform Google Provider" - size = 1 + initial_size = 1 node_template = google_compute_node_template.soletenant-tmpl.id } diff --git a/mmv1/templates/terraform/examples/node_group_share_settings.tf.erb b/mmv1/templates/terraform/examples/node_group_share_settings.tf.erb index 278cd3f0ffbb..b2658a831187 100644 --- a/mmv1/templates/terraform/examples/node_group_share_settings.tf.erb +++ b/mmv1/templates/terraform/examples/node_group_share_settings.tf.erb @@ -15,7 +15,7 @@ resource "google_compute_node_group" "<%= ctx[:primary_resource_id] %>" { zone = "us-central1-f" description = "example google_compute_node_group for Terraform Google Provider" - size = 1 + initial_size = 1 node_template = google_compute_node_template.soletenant-tmpl.id share_settings { diff --git a/mmv1/templates/terraform/examples/only_external_vpn_gateway_full.tf.erb b/mmv1/templates/terraform/examples/only_external_vpn_gateway_full.tf.erb index 6fc73528fdcb..08bde7a9dab8 100644 --- a/mmv1/templates/terraform/examples/only_external_vpn_gateway_full.tf.erb +++ b/mmv1/templates/terraform/examples/only_external_vpn_gateway_full.tf.erb @@ -8,6 +8,5 @@ resource "google_compute_external_vpn_gateway" "<%= ctx[:primary_resource_id] %> } labels = { key = "value" - otherkey = "" } } diff --git a/mmv1/templates/terraform/examples/redis_instance_private_service.tf.erb b/mmv1/templates/terraform/examples/redis_instance_private_service.tf.erb index 800df78e22aa..90e0e4ff5698 100644 --- a/mmv1/templates/terraform/examples/redis_instance_private_service.tf.erb +++ b/mmv1/templates/terraform/examples/redis_instance_private_service.tf.erb @@ -6,7 +6,7 @@ // If this network hasn't been created and you are using this example in your // config, add an additional network resource or change // this from "data"to "resource" -data "google_compute_network" "redis-network" { +resource "google_compute_network" "redis-network" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -15,11 +15,11 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.redis-network.id + network = google_compute_network.redis-network.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.redis-network.id + network = google_compute_network.redis-network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } @@ -32,7 +32,7 @@ resource "google_redis_instance" "<%= ctx[:primary_resource_id] %>" { location_id = "us-central1-a" alternative_location_id = "us-central1-f" - authorized_network = data.google_compute_network.redis-network.id + authorized_network = google_compute_network.redis-network.id connect_mode = "PRIVATE_SERVICE_ACCESS" redis_version = "REDIS_4_0" diff --git a/mmv1/templates/terraform/examples/tpu_node_full.tf.erb b/mmv1/templates/terraform/examples/tpu_node_full.tf.erb index 0f88b33e3210..cebe528b24ac 100644 --- a/mmv1/templates/terraform/examples/tpu_node_full.tf.erb +++ b/mmv1/templates/terraform/examples/tpu_node_full.tf.erb @@ -34,8 +34,8 @@ resource "google_tpu_node" "<%= ctx[:primary_resource_id] %>" { } } -data "google_compute_network" "network" { - name = "default" +resource "google_compute_network" "network" { + name = "<%= ctx[:vars]['network_name'] %>" } resource "google_compute_global_address" "service_range" { @@ -43,11 +43,11 @@ resource "google_compute_global_address" "service_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.network.id + network = google_compute_network.network.id } resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.network.id + network = google_compute_network.network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.service_range.name] } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/vertex_ai_dataset.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_dataset.tf.erb index e5a5828cf0a2..17b7440b4288 100644 --- a/mmv1/templates/terraform/examples/vertex_ai_dataset.tf.erb +++ b/mmv1/templates/terraform/examples/vertex_ai_dataset.tf.erb @@ -2,4 +2,8 @@ resource "google_vertex_ai_dataset" "dataset" { display_name = "<%= ctx[:vars]['display_name'] %>" metadata_schema_uri = "gs://google-cloud-aiplatform/schema/dataset/metadata/image_1.0.0.yaml" region = "us-central1" + + labels = { + env = "test" + } } diff --git a/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb index abe0b82b3080..752c25264502 100644 --- a/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb +++ b/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb @@ -7,7 +7,7 @@ resource "google_vertex_ai_endpoint" "<%= ctx[:primary_resource_id] %>" { labels = { label-one = "value-one" } - network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.vertex_network.name}" encryption_spec { kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" } @@ -17,7 +17,7 @@ resource "google_vertex_ai_endpoint" "<%= ctx[:primary_resource_id] %>" { } resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id + network = google_compute_network.vertex_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.vertex_range.name] } @@ -27,10 +27,10 @@ resource "google_compute_global_address" "vertex_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 24 - network = data.google_compute_network.vertex_network.id + network = google_compute_network.vertex_network.id } -data "google_compute_network" "vertex_network" { +resource "google_compute_network" "vertex_network" { name = "<%= ctx[:vars]['network_name'] %>" } diff --git a/mmv1/templates/terraform/examples/vertex_ai_index_endpoint.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_index_endpoint.tf.erb index c15e65269e41..2c0b78e4e339 100644 --- a/mmv1/templates/terraform/examples/vertex_ai_index_endpoint.tf.erb +++ b/mmv1/templates/terraform/examples/vertex_ai_index_endpoint.tf.erb @@ -5,14 +5,14 @@ resource "google_vertex_ai_index_endpoint" "<%= ctx[:primary_resource_id] %>" { labels = { label-one = "value-one" } - network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.vertex_network.name}" depends_on = [ google_service_networking_connection.vertex_vpc_connection ] } resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id + network = google_compute_network.vertex_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.vertex_range.name] } @@ -22,10 +22,10 @@ resource "google_compute_global_address" "vertex_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 24 - network = data.google_compute_network.vertex_network.id + network = google_compute_network.vertex_network.id } -data "google_compute_network" "vertex_network" { +resource "google_compute_network" "vertex_network" { name = "<%= ctx[:vars]['network_name'] %>" } diff --git a/mmv1/templates/terraform/examples/workflow_basic.tf.erb b/mmv1/templates/terraform/examples/workflow_basic.tf.erb index 3369b4985048..1ec0cc3b67ca 100644 --- a/mmv1/templates/terraform/examples/workflow_basic.tf.erb +++ b/mmv1/templates/terraform/examples/workflow_basic.tf.erb @@ -8,6 +8,9 @@ resource "google_workflows_workflow" "<%= ctx[:primary_resource_id] %>" { region = "us-central1" description = "Magic" service_account = google_service_account.test_account.id + labels = { + env = "test" + } source_contents = <<-EOF # This is a sample workflow. You can replace it with your source code. # diff --git a/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb b/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb index 2e154577d02f..807fa7964410 100644 --- a/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb +++ b/mmv1/templates/terraform/examples/workstation_config_basic.tf.erb @@ -38,6 +38,13 @@ resource "google_workstations_workstation_config" "<%= ctx[:primary_resource_id] running_timeout = "21600s" replica_zones = ["us-central1-a", "us-central1-b"] + annotations = { + label-one = "value-one" + } + + labels = { + "label" = "key" + } host { gce_instance { diff --git a/mmv1/templates/terraform/expand_property_method.erb b/mmv1/templates/terraform/expand_property_method.erb index d3a034e84ca2..d74d7bcc777c 100644 --- a/mmv1/templates/terraform/expand_property_method.erb +++ b/mmv1/templates/terraform/expand_property_method.erb @@ -75,6 +75,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d t func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { transformed := make(map[string]interface{}) <% property.nested_properties.each do |prop| -%> +<% next if prop.is_a?(Api::Type::KeyValuePairs) && prop.ignore_write -%> <% schemaPrefix = prop.flatten_object ? "nil" : "d.Get( \"#{prop.name.underscore}\" )" -%> transformed<%= titlelize_property(prop) -%>, err := expand<%= prefix -%><%= titlelize_property(property) -%><%= titlelize_property(prop) -%>(<%= schemaPrefix -%>, d, config) if err != nil { @@ -130,6 +131,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d t transformed := make(map[string]interface{}) <% property.nested_properties.each do |prop| -%> +<% next if prop.is_a?(Api::Type::KeyValuePairs) && prop.ignore_write -%> transformed<%= titlelize_property(prop) -%>, err := expand<%= prefix -%><%= titlelize_property(property) -%><%= titlelize_property(prop) -%>(original["<%= prop.name.underscore -%>"], d, config) if err != nil { return nil, err @@ -175,6 +177,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d t <% if !property.nested_properties.nil? -%> <% property.nested_properties.each do |prop| -%> +<% next if prop.is_a?(Api::Type::KeyValuePairs) && prop.ignore_write -%> <%# Map is a map from {key -> object} in the API, but Terraform can't represent that so we treat the key as a property of the object in Terraform schema. %> <%= lines(build_expand_method(prefix + titlelize_property(property), prop, object, pwd), 1) -%> diff --git a/mmv1/templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb b/mmv1/templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb deleted file mode 100644 index 7a1a8eec8f7a..000000000000 --- a/mmv1/templates/terraform/extra_schema_entry/cloudiot_device_registry.go.erb +++ /dev/null @@ -1,32 +0,0 @@ -"state_notification_config": { - Type: schema.TypeMap, - Description: `A PubSub topic to publish device state updates.`, - Optional: true, -}, -"mqtt_config": { - Type: schema.TypeMap, - Description: `Activate or deactivate MQTT.`, - Computed: true, - Optional: true, -}, -"http_config": { - Type: schema.TypeMap, - Description: `Activate or deactivate HTTP.`, - Computed: true, - Optional: true, -}, -"credentials": { - Type: schema.TypeList, - Description: `List of public key certificates to authenticate devices.`, - Optional: true, - MaxItems: 10, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "public_key_certificate": { - Type: schema.TypeMap, - Description: `A public key certificate format and data.`, - Required: true, - }, - }, - }, -}, diff --git a/mmv1/templates/terraform/flatten_property_method.erb b/mmv1/templates/terraform/flatten_property_method.erb index ed6eda44afcc..f13a7d670744 100644 --- a/mmv1/templates/terraform/flatten_property_method.erb +++ b/mmv1/templates/terraform/flatten_property_method.erb @@ -93,6 +93,19 @@ func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d <% end -%> }) } + return transformed +<% elsif (property.is_a?(Api::Type::KeyValueLabels)) || (property.is_a?(Api::Type::KeyValueAnnotations)) || (property.is_a?(Api::Type::KeyValueTerraformLabels)) -%> + if v == nil { + return v + } + + transformed := make(map[string]interface{}) + if l, ok := d.GetOkExists("<%= property.terraform_lineage -%>"); ok { + for k := range l.(map[string]interface{}) { + transformed[k] = v.(map[string]interface{})[k] + } + } + return transformed <% elsif property.is_a?(Api::Type::Integer) -%> // Handles the string fixed64 format diff --git a/mmv1/templates/terraform/post_create/labels.erb b/mmv1/templates/terraform/post_create/labels.erb index 83c6dcea64a9..1aaf5c26ce90 100644 --- a/mmv1/templates/terraform/post_create/labels.erb +++ b/mmv1/templates/terraform/post_create/labels.erb @@ -1,5 +1,8 @@ <% if properties.any?{ |p| p.name == "labels" } -%> -if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { +if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { + labels := d.Get("labels") + terraformLables := d.Get("terraform_labels") + // Labels cannot be set in a create. We'll have to set them here. err = resource<%= resource_name -%>Read(d, meta) if err != nil { @@ -7,8 +10,8 @@ if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v } obj := make(map[string]interface{}) - // d.Get("labels") will have been overridden by the Read call. - labelsProp, err := expand<%= resource_name -%>Labels(v, d, config) + // d.Get("effective_labels") will have been overridden by the Read call. + labelsProp, err := expand<%= resource_name -%>EffectiveLabels(v, d, config) if err != nil { return err } @@ -46,5 +49,19 @@ if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v return err } + // Set back the labels field, as it is needed to decide the value of "labels" in the state in the read function. + if err := d.Set("labels", labels); err != nil { + return fmt.Errorf("Error setting back labels: %s", err) + } + + // Set back the terraform_labels field, as it is needed to decide the value of "terraform_labels" in the state in the read function. + if err := d.Set("terraform_labels", terraformLables); err != nil { + return fmt.Errorf("Error setting back terraform_labels: %s", err) + } + + // Set back the effective_labels field, as it is needed to decide the value of "effective_labels" in the state in the read function. + if err := d.Set("effective_labels", v); err != nil { + return fmt.Errorf("Error setting back effective_labels: %s", err) + } } <% end -%> diff --git a/mmv1/templates/terraform/pre_create/compute_node_group_url_replace.go.erb b/mmv1/templates/terraform/pre_create/compute_node_group_url_replace.go.erb index 62e4828bb500..a85b927ba68a 100644 --- a/mmv1/templates/terraform/pre_create/compute_node_group_url_replace.go.erb +++ b/mmv1/templates/terraform/pre_create/compute_node_group_url_replace.go.erb @@ -1,8 +1,12 @@ var sizeParam string -if v, ok := d.GetOkExists("size"); ok { - sizeParam = fmt.Sprintf("%v", v) -} else if v, ok := d.GetOkExists("initial_size"); ok { +if v, ok := d.GetOkExists("initial_size"); ok { sizeParam = fmt.Sprintf("%v", v) +}else{ + if _, ok := d.GetOkExists("autoscaling_policy"); ok{ + sizeParam = fmt.Sprintf("%v", d.Get("autoscaling_policy.min_nodes")) + }else{ + return errors.New("An initial_size or autoscaling_policy must be configured on node group creation.") + } } url = regexp.MustCompile("PRE_CREATE_REPLACE_ME").ReplaceAllLiteralString(url, sizeParam) diff --git a/mmv1/templates/terraform/pre_update/cloudiot_device_registry.go.erb b/mmv1/templates/terraform/pre_update/cloudiot_device_registry.go.erb deleted file mode 100644 index 226c0efca146..000000000000 --- a/mmv1/templates/terraform/pre_update/cloudiot_device_registry.go.erb +++ /dev/null @@ -1,35 +0,0 @@ -log.Printf("[DEBUG] updateMask before adding extra schema entries %q: %v", d.Id(), updateMask) - -log.Printf("[DEBUG] Pre-update on state notification config: %q", d.Id()) -if d.HasChange("state_notification_config") { - log.Printf("[DEBUG] %q stateNotificationConfig.pubsubTopicName has a change. Adding it to the update mask", d.Id()) - updateMask = append(updateMask, "stateNotificationConfig.pubsubTopicName") -} - -log.Printf("[DEBUG] Pre-update on MQTT config: %q", d.Id()) -if d.HasChange("mqtt_config") { - log.Printf("[DEBUG] %q mqttConfig.mqttEnabledState has a change. Adding it to the update mask", d.Id()) - updateMask = append(updateMask, "mqttConfig.mqttEnabledState") -} - -log.Printf("[DEBUG] Pre-update on HTTP config: %q", d.Id()) -if d.HasChange("http_config") { - log.Printf("[DEBUG] %q httpConfig.httpEnabledState has a change. Adding it to the update mask", d.Id()) - updateMask = append(updateMask, "httpConfig.httpEnabledState") -} - -log.Printf("[DEBUG] Pre-update on credentials: %q", d.Id()) -if d.HasChange("credentials") { - log.Printf("[DEBUG] %q credentials has a change. Adding it to the update mask", d.Id()) - updateMask = append(updateMask, "credentials") -} - -log.Printf("[DEBUG] updateMask after adding extra schema entries %q: %v", d.Id(), updateMask) - -// Refreshing updateMask after adding extra schema entries -url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) -if err != nil { - return err -} - -log.Printf("[DEBUG] Update URL %q: %v", d.Id(), url) diff --git a/mmv1/templates/terraform/resource.erb b/mmv1/templates/terraform/resource.erb index 4306de057c7a..38461737ca95 100644 --- a/mmv1/templates/terraform/resource.erb +++ b/mmv1/templates/terraform/resource.erb @@ -65,6 +65,7 @@ import ( client_name_lower = client_name.downcase has_project = object.base_url.include?('{{project}}') || (object.create_url && object.create_url.include?('{{project}}')) has_region = object.base_url.include?('{{region}}') && object.parameters.any?{ |p| p.name == 'region' && p.ignore_read } + has_zone = object.base_url.include?('{{zone}}') && object.parameters.any?{ |p| p.name == 'zone' && p.ignore_read } # In order of preference, use TF override, # general defined timeouts, or default Timeouts timeouts = object.timeouts @@ -104,7 +105,7 @@ func Resource<%= resource_name -%>() *schema.Resource { <% if object.state_upgraders -%> StateUpgraders: []schema.StateUpgrader{ -<% for v in 0..object.schema_version-1 -%> +<% for v in object.state_upgrade_base_schema_version..object.schema_version-1 -%> { Type: resource<%= "#{resource_name}ResourceV#{v}" -%>().CoreConfigSchema().ImpliedType(), Upgrade: Resource<%= "#{resource_name}UpgradeV#{v}" -%>, @@ -113,7 +114,7 @@ func Resource<%= resource_name -%>() *schema.Resource { <% end -%> }, <% end -%> -<% if object.custom_diff.any? || object.settable_properties.any? {|p| p.unordered_list}-%> +<% if ((has_project || has_region || has_zone) && !object.skip_default_cdiff) || object.custom_diff.any? || object.settable_properties.any? {|p| p.unordered_list}-%> CustomizeDiff: customdiff.All( <% if object.settable_properties.any? {|p| p.unordered_list} -%> <%= @@ -126,6 +127,15 @@ func Resource<%= resource_name -%>() *schema.Resource { <% for cdiff in object.custom_diff-%> <%= cdiff%>, <% end -%> +<% end -%> +<% if has_project && !object.skip_default_cdiff -%> + tpgresource.DefaultProviderProject, +<% end -%> +<% if has_region && !object.skip_default_cdiff -%> + tpgresource.DefaultProviderRegion, +<% end -%> +<% if has_zone && !object.skip_default_cdiff -%> + tpgresource.DefaultProviderZone, <% end -%> ), <% end -%> @@ -640,6 +650,16 @@ func resource<%= resource_name -%>Read(d *schema.ResourceData, meta interface{}) } <% end -%> +<% if has_zone -%> + zone, err := tpgresource.GetZone(d, config) + if err != nil { + return err + } + if err := d.Set("zone", zone); err != nil { + return fmt.Errorf("Error reading <%= object.name -%>: %s", err) + } +<% end -%> + <% object.gettable_properties.reject{|p| p.ignore_read }.each do |prop| -%> <% if prop.flatten_object -%> // Terraform must set the top level schema field, but since this object contains collapsed properties @@ -1130,7 +1150,7 @@ func resource<%= resource_name -%>Import(d *schema.ResourceData, meta interface{ config := meta.(*transport_tpg.Config) if err := tpgresource.ParseImportId([]string{ <% for import_id in import_id_formats_from_resource(object) -%> - "<%= format2regex(import_id) %>", + "^<%= format2regex(import_id) %>$", <% end -%> }, d, config); err != nil { return nil, err diff --git a/mmv1/templates/terraform/state_migrations/cloud_run_domain_mapping.go.erb b/mmv1/templates/terraform/state_migrations/cloud_run_domain_mapping.go.erb new file mode 100644 index 000000000000..865a0a95c905 --- /dev/null +++ b/mmv1/templates/terraform/state_migrations/cloud_run_domain_mapping.go.erb @@ -0,0 +1,276 @@ +var domainMappingGoogleProvidedLocationLabel = "cloud.googleapis.com/location" +var domainMappingGoogleProvidedOverrideLabel = "run.googleapis.com/overrideAt" + +var domainMappingGoogleProvidedLabels = []string{ + domainMappingGoogleProvidedLocationLabel, + domainMappingGoogleProvidedOverrideLabel, +} + +func DomainMappingLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the labels provided by Google + for _, label := range domainMappingGoogleProvidedLabels { + if strings.Contains(k, label) && new == "" { + return true + } + } + + // Let diff be determined by labels (above) + if strings.Contains(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +func resourceCloudRunDomainMappingResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The location of the cloud run instance. eg us-central1`, + }, + "metadata": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Description: `Metadata associated with this DomainMapping.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "namespace": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `In Cloud Run the namespace must be equal to either the +project ID or project number.`, + }, + "annotations": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: cloudrunAnnotationDiffSuppress, + Description: `Annotations is a key value map stored with a resource that +may be set by external tools to store and retrieve arbitrary metadata. More +info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations + +**Note**: The Cloud Run API may add additional annotations that were not provided in your config. +If terraform plan shows a diff where a server-side annotation is added, you can add it to your config +or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: DomainMappingLabelDiffSuppress, + Description: `Map of string keys and values that can be used to organize and categorize +(scope and select) objects. May match selectors of replication controllers +and routes. +More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "generation": { + Type: schema.TypeInt, + Computed: true, + Description: `A sequence number representing a specific generation of the desired state.`, + }, + "resource_version": { + Type: schema.TypeString, + Computed: true, + Description: `An opaque value that represents the internal version of this object that +can be used by clients to determine when objects have changed. May be used +for optimistic concurrency, change detection, and the watch operation on a +resource or set of resources. They may only be valid for a +particular resource or set of resources. + +More info: +https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `SelfLink is a URL representing this object.`, + }, + "uid": { + Type: schema.TypeString, + Computed: true, + Description: `UID is a unique id generated by the server on successful creation of a resource and is not +allowed to change on PUT operations. + +More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids`, + }, + }, + }, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Name should be a [verified](https://support.google.com/webmasters/answer/9008080) domain`, + }, + "spec": { + Type: schema.TypeList, + Required: true, + ForceNew: true, + Description: `The spec for this DomainMapping.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "route_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name of the Cloud Run Service that this DomainMapping applies to. +The route must exist.`, + }, + "certificate_mode": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"NONE", "AUTOMATIC", ""}), + Description: `The mode of the certificate. Default value: "AUTOMATIC" Possible values: ["NONE", "AUTOMATIC"]`, + Default: "AUTOMATIC", + }, + "force_override": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `If set, the mapping will override any mapping set before this spec was set. +It is recommended that the user leaves this empty to receive an error +warning about a potential conflict and only set it once the respective UI +has given such a warning.`, + }, + }, + }, + }, + "status": { + Type: schema.TypeList, + Computed: true, + Description: `The current status of the DomainMapping.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resource_records": { + Type: schema.TypeList, + Optional: true, + Description: `The resource records required to configure this domain mapping. These +records must be added to the domain's DNS configuration in order to +serve the application via this domain mapping.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"A", "AAAA", "CNAME", ""}), + Description: `Resource record type. Example: 'AAAA'. Possible values: ["A", "AAAA", "CNAME"]`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `Relative name of the object affected by this record. Only applicable for +'CNAME' records. Example: 'www'.`, + }, + "rrdata": { + Type: schema.TypeString, + Computed: true, + Description: `Data for this record. Values vary by record type, as defined in RFC 1035 +(section 5) and RFC 1034 (section 3.6.1).`, + }, + }, + }, + }, + "conditions": { + Type: schema.TypeList, + Computed: true, + Description: `Array of observed DomainMappingConditions, indicating the current state +of the DomainMapping.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "message": { + Type: schema.TypeString, + Computed: true, + Description: `Human readable message indicating details about the current status.`, + }, + "reason": { + Type: schema.TypeString, + Computed: true, + Description: `One-word CamelCase reason for the condition's current status.`, + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: `Status of the condition, one of True, False, Unknown.`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `Type of domain mapping condition.`, + }, + }, + }, + }, + "mapped_route_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the route that the mapping currently points to.`, + }, + "observed_generation": { + Type: schema.TypeInt, + Computed: true, + Description: `ObservedGeneration is the 'Generation' of the DomainMapping that +was last processed by the controller.`, + }, + }, + }, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceCloudRunDomainMappingUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + log.Printf("[DEBUG] Attributes before migration: %#v", rawState) + + if rawState["metadata"] != nil { + rawMetadatas := rawState["metadata"].([]interface{}) + if len(rawMetadatas) > 0 && rawMetadatas[0] != nil { + // Upgrade labels fields + rawMetadata := rawMetadatas[0].(map[string]interface{}) + + rawLabels := rawMetadata["labels"] + if rawLabels != nil { + labels := make(map[string]interface{}) + effectiveLabels := make(map[string]interface{}) + + for k, v := range rawLabels.(map[string]interface{}) { + effectiveLabels[k] = v + + if !strings.Contains(k, domainMappingGoogleProvidedLocationLabel) && !strings.Contains(k, domainMappingGoogleProvidedOverrideLabel) { + labels[k] = v + } + } + + rawMetadata["labels"] = labels + rawMetadata["effective_labels"] = effectiveLabels + } + + upgradeAnnotations(rawMetadata) + + rawState["metadata"] = []interface{}{rawMetadata} + } + } + + log.Printf("[DEBUG] Attributes after migration: %#v", rawState) + return rawState, nil +} diff --git a/mmv1/templates/terraform/state_migrations/cloud_run_service.go.erb b/mmv1/templates/terraform/state_migrations/cloud_run_service.go.erb new file mode 100644 index 000000000000..9c807cef403f --- /dev/null +++ b/mmv1/templates/terraform/state_migrations/cloud_run_service.go.erb @@ -0,0 +1,1099 @@ +var cloudRunGoogleProvidedAnnotations = regexp.MustCompile(`serving\.knative\.dev/(?:(?:creator)|(?:lastModifier))$|run\.googleapis\.com/(?:(?:ingress-status)|(?:operation-id))$|cloud\.googleapis\.com/(?:(?:location))`) + +func cloudrunAnnotationDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the annotations provided by Google + if cloudRunGoogleProvidedAnnotations.MatchString(k) && new == "" { + return true + } + + if strings.HasSuffix(k, "run.googleapis.com/ingress") { + return old == "all" && new == "" + } + + // Let diff be determined by annotations (above) + if strings.Contains(k, "annotations.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +var cloudRunGoogleProvidedLabels = regexp.MustCompile(`cloud\.googleapis\.com/(?:(?:location))`) + +func cloudrunLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the labels provided by Google + if cloudRunGoogleProvidedLabels.MatchString(k) && new == "" { + return true + } + + // Let diff be determined by labels (above) + if strings.Contains(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +func resourceCloudRunServiceResourceV1() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The location of the cloud run instance. eg us-central1`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Name must be unique within a Google Cloud project and region. +Is required when creating resources. Name is primarily intended +for creation idempotence and configuration definition. Cannot be updated. +More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names`, + }, + "template": { + Type: schema.TypeList, + Optional: true, + Description: `template holds the latest specification for the Revision to +be stamped out. The template references the container image, and may also +include labels and annotations that should be attached to the Revision. +To correlate a Revision, and/or to force a Revision to be created when the +spec doesn't otherwise change, a nonce label may be provided in the +template metadata. For more details, see: +https://github.com/knative/serving/blob/main/docs/client-conventions.md#associate-modifications-with-revisions + +Cloud Run does not currently support referencing a build that is +responsible for materializing the container image from source.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "spec": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `RevisionSpec holds the desired state of the Revision (from the client).`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "containers": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Containers defines the unit of execution for this Revision.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "image": { + Type: schema.TypeString, + Required: true, + Description: `Docker image name. This is most often a reference to a container located +in the container registry, such as gcr.io/cloudrun/hello`, + }, + "args": { + Type: schema.TypeList, + Optional: true, + Description: `Arguments to the entrypoint. +The docker image's CMD is used if this is not provided.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "command": { + Type: schema.TypeList, + Optional: true, + Description: `Entrypoint array. Not executed within a shell. +The docker image's ENTRYPOINT is used if this is not provided.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "env": { + Type: schema.TypeSet, + Optional: true, + Description: `List of environment variables to set in the container.`, + Elem: cloudrunServiceSpecTemplateSpecContainersContainersEnvSchema(), + // Default schema.HashSchema is used. + }, + "env_from": { + Type: schema.TypeList, + Optional: true, + Deprecated: "`env_from` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API.", + ForceNew: true, + Description: `List of sources to populate environment variables in the container. +All invalid keys will be reported as an event when the container is starting. +When a key exists in multiple sources, the value associated with the last source will +take precedence. Values defined by an Env with a duplicate key will take +precedence.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "config_map_ref": { + Type: schema.TypeList, + Optional: true, + Description: `The ConfigMap to select from.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "local_object_reference": { + Type: schema.TypeList, + Optional: true, + Description: `The ConfigMap to select from.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `Name of the referent.`, + }, + }, + }, + }, + "optional": { + Type: schema.TypeBool, + Optional: true, + Description: `Specify whether the ConfigMap must be defined`, + }, + }, + }, + }, + "prefix": { + Type: schema.TypeString, + Optional: true, + Description: `An optional identifier to prepend to each key in the ConfigMap.`, + }, + "secret_ref": { + Type: schema.TypeList, + Optional: true, + Description: `The Secret to select from.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "local_object_reference": { + Type: schema.TypeList, + Optional: true, + Description: `The Secret to select from.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `Name of the referent.`, + }, + }, + }, + }, + "optional": { + Type: schema.TypeBool, + Optional: true, + Description: `Specify whether the Secret must be defined`, + }, + }, + }, + }, + }, + }, + }, + "liveness_probe": { + Type: schema.TypeList, + Optional: true, + Description: `Periodic probe of container liveness. Container will be restarted if the probe fails.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "failure_threshold": { + Type: schema.TypeInt, + Optional: true, + Description: `Minimum consecutive failures for the probe to be considered failed after +having succeeded. Defaults to 3. Minimum value is 1.`, + Default: 3, + }, + "grpc": { + Type: schema.TypeList, + Optional: true, + Description: `GRPC specifies an action involving a GRPC port.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + "service": { + Type: schema.TypeString, + Optional: true, + Description: `The name of the service to place in the gRPC HealthCheckRequest +(see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). +If this is not specified, the default behavior is defined by gRPC.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "http_get": { + Type: schema.TypeList, + Optional: true, + Description: `HttpGet specifies the http request to perform.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http_headers": { + Type: schema.TypeList, + Optional: true, + Description: `Custom headers to set in the request. HTTP allows repeated headers.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `The header field name.`, + }, + "value": { + Type: schema.TypeString, + Optional: true, + Description: `The header field value.`, + Default: "", + }, + }, + }, + }, + "path": { + Type: schema.TypeString, + Optional: true, + Description: `Path to access on the HTTP server. If set, it should not be empty string.`, + Default: "/", + }, + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "initial_delay_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of seconds after the container has started before the probe is +initiated. +Defaults to 0 seconds. Minimum value is 0. Maximum value is 3600.`, + Default: 0, + }, + "period_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `How often (in seconds) to perform the probe. +Default to 10 seconds. Minimum value is 1. Maximum value is 3600.`, + Default: 10, + }, + "timeout_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of seconds after which the probe times out. +Defaults to 1 second. Minimum value is 1. Maximum value is 3600. +Must be smaller than period_seconds.`, + Default: 1, + }, + }, + }, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Name of the container`, + }, + "ports": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `List of open ports in the container.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "container_port": { + Type: schema.TypeInt, + Optional: true, + Description: `Port number the container listens on. This must be a valid port number (between 1 and 65535). Defaults to "8080".`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `If specified, used to specify which protocol to use. Allowed values are "http1" (HTTP/1) and "h2c" (HTTP/2 end-to-end). Defaults to "http1".`, + }, + "protocol": { + Type: schema.TypeString, + Optional: true, + Description: `Protocol for port. Must be "TCP". Defaults to "TCP".`, + }, + }, + }, + }, + "resources": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Compute Resources required by this container. Used to set values such as max memory`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "limits": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + Description: `Limits describes the maximum amount of compute resources allowed. +The values of the map is string form of the 'quantity' k8s type: +https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "requests": { + Type: schema.TypeMap, + Optional: true, + Description: `Requests describes the minimum amount of compute resources required. +If Requests is omitted for a container, it defaults to Limits if that is +explicitly specified, otherwise to an implementation-defined value. +The values of the map is string form of the 'quantity' k8s type: +https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "startup_probe": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Startup probe of application within the container. +All other probes are disabled if a startup probe is provided, until it +succeeds. Container will not be added to service endpoints if the probe fails.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "failure_threshold": { + Type: schema.TypeInt, + Optional: true, + Description: `Minimum consecutive failures for the probe to be considered failed after +having succeeded. Defaults to 3. Minimum value is 1.`, + Default: 3, + }, + "grpc": { + Type: schema.TypeList, + Optional: true, + Description: `GRPC specifies an action involving a GRPC port.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + "service": { + Type: schema.TypeString, + Optional: true, + Description: `The name of the service to place in the gRPC HealthCheckRequest +(see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). +If this is not specified, the default behavior is defined by gRPC.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "http_get": { + Type: schema.TypeList, + Optional: true, + Description: `HttpGet specifies the http request to perform.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http_headers": { + Type: schema.TypeList, + Optional: true, + Description: `Custom headers to set in the request. HTTP allows repeated headers.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `The header field name.`, + }, + "value": { + Type: schema.TypeString, + Optional: true, + Description: `The header field value.`, + Default: "", + }, + }, + }, + }, + "path": { + Type: schema.TypeString, + Optional: true, + Description: `Path to access on the HTTP server. If set, it should not be empty string.`, + Default: "/", + }, + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "initial_delay_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of seconds after the container has started before the probe is +initiated. +Defaults to 0 seconds. Minimum value is 0. Maximum value is 240.`, + Default: 0, + }, + "period_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `How often (in seconds) to perform the probe. +Default to 10 seconds. Minimum value is 1. Maximum value is 240.`, + Default: 10, + }, + "tcp_socket": { + Type: schema.TypeList, + Optional: true, + Description: `TcpSocket specifies an action involving a TCP port.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "port": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `Port number to access on the container. Number must be in the range 1 to 65535. +If not specified, defaults to the same value as container.ports[0].containerPort.`, + }, + }, + }, + ExactlyOneOf: []string{}, + }, + "timeout_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of seconds after which the probe times out. +Defaults to 1 second. Minimum value is 1. Maximum value is 3600. +Must be smaller than periodSeconds.`, + Default: 1, + }, + }, + }, + }, + "volume_mounts": { + Type: schema.TypeList, + Optional: true, + Description: `Volume to mount into the container's filesystem. +Only supports SecretVolumeSources.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mount_path": { + Type: schema.TypeString, + Required: true, + Description: `Path within the container at which the volume should be mounted. Must +not contain ':'.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: `This must match the Name of a Volume.`, + }, + }, + }, + }, + "working_dir": { + Type: schema.TypeString, + Optional: true, + Deprecated: "`working_dir` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API.", + ForceNew: true, + Description: `Container's working directory. +If not specified, the container runtime's default will be used, which +might be configured in the container image.`, + }, + }, + }, + }, + "container_concurrency": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `ContainerConcurrency specifies the maximum allowed in-flight (concurrent) +requests per container of the Revision. Values are: +- '0' thread-safe, the system should manage the max concurrency. This is + the default value. +- '1' not-thread-safe. Single concurrency +- '2-N' thread-safe, max concurrency of N`, + }, + "service_account_name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Email address of the IAM service account associated with the revision of the +service. The service account represents the identity of the running revision, +and determines what permissions the revision has. If not provided, the revision +will use the project's default service account.`, + }, + "timeout_seconds": { + Type: schema.TypeInt, + Computed: true, + Optional: true, + Description: `TimeoutSeconds holds the max duration the instance is allowed for responding to a request.`, + }, + "volumes": { + Type: schema.TypeList, + Optional: true, + Description: `Volume represents a named volume in a container.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: `Volume's name.`, + }, +<% unless version == "ga" -%> + "empty_dir": { + Type: schema.TypeList, + Optional: true, + Description: `Ephemeral storage which can be backed by real disks (HD, SSD), network storage or memory (i.e. tmpfs). For now only in memory (tmpfs) is supported. It is ephemeral in the sense that when the sandbox is taken down, the data is destroyed with it (it does not persist across sandbox runs).`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "medium": { + Type: schema.TypeString, + Optional: true, + Description: `The medium on which the data is stored. The default is "" which means to use the node's default medium. Must be an empty string (default) or Memory.`, + }, + "size_limit": { + Type: schema.TypeString, + Optional: true, + Description: `Limit on the storage usable by this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. This field's values are of the 'Quantity' k8s type: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir.`, + }, + }, + }, + }, +<% end -%> + "secret": { + Type: schema.TypeList, + Optional: true, + Description: `The secret's value will be presented as the content of a file whose +name is defined in the item path. If no items are defined, the name of +the file is the secret_name.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "secret_name": { + Type: schema.TypeString, + Required: true, + Description: `The name of the secret in Cloud Secret Manager. By default, the secret +is assumed to be in the same project. +If the secret is in another project, you must define an alias. +An alias definition has the form: +{alias}:projects/{project-id|project-number}/secrets/{secret-name}. +If multiple alias definitions are needed, they must be separated by +commas. +The alias definitions must be set on the run.googleapis.com/secrets +annotation.`, + }, + "default_mode": { + Type: schema.TypeInt, + Optional: true, + Description: `Mode bits to use on created files by default. Must be a value between 0000 +and 0777. Defaults to 0644. Directories within the path are not affected by +this setting. This might be in conflict with other options that affect the +file mode, like fsGroup, and the result can be other mode bits set.`, + }, + "items": { + Type: schema.TypeList, + Optional: true, + Description: `If unspecified, the volume will expose a file whose name is the +secret_name. +If specified, the key will be used as the version to fetch from Cloud +Secret Manager and the path will be the name of the file exposed in the +volume. When items are defined, they must specify a key and a path.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Required: true, + Description: `The Cloud Secret Manager secret version. +Can be 'latest' for the latest value or an integer for a specific version.`, + }, + "path": { + Type: schema.TypeString, + Required: true, + Description: `The relative path of the file to map the key to. +May not be an absolute path. +May not contain the path element '..'. +May not start with the string '..'.`, + }, + "mode": { + Type: schema.TypeInt, + Optional: true, + Description: `Mode bits to use on this file, must be a value between 0000 and 0777. If +not specified, the volume defaultMode will be used. This might be in +conflict with other options that affect the file mode, like fsGroup, and +the result can be other mode bits set.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "serving_state": { + Type: schema.TypeString, + Computed: true, + Deprecated: "`serving_state` is deprecated and will be removed in a future major release. This field is not supported by the Cloud Run API.", + Description: `ServingState holds a value describing the state the resources +are in for this Revision. +It is expected +that the system will manipulate this based on routability and load.`, + }, + }, + }, + }, + "metadata": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Optional metadata for this Revision, including labels and annotations. +Name will be generated by the Configuration. To set minimum instances +for this revision, use the "autoscaling.knative.dev/minScale" annotation +key. To set maximum instances for this revision, use the +"autoscaling.knative.dev/maxScale" annotation key. To set Cloud SQL +connections for the revision, use the "run.googleapis.com/cloudsql-instances" +annotation key.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "annotations": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: cloudrunTemplateAnnotationDiffSuppress, + Description: `Annotations is a key value map stored with a resource that +may be set by external tools to store and retrieve arbitrary metadata. More +info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations + +**Note**: The Cloud Run API may add additional annotations that were not provided in your config. +If terraform plan shows a diff where a server-side annotation is added, you can add it to your config +or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field. + +Annotations with 'run.googleapis.com/' and 'autoscaling.knative.dev' are restricted. Use the following annotation +keys to configure features on a Revision template: + +- 'autoscaling.knative.dev/maxScale' sets the [maximum number of container + instances](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--max-instances) of the Revision to run. +- 'autoscaling.knative.dev/minScale' sets the [minimum number of container + instances](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--min-instances) of the Revision to run. +- 'run.googleapis.com/client-name' sets the client name calling the Cloud Run API. +- 'run.googleapis.com/cloudsql-instances' sets the [Cloud SQL + instances](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--add-cloudsql-instances) the Revision connects to. +- 'run.googleapis.com/cpu-throttling' sets whether to throttle the CPU when the container is not actively serving + requests. See https://cloud.google.com/sdk/gcloud/reference/run/deploy#--[no-]cpu-throttling. +- 'run.googleapis.com/encryption-key-shutdown-hours' sets the number of hours to wait before an automatic shutdown + server after CMEK key revocation is detected. +- 'run.googleapis.com/encryption-key' sets the [CMEK key](https://cloud.google.com/run/docs/securing/using-cmek) + reference to encrypt the container with. +- 'run.googleapis.com/execution-environment' sets the [execution + environment](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--execution-environment) + where the application will run. +- 'run.googleapis.com/post-key-revocation-action-type' sets the + [action type](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--post-key-revocation-action-type) + after CMEK key revocation. +- 'run.googleapis.com/secrets' sets a list of key-value pairs to set as + [secrets](https://cloud.google.com/run/docs/configuring/secrets#yaml). +- 'run.googleapis.com/sessionAffinity' sets whether to enable + [session affinity](https://cloud.google.com/sdk/gcloud/reference/beta/run/deploy#--[no-]session-affinity) + for connections to the Revision. +- 'run.googleapis.com/startup-cpu-boost' sets whether to allocate extra CPU to containers on startup. + See https://cloud.google.com/sdk/gcloud/reference/run/deploy#--[no-]cpu-boost. +- 'run.googleapis.com/vpc-access-connector' sets a [VPC connector](https://cloud.google.com/run/docs/configuring/connecting-vpc#terraform_1) + for the Revision. +- 'run.googleapis.com/vpc-access-egress' sets the outbound traffic to send through the VPC connector for this resource. + See https://cloud.google.com/sdk/gcloud/reference/run/deploy#--vpc-egress.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: cloudrunTemplateLabelDiffSuppress, + Description: `Map of string keys and values that can be used to organize and categorize +(scope and select) objects.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Name must be unique within a Google Cloud project and region. +Is required when creating resources. Name is primarily intended +for creation idempotence and configuration definition. Cannot be updated.`, + }, + "namespace": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `In Cloud Run the namespace must be equal to either the +project ID or project number. It will default to the resource's project.`, + }, + "generation": { + Type: schema.TypeInt, + Computed: true, + Description: `A sequence number representing a specific generation of the desired state.`, + }, + "resource_version": { + Type: schema.TypeString, + Computed: true, + Description: `An opaque value that represents the internal version of this object that +can be used by clients to determine when objects have changed. May be used +for optimistic concurrency, change detection, and the watch operation on a +resource or set of resources. They may only be valid for a +particular resource or set of resources.`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `SelfLink is a URL representing this object.`, + }, + "uid": { + Type: schema.TypeString, + Computed: true, + Description: `UID is a unique id generated by the server on successful creation of a resource and is not +allowed to change on PUT operations.`, + }, + }, + }, + }, + }, + }, + }, + "traffic": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Traffic specifies how to distribute traffic over a collection of Knative Revisions +and Configurations`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "percent": { + Type: schema.TypeInt, + Required: true, + Description: `Percent specifies percent of the traffic to this Revision or Configuration.`, + }, + "latest_revision": { + Type: schema.TypeBool, + Optional: true, + Description: `LatestRevision may be optionally provided to indicate that the latest ready +Revision of the Configuration should be used for this traffic target. When +provided LatestRevision must be true if RevisionName is empty; it must be +false when RevisionName is non-empty.`, + }, + "revision_name": { + Type: schema.TypeString, + Optional: true, + Description: `RevisionName of a specific revision to which to send this portion of traffic.`, + }, + "tag": { + Type: schema.TypeString, + Optional: true, + Description: `Tag is optionally used to expose a dedicated url for referencing this target exclusively.`, + }, + "url": { + Type: schema.TypeString, + Computed: true, + Description: `URL displays the URL for accessing tagged traffic targets. URL is displayed in status, +and is disallowed on spec. URL must contain a scheme (e.g. http://) and a hostname, +but may not contain anything else (e.g. basic auth, url path, etc.)`, + }, + }, + }, + }, + + "metadata": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Metadata associated with this Service, including name, namespace, labels, +and annotations.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "annotations": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: cloudrunAnnotationDiffSuppress, + Description: `Annotations is a key value map stored with a resource that +may be set by external tools to store and retrieve arbitrary metadata. More +info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations + +**Note**: The Cloud Run API may add additional annotations that were not provided in your config. +If terraform plan shows a diff where a server-side annotation is added, you can add it to your config +or apply the lifecycle.ignore_changes rule to the metadata.0.annotations field. + +Annotations with 'run.googleapis.com/' and 'autoscaling.knative.dev' are restricted. Use the following annotation +keys to configure features on a Service: + +- 'run.googleapis.com/binary-authorization-breakglass' sets the [Binary Authorization breakglass](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--breakglass). +- 'run.googleapis.com/binary-authorization' sets the [Binary Authorization](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--binary-authorization). +- 'run.googleapis.com/client-name' sets the client name calling the Cloud Run API. +- 'run.googleapis.com/custom-audiences' sets the [custom audiences](https://cloud.google.com/sdk/gcloud/reference/alpha/run/deploy#--add-custom-audiences) + that can be used in the audience field of ID token for authenticated requests. +- 'run.googleapis.com/description' sets a user defined description for the Service. +- 'run.googleapis.com/ingress' sets the [ingress settings](https://cloud.google.com/sdk/gcloud/reference/run/deploy#--ingress) + for the Service. For example, '"run.googleapis.com/ingress" = "all"'. +- 'run.googleapis.com/launch-stage' sets the [launch stage](https://cloud.google.com/run/docs/troubleshooting#launch-stage-validation) + when a preview feature is used. For example, '"run.googleapis.com/launch-stage": "BETA"'`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: cloudrunLabelDiffSuppress, + Description: `Map of string keys and values that can be used to organize and categorize +(scope and select) objects. May match selectors of replication controllers +and routes.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "namespace": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `In Cloud Run the namespace must be equal to either the +project ID or project number.`, + }, + "generation": { + Type: schema.TypeInt, + Computed: true, + Description: `A sequence number representing a specific generation of the desired state.`, + }, + "resource_version": { + Type: schema.TypeString, + Computed: true, + Description: `An opaque value that represents the internal version of this object that +can be used by clients to determine when objects have changed. May be used +for optimistic concurrency, change detection, and the watch operation on a +resource or set of resources. They may only be valid for a +particular resource or set of resources.`, + }, + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `SelfLink is a URL representing this object.`, + }, + "uid": { + Type: schema.TypeString, + Computed: true, + Description: `UID is a unique id generated by the server on successful creation of a resource and is not +allowed to change on PUT operations.`, + }, + }, + }, + }, + "status": { + Type: schema.TypeList, + Computed: true, + Description: `The current status of the Service.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "conditions": { + Type: schema.TypeList, + Computed: true, + Description: `Array of observed Service Conditions, indicating the current ready state of the service.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "message": { + Type: schema.TypeString, + Computed: true, + Description: `Human readable message indicating details about the current status.`, + }, + "reason": { + Type: schema.TypeString, + Computed: true, + Description: `One-word CamelCase reason for the condition's current status.`, + }, + "status": { + Type: schema.TypeString, + Computed: true, + Description: `Status of the condition, one of True, False, Unknown.`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `Type of domain mapping condition.`, + }, + }, + }, + }, + "latest_created_revision_name": { + Type: schema.TypeString, + Computed: true, + Description: `From ConfigurationStatus. LatestCreatedRevisionName is the last revision that was created +from this Service's Configuration. It might not be ready yet, for that use +LatestReadyRevisionName.`, + }, + "latest_ready_revision_name": { + Type: schema.TypeString, + Computed: true, + Description: `From ConfigurationStatus. LatestReadyRevisionName holds the name of the latest Revision +stamped out from this Service's Configuration that has had its "Ready" condition become +"True".`, + }, + "observed_generation": { + Type: schema.TypeInt, + Computed: true, + Description: `ObservedGeneration is the 'Generation' of the Route that was last processed by the +controller. + +Clients polling for completed reconciliation should poll until observedGeneration = +metadata.generation and the Ready condition's status is True or False.`, + }, + "traffic": { + Type: schema.TypeList, + Computed: true, + Description: `Traffic specifies how to distribute traffic over a collection of Knative Revisions +and Configurations`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "latest_revision": { + Type: schema.TypeBool, + Computed: true, + Description: `LatestRevision may be optionally provided to indicate that the latest ready +Revision of the Configuration should be used for this traffic target. When +provided LatestRevision must be true if RevisionName is empty; it must be +false when RevisionName is non-empty.`, + }, + "percent": { + Type: schema.TypeInt, + Computed: true, + Description: `Percent specifies percent of the traffic to this Revision or Configuration.`, + }, + "revision_name": { + Type: schema.TypeString, + Computed: true, + Description: `RevisionName of a specific revision to which to send this portion of traffic.`, + }, + "tag": { + Type: schema.TypeString, + Computed: true, + Description: `Tag is optionally used to expose a dedicated url for referencing this target exclusively.`, + }, + "url": { + Type: schema.TypeString, + Computed: true, + Description: `URL displays the URL for accessing tagged traffic targets. URL is displayed in status, +and is disallowed on spec. URL must contain a scheme (e.g. http://) and a hostname, +but may not contain anything else (e.g. basic auth, url path, etc.)`, + }, + }, + }, + }, + "url": { + Type: schema.TypeString, + Computed: true, + Description: `From RouteStatus. URL holds the url that will distribute traffic over the provided traffic +targets. It generally has the form +https://{route-hash}-{project-hash}-{cluster-level-suffix}.a.run.app`, + }, + }, + }, + }, + "autogenerate_revision_name": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `If set to 'true', the revision name (template.metadata.name) will be omitted and +autogenerated by Cloud Run. This cannot be set to 'true' while 'template.metadata.name' +is also set. +(For legacy support, if 'template.metadata.name' is unset in state while +this field is set to false, the revision name will still autogenerate.)`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func upgradeAnnotations(rawMetadata map[string]interface{}) { + rawAnnotations := rawMetadata["annotations"] + if rawAnnotations != nil { + annotations := make(map[string]interface{}) + effectiveAnnotations := make(map[string]interface{}) + + for k, v := range rawAnnotations.(map[string]interface{}) { + effectiveAnnotations[k] = v + + if !(cloudRunGoogleProvidedAnnotations.MatchString(k) || (strings.HasSuffix(k, "run.googleapis.com/ingress") && v == "all")) { + annotations[k] = v + } + } + + rawMetadata["annotations"] = annotations + rawMetadata["effective_annotations"] = effectiveAnnotations + } +} + +func ResourceCloudRunServiceUpgradeV1(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + log.Printf("[DEBUG] Attributes before migration: %#v", rawState) + + if rawState["metadata"] != nil { + rawMetadatas := rawState["metadata"].([]interface{}) + + // Upgrade labels fields + if len(rawMetadatas) > 0 && rawMetadatas[0] != nil { + rawMetadata := rawMetadatas[0].(map[string]interface{}) + + rawLabels := rawMetadata["labels"] + if rawLabels != nil { + labels := make(map[string]interface{}) + effectiveLabels := make(map[string]interface{}) + + for k, v := range rawLabels.(map[string]interface{}) { + effectiveLabels[k] = v + + if !cloudRunGoogleProvidedLabels.MatchString(k) { + labels[k] = v + } + } + + rawMetadata["labels"] = labels + rawMetadata["effective_labels"] = effectiveLabels + } + + upgradeAnnotations(rawMetadata) + + rawState["metadata"] = []interface{}{rawMetadata} + } + } + + log.Printf("[DEBUG] Attributes after migration: %#v", rawState) + return rawState, nil +} diff --git a/mmv1/templates/terraform/state_migrations/notebooks_instance.go.erb b/mmv1/templates/terraform/state_migrations/notebooks_instance.go.erb new file mode 100644 index 000000000000..069dacdd5216 --- /dev/null +++ b/mmv1/templates/terraform/state_migrations/notebooks_instance.go.erb @@ -0,0 +1,407 @@ +const notebooksInstanceGoogleProvidedLabel = "goog-caip-notebook" + +func NotebooksInstanceLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the label provided by Google + if strings.Contains(k, notebooksInstanceGoogleProvidedLabel) && new == "" { + return true + } + + // Let diff be determined by labels (above) + if strings.Contains(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + +func resourceNotebooksInstanceResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `A reference to the zone where the machine resides.`, + }, + "machine_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `A reference to a machine type which defines VM kind.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name specified for the Notebook instance.`, + }, + "accelerator_config": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `The hardware accelerator used on this instance. If you use accelerators, +make sure that your configuration has enough vCPUs and memory to support the +machineType you have selected.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "core_count": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: `Count of cores of this accelerator.`, + }, + "type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"ACCELERATOR_TYPE_UNSPECIFIED", "NVIDIA_TESLA_K80", "NVIDIA_TESLA_P100", "NVIDIA_TESLA_V100", "NVIDIA_TESLA_P4", "NVIDIA_TESLA_T4", "NVIDIA_TESLA_T4_VWS", "NVIDIA_TESLA_P100_VWS", "NVIDIA_TESLA_P4_VWS", "NVIDIA_TESLA_A100", "TPU_V2", "TPU_V3"}), + Description: `Type of this accelerator. Possible values: ["ACCELERATOR_TYPE_UNSPECIFIED", "NVIDIA_TESLA_K80", "NVIDIA_TESLA_P100", "NVIDIA_TESLA_V100", "NVIDIA_TESLA_P4", "NVIDIA_TESLA_T4", "NVIDIA_TESLA_T4_VWS", "NVIDIA_TESLA_P100_VWS", "NVIDIA_TESLA_P4_VWS", "NVIDIA_TESLA_A100", "TPU_V2", "TPU_V3"]`, + }, + }, + }, + }, + "boot_disk_size_gb": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `The size of the boot disk in GB attached to this instance, +up to a maximum of 64000 GB (64 TB). The minimum recommended value is 100 GB. +If not specified, this defaults to 100.`, + }, + "boot_disk_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"DISK_TYPE_UNSPECIFIED", "PD_STANDARD", "PD_SSD", "PD_BALANCED", "PD_EXTREME", ""}), + Description: `Possible disk types for notebook instances. Possible values: ["DISK_TYPE_UNSPECIFIED", "PD_STANDARD", "PD_SSD", "PD_BALANCED", "PD_EXTREME"]`, + }, + "container_image": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Use a container image to start the notebook instance.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "repository": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The path to the container image repository. +For example: gcr.io/{project_id}/{imageName}`, + }, + "tag": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The tag of the container image. If not specified, this defaults to the latest tag.`, + }, + }, + }, + ExactlyOneOf: []string{"vm_image", "container_image"}, + }, + "custom_gpu_driver_path": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Specify a custom Cloud Storage path where the GPU driver is stored. +If not specified, we'll automatically choose from official GPU drivers.`, + }, + "data_disk_size_gb": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `The size of the data disk in GB attached to this instance, +up to a maximum of 64000 GB (64 TB). +You can choose the size of the data disk based on how big your notebooks and data are. +If not specified, this defaults to 100.`, + }, + "data_disk_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"DISK_TYPE_UNSPECIFIED", "PD_STANDARD", "PD_SSD", "PD_BALANCED", "PD_EXTREME", ""}), + Description: `Possible disk types for notebook instances. Possible values: ["DISK_TYPE_UNSPECIFIED", "PD_STANDARD", "PD_SSD", "PD_BALANCED", "PD_EXTREME"]`, + }, + "disk_encryption": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"DISK_ENCRYPTION_UNSPECIFIED", "GMEK", "CMEK", ""}), + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("DISK_ENCRYPTION_UNSPECIFIED"), + Description: `Disk encryption method used on the boot and data disks, defaults to GMEK. Possible values: ["DISK_ENCRYPTION_UNSPECIFIED", "GMEK", "CMEK"]`, + }, + "install_gpu_driver": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Whether the end user authorizes Google Cloud to install GPU driver +on this instance. If this field is empty or set to false, the GPU driver +won't be installed. Only applicable to instances with GPUs.`, + }, + "instance_owners": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `The list of owners of this instance after creation. +Format: alias@example.com. +Currently supports one owner only. +If not specified, all of the service account users of +your VM instance's service account can use the instance.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "kms_key": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The KMS key used to encrypt the disks, only applicable if diskEncryption is CMEK. +Format: projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}`, + }, + "labels": { + Type: schema.TypeMap, + Computed: true, + Optional: true, + DiffSuppressFunc: NotebooksInstanceLabelDiffSuppress, + Description: `Labels to apply to this instance. These can be later modified by the setLabels method. +An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "metadata": { + Type: schema.TypeMap, + Optional: true, + Description: `Custom metadata to apply to this instance. +An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "network": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name of the VPC that this instance is in. +Format: projects/{project_id}/global/networks/{network_id}`, + }, + "nic_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"UNSPECIFIED_NIC_TYPE", "VIRTIO_NET", "GVNIC", ""}), + Description: `The type of vNIC driver. Possible values: ["UNSPECIFIED_NIC_TYPE", "VIRTIO_NET", "GVNIC"]`, + }, + "no_proxy_access": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `The notebook instance will not register with the proxy..`, + }, + "no_public_ip": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `No public IP will be assigned to this instance.`, + }, + "no_remove_data_disk": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `If true, the data disk will not be auto deleted when deleting the instance.`, + }, + "post_startup_script": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Path to a Bash script that automatically runs after a +notebook instance fully boots up. The path must be a URL +or Cloud Storage path (gs://path-to-file/file-name).`, + }, + "reservation_affinity": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Reservation Affinity for consuming Zonal reservation.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "consume_reservation_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidateEnum([]string{"NO_RESERVATION", "ANY_RESERVATION", "SPECIFIC_RESERVATION"}), + Description: `The type of Compute Reservation. Possible values: ["NO_RESERVATION", "ANY_RESERVATION", "SPECIFIC_RESERVATION"]`, + }, + "key": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Corresponds to the label key of reservation resource.`, + }, + "values": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Corresponds to the label values of reservation resource.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "service_account": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + Description: `The service account on this instance, giving access to other +Google Cloud services. You can use any service account within +the same project, but you must have the service account user +permission to use the instance. If not specified, +the Compute Engine default service account is used.`, + }, + "service_account_scopes": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Optional. The URIs of service account scopes to be included in Compute Engine instances. +If not specified, the following scopes are defined: +- https://www.googleapis.com/auth/cloud-platform +- https://www.googleapis.com/auth/userinfo.email`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "shielded_instance_config": { + Type: schema.TypeList, + Computed: true, + Optional: true, + ForceNew: true, + Description: `A set of Shielded Instance options. Check [Images using supported Shielded VM features] +Not all combinations are valid`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Defines whether the instance has integrity monitoring enabled. Enables monitoring and attestation of the +boot integrity of the instance. The attestation is performed against the integrity policy baseline. +This baseline is initially derived from the implicitly trusted boot image when the instance is created. +Enabled by default.`, + Default: true, + }, + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Defines whether the instance has Secure Boot enabled. Secure Boot helps ensure that the system only runs +authentic software by verifying the digital signature of all boot components, and halting the boot process +if signature verification fails. +Disabled by default.`, + }, + "enable_vtpm": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Defines whether the instance has the vTPM enabled. +Enabled by default.`, + Default: true, + }, + }, + }, + }, + "subnet": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name of the subnet that this instance is in. +Format: projects/{project_id}/regions/{region}/subnetworks/{subnetwork_id}`, + }, + "tags": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `The Compute Engine tags to add to instance.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "vm_image": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Use a Compute Engine VM image to start the notebook instance.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the Google Cloud project that this VM image belongs to. +Format: projects/{project_id}`, + }, + "image_family": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Use this VM image family to find the image; the newest image in this family will be used.`, + }, + "image_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `Use VM image name to find the image.`, + }, + }, + }, + ExactlyOneOf: []string{"vm_image", "container_image"}, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Instance creation time`, + }, + "proxy_uri": { + Type: schema.TypeString, + Computed: true, + Description: `The proxy endpoint that is used to access the Jupyter notebook. +Only returned when the resource is in a 'PROVISIONED' state. If +needed you can utilize 'terraform apply -refresh-only' to await +the population of this value.`, + }, + "state": { + Type: schema.TypeString, + Computed: true, + Description: `The state of this instance.`, + }, + "update_time": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `Instance update time.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceNotebooksInstanceUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return tpgresource.LabelsStateUpgrade(rawState, notebooksInstanceGoogleProvidedLabel) +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go index 9f14e6d713c8..6e7fd8587405 100644 --- a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go +++ b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go @@ -13,6 +13,7 @@ import ( tpgcompute "github.com/hashicorp/terraform-provider-google/google/services/compute" "github.com/hashicorp/terraform-provider-google/google/services/privateca" "github.com/hashicorp/terraform-provider-google/google/services/resourcemanager" + tpgservicenetworking "github.com/hashicorp/terraform-provider-google/google/services/servicenetworking" "github.com/hashicorp/terraform-provider-google/google/services/sql" "github.com/hashicorp/terraform-provider-google/google/tpgiamresource" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -23,6 +24,7 @@ import ( cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1" iam "google.golang.org/api/iam/v1" "google.golang.org/api/iamcredentials/v1" + "google.golang.org/api/servicenetworking/v1" "google.golang.org/api/serviceusage/v1" sqladmin "google.golang.org/api/sqladmin/v1beta4" ) @@ -354,6 +356,135 @@ func BootstrapSharedTestNetwork(t *testing.T, testId string) string { return network.Name } +const SharedTestGlobalAddressPrefix = "tf-bootstrap-addr-" + +func BootstrapSharedTestGlobalAddress(t *testing.T, testId, networkId string) string { + project := envvar.GetTestProjectFromEnv() + addressName := SharedTestGlobalAddressPrefix + testId + + config := BootstrapConfig(t) + if config == nil { + return "" + } + + log.Printf("[DEBUG] Getting shared test global address %q", addressName) + _, err := config.NewComputeClient(config.UserAgent).GlobalAddresses.Get(project, addressName).Do() + if err != nil && transport_tpg.IsGoogleApiErrorWithCode(err, 404) { + log.Printf("[DEBUG] Global address %q not found, bootstrapping", addressName) + url := fmt.Sprintf("%sprojects/%s/global/addresses", config.ComputeBasePath, project) + netObj := map[string]interface{}{ + "name": addressName, + "address_type": "INTERNAL", + "purpose": "VPC_PEERING", + "prefix_length": 16, + "network": networkId, + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: url, + UserAgent: config.UserAgent, + Body: netObj, + Timeout: 4 * time.Minute, + }) + if err != nil { + t.Fatalf("Error bootstrapping shared test global address %q: %s", addressName, err) + } + + log.Printf("[DEBUG] Waiting for global address creation to finish") + err = tpgcompute.ComputeOperationWaitTime(config, res, project, "Error bootstrapping shared test global address", config.UserAgent, 4*time.Minute) + if err != nil { + t.Fatalf("Error bootstrapping shared test global address %q: %s", addressName, err) + } + } + + address, err := config.NewComputeClient(config.UserAgent).GlobalAddresses.Get(project, addressName).Do() + if err != nil { + t.Errorf("Error getting shared test global address %q: %s", addressName, err) + } + if address == nil { + t.Fatalf("Error getting shared test global address %q: is nil", addressName) + } + return address.Name +} + +// BootstrapSharedServiceNetworkingConnection will create a shared network +// if it hasn't been created in the test project, a global address +// if it hasn't been created in the test project, and a service networking connection +// if it hasn't been created in the test project. +// +// BootstrapSharedServiceNetworkingConnection returns a persistent compute network name +// for a test or set of tests. +// +// To delete a service networking conneciton, all of the service instances that use that connection +// must be deleted first. After the service instances are deleted, some service producers delay the deletion +// utnil a waiting period has passed. For example, after four days that you delete a SQL instance, +// the service networking connection can be deleted. +// That is the reason to use the shared service networking connection for thest resources. +// https://cloud.google.com/vpc/docs/configure-private-services-access#removing-connection +// +// testId specifies the test for which a shared network and a gobal address are used/initialized. +func BootstrapSharedServiceNetworkingConnection(t *testing.T, testId string) string { + parentService := "services/servicenetworking.googleapis.com" + project := envvar.GetTestProjectFromEnv() + projectNumber := envvar.GetTestProjectNumberFromEnv() + + config := BootstrapConfig(t) + if config == nil { + return "" + } + + networkName := BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + globalAddressName := BootstrapSharedTestGlobalAddress(t, testId, networkId) + + readCall := config.NewServiceNetworkingClient(config.UserAgent).Services.Connections.List(parentService).Network(networkId) + if config.UserProjectOverride { + readCall.Header().Add("X-Goog-User-Project", project) + } + response, err := readCall.Do() + if err != nil { + t.Errorf("Error getting shared test service networking connection: %s", err) + } + + var connection *servicenetworking.Connection + for _, c := range response.Connections { + if c.Network == networkId { + connection = c + break + } + } + + if connection == nil { + log.Printf("[DEBUG] Service networking connection not found, bootstrapping") + + connection := &servicenetworking.Connection{ + Network: networkId, + ReservedPeeringRanges: []string{globalAddressName}, + } + + createCall := config.NewServiceNetworkingClient(config.UserAgent).Services.Connections.Create(parentService, connection) + if config.UserProjectOverride { + createCall.Header().Add("X-Goog-User-Project", project) + } + op, err := createCall.Do() + if err != nil { + t.Fatalf("Error bootstrapping shared test service networking connection: %s", err) + } + + log.Printf("[DEBUG] Waiting for service networking connection creation to finish") + if err := tpgservicenetworking.ServiceNetworkingOperationWaitTime(config, op, "Create Service Networking Connection", config.UserAgent, project, 4*time.Minute); err != nil { + t.Fatalf("Error bootstrapping shared test service networking connection: %s", err) + } + } + + log.Printf("[DEBUG] Getting shared test service networking connection") + + return networkName +} + var SharedServicePerimeterProjectPrefix = "tf-bootstrap-sp-" func BootstrapServicePerimeterProjects(t *testing.T, desiredProjects int) []*cloudresourcemanager.Project { diff --git a/mmv1/third_party/terraform/acctest/test_utils.go.erb b/mmv1/third_party/terraform/acctest/test_utils.go.erb index bf081eac3c9a..3fc319222497 100644 --- a/mmv1/third_party/terraform/acctest/test_utils.go.erb +++ b/mmv1/third_party/terraform/acctest/test_utils.go.erb @@ -50,6 +50,12 @@ func CheckDataSourceStateMatchesResourceStateWithIgnores(dataSourceName, resourc if _, ok := ignoreFields[k]; ok { continue } + if _, ok := ignoreFields["labels.%"]; ok && strings.HasPrefix(k, "labels.") { + continue + } + if _, ok := ignoreFields["terraform_labels.%"]; ok && strings.HasPrefix(k, "terraform_labels.") { + continue + } if k == "%" { continue } diff --git a/mmv1/third_party/terraform/fwmodels/provider_model.go.erb b/mmv1/third_party/terraform/fwmodels/provider_model.go.erb index a7583193bad2..38e69d8748ba 100644 --- a/mmv1/third_party/terraform/fwmodels/provider_model.go.erb +++ b/mmv1/third_party/terraform/fwmodels/provider_model.go.erb @@ -21,6 +21,7 @@ type ProviderModel struct { UserProjectOverride types.Bool `tfsdk:"user_project_override"` RequestTimeout types.String `tfsdk:"request_timeout"` RequestReason types.String `tfsdk:"request_reason"` + DefaultLabels types.Map `tfsdk:"default_labels"` // Generated Products <% products.each do |product| -%> diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb b/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb index a6eaaee55dd0..dffa3d43f30f 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb +++ b/mmv1/third_party/terraform/fwprovider/framework_provider.go.erb @@ -71,6 +71,7 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, path.MatchRoot("access_token"), }...), CredentialsValidator(), + NonEmptyStringValidator(), }, }, "access_token": schema.StringAttribute{ @@ -79,10 +80,14 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, stringvalidator.ConflictsWith(path.Expressions{ path.MatchRoot("credentials"), }...), + NonEmptyStringValidator(), }, }, "impersonate_service_account": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "impersonate_service_account_delegates": schema.ListAttribute{ Optional: true, @@ -90,15 +95,27 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, }, "project": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "billing_project": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "region": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "zone": schema.StringAttribute{ Optional: true, + Validators: []validator.String{ + NonEmptyStringValidator(), + }, }, "scopes": schema.ListAttribute{ Optional: true, @@ -113,6 +130,10 @@ func (p *FrameworkProvider) Schema(_ context.Context, _ provider.SchemaRequest, "request_reason": schema.StringAttribute{ Optional: true, }, + "default_labels": schema.MapAttribute{ + Optional: true, + ElementType: types.StringType, + }, // Generated Products <% products.each do |product| -%> diff --git a/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go b/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go index e81196794205..aa866ac10451 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go +++ b/mmv1/third_party/terraform/fwprovider/framework_provider_internal_test.go @@ -44,10 +44,11 @@ func TestFrameworkProvider_CredentialsValidator(t *testing.T) { return types.StringValue(stringContents) }, }, - "configuring credentials as an empty string is valid": { + "configuring credentials as an empty string is not valid": { ConfigValue: func(t *testing.T) types.String { return types.StringValue("") }, + ExpectedErrorCount: 1, }, "leaving credentials unconfigured is valid": { ConfigValue: func(t *testing.T) types.String { diff --git a/mmv1/third_party/terraform/fwprovider/framework_validators.go b/mmv1/third_party/terraform/fwprovider/framework_validators.go index 31bf849d0368..3af98fd9db92 100644 --- a/mmv1/third_party/terraform/fwprovider/framework_validators.go +++ b/mmv1/third_party/terraform/fwprovider/framework_validators.go @@ -7,7 +7,6 @@ import ( "time" "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/hashicorp/terraform-plugin-framework/types" googleoauth "golang.org/x/oauth2/google" ) @@ -31,7 +30,7 @@ func (v credentialsValidator) MarkdownDescription(ctx context.Context) string { // ValidateString performs the validation. func (v credentialsValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { - if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() || request.ConfigValue.Equal(types.StringValue("")) { + if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() { return } @@ -85,3 +84,34 @@ func (v nonnegativedurationValidator) ValidateString(ctx context.Context, reques func NonNegativeDurationValidator() validator.String { return nonnegativedurationValidator{} } + +// Non Empty String Validator +type nonEmptyStringValidator struct { +} + +// Description describes the validation in plain text formatting. +func (v nonEmptyStringValidator) Description(_ context.Context) string { + return "value expected to be a string that isn't an empty string" +} + +// MarkdownDescription describes the validation in Markdown formatting. +func (v nonEmptyStringValidator) MarkdownDescription(ctx context.Context) string { + return v.Description(ctx) +} + +// ValidateString performs the validation. +func (v nonEmptyStringValidator) ValidateString(ctx context.Context, request validator.StringRequest, response *validator.StringResponse) { + if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() { + return + } + + value := request.ConfigValue.ValueString() + + if value == "" { + response.Diagnostics.AddError("expected a non-empty string", fmt.Sprintf("%s was set to `%s`", request.Path, value)) + } +} + +func NonEmptyStringValidator() validator.String { + return nonEmptyStringValidator{} +} diff --git a/mmv1/third_party/terraform/fwresource/framework_location.go b/mmv1/third_party/terraform/fwresource/framework_location.go index 5a0559a290ef..609ab65b98b1 100644 --- a/mmv1/third_party/terraform/fwresource/framework_location.go +++ b/mmv1/third_party/terraform/fwresource/framework_location.go @@ -32,12 +32,14 @@ type LocationDescription struct { func (ld *LocationDescription) GetLocation() (types.String, error) { // Location from resource config if !ld.ResourceLocation.IsNull() && !ld.ResourceLocation.IsUnknown() && !ld.ResourceLocation.Equal(types.StringValue("")) { - return ld.ResourceLocation, nil + location := tpgresource.GetResourceNameFromSelfLink(ld.ResourceLocation.ValueString()) // Location could be a self link + return types.StringValue(location), nil } // Location from region in resource config if !ld.ResourceRegion.IsNull() && !ld.ResourceRegion.IsUnknown() && !ld.ResourceRegion.Equal(types.StringValue("")) { - return ld.ResourceRegion, nil + region := tpgresource.GetResourceNameFromSelfLink(ld.ResourceRegion.ValueString()) // Region could be a self link + return types.StringValue(region), nil } // Location from zone in resource config @@ -46,9 +48,16 @@ func (ld *LocationDescription) GetLocation() (types.String, error) { return types.StringValue(location), nil } + // Location from region in provider config + if !ld.ProviderRegion.IsNull() && !ld.ProviderRegion.IsUnknown() && !ld.ProviderRegion.Equal(types.StringValue("")) { + location := tpgresource.GetResourceNameFromSelfLink(ld.ProviderRegion.ValueString()) // Region could be a self link + return types.StringValue(location), nil + } + // Location from zone in provider config if !ld.ProviderZone.IsNull() && !ld.ProviderZone.IsUnknown() && !ld.ProviderZone.Equal(types.StringValue("")) { - return ld.ProviderZone, nil + location := tpgresource.GetResourceNameFromSelfLink(ld.ProviderZone.ValueString()) // Zone could be a self link + return types.StringValue(location), nil } var err error @@ -71,17 +80,18 @@ func (ld *LocationDescription) GetRegion() (types.String, error) { } // Region from zone in resource config if !ld.ResourceZone.IsNull() && !ld.ResourceZone.IsUnknown() && !ld.ResourceZone.Equal(types.StringValue("")) { - region := tpgresource.GetRegionFromZone(ld.ResourceZone.ValueString()) - return types.StringValue(region), nil + region := tpgresource.GetResourceNameFromSelfLink(ld.ResourceZone.ValueString()) // Region could be a self link + return types.StringValue(tpgresource.GetRegionFromZone(region)), nil } // Region from provider config if !ld.ProviderRegion.IsNull() && !ld.ProviderRegion.IsUnknown() && !ld.ProviderRegion.Equal(types.StringValue("")) { - return ld.ProviderRegion, nil + region := tpgresource.GetResourceNameFromSelfLink(ld.ProviderRegion.ValueString()) // Region could be a self link + return types.StringValue(region), nil } // Region from zone in provider config if !ld.ProviderZone.IsNull() && !ld.ProviderZone.IsUnknown() && !ld.ProviderZone.Equal(types.StringValue("")) { - region := tpgresource.GetRegionFromZone(ld.ProviderZone.ValueString()) - return types.StringValue(region), nil + region := tpgresource.GetResourceNameFromSelfLink(ld.ProviderZone.ValueString()) // Region could be a self link + return types.StringValue(tpgresource.GetRegionFromZone(region)), nil } var err error @@ -103,7 +113,9 @@ func (ld *LocationDescription) GetZone() (types.String, error) { return types.StringValue(zone), nil } if !ld.ProviderZone.IsNull() && !ld.ProviderZone.IsUnknown() && !ld.ProviderZone.Equal(types.StringValue("")) { - return ld.ProviderZone, nil + // Zone could be a self link + zone := tpgresource.GetResourceNameFromSelfLink(ld.ProviderZone.ValueString()) + return types.StringValue(zone), nil } var err error diff --git a/mmv1/third_party/terraform/fwresource/framework_location_test.go b/mmv1/third_party/terraform/fwresource/framework_location_test.go index 8204030d68e1..1e5c5026715a 100644 --- a/mmv1/third_party/terraform/fwresource/framework_location_test.go +++ b/mmv1/third_party/terraform/fwresource/framework_location_test.go @@ -126,11 +126,23 @@ func TestLocationDescription_GetRegion(t *testing.T) { }, ExpectedRegion: types.StringValue("provider-zone"), // is truncated }, - "does not shorten region values when derived from a zone self link set in the resource config": { + "shortens region values when derived from a zone self link set in the resource config": { ld: LocationDescription{ ResourceZone: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a"), }, - ExpectedRegion: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1"), // Value isn't shortened from URI to name + ExpectedRegion: types.StringValue("us-central1"), + }, + "shortens region values set as self links in the provider config": { + ld: LocationDescription{ + ProviderRegion: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/regions/us-central1"), + }, + ExpectedRegion: types.StringValue("us-central1"), + }, + "shortens region values when derived from a zone self link set in the provider config": { + ld: LocationDescription{ + ProviderZone: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a"), + }, + ExpectedRegion: types.StringValue("us-central1"), }, "returns the value of the region field in provider config when region/zone is unset in resource config": { ld: LocationDescription{ @@ -228,11 +240,11 @@ func TestLocationDescription_GetLocation(t *testing.T) { }, ExpectedLocation: types.StringValue("resource-location"), }, - "does not shorten the location value when it is set as a self link in the resource config": { + "shortens the location value when it is set as a self link in the resource config": { ld: LocationDescription{ ResourceLocation: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/locations/resource-location"), }, - ExpectedLocation: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/locations/resource-location"), + ExpectedLocation: types.StringValue("resource-location"), }, "returns the region value set in the resource config when location is not in the schema": { ld: LocationDescription{ @@ -241,11 +253,11 @@ func TestLocationDescription_GetLocation(t *testing.T) { }, ExpectedLocation: types.StringValue("resource-region"), }, - "does not shorten the region value when it is set as a self link in the resource config": { + "shortens the region value when it is set as a self link in the resource config": { ld: LocationDescription{ ResourceRegion: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/regions/resource-region"), }, - ExpectedLocation: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/regions/resource-region"), + ExpectedLocation: types.StringValue("resource-region"), }, "returns the zone value set in the resource config when neither location nor region in the schema": { ld: LocationDescription{ @@ -259,18 +271,24 @@ func TestLocationDescription_GetLocation(t *testing.T) { }, ExpectedLocation: types.StringValue("resource-zone-a"), }, - "returns the zone value from the provider config when none of location/region/zone are set in the resource config": { + "returns the region value from the provider config when none of location/region/zone are set in the resource config": { ld: LocationDescription{ - ProviderRegion: types.StringValue("provider-region"), // unused + ProviderRegion: types.StringValue("provider-region"), // Preferred to use region value over zone value if both are set ProviderZone: types.StringValue("provider-zone-a"), }, + ExpectedLocation: types.StringValue("provider-region"), + }, + "returns the zone value from the provider config when none of location/region/zone are set in the resource config and region is not set in the provider config": { + ld: LocationDescription{ + ProviderZone: types.StringValue("provider-zone-a"), + }, ExpectedLocation: types.StringValue("provider-zone-a"), }, - "does not shorten the zone value when it is set as a self link in the provider config": { + "shortens the zone value when it is set as a self link in the provider config": { ld: LocationDescription{ ProviderZone: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/provider-zone-a"), }, - ExpectedLocation: types.StringValue("https://www.googleapis.com/compute/v1/projects/my-project/zones/provider-zone-a"), + ExpectedLocation: types.StringValue("provider-zone-a"), }, // Handling of empty strings "returns the region value set in the resource config when location is an empty string": { @@ -297,13 +315,6 @@ func TestLocationDescription_GetLocation(t *testing.T) { }, ExpectedLocation: types.StringValue("provider-zone-a"), }, - // Error states - "does not use the region value set in the provider config": { - ld: LocationDescription{ - ProviderRegion: types.StringValue("provider-region"), - }, - ExpectedError: true, - }, "returns an error when none of location/region/zone are set on the resource, and neither region or zone is set on the provider": { ExpectedError: true, }, diff --git a/mmv1/third_party/terraform/fwtransport/framework_config.go.erb b/mmv1/third_party/terraform/fwtransport/framework_config.go.erb index 8a1bc8c7b6ba..8c510cbe155c 100644 --- a/mmv1/third_party/terraform/fwtransport/framework_config.go.erb +++ b/mmv1/third_party/terraform/fwtransport/framework_config.go.erb @@ -17,7 +17,6 @@ import ( "google.golang.org/grpc" "github.com/hashicorp/go-cleanhttp" - "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -56,15 +55,6 @@ type FrameworkProviderConfig struct { // LoadAndValidateFramework handles the bulk of configuring the provider // it is pulled out so that we can manually call this from our testing provider as well func (p *FrameworkProviderConfig) LoadAndValidateFramework(ctx context.Context, data *fwmodels.ProviderModel, tfVersion string, diags *diag.Diagnostics, providerversion string) { - - - // Make the plugin framwork code behave like the SDK by ignoring zero values. This means re-setting zero values to null. - // This is added to fix https://github.com/hashicorp/terraform-provider-google/issues/14255 in a v4.x.x release - // TODO(SarahFrench) remove as part of https://github.com/hashicorp/terraform-provider-google/issues/14447 in 5.0.0 - p.HandleZeroValues(ctx, data, diags) - if diags.HasError() { - return - } // Set defaults if needed p.HandleDefaults(ctx, data, diags) @@ -115,77 +105,6 @@ func (p *FrameworkProviderConfig) LoadAndValidateFramework(ctx context.Context, p.RequestBatcherIam = transport_tpg.NewRequestBatcher("IAM", ctx, batchingConfig) } -// HandleZeroValues will make the plugin framework act like the SDK; zero value, particularly empty strings, are converted to null. -// This causes the plugin framework to treat the field as unset, just like how the SDK ignores empty strings. -func (p *FrameworkProviderConfig) HandleZeroValues(ctx context.Context, data *fwmodels.ProviderModel, diags *diag.Diagnostics) { - - // Change empty strings to null values - if data.AccessToken.Equal(types.StringValue("")) { - data.AccessToken = types.StringNull() - } - if data.BillingProject.Equal(types.StringValue("")) { - data.BillingProject = types.StringNull() - } - if data.Credentials.Equal(types.StringValue("")) { - data.Credentials = types.StringNull() - } - if data.ImpersonateServiceAccount.Equal(types.StringValue("")) { - data.ImpersonateServiceAccount = types.StringNull() - } - if data.Project.Equal(types.StringValue("")) { - data.Project = types.StringNull() - } - if data.Region.Equal(types.StringValue("")) { - data.Region = types.StringNull() - } - if data.RequestReason.Equal(types.StringValue("")) { - data.RequestReason = types.StringNull() - } - if data.RequestTimeout.Equal(types.StringValue("")) { - data.RequestTimeout = types.StringNull() - } - if data.Zone.Equal(types.StringValue("")) { - data.Zone = types.StringNull() - } - - // Change lists that aren't null or unknown with length of zero to null lists - if !data.Scopes.IsNull() && !data.Scopes.IsUnknown() && (len(data.Scopes.Elements()) == 0) { - data.Scopes = types.ListNull(types.StringType) - } - if !data.ImpersonateServiceAccountDelegates.IsNull() && !data.ImpersonateServiceAccountDelegates.IsUnknown() && (len(data.ImpersonateServiceAccountDelegates.Elements()) == 0) { - data.ImpersonateServiceAccountDelegates = types.ListNull(types.StringType) - } - - // Batching implementation will change in future, but this code will be removed in 5.0.0 so may be unaffected - if !data.Batching.IsNull() && !data.Batching.IsUnknown() && (len(data.Batching.Elements()) > 0) { - var pbConfigs []fwmodels.ProviderBatching - d := data.Batching.ElementsAs(ctx, &pbConfigs, true) - diags.Append(d...) - if diags.HasError() { - return - } - if pbConfigs[0].SendAfter.Equal(types.StringValue("")) { - pbConfigs[0].SendAfter = types.StringNull() // Convert empty string to null - } - b, _ := types.ObjectValue( - map[string]attr.Type{ - "enable_batching": types.BoolType, - "send_after": types.StringType, - }, - map[string]attr.Value{ - "enable_batching": pbConfigs[0].EnableBatching, - "send_after": pbConfigs[0].SendAfter, - }, - ) - newBatching, d := types.ListValue(types.ObjectType{}.WithAttributeTypes(fwmodels.ProviderBatchingAttributes), []attr.Value{b}) - diags.Append(d...) - if diags.HasError() { - return - } - data.Batching = newBatching - } -} - // HandleDefaults will handle all the defaults necessary in the provider func (p *FrameworkProviderConfig) HandleDefaults(ctx context.Context, data *fwmodels.ProviderModel, diags *diag.Diagnostics) { if (data.AccessToken.IsNull() || data.AccessToken.IsUnknown()) && (data.Credentials.IsNull() || data.Credentials.IsUnknown()) { diff --git a/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb b/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb index e7b8fdf8ae02..6a273183d4ad 100644 --- a/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb +++ b/mmv1/third_party/terraform/fwtransport/framework_config_test.go.erb @@ -102,22 +102,22 @@ func TestFrameworkProvider_LoadAndValidateFramework_project(t *testing.T) { ExpectedConfigStructValue: types.StringNull(), }, // Handling empty strings in config - "when project is set as an empty string the field is treated as if it's unset, without error": { + "when project is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ Project: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), - ExpectedConfigStructValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, - "when project is set as an empty string an environment variable will be used": { + "when project is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ Project: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_PROJECT": "project-from-GOOGLE_PROJECT", }, - ExpectedDataModelValue: types.StringValue("project-from-GOOGLE_PROJECT"), - ExpectedConfigStructValue: types.StringValue("project-from-GOOGLE_PROJECT"), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, // Handling unknown values "when project is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -143,7 +143,7 @@ func TestFrameworkProvider_LoadAndValidateFramework_project(t *testing.T) { tfVersion := "foobar" providerversion := "999" diags := diag.Diagnostics{} - + data := tc.ConfigValues data.Credentials = types.StringValue(transport_tpg.TestFakeCredentialsPath) impersonateServiceAccountDelegates, _ := types.ListValue(types.StringType, []attr.Value{}) // empty list @@ -194,40 +194,40 @@ func TestFrameworkProvider_LoadAndValidateFramework_credentials(t *testing.T) { }{ "credentials can be configured as a path to a credentials JSON file": { ConfigValues: fwmodels.ProviderModel{ - Credentials: types.StringValue(transport_tpg.TestFakeCredentialsPath), - }, - ExpectedDataModelValue: types.StringValue(transport_tpg.TestFakeCredentialsPath), - }, - "configuring credentials as a path to a non-existent file results in an error": { - ConfigValues: fwmodels.ProviderModel{ - Credentials: types.StringValue(pathToMissingFile), - }, - ExpectError: true, - }, - "credentials set in the config are not overridden by environment variables": { - ConfigValues: fwmodels.ProviderModel{ - Credentials: types.StringValue(acctest.GenerateFakeCredentialsJson("test")), - }, - EnvVariables: map[string]string{ - "GOOGLE_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS"), - "GOOGLE_CLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GOOGLE_CLOUD_KEYFILE_JSON"), - "GCLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GCLOUD_KEYFILE_JSON"), - "GOOGLE_APPLICATION_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_APPLICATION_CREDENTIALS"), - }, - ExpectedDataModelValue: types.StringValue(acctest.GenerateFakeCredentialsJson("test")), - }, - "when credentials is unset in the config, environment variables are used: GOOGLE_CREDENTIALS used first": { - ConfigValues: fwmodels.ProviderModel{ - Credentials: types.StringNull(), // unset - }, - EnvVariables: map[string]string{ - "GOOGLE_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS"), - "GOOGLE_CLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GOOGLE_CLOUD_KEYFILE_JSON"), - "GCLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GCLOUD_KEYFILE_JSON"), - "GOOGLE_APPLICATION_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_APPLICATION_CREDENTIALS"), - }, - ExpectedDataModelValue: types.StringValue(acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS")), + Credentials: types.StringValue(transport_tpg.TestFakeCredentialsPath), + }, + ExpectedDataModelValue: types.StringValue(transport_tpg.TestFakeCredentialsPath), + }, + "configuring credentials as a path to a non-existent file results in an error": { + ConfigValues: fwmodels.ProviderModel{ + Credentials: types.StringValue(pathToMissingFile), + }, + ExpectError: true, + }, + "credentials set in the config are not overridden by environment variables": { + ConfigValues: fwmodels.ProviderModel{ + Credentials: types.StringValue(acctest.GenerateFakeCredentialsJson("test")), + }, + EnvVariables: map[string]string{ + "GOOGLE_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS"), + "GOOGLE_CLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GOOGLE_CLOUD_KEYFILE_JSON"), + "GCLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GCLOUD_KEYFILE_JSON"), + "GOOGLE_APPLICATION_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_APPLICATION_CREDENTIALS"), + }, + ExpectedDataModelValue: types.StringValue(acctest.GenerateFakeCredentialsJson("test")), + }, + "when credentials is unset in the config, environment variables are used: GOOGLE_CREDENTIALS used first": { + ConfigValues: fwmodels.ProviderModel{ + Credentials: types.StringNull(), // unset + }, + EnvVariables: map[string]string{ + "GOOGLE_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS"), + "GOOGLE_CLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GOOGLE_CLOUD_KEYFILE_JSON"), + "GCLOUD_KEYFILE_JSON": acctest.GenerateFakeCredentialsJson("GCLOUD_KEYFILE_JSON"), + "GOOGLE_APPLICATION_CREDENTIALS": acctest.GenerateFakeCredentialsJson("GOOGLE_APPLICATION_CREDENTIALS"), }, + ExpectedDataModelValue: types.StringValue(acctest.GenerateFakeCredentialsJson("GOOGLE_CREDENTIALS")), + }, "when credentials is unset in the config, environment variables are used: GOOGLE_CLOUD_KEYFILE_JSON used second": { ConfigValues: fwmodels.ProviderModel{ Credentials: types.StringNull(), // unset @@ -264,15 +264,15 @@ func TestFrameworkProvider_LoadAndValidateFramework_credentials(t *testing.T) { }, ExpectedDataModelValue: types.StringNull(), }, - // Handling empty strings in config - "when credentials is set to an empty string in the config (and access_token unset), GOOGLE_APPLICATION_CREDENTIALS is used": { + // Error states + "when credentials is set to an empty string in the config the value isn't ignored and results in an error": { ConfigValues: fwmodels.ProviderModel{ Credentials: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_APPLICATION_CREDENTIALS": transport_tpg.TestFakeCredentialsPath, // needs to be a path to a file when used by code }, - ExpectedDataModelValue: types.StringNull(), + ExpectError: true, }, // NOTE: these tests can't run in Cloud Build due to ADC locating credentials despite `GOOGLE_APPLICATION_CREDENTIALS` being unset // See https://cloud.google.com/docs/authentication/application-default-credentials#search_order @@ -435,22 +435,22 @@ func TestFrameworkProvider_LoadAndValidateFramework_billingProject(t *testing.T) ExpectedConfigStructValue: types.StringNull(), }, // Handling empty strings in config - "when billing_project is set as an empty string the field is treated as if it's unset, without error": { + "when billing_project is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ BillingProject: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), - ExpectedConfigStructValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, - "when billing_project is set as an empty string an environment variable will be used": { + "when billing_project is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ BillingProject: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_BILLING_PROJECT": "billing-project-from-env", }, - ExpectedDataModelValue: types.StringValue("billing-project-from-env"), - ExpectedConfigStructValue: types.StringValue("billing-project-from-env"), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, } @@ -498,7 +498,6 @@ func TestFrameworkProvider_LoadAndValidateFramework_billingProject(t *testing.T) } } - func TestFrameworkProvider_LoadAndValidateFramework_region(t *testing.T) { // Note: In the test function we need to set the below fields in test case's fwmodels.ProviderModel value @@ -550,22 +549,22 @@ func TestFrameworkProvider_LoadAndValidateFramework_region(t *testing.T) { ExpectedConfigStructValue: types.StringNull(), }, // Handling empty strings in config - "when region is set as an empty string the field is treated as if it's unset, without error": { + "when region is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ Region: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), - ExpectedConfigStructValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, - "when region is set as an empty string an environment variable will be used": { + "when region is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ Region: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_REGION": "region-from-env", }, - ExpectedDataModelValue: types.StringValue("region-from-env"), - ExpectedConfigStructValue: types.StringValue("region-from-env"), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, // Handling unknown values "when region is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -700,22 +699,22 @@ func TestFrameworkProvider_LoadAndValidateFramework_zone(t *testing.T) { ExpectedConfigStructValue: types.StringNull(), }, // Handling empty strings in config - "when zone is set as an empty string the field is treated as if it's unset, without error": { + "when zone is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ Zone: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), - ExpectedConfigStructValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, - "when zone is set as an empty string an environment variable will be used": { + "when zone is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ Zone: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_ZONE": "zone-from-env", }, - ExpectedDataModelValue: types.StringValue("zone-from-env"), - ExpectedConfigStructValue: types.StringValue("zone-from-env"), + ExpectedDataModelValue: types.StringValue(""), + ExpectedConfigStructValue: types.StringValue(""), }, // Handling unknown values "when zone is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -782,11 +781,11 @@ func TestFrameworkProvider_LoadAndValidateFramework_accessToken(t *testing.T) { // - ImpersonateServiceAccountDelegates: If we don't set this, we get a nil pointer exception ¯\_(ツ)_/¯ cases := map[string]struct { - ConfigValues fwmodels.ProviderModel - EnvVariables map[string]string - ExpectedDataModelValue basetypes.StringValue // Sometimes the value is mutated, and no longer matches the original value we supply + ConfigValues fwmodels.ProviderModel + EnvVariables map[string]string + ExpectedDataModelValue basetypes.StringValue // Sometimes the value is mutated, and no longer matches the original value we supply // ExpectedConfigStructValue not used here, as credentials info isn't stored in the config struct - ExpectError bool + ExpectError bool }{ "access_token configured in the provider can be invalid without resulting in errors": { ConfigValues: fwmodels.ProviderModel{ @@ -817,21 +816,20 @@ func TestFrameworkProvider_LoadAndValidateFramework_accessToken(t *testing.T) { ExpectedDataModelValue: types.StringNull(), }, // Handling empty strings in config - "when access_token is set as an empty string the field is treated as if it's unset, without error (as long as credentials supplied in its absence)": { + "when access_token is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ AccessToken: types.StringValue(""), - Credentials: types.StringValue(transport_tpg.TestFakeCredentialsPath), }, - ExpectedDataModelValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), }, - "when access_token is set as an empty string in the config, an environment variable is used": { + "when access_token is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ AccessToken: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_OAUTH_ACCESS_TOKEN": "value-from-GOOGLE_OAUTH_ACCESS_TOKEN", }, - ExpectedDataModelValue: types.StringValue("value-from-GOOGLE_OAUTH_ACCESS_TOKEN"), + ExpectedDataModelValue: types.StringValue(""), }, // Handling unknown values "when access_token is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -1060,20 +1058,20 @@ func TestFrameworkProvider_LoadAndValidateFramework_impersonateServiceAccount(t ExpectedDataModelValue: types.StringNull(), }, // Handling empty strings in config - "when impersonate_service_account is set as an empty string the field is treated as if it's unset, without error": { + "when impersonate_service_account is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ ImpersonateServiceAccount: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), }, - "when impersonate_service_account is set as an empty string in the config, an environment variable is used": { + "when impersonate_service_account is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ ImpersonateServiceAccount: types.StringValue(""), }, EnvVariables: map[string]string{ "GOOGLE_IMPERSONATE_SERVICE_ACCOUNT": "value-from-env@example.com", }, - ExpectedDataModelValue: types.StringValue("value-from-env@example.com"), + ExpectedDataModelValue: types.StringValue(""), }, // Handling unknown values "when impersonate_service_account is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -1160,13 +1158,13 @@ func TestFrameworkProvider_LoadAndValidateFramework_impersonateServiceAccountDel }, // Note: no environment variables can be used for impersonate_service_account_delegates "when no impersonate_service_account_delegates value is provided via config, the field remains unset without error": { - SetAsNull: true, // not setting impersonate_service_account_delegates + SetAsNull: true, // not setting impersonate_service_account_delegates ExpectedNull: true, }, // Handling empty values in config - "when impersonate_service_account_delegates is set as an empty array the field is treated as if it's unset, without error": { + "when impersonate_service_account_delegates is set as an empty array, that value isn't ignored": { ImpersonateServiceAccountDelegatesValue: []string{}, - ExpectedDataModelValue: nil, + ExpectedDataModelValue: []string{}, }, // Handling unknown values "when impersonate_service_account_delegates is an unknown value, the provider treats it as if it's unset, without error": { @@ -1373,20 +1371,20 @@ func TestFrameworkProvider_LoadAndValidateFramework_requestReason(t *testing.T) ExpectedDataModelValue: types.StringNull(), }, // Handling empty strings in config - "when request_reason is set as an empty string in the config it is overridden by environment variables": { + "when request_reason is set as an empty string, the empty string is not ignored in favor of an environment variable": { ConfigValues: fwmodels.ProviderModel{ RequestReason: types.StringValue(""), }, EnvVariables: map[string]string{ "CLOUDSDK_CORE_REQUEST_REASON": "foo", }, - ExpectedDataModelValue: types.StringValue("foo"), + ExpectedDataModelValue: types.StringValue(""), }, - "when request_reason is set as an empty string in the config the field is treated as if it's unset, without error": { + "when request_reason is set as an empty string the empty string is used and not ignored": { ConfigValues: fwmodels.ProviderModel{ RequestReason: types.StringValue(""), }, - ExpectedDataModelValue: types.StringNull(), + ExpectedDataModelValue: types.StringValue(""), }, // Handling unknown values "when request_reason is an unknown value, the provider treats it as if it's unset and uses an environment variable instead": { @@ -1468,6 +1466,12 @@ func TestFrameworkProvider_LoadAndValidateFramework_requestTimeout(t *testing.T) }, ExpectError: true, }, + "when request_timeout is set as an empty string, the empty string isn't ignored and an error will occur": { + ConfigValues: fwmodels.ProviderModel{ + RequestTimeout: types.StringValue(""), + }, + ExpectError: true, + }, // In the SDK version of the provider config code, this scenario results in a value of "0s" // instead of "120s", but the final 'effective' value is also "120s" // See : https://github.com/hashicorp/terraform-provider-google/blob/09cb850ee64bcd78e4457df70905530c1ed75f19/google/transport/config.go#L1228-L1233 @@ -1477,13 +1481,6 @@ func TestFrameworkProvider_LoadAndValidateFramework_requestTimeout(t *testing.T) }, ExpectedDataModelValue: types.StringValue("120s"), }, - // Handling empty strings in config - "when request_timeout is set as an empty string, the default value is 120s.": { - ConfigValues: fwmodels.ProviderModel{ - RequestTimeout: types.StringValue(""), - }, - ExpectedDataModelValue: types.StringValue("120s"), - }, // Handling unknown values "when request_timeout is an unknown value, the provider treats it as if it's unset and uses the default value 120s": { ConfigValues: fwmodels.ProviderModel{ @@ -1587,13 +1584,6 @@ func TestFrameworkProvider_LoadAndValidateFramework_batching(t *testing.T) { ExpectEnableBatchingValue: types.BoolValue(true), ExpectSendAfterValue: types.StringValue("3s"), }, - // Handling empty strings in config - "when batching is configured with send_after as an empty string, send_after will be set to a default value": { - EnableBatchingValue: types.BoolValue(true), - SendAfterValue: types.StringValue(""), - ExpectEnableBatchingValue: types.BoolValue(true), - ExpectSendAfterValue: types.StringValue("10s"), // When batching block is present but has missing arguments inside, default is 10s - }, // Handling unknown values "when batching is an unknown value, the provider treats it as if it's unset (align to SDK behaviour)": { SetBatchingAsUnknown: true, @@ -1613,6 +1603,11 @@ func TestFrameworkProvider_LoadAndValidateFramework_batching(t *testing.T) { ExpectSendAfterValue: types.StringValue("45s"), }, // Error states + "when batching is configured with send_after as an empty string, the empty string is not ignored and results in an error": { + EnableBatchingValue: types.BoolValue(true), + SendAfterValue: types.StringValue(""), + ExpectError: true, + }, "if batching is configured with send_after as an invalid value, there's an error": { SendAfterValue: types.StringValue("invalid value"), ExpectError: true, @@ -1718,4 +1713,3 @@ func TestFrameworkProvider_LoadAndValidateFramework_batching(t *testing.T) { }) } } - diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index 544dd16ee673..1ff9b52ae7a9 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -4,7 +4,7 @@ go 1.19 require ( cloud.google.com/go/bigtable v1.19.0 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0 github.com/apparentlymart/go-cidr v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/dnaeon/go-vcr v1.0.1 diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index dab59d4c04e6..69175dcd310e 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -17,6 +17,8 @@ cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHS github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 h1:YhWTPhOf6gVpA9mSfnLOuL8Y6j8W5pzmHE7flXjTke4= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0 h1:KswxXF4E5iWv2ggktqv265zOvwmXA3mgma3UQfYA4tU= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= @@ -428,5 +430,3 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 h1:YhWTPhOf6gVpA9mSfnLOuL8Y6j8W5pzmHE7flXjTke4= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= diff --git a/mmv1/third_party/terraform/provider/provider.go.erb b/mmv1/third_party/terraform/provider/provider.go.erb index bffaf4b4764c..c8eb25e8b554 100644 --- a/mmv1/third_party/terraform/provider/provider.go.erb +++ b/mmv1/third_party/terraform/provider/provider.go.erb @@ -39,8 +39,6 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgiamresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" - - googleoauth "golang.org/x/oauth2/google" ) // Provider returns a *schema.Provider. @@ -60,21 +58,23 @@ func Provider() *schema.Provider { provider := &schema.Provider{ Schema: map[string]*schema.Schema{ "credentials": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: ValidateCredentials, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateCredentials, ConflictsWith: []string{"access_token"}, }, "access_token": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, ConflictsWith: []string{"credentials"}, }, "impersonate_service_account": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "impersonate_service_account_delegates": { @@ -84,23 +84,27 @@ func Provider() *schema.Provider { }, "project": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "billing_project": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "region": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "zone": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: ValidateEmptyStrings, }, "scopes": { @@ -143,6 +147,12 @@ func Provider() *schema.Provider { Optional: true, }, + "default_labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + // Generated Products <% products.each do |product| -%> "<%= product[:definitions].name.underscore -%>_custom_endpoint": { @@ -273,7 +283,6 @@ func DatasourceMapWithErrors() (map[string]*schema.Resource, error) { "google_container_registry_repository": containeranalysis.DataSourceGoogleContainerRepo(), "google_dataproc_metastore_service": dataprocmetastore.DataSourceDataprocMetastoreService(), "google_datastream_static_ips": datastream.DataSourceGoogleDatastreamStaticIps(), - "google_game_services_game_server_deployment_rollout": gameservices.DataSourceGameServicesGameServerDeploymentRollout(), "google_iam_policy": resourcemanager.DataSourceGoogleIamPolicy(), "google_iam_role": resourcemanager.DataSourceGoogleIamRole(), "google_iam_testable_permissions": resourcemanager.DataSourceGoogleIamTestablePermissions(), @@ -717,6 +726,13 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr config.Scopes[i] = scope.(string) } + config.DefaultLabels = make(map[string]string) + defaultLabels := d.Get("default_labels").(map[string]interface{}) + + for k, v := range defaultLabels { + config.DefaultLabels[k] = v.(string) + } + batchCfg, err := transport_tpg.ExpandProviderBatchingConfig(d.Get("batching")) if err != nil { return nil, diag.FromErr(err) @@ -759,23 +775,6 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr return transport_tpg.ProviderDCLConfigure(d, &config), nil } -func ValidateCredentials(v interface{}, k string) (warnings []string, errors []error) { - if v == nil || v.(string) == "" { - return - } - creds := v.(string) - // if this is a path and we can stat it, assume it's ok - if _, err := os.Stat(creds); err == nil { - return - } - if _, err := googleoauth.CredentialsFromJSON(context.Background(), []byte(creds)); err != nil { - errors = append(errors, - fmt.Errorf("JSON credentials are not valid: %s", err)) - } - - return -} - func mergeResourceMaps(ms ...map[string]*schema.Resource) (map[string]*schema.Resource, error) { merged := make(map[string]*schema.Resource) duplicates := []string{} diff --git a/mmv1/third_party/terraform/provider/provider_internal_test.go b/mmv1/third_party/terraform/provider/provider_internal_test.go index 27a15710ffda..5bf88ff03983 100644 --- a/mmv1/third_party/terraform/provider/provider_internal_test.go +++ b/mmv1/third_party/terraform/provider/provider_internal_test.go @@ -42,10 +42,13 @@ func TestProvider_ValidateCredentials(t *testing.T) { return string(contents) }, }, - "configuring credentials as an empty string is valid": { + "configuring credentials as an empty string is not valid": { ConfigValue: func(t *testing.T) interface{} { return "" }, + ExpectedErrors: []error{ + errors.New("expected a non-empty string"), + }, }, "leaving credentials unconfigured is valid": { ValueNotProvided: true, @@ -67,15 +70,65 @@ func TestProvider_ValidateCredentials(t *testing.T) { // Assert if len(ws) != len(tc.ExpectedWarnings) { - t.Errorf("Expected %d warnings, got %d: %v", len(tc.ExpectedWarnings), len(ws), ws) + t.Fatalf("Expected %d warnings, got %d: %v", len(tc.ExpectedWarnings), len(ws), ws) + } + if len(es) != len(tc.ExpectedErrors) { + t.Fatalf("Expected %d errors, got %d: %v", len(tc.ExpectedErrors), len(es), es) + } + + if len(tc.ExpectedErrors) > 0 && len(es) > 0 { + if es[0].Error() != tc.ExpectedErrors[0].Error() { + t.Fatalf("Expected first error to be \"%s\", got \"%s\"", tc.ExpectedErrors[0], es[0]) + } + } + }) + } +} + +func TestProvider_ValidateEmptyStrings(t *testing.T) { + cases := map[string]struct { + ConfigValue interface{} + ValueNotProvided bool + ExpectedWarnings []string + ExpectedErrors []error + }{ + "non-empty strings are valid": { + ConfigValue: "foobar", + }, + "unconfigured values are valid": { + ValueNotProvided: true, + }, + "empty strings are not valid": { + ConfigValue: "", + ExpectedErrors: []error{ + errors.New("expected a non-empty string"), + }, + }, + } + for tn, tc := range cases { + t.Run(tn, func(t *testing.T) { + + // Arrange + var configValue interface{} + if !tc.ValueNotProvided { + configValue = tc.ConfigValue + } + + // Act + // Note: second argument is currently unused by the function but is necessary to fulfill the SchemaValidateFunc type's function signature + ws, es := provider.ValidateEmptyStrings(configValue, "") + + // Assert + if len(ws) != len(tc.ExpectedWarnings) { + t.Fatalf("Expected %d warnings, got %d: %v", len(tc.ExpectedWarnings), len(ws), ws) } if len(es) != len(tc.ExpectedErrors) { - t.Errorf("Expected %d errors, got %d: %v", len(tc.ExpectedErrors), len(es), es) + t.Fatalf("Expected %d errors, got %d: %v", len(tc.ExpectedErrors), len(es), es) } - if len(tc.ExpectedErrors) > 0 { + if len(tc.ExpectedErrors) > 0 && len(es) > 0 { if es[0].Error() != tc.ExpectedErrors[0].Error() { - t.Errorf("Expected first error to be \"%s\", got \"%s\"", tc.ExpectedErrors[0], es[0]) + t.Fatalf("Expected first error to be \"%s\", got \"%s\"", tc.ExpectedErrors[0], es[0]) } } }) diff --git a/mmv1/third_party/terraform/provider/provider_test.go.erb b/mmv1/third_party/terraform/provider/provider_test.go.erb index ad0744de45ca..83186a25949e 100644 --- a/mmv1/third_party/terraform/provider/provider_test.go.erb +++ b/mmv1/third_party/terraform/provider/provider_test.go.erb @@ -294,6 +294,75 @@ func TestAccProviderCredentialsUnknownValue(t *testing.T) { }) } +func TestAccProviderEmptyStrings(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + // No TestDestroy since that's not really the point of this test + Steps: []resource.TestStep{ + // When no values are set in the provider block there are no errors + // This test case is a control to show validation doesn't accidentally flag unset fields + // The "" argument is a lack of key = value being passed into the provider block + { + Config: testAccProvider_checkPlanTimeErrors("", acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + }, + // credentials as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`credentials = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // access_token as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`access_token = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // impersonate_service_account as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`impersonate_service_account = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // project as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`project = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // billing_project as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`billing_project = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // region as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`region = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + // zone as an empty string causes a validation error + { + Config: testAccProvider_checkPlanTimeErrors(`zone = ""`, acctest.RandString(t, 10)), + PlanOnly: true, + ExpectNonEmptyPlan: true, + ExpectError: regexp.MustCompile(`expected a non-empty string`), + }, + }, + }) +} + func testAccProviderBasePath_setBasePath(endpoint, name string) string { return fmt.Sprintf(` provider "google" { @@ -541,3 +610,16 @@ resource "google_firebase_project" "this" { ] }`, credentials, pid, pid, pid, org, billing) } + +func testAccProvider_checkPlanTimeErrors(providerArgument, randString string) string { + return fmt.Sprintf(` +provider "google" { + %s +} + +# A random resource so that the test can generate a plan (can't check validation errors when plan is empty) +resource "google_pubsub_topic" "example" { + name = "tf-test-planned-resource-%s" +} +`, providerArgument, randString) +} diff --git a/mmv1/third_party/terraform/provider/provider_validators.go.erb b/mmv1/third_party/terraform/provider/provider_validators.go.erb new file mode 100644 index 000000000000..25b7825f0703 --- /dev/null +++ b/mmv1/third_party/terraform/provider/provider_validators.go.erb @@ -0,0 +1,48 @@ +<% autogen_exception -%> +package provider + +import ( + "context" + "fmt" + "os" + + googleoauth "golang.org/x/oauth2/google" +) + +func ValidateCredentials(v interface{}, k string) (warnings []string, errors []error) { + if v == nil { + return + } + creds := v.(string) + + // reject empty strings + if v.(string) == "" { + errors = append(errors, + fmt.Errorf("expected a non-empty string")) + return + } + + // if this is a path and we can stat it, assume it's ok + if _, err := os.Stat(creds); err == nil { + return + } + if _, err := googleoauth.CredentialsFromJSON(context.Background(), []byte(creds)); err != nil { + errors = append(errors, + fmt.Errorf("JSON credentials are not valid: %s", err)) + } + + return +} + +func ValidateEmptyStrings(v interface{}, k string) (warnings []string, errors []error) { + if v == nil { + return + } + + if v.(string) == "" { + errors = append(errors, + fmt.Errorf("expected a non-empty string")) + } + + return +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_folder_service_account.go b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_folder_service_account.go index 2bc48454a986..4727870ba944 100644 --- a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_folder_service_account.go +++ b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_folder_service_account.go @@ -56,7 +56,7 @@ func dataSourceAccessApprovalFolderServiceAccountRead(d *schema.ResourceData, me UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("AccessApprovalFolderServiceAccount %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("AccessApprovalFolderServiceAccount %q", d.Id()), url) } if err := d.Set("name", res["name"]); err != nil { diff --git a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_organization_service_account.go b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_organization_service_account.go index b7b2005fbc6e..d785f52f82ed 100644 --- a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_organization_service_account.go +++ b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_organization_service_account.go @@ -56,7 +56,7 @@ func dataSourceAccessApprovalOrganizationServiceAccountRead(d *schema.ResourceDa UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("AccessApprovalOrganizationServiceAccount %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("AccessApprovalOrganizationServiceAccount %q", d.Id()), url) } if err := d.Set("name", res["name"]); err != nil { diff --git a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_project_service_account.go b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_project_service_account.go index 1f9794f50e5e..4a0cf4b73036 100644 --- a/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_project_service_account.go +++ b/mmv1/third_party/terraform/services/accessapproval/data_source_access_approval_project_service_account.go @@ -56,7 +56,7 @@ func dataSourceAccessApprovalProjectServiceAccountRead(d *schema.ResourceData, m UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("AccessApprovalProjectServiceAccount %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("AccessApprovalProjectServiceAccount %q", d.Id()), url) } if err := d.Set("name", res["name"]); err != nil { diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.erb b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.erb index 8e945af590f8..42849562162d 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.erb +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go.erb @@ -207,6 +207,83 @@ resource "google_access_context_manager_service_perimeter" "test-access" { name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" title = "%s" perimeter_type = "PERIMETER_TYPE_REGULAR" + use_explicit_dry_run_spec = true + spec { + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + access_levels = [google_access_context_manager_access_level.test-access.name] + + vpc_accessible_services { + enable_restriction = true + allowed_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + } + + ingress_policies { + ingress_from { + sources { + access_level = google_access_context_manager_access_level.test-access.name + } + identity_type = "ANY_IDENTITY" + } + + ingress_to { + resources = [ "*" ] + operations { + service_name = "bigquery.googleapis.com" + + method_selectors { + method = "BigQueryStorage.ReadRows" + } + + method_selectors { + method = "TableService.ListTables" + } + + method_selectors { + permission = "bigquery.jobs.get" + } + } + + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + ingress_policies { + ingress_from { + identities = ["user:test@google.com"] + } + ingress_to { + resources = ["*"] + } + } + + egress_policies { + egress_from { + identity_type = "ANY_USER_ACCOUNT" + } + egress_to { + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + permission = "externalResource.read" + } + } + external_resources = ["s3://bucket1"] + } + } + egress_policies { + egress_from { + identities = ["user:test@google.com"] + } + egress_to { + resources = ["*"] + } + } + } status { restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] access_levels = [google_access_context_manager_access_level.test-access.name] @@ -251,11 +328,36 @@ resource "google_access_context_manager_service_perimeter" "test-access" { } } } + ingress_policies { + ingress_from { + identities = ["user:test@google.com"] + } + ingress_to { + resources = ["*"] + } + } egress_policies { egress_from { identity_type = "ANY_USER_ACCOUNT" } + egress_to { + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + permission = "externalResource.read" + } + } + external_resources = ["s3://bucket1"] + } + } + egress_policies { + egress_from { + identities = ["user:test@google.com"] + } + egress_to { + resources = ["*"] + } } } } diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go index d66bb2950e49..a220ea5a5e26 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go @@ -199,17 +199,156 @@ resource "google_access_context_manager_service_perimeters" "test-access" { name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" title = "%s" perimeter_type = "PERIMETER_TYPE_REGULAR" + use_explicit_dry_run_spec = true + spec { + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + access_levels = [google_access_context_manager_access_level.test-access.name] + + vpc_accessible_services { + enable_restriction = true + allowed_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + } + + ingress_policies { + ingress_from { + sources { + access_level = google_access_context_manager_access_level.test-access.name + } + identity_type = "ANY_IDENTITY" + } + + ingress_to { + resources = [ "*" ] + operations { + service_name = "bigquery.googleapis.com" + + method_selectors { + method = "BigQueryStorage.ReadRows" + } + + method_selectors { + method = "TableService.ListTables" + } + + method_selectors { + permission = "bigquery.jobs.get" + } + } + + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + ingress_policies { + ingress_from { + identities = ["user:test@google.com"] + } + ingress_to { + resources = ["*"] + } + } + + egress_policies { + egress_from { + identity_type = "ANY_USER_ACCOUNT" + } + egress_to { + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + permission = "externalResource.read" + } + } + external_resources = ["s3://bucket1"] + } + } + egress_policies { + egress_from { + identities = ["user:test@google.com"] + } + egress_to { + resources = ["*"] + } + } + } status { - restricted_services = ["bigquery.googleapis.com"] + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + access_levels = [google_access_context_manager_access_level.test-access.name] + + vpc_accessible_services { + enable_restriction = true + allowed_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + } + + ingress_policies { + ingress_from { + sources { + access_level = google_access_context_manager_access_level.test-access.name + } + identity_type = "ANY_IDENTITY" + } + + ingress_to { + resources = [ "*" ] + operations { + service_name = "bigquery.googleapis.com" + + method_selectors { + method = "BigQueryStorage.ReadRows" + } + + method_selectors { + method = "TableService.ListTables" + } + + method_selectors { + permission = "bigquery.jobs.get" + } + } + + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + ingress_policies { + ingress_from { + identities = ["user:test@google.com"] + } + ingress_to { + resources = ["*"] + } + } + egress_policies { + egress_from { + identity_type = "ANY_USER_ACCOUNT" + } egress_to { - external_resources = ["s3://bucket2"] operations { service_name = "bigquery.googleapis.com" method_selectors { - method = "*" + permission = "externalResource.read" } } + external_resources = ["s3://bucket1"] + } + } + egress_policies { + egress_from { + identities = ["user:test@google.com"] + } + egress_to { + resources = ["*"] } } } diff --git a/mmv1/third_party/terraform/services/activedirectory/resource_active_directory_domain_update_test.go b/mmv1/third_party/terraform/services/activedirectory/resource_active_directory_domain_update_test.go index f88bc7f5e808..de9069c50cc4 100644 --- a/mmv1/third_party/terraform/services/activedirectory/resource_active_directory_domain_update_test.go +++ b/mmv1/third_party/terraform/services/activedirectory/resource_active_directory_domain_update_test.go @@ -39,7 +39,7 @@ func TestAccActiveDirectoryDomain_update(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"domain_name"}, + ImportStateVerifyIgnore: []string{"domain_name", "labels", "terraform_labels"}, }, { Config: testAccADDomainUpdate(context), @@ -48,7 +48,7 @@ func TestAccActiveDirectoryDomain_update(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"domain_name"}, + ImportStateVerifyIgnore: []string{"domain_name", "labels", "terraform_labels"}, }, { Config: testAccADDomainBasic(context), @@ -57,7 +57,7 @@ func TestAccActiveDirectoryDomain_update(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"domain_name"}, + ImportStateVerifyIgnore: []string{"domain_name", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_locations.go b/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_locations.go index d23793f6a7d2..e79df23ac67b 100644 --- a/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_locations.go +++ b/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_locations.go @@ -94,7 +94,7 @@ func dataSourceAlloydbLocationsRead(d *schema.ResourceData, meta interface{}) er UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Locations %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Locations %q", d.Id()), url) } var locations []map[string]interface{} for { @@ -142,7 +142,7 @@ func dataSourceAlloydbLocationsRead(d *schema.ResourceData, meta interface{}) er UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Locations %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Locations %q", d.Id()), url) } } diff --git a/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_supported_database_flags.go b/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_supported_database_flags.go index 6404eaa63247..a1615661d5cc 100644 --- a/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_supported_database_flags.go +++ b/mmv1/third_party/terraform/services/alloydb/data_source_alloydb_supported_database_flags.go @@ -147,7 +147,7 @@ func dataSourceAlloydbSupportedDatabaseFlagsRead(d *schema.ResourceData, meta in UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id()), url) } var supportedDatabaseFlags []map[string]interface{} for { @@ -221,7 +221,7 @@ func dataSourceAlloydbSupportedDatabaseFlagsRead(d *schema.ResourceData, meta in UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("SupportedDatabaseFlags %q", d.Id()), url) } } if err := d.Set("supported_database_flags", supportedDatabaseFlags); err != nil { diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go index 4da0e5c86fa7..6f5c9c6c8616 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go @@ -10,9 +10,10 @@ import ( func TestAccAlloydbBackup_update(t *testing.T) { t.Parallel() + random_suffix := acctest.RandString(t, 10) context := map[string]interface{}{ - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-update"), - "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-update-1"), + "random_suffix": random_suffix, } acctest.VcrTest(t, resource.TestCase{ @@ -21,13 +22,13 @@ func TestAccAlloydbBackup_update(t *testing.T) { CheckDestroy: testAccCheckAlloydbBackupDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccAlloydbBackup_alloydbBackupFullExample(context), + Config: testAccAlloydbBackup_alloydbBackupBasic(context), }, { ResourceName: "google_alloydb_backup.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time"}, + ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time", "labels", "terraform_labels"}, }, { Config: testAccAlloydbBackup_update(context), @@ -36,14 +37,13 @@ func TestAccAlloydbBackup_update(t *testing.T) { ResourceName: "google_alloydb_backup.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time"}, + ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time", "labels", "terraform_labels"}, }, }, }) } -// Updates "label" field from testAccAlloydbBackup_alloydbBackupFullExample -func testAccAlloydbBackup_update(context map[string]interface{}) string { +func testAccAlloydbBackup_alloydbBackupBasic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_alloydb_backup" "default" { location = "us-central1" @@ -52,8 +52,7 @@ resource "google_alloydb_backup" "default" { description = "example description" labels = { - "label" = "updated_key" - "label2" = "updated_key2" + "label" = "key" } depends_on = [google_alloydb_instance.default] } @@ -68,22 +67,40 @@ resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" +} - depends_on = [google_service_networking_connection.vpc_connection] +data "google_compute_network" "default" { + name = "%{network_name}" +} +`, context) } -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id +// Updates "label" field +func testAccAlloydbBackup_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_backup" "default" { + location = "us-central1" + backup_id = "tf-test-alloydb-backup%{random_suffix}" + cluster_name = google_alloydb_cluster.default.name + + description = "example description" + labels = { + "label" = "updated_key" + "label2" = "updated_key2" + } + depends_on = [google_alloydb_instance.default] } -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = data.google_compute_network.default.id +} + +resource "google_alloydb_instance" "default" { + cluster = google_alloydb_cluster.default.name + instance_id = "tf-test-alloydb-instance%{random_suffix}" + instance_type = "PRIMARY" } data "google_compute_network" "default" { @@ -98,7 +115,7 @@ func TestAccAlloydbBackup_createBackupWithMandatoryFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbbackup-mandatory"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-mandatory-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -138,32 +155,6 @@ resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] -} - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id - lifecycle { - ignore_changes = [ - address, - creation_timestamp, - id, - network, - project, - self_link - ] - } -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } `, context) } @@ -172,7 +163,7 @@ func TestAccAlloydbBackup_usingCMEK(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydb-backup-cmek"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-backup-cmek-1"), "random_suffix": acctest.RandString(t, 10), "key_name": "tf-test-key-" + acctest.RandString(t, 10), } @@ -189,7 +180,7 @@ func TestAccAlloydbBackup_usingCMEK(t *testing.T) { ResourceName: "google_alloydb_backup.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time"}, + ImportStateVerifyIgnore: []string{"backup_id", "location", "reconciling", "update_time", "labels", "terraform_labels"}, }, }, }) @@ -222,22 +213,6 @@ resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] -} - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } data "google_compute_network" "default" { diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go index d6def69f6832..5288d8ea62f8 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_restore_test.go @@ -19,7 +19,7 @@ func TestAccAlloydbCluster_restore(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-restore"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-restore-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -93,8 +93,6 @@ resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -110,20 +108,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -140,8 +124,6 @@ resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -174,20 +156,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -204,8 +172,6 @@ resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -235,20 +201,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -264,8 +216,6 @@ resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -294,20 +244,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -325,8 +261,6 @@ resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -369,20 +303,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -400,8 +320,6 @@ resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -454,20 +372,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -485,8 +389,6 @@ resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -549,20 +451,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -580,8 +468,6 @@ resource "google_alloydb_instance" "source" { cluster = google_alloydb_cluster.source.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_backup" "default" { @@ -616,19 +502,5 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go index 3d8ad93a789a..21ba1948a2ff 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go @@ -26,7 +26,7 @@ func TestAccAlloydbCluster_update(t *testing.T) { ResourceName: "google_alloydb_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location", "labels", "terraform_labels"}, }, { Config: testAccAlloydbCluster_update(context), @@ -35,7 +35,7 @@ func TestAccAlloydbCluster_update(t *testing.T) { ResourceName: "google_alloydb_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location", "labels", "terraform_labels"}, }, { Config: testAccAlloydbCluster_alloydbClusterBasicExample(context), diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go index b7533cf6060c..9009f1493a9c 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_instance_test.go @@ -1,18 +1,21 @@ package alloydb_test import ( + "fmt" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" ) func TestAccAlloydbInstance_update(t *testing.T) { t.Parallel() + random_suffix := acctest.RandString(t, 10) context := map[string]interface{}{ - "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-update"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-update-1"), + "random_suffix": random_suffix, } acctest.VcrTest(t, resource.TestCase{ @@ -21,7 +24,7 @@ func TestAccAlloydbInstance_update(t *testing.T) { CheckDestroy: testAccCheckAlloydbInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccAlloydbInstance_alloydbInstanceBasicExample(context), + Config: testAccAlloydbInstance_alloydbInstanceBasic(context), }, { ResourceName: "google_alloydb_instance.default", @@ -36,12 +39,40 @@ func TestAccAlloydbInstance_update(t *testing.T) { ResourceName: "google_alloydb_instance.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"cluster", "instance_id", "reconciling", "update_time"}, + ImportStateVerifyIgnore: []string{"cluster", "instance_id", "reconciling", "update_time", "labels", "terraform_labels"}, }, }, }) } +func testAccAlloydbInstance_alloydbInstanceBasic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_instance" "default" { + cluster = google_alloydb_cluster.default.name + instance_id = "tf-test-alloydb-instance%{random_suffix}" + instance_type = "PRIMARY" + + machine_config { + cpu_count = 2 + } +} + +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = data.google_compute_network.default.id + + initial_user { + password = "tf-test-alloydb-cluster%{random_suffix}" + } +} + +data "google_compute_network" "default" { + name = "%{network_name}" +} +`, context) +} + func testAccAlloydbInstance_update(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_alloydb_instance" "default" { @@ -56,8 +87,6 @@ resource "google_alloydb_instance" "default" { labels = { test = "tf-test-alloydb-instance%{random_suffix}" } - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { @@ -70,26 +99,9 @@ resource "google_alloydb_cluster" "default" { } } -data "google_project" "project" { -} - data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -99,7 +111,7 @@ func TestAccAlloydbInstance_createInstanceWithMandatoryFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-mandatory"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-mandatory-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -120,8 +132,6 @@ resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { @@ -135,20 +145,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -158,7 +154,7 @@ resource "google_service_networking_connection" "vpc_connection" { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-maximum"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-maximum-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -219,20 +215,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) }*/ @@ -242,7 +224,7 @@ func TestAccAlloydbInstance_createPrimaryAndReadPoolInstance(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-readpool"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-readpool-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -263,7 +245,6 @@ resource "google_alloydb_instance" "primary" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_instance" "read_pool" { @@ -273,7 +254,7 @@ resource "google_alloydb_instance" "read_pool" { read_pool_config { node_count = 4 } - depends_on = [google_service_networking_connection.vpc_connection, google_alloydb_instance.primary] + depends_on = [google_alloydb_instance.primary] } resource "google_alloydb_cluster" "default" { @@ -287,20 +268,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -310,7 +277,7 @@ resource "google_service_networking_connection" "vpc_connection" { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-updatedb"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "alloydb-instance-updatedb-1"), } acctest.VcrTest(t, resource.TestCase{ @@ -342,7 +309,6 @@ resource "google_alloydb_instance" "primary" { database_flags = { "alloydb.enable_auto_explain" = "true" } - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { @@ -356,20 +322,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) }*/ @@ -382,7 +334,6 @@ resource "google_alloydb_instance" "primary" { database_flags = { "alloydb.enable_auto_explain" = "false" } - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { @@ -396,20 +347,6 @@ data "google_project" "project" {} data "google_compute_network" "default" { name = "%{network_name}" } - -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] -} `, context) } @@ -417,9 +354,17 @@ resource "google_service_networking_connection" "vpc_connection" { func TestAccAlloydbInstance_createInstanceWithNetworkConfigAndAllocatedIPRange(t *testing.T) { t.Parallel() + projectNumber := envvar.GetTestProjectNumberFromEnv() + testId := "alloydbinstance-network-config-1" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) + context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), - "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-network-config"), + "network_name": networkName, + "address_name": addressName, } acctest.VcrTest(t, resource.TestCase{ @@ -440,7 +385,6 @@ resource "google_alloydb_instance" "default" { cluster = google_alloydb_cluster.default.name instance_id = "tf-test-alloydb-instance%{random_suffix}" instance_type = "PRIMARY" - depends_on = [google_service_networking_connection.vpc_connection] } resource "google_alloydb_cluster" "default" { @@ -448,29 +392,16 @@ resource "google_alloydb_cluster" "default" { location = "us-central1" network_config { network = data.google_compute_network.default.id - allocated_ip_range = google_compute_global_address.private_ip_alloc.name + allocated_ip_range = data.google_compute_global_address.private_ip_alloc.name } - } -data "google_project" "project" {} - data "google_compute_network" "default" { name = "%{network_name}" } -resource "google_compute_global_address" "private_ip_alloc" { - name = "tf-test-alloydb-cluster%{random_suffix}" - address_type = "INTERNAL" - purpose = "VPC_PEERING" - prefix_length = 16 - network = data.google_compute_network.default.id -} - -resource "google_service_networking_connection" "vpc_connection" { - network = data.google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] +data "google_compute_global_address" "private_ip_alloc" { + name = "%{address_name}" } `, context) } diff --git a/mmv1/third_party/terraform/services/appengine/data_source_google_app_engine_default_service_account.go b/mmv1/third_party/terraform/services/appengine/data_source_google_app_engine_default_service_account.go index bd38291084d5..99764bfe0fcf 100644 --- a/mmv1/third_party/terraform/services/appengine/data_source_google_app_engine_default_service_account.go +++ b/mmv1/third_party/terraform/services/appengine/data_source_google_app_engine_default_service_account.go @@ -62,7 +62,7 @@ func dataSourceGoogleAppEngineDefaultServiceAccountRead(d *schema.ResourceData, sa, err := config.NewIamClient(userAgent).Projects.ServiceAccounts.Get(serviceAccountName).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName), serviceAccountName) } d.SetId(sa.Name) diff --git a/mmv1/third_party/terraform/services/appengine/resource_app_engine_application.go b/mmv1/third_party/terraform/services/appengine/resource_app_engine_application.go index 0ca799ade56d..c7d631e84806 100644 --- a/mmv1/third_party/terraform/services/appengine/resource_app_engine_application.go +++ b/mmv1/third_party/terraform/services/appengine/resource_app_engine_application.go @@ -32,6 +32,7 @@ func ResourceAppEngineApplication() *schema.Resource { }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, appEngineApplicationLocationIDCustomizeDiff, ), diff --git a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go index 09c832b4aff9..272ec3411b70 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go +++ b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository.go @@ -38,12 +38,21 @@ func dataSourceArtifactRegistryRepositoryRead(d *schema.ResourceData, meta inter } repository_id := d.Get("repository_id").(string) - d.SetId(fmt.Sprintf("projects/%s/locations/%s/repositories/%s", project, location, repository_id)) + id := fmt.Sprintf("projects/%s/locations/%s/repositories/%s", project, location, repository_id) + d.SetId(id) err = resourceArtifactRegistryRepositoryRead(d, meta) if err != nil { return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go index 7c663fbe0a60..22c2f610e1e8 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go +++ b/mmv1/third_party/terraform/services/artifactregistry/data_source_artifact_registry_repository_test.go @@ -38,6 +38,10 @@ resource "google_artifact_registry_repository" "my-repo" { repository_id = "tf-test-my-repository%{random_suffix}" description = "example docker repository%{random_suffix}" format = "DOCKER" + labels = { + my_key = "my_val" + other_key = "other_val" + } } data "google_artifact_registry_repository" "my-repo" { diff --git a/mmv1/third_party/terraform/services/artifactregistry/resource_artifact_registry_repository_test.go.erb b/mmv1/third_party/terraform/services/artifactregistry/resource_artifact_registry_repository_test.go.erb index d098eb1c0edc..6f409d267936 100644 --- a/mmv1/third_party/terraform/services/artifactregistry/resource_artifact_registry_repository_test.go.erb +++ b/mmv1/third_party/terraform/services/artifactregistry/resource_artifact_registry_repository_test.go.erb @@ -26,6 +26,7 @@ func TestAccArtifactRegistryRepository_update(t *testing.T) { ResourceName: "google_artifact_registry_repository.test", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccArtifactRegistryRepository_update2(repositoryID), @@ -34,6 +35,7 @@ func TestAccArtifactRegistryRepository_update(t *testing.T) { ResourceName: "google_artifact_registry_repository.test", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go index fef0cf119493..38240dbb8e5f 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection.go @@ -38,7 +38,21 @@ func dataSourceGoogleBeyondcorpAppConnectionRead(d *schema.ResourceData, meta in return err } - d.SetId(fmt.Sprintf("projects/%s/locations/%s/appConnections/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/locations/%s/appConnections/%s", project, region, name) + d.SetId(id) - return resourceBeyondcorpAppConnectionRead(d, meta) + err = resourceBeyondcorpAppConnectionRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go index 66a488a29163..44288c2a5eca 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connection_test.go @@ -76,6 +76,9 @@ resource "google_beyondcorp_app_connection" "foo" { port = 8080 } connectors = [google_beyondcorp_app_connector.app_connector.id] + labels = { + my-label = "my-label-value" + } } data "google_beyondcorp_app_connection" "foo" { diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go index 202941b1448c..1f4132bababc 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector.go @@ -38,7 +38,21 @@ func dataSourceGoogleBeyondcorpAppConnectorRead(d *schema.ResourceData, meta int return err } - d.SetId(fmt.Sprintf("projects/%s/locations/%s/appConnectors/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/locations/%s/appConnectors/%s", project, region, name) + d.SetId(id) - return resourceBeyondcorpAppConnectorRead(d, meta) + err = resourceBeyondcorpAppConnectorRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector_test.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector_test.go index 5bf5acf3b67a..4a8274f905bc 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector_test.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_connector_test.go @@ -179,6 +179,9 @@ resource "google_beyondcorp_app_connector" "foo" { email = google_service_account.service_account.email } } + labels = { + my-label = "my-label-value" + } } data "google_beyondcorp_app_connector" "foo" { diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go index a713c74e6a25..6f31635a2954 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway.go @@ -38,7 +38,21 @@ func dataSourceGoogleBeyondcorpAppGatewayRead(d *schema.ResourceData, meta inter return err } - d.SetId(fmt.Sprintf("projects/%s/locations/%s/appGateways/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/locations/%s/appGateways/%s", project, region, name) + d.SetId(id) - return resourceBeyondcorpAppGatewayRead(d, meta) + err = resourceBeyondcorpAppGatewayRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway_test.go b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway_test.go index c7c8f943d446..ca345530c263 100644 --- a/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway_test.go +++ b/mmv1/third_party/terraform/services/beyondcorp/data_source_google_beyondcorp_app_gateway_test.go @@ -101,6 +101,9 @@ resource "google_beyondcorp_app_gateway" "foo" { name = "tf-test-appgateway-%{random_suffix}" type = "TCP_PROXY" host_type = "GCP_REGIONAL_MIG" + labels = { + my-label = "my-label-value" + } } data "google_beyondcorp_app_gateway" "foo" { diff --git a/mmv1/third_party/terraform/services/bigquery/data_source_google_bigquery_default_service_account.go b/mmv1/third_party/terraform/services/bigquery/data_source_google_bigquery_default_service_account.go index cc1e4f0a6d2a..d25349166440 100644 --- a/mmv1/third_party/terraform/services/bigquery/data_source_google_bigquery_default_service_account.go +++ b/mmv1/third_party/terraform/services/bigquery/data_source_google_bigquery_default_service_account.go @@ -43,7 +43,7 @@ func dataSourceGoogleBigqueryDefaultServiceAccountRead(d *schema.ResourceData, m projectResource, err := config.NewBigQueryClient(userAgent).Projects.GetServiceAccount(project).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, "BigQuery service account not found") + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Project %q BigQuery service account", project), fmt.Sprintf("Project %q BigQuery service account", project)) } d.SetId(projectResource.Email) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go index 864cc9a7d014..11c14014ace9 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go @@ -22,7 +22,11 @@ func TestAccBigQueryDataset_basic(t *testing.T) { CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccBigQueryDataset(datasetID), + Config: testAccBigQueryDataset_withoutLabels(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "labels.%"), + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "effective_labels.%"), + ), }, { ResourceName: "google_bigquery_dataset.test", @@ -30,16 +34,59 @@ func TestAccBigQueryDataset_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccBigQueryDatasetUpdated(datasetID), + Config: testAccBigQueryDataset(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.default_table_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.env", "foo"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.default_table_expiration_ms", "3600000"), + ), }, { ResourceName: "google_bigquery_dataset.test", ImportState: true, ImportStateVerify: true, + // The labels field in the state is decided by the configuration. + // During importing, the configuration is unavailable, so the labels field in the state after importing is empty. + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccBigQueryDatasetUpdated(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.env", "bar"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.default_table_expiration_ms", "7200000"), + + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.env", "bar"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.default_table_expiration_ms", "7200000"), + ), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetUpdated2(datasetID), }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccBigQueryDataset_withoutLabels(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "labels.%"), + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "effective_labels.%"), + ), + }, { ResourceName: "google_bigquery_dataset.test", ImportState: true, @@ -49,6 +96,90 @@ func TestAccBigQueryDataset_basic(t *testing.T) { }) } +func TestAccBigQueryDataset_withProvider5(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.75.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDataset_withoutLabels(datasetID), + ExternalProviders: oldVersion, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "labels.%"), + resource.TestCheckNoResourceAttr("google_bigquery_dataset.test", "effective_labels.%"), + ), + }, + { + Config: testAccBigQueryDataset(datasetID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.default_table_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.env", "foo"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.default_table_expiration_ms", "3600000"), + ), + }, + }, + }) +} + +func TestAccBigQueryDataset_withOutOfBandLabels(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDataset(datasetID), + Check: addOutOfBandLabels(t, datasetID), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels", "terraform_labels"}, + }, + { + Config: testAccBigQueryDatasetUpdated(datasetID), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels", "terraform_labels"}, + }, + { + Config: testAccBigQueryDatasetUpdated_withOutOfBandLabels(datasetID), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels", "terraform_labels"}, + }, + }, + }) +} + func TestAccBigQueryDataset_datasetWithContents(t *testing.T) { t.Parallel() @@ -68,7 +199,7 @@ func TestAccBigQueryDataset_datasetWithContents(t *testing.T) { ResourceName: "google_bigquery_dataset.contents_test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"delete_contents_on_destroy"}, + ImportStateVerifyIgnore: []string{"delete_contents_on_destroy", "labels", "terraform_labels"}, }, }, }) @@ -90,33 +221,37 @@ func TestAccBigQueryDataset_access(t *testing.T) { Config: testAccBigQueryDatasetWithOneAccess(datasetID), }, { - ResourceName: "google_bigquery_dataset.access_test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.access_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetWithTwoAccess(datasetID), }, { - ResourceName: "google_bigquery_dataset.access_test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.access_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetWithOneAccess(datasetID), }, { - ResourceName: "google_bigquery_dataset.access_test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.access_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccBigQueryDatasetWithViewAccess(datasetID, otherDatasetID, otherTableID), }, { - ResourceName: "google_bigquery_dataset.access_test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.access_test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -136,9 +271,10 @@ func TestAccBigQueryDataset_regionalLocation(t *testing.T) { Config: testAccBigQueryRegionalDataset(datasetID1, "asia-south1"), }, { - ResourceName: "google_bigquery_dataset.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -181,9 +317,10 @@ func TestAccBigQueryDataset_storageBillModel(t *testing.T) { Config: testAccBigQueryDatasetStorageBillingModel(datasetID), }, { - ResourceName: "google_bigquery_dataset.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -208,6 +345,38 @@ func testAccAddTable(t *testing.T, datasetID string, tableID string) resource.Te } } +func addOutOfBandLabels(t *testing.T, datasetID string) resource.TestCheckFunc { + // Not actually a check, but adds labels independently of terraform + return func(s *terraform.State) error { + config := acctest.GoogleProviderConfig(t) + + dataset, err := config.NewBigQueryClient(config.UserAgent).Datasets.Get(config.Project, datasetID).Do() + if err != nil { + return fmt.Errorf("Could not get dataset with ID %s", datasetID) + } + + dataset.Labels["outband_key"] = "test" + _, err = config.NewBigQueryClient(config.UserAgent).Datasets.Patch(config.Project, datasetID, dataset).Do() + if err != nil { + return fmt.Errorf("Could not update labele for the dataset") + } + return nil + } +} + +func testAccBigQueryDataset_withoutLabels(datasetID string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" + friendly_name = "foo" + description = "This is a foo description" + location = "EU" + default_partition_expiration_ms = 3600000 + default_table_expiration_ms = 3600000 +} +`, datasetID) +} + func testAccBigQueryDataset(datasetID string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "test" { @@ -244,6 +413,25 @@ resource "google_bigquery_dataset" "test" { `, datasetID) } +func testAccBigQueryDatasetUpdated_withOutOfBandLabels(datasetID string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" + friendly_name = "bar" + description = "This is a bar description" + location = "EU" + default_partition_expiration_ms = 7200000 + default_table_expiration_ms = 7200000 + + labels = { + env = "bar" + default_table_expiration_ms = 7200000 + outband_key = "test-update" + } +} +`, datasetID) +} + func testAccBigQueryDatasetUpdated2(datasetID string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "test" { diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_job_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_job_test.go index 9de93bb6a2f7..3e8b4b832e3f 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_job_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_job_test.go @@ -32,7 +32,7 @@ func TestAccBigQueryJob_withLocation(t *testing.T) { ImportStateId: importID, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "status.0.state"}, + ImportStateVerifyIgnore: []string{"etag", "status.0.state", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go index 90a108b4cc15..fda303300f2f 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -394,6 +394,32 @@ func resourceBigQueryTableSchemaCustomizeDiff(_ context.Context, d *schema.Resou return resourceBigQueryTableSchemaCustomizeDiffFunc(d) } +func validateBigQueryTableSchema(v interface{}, k string) (warnings []string, errs []error) { + if v == nil { + return + } + + if _, e := validation.StringIsJSON(v, k); e != nil { + errs = append(errs, e...) + return + } + + var jsonList []interface{} + if err := json.Unmarshal([]byte(v.(string)), &jsonList); err != nil { + errs = append(errs, fmt.Errorf("\"schema\" is not a JSON array: %s", err)) + return + } + + for _, v := range jsonList { + if v == nil { + errs = append(errs, errors.New("\"schema\" contains a nil element")) + return + } + } + + return +} + func ResourceBigQueryTable() *schema.Resource { return &schema.Resource{ Create: resourceBigQueryTableCreate, @@ -404,7 +430,9 @@ func ResourceBigQueryTable() *schema.Resource { State: resourceBigQueryTableImport, }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, resourceBigQueryTableSchemaCustomizeDiff, + tpgresource.SetLabelsDiff, ), Schema: map[string]*schema.Schema{ // TableId: [Required] The ID of the table. The ID must contain only @@ -508,7 +536,7 @@ func ResourceBigQueryTable() *schema.Resource { Optional: true, Computed: true, ForceNew: true, - ValidateFunc: validation.StringIsJSON, + ValidateFunc: validateBigQueryTableSchema, StateFunc: func(v interface{}) string { json, _ := structure.NormalizeJsonString(v) return json @@ -772,26 +800,43 @@ func ResourceBigQueryTable() *schema.Resource { // start with a letter and each label in the list must have a different // key. "labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A mapping of labels to assign to the resource. + + **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.`, + }, + "terraform_labels": { Type: schema.TypeMap, - Optional: true, + 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}, + }, + "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}, - Description: `A mapping of labels to assign to the resource.`, }, - // Schema: [Optional] Describes the schema of this table. + // Schema is mutually exclusive with View and Materialized View. "schema": { Type: schema.TypeString, Optional: true, Computed: true, - ValidateFunc: validation.StringIsJSON, + ValidateFunc: validateBigQueryTableSchema, StateFunc: func(v interface{}) string { json, _ := structure.NormalizeJsonString(v) return json }, DiffSuppressFunc: bigQueryTableSchemaDiffSuppress, Description: `A JSON schema for the table.`, + ConflictsWith: []string{"view", "materialized_view"}, }, // View: [Optional] If specified, configures this table as a view. + // View is mutually exclusive with Schema and Materialized View. "view": { Type: schema.TypeList, Optional: true, @@ -818,9 +863,11 @@ func ResourceBigQueryTable() *schema.Resource { }, }, }, + ConflictsWith: []string{"schema", "materialized_view"}, }, // Materialized View: [Optional] If specified, configures this table as a materialized view. + // Materialized View is mutually exclusive with Schema and View. "materialized_view": { Type: schema.TypeList, Optional: true, @@ -865,6 +912,7 @@ func ResourceBigQueryTable() *schema.Resource { }, }, }, + ConflictsWith: []string{"schema", "view"}, }, // TimePartitioning: [Experimental] If specified, configures time-based @@ -1256,7 +1304,7 @@ func resourceTable(d *schema.ResourceData, meta interface{}) (*bigquery.Table, e } } - if v, ok := d.GetOk("labels"); ok { + if v, ok := d.GetOk("effective_labels"); ok { labels := map[string]string{} for k, v := range v.(map[string]interface{}) { @@ -1328,41 +1376,16 @@ func resourceBigQueryTableCreate(d *schema.ResourceData, meta interface{}) error datasetID := d.Get("dataset_id").(string) - if table.View != nil && table.Schema != nil { - - log.Printf("[INFO] Removing schema from table definition because big query does not support setting schema on view creation") - schemaBack := table.Schema - table.Schema = nil - - log.Printf("[INFO] Creating BigQuery table: %s without schema", table.TableReference.TableId) - - res, err := config.NewBigQueryClient(userAgent).Tables.Insert(project, datasetID, table).Do() - if err != nil { - return err - } - - log.Printf("[INFO] BigQuery table %s has been created", res.Id) - d.SetId(fmt.Sprintf("projects/%s/datasets/%s/tables/%s", res.TableReference.ProjectId, res.TableReference.DatasetId, res.TableReference.TableId)) - - table.Schema = schemaBack - log.Printf("[INFO] Updating BigQuery table: %s with schema", table.TableReference.TableId) - if _, err = config.NewBigQueryClient(userAgent).Tables.Update(project, datasetID, res.TableReference.TableId, table).Do(); err != nil { - return err - } + log.Printf("[INFO] Creating BigQuery table: %s", table.TableReference.TableId) - log.Printf("[INFO] BigQuery table %s has been update with schema", res.Id) - } else { - log.Printf("[INFO] Creating BigQuery table: %s", table.TableReference.TableId) - - res, err := config.NewBigQueryClient(userAgent).Tables.Insert(project, datasetID, table).Do() - if err != nil { - return err - } - - log.Printf("[INFO] BigQuery table %s has been created", res.Id) - d.SetId(fmt.Sprintf("projects/%s/datasets/%s/tables/%s", res.TableReference.ProjectId, res.TableReference.DatasetId, res.TableReference.TableId)) + res, err := config.NewBigQueryClient(userAgent).Tables.Insert(project, datasetID, table).Do() + if err != nil { + return err } + log.Printf("[INFO] BigQuery table %s has been created", res.Id) + d.SetId(fmt.Sprintf("projects/%s/datasets/%s/tables/%s", res.TableReference.ProjectId, res.TableReference.DatasetId, res.TableReference.TableId)) + return resourceBigQueryTableRead(d, meta) } @@ -1403,9 +1426,15 @@ func resourceBigQueryTableRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("max_staleness", res.MaxStaleness); err != nil { return fmt.Errorf("Error setting max_staleness: %s", err) } - if err := d.Set("labels", res.Labels); err != nil { + 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) + } if err := d.Set("creation_time", res.CreationTime); err != nil { return fmt.Errorf("Error setting creation_time: %s", err) } diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go index 611ca07e2826..574fe2d488d0 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go @@ -454,22 +454,8 @@ func TestAccBigQueryTable_WithViewAndSchema(t *testing.T) { CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccBigQueryTableWithViewAndSchema(datasetID, tableID, "table description1"), - }, - { - ResourceName: "google_bigquery_table.test", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection"}, - }, - { - Config: testAccBigQueryTableWithViewAndSchema(datasetID, tableID, "table description2"), - }, - { - ResourceName: "google_bigquery_table.test", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection"}, + Config: testAccBigQueryTableWithViewAndSchema(datasetID, tableID, "table description"), + ExpectError: regexp.MustCompile("\"view\": conflicts with schema"), }, }, }) @@ -607,6 +593,51 @@ func TestAccBigQueryTable_MaterializedView_NonIncremental_basic(t *testing.T) { }) } +func TestAccBigQueryTable_MaterializedView_WithSchema(t *testing.T) { + t.Parallel() + // Pending VCR support in https://github.com/hashicorp/terraform-provider-google/issues/15427. + acctest.SkipIfVcr(t) + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + materializedViewID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + query := fmt.Sprintf("SELECT some_int FROM `%s.%s`", datasetID, tableID) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableWithMatViewAndSchema(datasetID, tableID, materializedViewID, query), + ExpectError: regexp.MustCompile("\"materialized_view\": conflicts with schema"), + }, + }, + }) +} + +func TestAccBigQueryTable_MaterializedView_WithView(t *testing.T) { + t.Parallel() + acctest.SkipIfVcr(t) + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + materializedViewID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + query := fmt.Sprintf("SELECT some_int FROM `%s.%s`", datasetID, tableID) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableWithMatViewAndView(datasetID, tableID, materializedViewID, query), + ExpectError: regexp.MustCompile("\"materialized_view\": conflicts with view"), + }, + }, + }) +} + func TestAccBigQueryExternalDataTable_parquet(t *testing.T) { t.Parallel() @@ -903,6 +934,36 @@ func TestAccBigQueryExternalDataTable_CSV(t *testing.T) { }) } +func TestAccBigQueryExternalDataTable_CSV_WithSchema_InvalidSchemas(t *testing.T) { + t.Parallel() + + bucketName := acctest.TestBucketName(t) + objectName := fmt.Sprintf("tf_test_%s.csv", acctest.RandString(t, 10)) + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_NOT_JSON), + ExpectError: regexp.MustCompile("contains an invalid JSON"), + }, + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_NOT_JSON_LIST), + ExpectError: regexp.MustCompile("\"schema\" is not a JSON array"), + }, + { + Config: testAccBigQueryTableFromGCSWithExternalDataConfigSchema(datasetID, tableID, bucketName, objectName, TEST_SIMPLE_CSV, TEST_INVALID_SCHEMA_JSON_LIST_WITH_NULL_ELEMENT), + ExpectError: regexp.MustCompile("\"schema\" contains a nil element"), + }, + }, + }) +} + func TestAccBigQueryExternalDataTable_CSV_WithSchemaAndConnectionID_UpdateNoConnectionID(t *testing.T) { t.Parallel() @@ -1095,7 +1156,7 @@ func TestAccBigQueryDataTable_jsonEquivalency(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels", "terraform_labels"}, }, { Config: testAccBigQueryTable_jsonEqModeRemoved(datasetID, tableID), @@ -1104,7 +1165,7 @@ func TestAccBigQueryDataTable_jsonEquivalency(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels", "terraform_labels"}, }, }, }) @@ -1154,7 +1215,7 @@ func TestAccBigQueryDataTable_expandArray(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels", "terraform_labels"}, }, { Config: testAccBigQueryTable_arrayExpanded(datasetID, tableID), @@ -1163,7 +1224,7 @@ func TestAccBigQueryDataTable_expandArray(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection"}, + ImportStateVerifyIgnore: []string{"etag", "last_modified_time", "deletion_protection", "labels", "terraform_labels"}, }, }, }) @@ -1187,7 +1248,7 @@ func TestAccBigQueryTable_allowDestroy(t *testing.T) { ResourceName: "google_bigquery_table.test", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"deletion_protection"}, + ImportStateVerifyIgnore: []string{"deletion_protection", "labels", "terraform_labels"}, }, { Config: testAccBigQueryTable_noAllowDestroy(datasetID, tableID), @@ -1370,6 +1431,35 @@ func TestAccBigQueryTable_Update_SchemaWithPolicyTagsToEmptyPolicyTagNames(t *te }) } +func TestAccBigQueryTable_invalidSchemas(t *testing.T) { + t.Parallel() + // Pending VCR support in https://github.com/hashicorp/terraform-provider-google/issues/15427. + acctest.SkipIfVcr(t) + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_NOT_JSON), + ExpectError: regexp.MustCompile("contains an invalid JSON"), + }, + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_NOT_JSON_LIST), + ExpectError: regexp.MustCompile("\"schema\" is not a JSON array"), + }, + { + Config: testAccBigQueryTableWithSchema(datasetID, tableID, TEST_INVALID_SCHEMA_JSON_LIST_WITH_NULL_ELEMENT), + ExpectError: regexp.MustCompile("\"schema\" contains a nil element"), + }, + }, + }) +} + func testAccCheckBigQueryExtData(t *testing.T, expectedQuoteChar string) resource.TestCheckFunc { return func(s *terraform.State) error { for _, rs := range s.RootModule().Resources { @@ -2084,7 +2174,57 @@ resource "google_bigquery_table" "mv_test" { `, datasetID, tableID, mViewID, enable_refresh, refresh_interval, query) } -func testAccBigQueryTableWithMatViewNonIncremental_basic(datasetID, tableID, mViewID, query, maxStaleness string) string { +func testAccBigQueryTableWithMatViewAndSchema(datasetID, tableID, mViewID, query string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" +} + +resource "google_bigquery_table" "test" { + deletion_protection = false + table_id = "%s" + dataset_id = google_bigquery_dataset.test.dataset_id + + schema = < 0 { - t.Errorf("Failed to validate CloudIoT ID names: %v", es) - } -} diff --git a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_update_test.go b/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_update_test.go deleted file mode 100644 index 799b4a58c372..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_device_update_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package cloudiot_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-provider-google/google/acctest" -) - -func TestAccCloudIoTDevice_update(t *testing.T) { - t.Parallel() - - registryName := fmt.Sprintf("psregistry-test-%s", acctest.RandString(t, 10)) - deviceName := fmt.Sprintf("psdevice-test-%s", acctest.RandString(t, 10)) - resourceName := fmt.Sprintf("google_cloudiot_device.%s", deviceName) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckCloudIotDeviceDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccCloudIoTDeviceBasic(deviceName, registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccCloudIoTDeviceExtended(deviceName, registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccCloudIoTDeviceBasic(deviceName, registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccCloudIoTDeviceBasic(deviceName string, registryName string) string { - return fmt.Sprintf(` - -resource "google_cloudiot_registry" "%s" { - name = "%s" -} - -resource "google_cloudiot_device" "%s" { - name = "%s" - registry = google_cloudiot_registry.%s.id - - gateway_config { - gateway_auth_method = "DEVICE_AUTH_TOKEN_ONLY" - gateway_type = "GATEWAY" - } -} - - -`, registryName, registryName, deviceName, deviceName, registryName) -} - -func testAccCloudIoTDeviceExtended(deviceName string, registryName string) string { - return fmt.Sprintf(` - -resource "google_cloudiot_registry" "%s" { - name = "%s" -} - -resource "google_cloudiot_device" "%s" { - name = "%s" - registry = google_cloudiot_registry.%s.id - - credentials { - public_key { - format = "RSA_PEM" - key = file("test-fixtures/rsa_public.pem") - } - } - - blocked = false - - log_level = "INFO" - - metadata = { - test_key_1 = "test_value_1" - } - - gateway_config { - gateway_auth_method = "ASSOCIATION_AND_DEVICE_AUTH_TOKEN" - gateway_type = "GATEWAY" - } -} -`, registryName, registryName, deviceName, deviceName, registryName) -} diff --git a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_registry_update_test.go b/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_registry_update_test.go deleted file mode 100644 index 9493f26bd4ca..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/resource_cloudiot_registry_update_test.go +++ /dev/null @@ -1,110 +0,0 @@ -package cloudiot_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-provider-google/google/acctest" -) - -func TestAccCloudIoTRegistry_update(t *testing.T) { - t.Parallel() - - registryName := fmt.Sprintf("psregistry-test-%s", acctest.RandString(t, 10)) - resourceName := fmt.Sprintf("google_cloudiot_registry.%s", registryName) - deviceStatus := fmt.Sprintf("psregistry-test-devicestatus-%s", acctest.RandString(t, 10)) - defaultTelemetry := fmt.Sprintf("psregistry-test-telemetry-%s", acctest.RandString(t, 10)) - additionalTelemetry := fmt.Sprintf("psregistry-additional-test-telemetry-%s", acctest.RandString(t, 10)) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckCloudIotDeviceRegistryDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccCloudIoTRegistryBasic(registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccCloudIoTRegistryExtended(registryName, deviceStatus, defaultTelemetry, additionalTelemetry), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccCloudIoTRegistryBasic(registryName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccCloudIoTRegistryBasic(registryName string) string { - return fmt.Sprintf(` - -resource "google_cloudiot_registry" "%s" { - name = "%s" -} -`, registryName, registryName) -} - -func testAccCloudIoTRegistryExtended(registryName string, deviceStatus string, defaultTelemetry string, additionalTelemetry string) string { - return fmt.Sprintf(` - -resource "google_pubsub_topic" "default-devicestatus" { - name = "psregistry-test-devicestatus-%s" -} - -resource "google_pubsub_topic" "default-telemetry" { - name = "psregistry-test-telemetry-%s" -} - -resource "google_pubsub_topic" "additional-telemetry" { - name = "psregistry-additional-test-telemetry-%s" -} - -resource "google_cloudiot_registry" "%s" { - name = "%s" - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.additional-telemetry.id - subfolder_matches = "test/directory" - } - - event_notification_configs { - pubsub_topic_name = google_pubsub_topic.default-telemetry.id - subfolder_matches = "" - } - - state_notification_config = { - pubsub_topic_name = google_pubsub_topic.default-devicestatus.id - } - - mqtt_config = { - mqtt_enabled_state = "MQTT_DISABLED" - } - - http_config = { - http_enabled_state = "HTTP_DISABLED" - } - - credentials { - public_key_certificate = { - format = "X509_CERTIFICATE_PEM" - certificate = file("test-fixtures/rsa_cert.pem") - } - } -} -`, deviceStatus, defaultTelemetry, additionalTelemetry, registryName, registryName) -} diff --git a/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_cert.pem b/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_cert.pem deleted file mode 100644 index d8a834633c91..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_cert.pem +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICoDCCAYgCCQDzZ6R7RYs0sTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ1 -bnVzZWQwIBcNMTgwMTIwMTA0OTIzWhgPNDc1NTEyMTgxMDQ5MjNaMBExDzANBgNV -BAMMBnVudXNlZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMXX/5jI -tvxpst1mFVKVXfyu5S5AOQF+i/ny6Ef+h8py8y42XfsE2AAPSTE3JCIgWemw7NQ/ -xnTQ3f6b7/6+ZsdM4/hoiedwYV8X3LVPB9NRnKe82OHUhzo1psVMJVvHtE3GsD/V -i40ki/L4Xs64E2GJqQfrkgeNfIyCeKev64fR5aMazqOw1cNrVe34mY3L1hgXpn7e -SnO0oqnV86pTh+jTT8EKgo9AI7/QuJbPWpJhnj1/Fm8i3DdCdpQqloX9Fc4f6whA -XlZ2tkma0PsBraxMua5GPglJ7m3RabQIoyAW+4hEYAcu7U0wIhCK+C8WTNgEYZaK -zvp8vK6vOgBIjE0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAvVXus7dLikEAM6+I -6xeN7aHEMJRR0h2rigLiYjfl8R9zG/zxUPUunWPAYaKvWOFviXcX/KqpjDqIIeWx -Gm0yNfyalHq476nRCf/0t9AH5X4Qy0KJSW5KfhQLG9X2z/UiJxwHKCwaWZtEEzPu -mGqvwhNXUOL/GuAZCJWPdWrUGM4kHHz3kw5v3UPNS2xA7yMtN9N1b8/pkTQ77XNk -DA4wngA5zc7Ae72SJDrY8XXqLfL4Nagkrn6AOhGK3/Ewvca6hkThMcHI0WF2AqFo -mo3iGUJzR5lOUx+4RiEBC5NNEZsE9GMNEiu8kYvCAS0FMKYmxFPGx1U/kiOeeuIw -W3sOEA== ------END CERTIFICATE----- diff --git a/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_public.pem b/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_public.pem deleted file mode 100644 index 2b2acadf6760..000000000000 --- a/mmv1/third_party/terraform/services/cloudiot/test-fixtures/rsa_public.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv6weC1aT16l2qS6qdYcy -7BOjzP7TwT9zUAiFhWpL256GRqC8yQRdqMsi68Q//762IUyu/qaHbEgQ8WRmQdVV -GDlxkBfrA/iXB2dgujq8jh0HWIV2ev3TerV3aUwvYUlrowhq027SX9U1hbufdGCM -uKsHiF05ErgNvEuR8XAkeJ/YV2DV2+sRq+Wg9y4RwUYbdchdFty1d5SX/s0Yqswg -yOG9VoCdR7baF22ughVR44aRm+83mgtqAZ4M+Rpe7JGRsUGY/pR391Toi0s8En15 -JGiAhqX2W0Uo/FZZry3yuqRfdHYENB+ADuyTMTrUaKZv7eua0lTBz5oom3jSF3gv -I7SQoLdK/jhEVOOq41IjB8D60Sgd69bD7yTI516yvZ/s3AyKzW6f6KnjdbCcZKKT -0GAePNLNhDYfSlA9bwJ8HQS2FenSpSTArKvGiVrsinJuNjbQdPuQHcpWf9x1m3GR -TMvF+TNYM/lp7IL2VMbJRfWPy1iWxm9F1Yr6dkHVoLP7ocYkNRHoPLut5E6IFJtK -lVI2NneUYJGnYSO+1xPV9TqlJeMNwr3uFMAN8N/oB3f4WWwuRYgR0L5g2A+Lvx+g -bbdl+Tb/0CNfslfSuDrFV8Z4n6gVwb9ZPGlNHCvnqRfLUpRFJwmR7UYvzi/E7rXJ -EDkK+tcnPkz2JtjdLKR7qVcCAwEAAQ== ------END PUBLIC KEY----- diff --git a/mmv1/third_party/terraform/services/cloudrun/data_source_cloud_run_service.go b/mmv1/third_party/terraform/services/cloudrun/data_source_cloud_run_service.go index f689e97107e4..c674b097723d 100644 --- a/mmv1/third_party/terraform/services/cloudrun/data_source_cloud_run_service.go +++ b/mmv1/third_party/terraform/services/cloudrun/data_source_cloud_run_service.go @@ -28,5 +28,14 @@ func dataSourceGoogleCloudRunServiceRead(d *schema.ResourceData, meta interface{ return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceCloudRunServiceRead(d, meta) + err = resourceCloudRunServiceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_domain_mapping_test.go b/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_domain_mapping_test.go index 743143b46db2..85232bd55fe3 100644 --- a/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_domain_mapping_test.go +++ b/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_domain_mapping_test.go @@ -29,7 +29,7 @@ func TestAccCloudRunDomainMapping_foregroundDeletion(t *testing.T) { ResourceName: "google_cloud_run_domain_mapping.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location", "status", "metadata.0.resource_version"}, + ImportStateVerifyIgnore: []string{"name", "location", "status", "metadata.0.labels", "metadata.0.terraform_labels", "metadata.0.resource_version"}, }, { Config: testAccCloudRunDomainMapping_cloudRunDomainMappingUpdated2(context), @@ -38,7 +38,7 @@ func TestAccCloudRunDomainMapping_foregroundDeletion(t *testing.T) { ResourceName: "google_cloud_run_domain_mapping.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location", "status", "metadata.0.resource_version"}, + ImportStateVerifyIgnore: []string{"name", "location", "status", "metadata.0.labels", "metadata.0.terraform_labels", "metadata.0.resource_version"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_service_test.go.erb b/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_service_test.go.erb index a0f84d5ebb97..7dcd04a4a01c 100644 --- a/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_service_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudrun/resource_cloud_run_service_test.go.erb @@ -27,7 +27,7 @@ func TestAccCloudRunService_cloudRunServiceUpdate(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdate(name, project, "50", "300"), @@ -36,7 +36,7 @@ func TestAccCloudRunService_cloudRunServiceUpdate(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) @@ -61,7 +61,7 @@ func TestAccCloudRunService_cloudRunServiceCreateHasStatus(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels"}, }, }, }) @@ -85,7 +85,7 @@ func TestAccCloudRunService_foregroundDeletion(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: " ", // very explicitly add a space, as the test runner fails if this is just "" @@ -97,7 +97,7 @@ func TestAccCloudRunService_foregroundDeletion(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) @@ -110,10 +110,14 @@ resource "google_cloud_run_service" "default" { location = "us-central1" metadata { - namespace = "%s" - annotations = { + namespace = "%s" + annotations = { generated-by = "magic-modules" } + labels = { + env = "foo" + default_expiration_ms = 3600000 + } } template { @@ -161,7 +165,7 @@ func TestAccCloudRunService_secretVolume(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithSecretVolume(name, project, "secret-"+acctest.RandString(t, 10), "secret-"+acctest.RandString(t, 11), "google_secret_manager_secret.secret2.secret_id"), @@ -170,7 +174,7 @@ func TestAccCloudRunService_secretVolume(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) @@ -285,7 +289,7 @@ func TestAccCloudRunService_secretEnvironmentVariable(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithSecretEnvVar(name, project, "secret-"+acctest.RandString(t, 10), "secret-"+acctest.RandString(t, 11), "google_secret_manager_secret.secret2.secret_id"), @@ -294,7 +298,7 @@ func TestAccCloudRunService_secretEnvironmentVariable(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) @@ -387,6 +391,314 @@ resource "google_cloud_run_service" "default" { `, secretName1, secretName2, name, secretRef, project) } +func TestAccCloudRunService_withProviderDefaultLabels(t *testing.T) { + // The test failed if VCR testing is enabled, because the cached provider config is used. + // With the cached provider config, any changes in the provider default labels will not be applied. + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunService_withProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "2"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_key1", "default_value1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "4"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.%", "1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.generated-by", "magic-modules"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_annotations.%", "6"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + { + Config: testAccCloudRunService_resourceLabelsOverridesProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "4"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.%", "1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.generated-by", "magic-modules-update"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_annotations.%", "6"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + { + Config: testAccCloudRunService_moveResourceLabelToProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "2"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "4"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + { + Config: testAccCloudRunService_resourceLabelsOverridesProviderDefaultLabels(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "4"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + { + Config: testAccCloudRunService_cloudRunServiceBasic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "1"), + + resource.TestCheckNoResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.%"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_annotations.%", "5"), + ), + }, + { + ResourceName: "google_cloud_run_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, + }, + }, + }) +} + +func TestAccCloudRunServiceMigration_withLabels(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + name := "tftest-cloudrun-" + acctest.RandString(t, 6) + project := envvar.GetTestProjectFromEnv() + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.83.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccCloudRunService_cloudRunServiceUpdate(name, project, "10", "600"), + ExternalProviders: oldVersion, + }, + { + Config: testAccCloudRunService_cloudRunServiceUpdate(name, project, "10", "600"), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.labels.%", "2"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_labels.%", "3"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.annotations.%", "1"), + resource.TestCheckResourceAttr("google_cloud_run_service.default", "metadata.0.effective_annotations.%", "6"), + ), + }, + }, + }) +} + +func testAccCloudRunService_withProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_cloud_run_service" "default" { + name = "tf-test-cloudrun-srv%{random_suffix}" + location = "us-central1" + + template { + spec { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + } + + metadata { + namespace = "%{project}" + annotations = { + generated-by = "magic-modules" + } + labels = { + env = "foo" + default_expiration_ms = 3600000 + } + } + + traffic { + percent = 100 + latest_revision = true + } +} +`, context) +} + +func testAccCloudRunService_resourceLabelsOverridesProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_cloud_run_service" "default" { + name = "tf-test-cloudrun-srv%{random_suffix}" + location = "us-central1" + + template { + spec { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + } + + metadata { + namespace = "%{project}" + annotations = { + generated-by = "magic-modules-update" + } + labels = { + env = "foo" + default_expiration_ms = 3600000 + default_key1 = "value1" + } + } + + traffic { + percent = 100 + latest_revision = true + } +} +`, context) +} + +func testAccCloudRunService_moveResourceLabelToProviderDefaultLabels(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + env = "foo" + } +} + +resource "google_cloud_run_service" "default" { + name = "tf-test-cloudrun-srv%{random_suffix}" + location = "us-central1" + + template { + spec { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + } + + metadata { + namespace = "%{project}" + annotations = { + generated-by = "magic-modules" + } + labels = { + default_expiration_ms = 3600000 + default_key1 = "value1" + } + } + + traffic { + percent = 100 + latest_revision = true + } +} +`, context) +} + +func testAccCloudRunService_cloudRunServiceBasic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_service" "default" { + name = "tf-test-cloudrun-srv%{random_suffix}" + location = "us-central1" + + template { + spec { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + } + + metadata { + namespace = "%{project}" + } + + traffic { + percent = 100 + latest_revision = true + } +} +`, context) +} + <% unless version == 'ga' -%> func TestAccCloudRunService_probes(t *testing.T) { @@ -406,7 +718,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithTCPStartupProbeAndHTTPLivenessProbe(name, project, "2", "1", "5", "2"), @@ -415,7 +727,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithEmptyHTTPStartupProbe(name, project), @@ -424,7 +736,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithHTTPStartupProbe(name, project), @@ -433,7 +745,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithEmptyGRPCLivenessProbe(name, project), @@ -442,7 +754,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, { Config: testAccCloudRunService_cloudRunServiceUpdateWithGRPCLivenessProbe(name, project), @@ -451,7 +763,7 @@ func TestAccCloudRunService_probes(t *testing.T) { ResourceName: "google_cloud_run_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "status.0.conditions"}, + ImportStateVerifyIgnore: []string{"metadata.0.resource_version", "metadata.0.annotations", "metadata.0.labels", "metadata.0.terraform_labels", "status.0.conditions"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go index 6b35cff4101e..5f4ea13f0a54 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go @@ -27,7 +27,7 @@ func TestAccCloudRunV2Job_cloudrunv2JobFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_job.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + ImportStateVerifyIgnore: []string{"location", "launch_stage", "labels", "terraform_labels", "annotations"}, }, { Config: testAccCloudRunV2Job_cloudrunv2JobFullUpdate(context), @@ -36,7 +36,7 @@ func TestAccCloudRunV2Job_cloudrunv2JobFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_job.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + ImportStateVerifyIgnore: []string{"location", "launch_stage", "labels", "terraform_labels", "annotations"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go index 803446aaf7ba..f127fd6416cb 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go @@ -30,7 +30,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels"}, }, { Config: testAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(context), @@ -39,7 +39,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels"}, }, }, }) @@ -227,7 +227,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceTCPProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, { Config: testAccCloudRunV2Service_cloudrunv2ServiceUpdateWithTCPStartupProbeAndHTTPLivenessProbe(context), @@ -236,7 +236,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceTCPProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, }, }) @@ -261,7 +261,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceHTTPProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, { Config: testAccCloudRunV2Service_cloudrunv2ServiceUpdateWithHTTPStartupProbe(context), @@ -270,7 +270,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceHTTPProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, }, }) @@ -296,7 +296,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceGRPCProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, { Config: testAccCloudRunV2Service_cloudRunServiceUpdateWithGRPCLivenessProbe(context), @@ -305,7 +305,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceGRPCProbesUpdate(t *testing.T) { ResourceName: "google_cloud_run_v2_service.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "annotations"}, }, // The following test steps of gRPC startup probe are expected to fail with startup probe check failures. // This is because, due to the unavailability of ready-to-use container images of a gRPC service that diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go index f536428c6d3c..cf52d32638d6 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment.go @@ -35,7 +35,20 @@ func dataSourceGoogleComposerEnvironmentRead(d *schema.ResourceData, meta interf } envName := d.Get("name").(string) - d.SetId(fmt.Sprintf("projects/%s/locations/%s/environments/%s", project, region, envName)) + id := fmt.Sprintf("projects/%s/locations/%s/environments/%s", project, region, envName) + d.SetId(id) + err = resourceComposerEnvironmentRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } - return resourceComposerEnvironmentRead(d, meta) + return nil } diff --git a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment_test.go b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment_test.go index b01db3b3e114..a81eff7b2284 100644 --- a/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment_test.go +++ b/mmv1/third_party/terraform/services/composer/data_source_google_composer_environment_test.go @@ -25,6 +25,8 @@ func TestAccDataSourceComposerEnvironment_basic(t *testing.T) { { Config: testAccDataSourceComposerEnvironment_basic(context), Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceState("data.google_composer_environment.test", + "google_composer_environment.test"), testAccCheckGoogleComposerEnvironmentMeta("data.google_composer_environment.test"), ), }, @@ -91,6 +93,9 @@ resource "google_composer_environment" "test" { image_version = "composer-1-airflow-2" } } + labels = { + my-label = "my-label-value" + } } // use a separate network to avoid conflicts with other tests running in parallel diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb index 82e7ea37ac2c..31ee4210c65d 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb @@ -9,6 +9,7 @@ import ( "time" "github.com/hashicorp/go-version" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -156,6 +157,12 @@ func ResourceComposerEnvironment() *schema.Resource { Delete: schema.DefaultTimeout(30 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + tpgresource.SetLabelsDiff, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -874,7 +881,24 @@ func ResourceComposerEnvironment() *schema.Resource { Type: schema.TypeMap, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `User-defined labels for this environment. The labels map can contain no more than 64 entries. Entries of the labels map are UTF8 strings that comply with the following restrictions: Label keys must be between 1 and 63 characters long and must conform to the following regular expression: [a-z]([-a-z0-9]*[a-z0-9])?. Label values must be between 0 and 63 characters long and must conform to the regular expression ([a-z]([-a-z0-9]*[a-z0-9])?)?. No more than 64 labels can be associated with a given environment. Both keys and values must be <= 128 bytes in size.`, + Description: `User-defined labels for this environment. The labels map can contain no more than 64 entries. Entries of the labels map are UTF8 strings that comply with the following restrictions: Label keys must be between 1 and 63 characters long and must conform to the following regular expression: [a-z]([-a-z0-9]*[a-z0-9])?. Label values must be between 0 and 63 characters long and must conform to the regular expression ([a-z]([-a-z0-9]*[a-z0-9])?)?. No more than 64 labels can be associated with a given environment. Both keys and values must be <= 128 bytes in size. + + **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.`, + }, + + "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}, + }, + + "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}, }, }, UseJSONNumber: true, @@ -900,7 +924,7 @@ func resourceComposerEnvironmentCreate(d *schema.ResourceData, meta interface{}) env := &composer.Environment{ Name: envName.ResourceName(), - Labels: tpgresource.ExpandLabels(d), + Labels: tpgresource.ExpandEffectiveLabels(d), Config: transformedConfig, } @@ -978,8 +1002,14 @@ func resourceComposerEnvironmentRead(d *schema.ResourceData, meta interface{}) e if err := d.Set("config", flattenComposerEnvironmentConfig(res.Config)); err != nil { return fmt.Errorf("Error setting Environment: %s", err) } - if err := d.Set("labels", res.Labels); err != nil { - return fmt.Errorf("Error setting Environment: %s", err) + if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { + return fmt.Errorf("Error setting Environment 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 Environment effective_labels: %s", err) } return nil } @@ -1222,8 +1252,8 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) } } - if d.HasChange("labels") { - patchEnv := &composer.Environment{Labels: tpgresource.ExpandLabels(d)} + if d.HasChange("effective_labels") { + patchEnv := &composer.Environment{Labels: tpgresource.ExpandEffectiveLabels(d)} err := resourceComposerEnvironmentPatchField("labels", userAgent, patchEnv, d, tfConfig) if err != nil { return err diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb index 3637d3da4e16..d02d58f7e181 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb @@ -100,6 +100,7 @@ func TestAccComposerEnvironment_update(t *testing.T) { ResourceName: "google_composer_environment.test", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, // This is a terrible clean-up step in order to get destroy to succeed, // due to dangling firewall rules left by the Composer Environment blocking network deletion. diff --git a/mmv1/third_party/terraform/services/compute/data_source_compute_health_check.go b/mmv1/third_party/terraform/services/compute/data_source_compute_health_check.go index e47066ea9b26..8703c6fcaf7f 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_compute_health_check.go +++ b/mmv1/third_party/terraform/services/compute/data_source_compute_health_check.go @@ -1,6 +1,8 @@ package compute 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" @@ -29,5 +31,14 @@ func dataSourceGoogleComputeHealthCheckRead(d *schema.ResourceData, meta interfa } d.SetId(id) - return resourceComputeHealthCheckRead(d, meta) + err = resourceComputeHealthCheckRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_compute_network_endpoint_group.go b/mmv1/third_party/terraform/services/compute/data_source_compute_network_endpoint_group.go index e12c2958b4d5..bb5d4db55efa 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_compute_network_endpoint_group.go +++ b/mmv1/third_party/terraform/services/compute/data_source_compute_network_endpoint_group.go @@ -27,6 +27,7 @@ func DataSourceGoogleComputeNetworkEndpointGroup() *schema.Resource { func dataSourceComputeNetworkEndpointGroupRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) + id := "" if name, ok := d.GetOk("name"); ok { project, err := tpgresource.GetProject(d, config) if err != nil { @@ -36,7 +37,8 @@ func dataSourceComputeNetworkEndpointGroupRead(d *schema.ResourceData, meta inte if err != nil { return err } - d.SetId(fmt.Sprintf("projects/%s/zones/%s/networkEndpointGroups/%s", project, zone, name.(string))) + id = fmt.Sprintf("projects/%s/zones/%s/networkEndpointGroups/%s", project, zone, name.(string)) + d.SetId(id) } else if selfLink, ok := d.GetOk("self_link"); ok { parsed, err := tpgresource.ParseNetworkEndpointGroupFieldValue(selfLink.(string), d, config) if err != nil { @@ -51,10 +53,20 @@ func dataSourceComputeNetworkEndpointGroupRead(d *schema.ResourceData, meta inte if err := d.Set("project", parsed.Project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/zones/%s/networkEndpointGroups/%s", parsed.Project, parsed.Zone, parsed.Name)) + id = fmt.Sprintf("projects/%s/zones/%s/networkEndpointGroups/%s", parsed.Project, parsed.Zone, parsed.Name) + d.SetId(id) } else { return errors.New("Must provide either `self_link` or `zone/name`") } - return resourceComputeNetworkEndpointGroupRead(d, meta) + err := resourceComputeNetworkEndpointGroupRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_compute_network_peering.go b/mmv1/third_party/terraform/services/compute/data_source_compute_network_peering.go index fed49bd6ba1e..edc7827e5fbf 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_compute_network_peering.go +++ b/mmv1/third_party/terraform/services/compute/data_source_compute_network_peering.go @@ -35,7 +35,17 @@ func dataSourceComputeNetworkPeeringRead(d *schema.ResourceData, meta interface{ if err != nil { return err } - d.SetId(fmt.Sprintf("%s/%s", networkFieldValue.Name, d.Get("name").(string))) + id := fmt.Sprintf("%s/%s", networkFieldValue.Name, d.Get("name").(string)) + d.SetId(id) - return resourceComputeNetworkPeeringRead(d, meta) + err = resourceComputeNetworkPeeringRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_address.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_address.go index f987531b05d7..f8faecfec4cd 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_address.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_address.go @@ -108,9 +108,11 @@ func dataSourceGoogleComputeAddressRead(d *schema.ResourceData, meta interface{} } name := d.Get("name").(string) + id := fmt.Sprintf("projects/%s/regions/%s/addresses/%s", project, region, name) + address, err := config.NewComputeClient(userAgent).Addresses.Get(project, region, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Address Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Address Not Found : %s", name), id) } if err := d.Set("address", address.Address); err != nil { @@ -147,7 +149,7 @@ func dataSourceGoogleComputeAddressRead(d *schema.ResourceData, meta interface{} return fmt.Errorf("Error setting region: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/addresses/%s", project, region, name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_bucket.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_bucket.go index b56c80f7c5bc..43e555c17d7b 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_bucket.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_bucket.go @@ -33,7 +33,17 @@ func dataSourceComputeBackendBucketRead(d *schema.ResourceData, meta interface{} return err } - d.SetId(fmt.Sprintf("projects/%s/global/backendBuckets/%s", project, backendBucketName)) + id := fmt.Sprintf("projects/%s/global/backendBuckets/%s", project, backendBucketName) + d.SetId(id) - return resourceComputeBackendBucketRead(d, meta) + err = resourceComputeBackendBucketRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_service.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_service.go index eac09d83ae6a..284dc85905f9 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_service.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_backend_service.go @@ -33,7 +33,17 @@ func dataSourceComputeBackendServiceRead(d *schema.ResourceData, meta interface{ return err } - d.SetId(fmt.Sprintf("projects/%s/global/backendServices/%s", project, serviceName)) + id := fmt.Sprintf("projects/%s/global/backendServices/%s", project, serviceName) + d.SetId(id) - return resourceComputeBackendServiceRead(d, meta) + err = resourceComputeBackendServiceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_default_service_account.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_default_service_account.go index 7789eb53fe50..1f6f45a40b76 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_default_service_account.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_default_service_account.go @@ -55,7 +55,7 @@ func dataSourceGoogleComputeDefaultServiceAccountRead(d *schema.ResourceData, me projectCompResource, err := config.NewComputeClient(userAgent).Projects.Get(project).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, "GCE default service account") + return transport_tpg.HandleDataSourceNotFoundError(err, d, "GCE default service account", fmt.Sprintf("%q GCE default service account", project)) } serviceAccountName, err := tpgresource.ServiceAccountFQN(projectCompResource.DefaultServiceAccount, d, config) @@ -65,7 +65,7 @@ func dataSourceGoogleComputeDefaultServiceAccountRead(d *schema.ResourceData, me sa, err := config.NewIamClient(userAgent).Projects.ServiceAccounts.Get(serviceAccountName).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName), serviceAccountName) } d.SetId(sa.Name) diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go index 9b660c8989e5..d96674df17d7 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk.go @@ -29,5 +29,18 @@ func dataSourceGoogleComputeDiskRead(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceComputeDiskRead(d, meta) + err = resourceComputeDiskRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk_test.go index 3ab5cb82b9eb..b978a3834c4c 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_disk_test.go @@ -32,7 +32,10 @@ func TestAccDataSourceGoogleComputeDisk_basic(t *testing.T) { func testAccDataSourceGoogleComputeDisk_basic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_compute_disk" "foo" { - name = "tf-test-compute-disk-%{random_suffix}" + name = "tf-test-compute-disk-%{random_suffix}" + labels = { + my-label = "my-label-value" + } } data "google_compute_disk" "foo" { diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go index 9dc06385eb78..3e7abe2278d1 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule.go @@ -39,7 +39,21 @@ func dataSourceGoogleComputeForwardingRuleRead(d *schema.ResourceData, meta inte return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/forwardingRules/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/regions/%s/forwardingRules/%s", project, region, name) + d.SetId(id) - return resourceComputeForwardingRuleRead(d, meta) + err = resourceComputeForwardingRuleRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule_test.go index 1238648064a5..b30bb8ce3056 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rule_test.go @@ -40,6 +40,9 @@ resource "google_compute_forwarding_rule" "foobar-fr" { name = "%s" port_range = "80-81" target = google_compute_target_pool.foobar-tp.self_link + labels = { + my-label = "my-label-value" + } } data "google_compute_forwarding_rule" "my_forwarding_rule" { diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_global_address.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_global_address.go index 14e6a8d1a8e0..44239ffdb887 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_global_address.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_global_address.go @@ -89,9 +89,11 @@ func dataSourceGoogleComputeGlobalAddressRead(d *schema.ResourceData, meta inter return err } name := d.Get("name").(string) + id := fmt.Sprintf("projects/%s/global/addresses/%s", project, name) + address, err := config.NewComputeClient(userAgent).GlobalAddresses.Get(project, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Global Address Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Global Address Not Found : %s", name), id) } if err := d.Set("address", address.Address); err != nil { @@ -124,6 +126,6 @@ func dataSourceGoogleComputeGlobalAddressRead(d *schema.ResourceData, meta inter if err := d.Set("project", project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/global/addresses/%s", project, name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ha_vpn_gateway.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ha_vpn_gateway.go index a5408b608dea..c658e4cdf376 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ha_vpn_gateway.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ha_vpn_gateway.go @@ -39,7 +39,17 @@ func dataSourceGoogleComputeHaVpnGatewayRead(d *schema.ResourceData, meta interf return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/vpnGateways/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/regions/%s/vpnGateways/%s", project, region, name) + d.SetId(id) - return resourceComputeHaVpnGatewayRead(d, meta) + err = resourceComputeHaVpnGatewayRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb index 19a49a5b4410..7b0734cf6455 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance.go.erb @@ -34,9 +34,11 @@ func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{ return err } + id := fmt.Sprintf("projects/%s/zones/%s/instances/%s", project, zone, name) + instance, err := config.NewComputeClient(userAgent).Instances.Get(project, zone, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Instance %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Instance %s", name), id) } md := flattenMetadataBeta(instance.Metadata) @@ -96,6 +98,10 @@ func dataSourceGoogleComputeInstanceRead(d *schema.ResourceData, meta interface{ return err } + if err := d.Set("terraform_labels", instance.Labels); err != nil { + return err + } + if instance.LabelFingerprint != "" { if err := d.Set("label_fingerprint", instance.LabelFingerprint); err != nil { return fmt.Errorf("Error setting label_fingerprint: %s", err) diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_group.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_group.go index 7be1e9c072fe..bbe683b335dd 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_group.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_group.go @@ -84,6 +84,7 @@ func DataSourceGoogleComputeInstanceGroup() *schema.Resource { func dataSourceComputeInstanceGroupRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) + id := "" if name, ok := d.GetOk("name"); ok { zone, err := tpgresource.GetZone(d, config) if err != nil { @@ -93,7 +94,7 @@ func dataSourceComputeInstanceGroupRead(d *schema.ResourceData, meta interface{} if err != nil { return err } - d.SetId(fmt.Sprintf("projects/%s/zones/%s/instanceGroups/%s", project, zone, name.(string))) + id = fmt.Sprintf("projects/%s/zones/%s/instanceGroups/%s", project, zone, name.(string)) } else if selfLink, ok := d.GetOk("self_link"); ok { parsed, err := tpgresource.ParseInstanceGroupFieldValue(selfLink.(string), d, config) if err != nil { @@ -108,10 +109,20 @@ func dataSourceComputeInstanceGroupRead(d *schema.ResourceData, meta interface{} if err := d.Set("project", parsed.Project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/zones/%s/instanceGroups/%s", parsed.Project, parsed.Zone, parsed.Name)) + id = fmt.Sprintf("projects/%s/zones/%s/instanceGroups/%s", parsed.Project, parsed.Zone, parsed.Name) } else { return errors.New("Must provide either `self_link` or `zone/name`") } + d.SetId(id) - return resourceComputeInstanceGroupRead(d, meta) + err := resourceComputeInstanceGroupRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template.go.erb index ee82da732187..bd0cdca09643 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template.go.erb @@ -92,7 +92,10 @@ func datasourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interfac func retrieveInstance(d *schema.ResourceData, meta interface{}, project, name string) error { d.SetId("projects/" + project + "/global/instanceTemplates/" + name) - return resourceComputeInstanceTemplateRead(d, meta) + if err := resourceComputeInstanceTemplateRead(d, meta); err != nil { + return err + } + return tpgresource.SetDataSourceLabels(d) } func retrieveInstanceFromUniqueId(d *schema.ResourceData, meta interface{}, project, self_link_unique string) error { @@ -100,7 +103,10 @@ func retrieveInstanceFromUniqueId(d *schema.ResourceData, meta interface{}, proj d.SetId(normalId) d.Set("self_link_unique", self_link_unique) - return resourceComputeInstanceTemplateRead(d, meta) + if err := resourceComputeInstanceTemplateRead(d, meta); err != nil { + return err + } + return tpgresource.SetDataSourceLabels(d) } // ByCreationTimestamp implements sort.Interface for []*InstanceTemplate based on diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template_test.go index 9ed0dffc7f67..ef8e82a26180 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_instance_template_test.go @@ -115,6 +115,9 @@ resource "google_compute_instance_template" "default" { network_interface { network = "default" } + labels = { + my-label = "my-label-value" + } } data "google_compute_instance_template" "default" { diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go index aa12f0b8423e..e0a6b9b63201 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_network.go @@ -59,9 +59,12 @@ func dataSourceGoogleComputeNetworkRead(d *schema.ResourceData, meta interface{} return err } name := d.Get("name").(string) + + id := fmt.Sprintf("projects/%s/global/networks/%s", project, name) + network, err := config.NewComputeClient(userAgent).Networks.Get(project, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Network Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Network Not Found : %s", name), id) } if err := d.Set("gateway_ipv4", network.GatewayIPv4); err != nil { return fmt.Errorf("Error setting gateway_ipv4: %s", err) @@ -75,6 +78,6 @@ func dataSourceGoogleComputeNetworkRead(d *schema.ResourceData, meta interface{} if err := d.Set("subnetworks_self_links", network.Subnetworks); err != nil { return fmt.Errorf("Error setting subnetworks_self_links: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/global/networks/%s", project, network.Name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_group.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_group.go.erb index 43c8499ce26b..b4820f426979 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_group.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_group.go.erb @@ -104,11 +104,11 @@ func dataSourceComputeRegionInstanceGroupRead(d *schema.ResourceData, meta inter if err != nil { return err } - + id := fmt.Sprintf("projects/%s/regions/%s/instanceGroups/%s", project, region, name) instanceGroup, err := config.NewComputeClient(userAgent).RegionInstanceGroups.Get( project, region, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Region Instance Group %q", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Region Instance Group %q", name), id) } members, err := config.NewComputeClient(userAgent).RegionInstanceGroups.ListInstances( @@ -129,7 +129,7 @@ func dataSourceComputeRegionInstanceGroupRead(d *schema.ResourceData, meta inter return fmt.Errorf("Error setting instances: %s", err) } } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/instanceGroups/%s", project, region, name)) + d.SetId(id) if err := d.Set("self_link", instanceGroup.SelfLink); err != nil { return fmt.Errorf("Error setting self_link: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template.go.erb index 6ebe245ba3ae..e69a2857ff38 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template.go.erb @@ -124,5 +124,8 @@ func datasourceComputeRegionInstanceTemplateRead(d *schema.ResourceData, meta in func retrieveInstances(d *schema.ResourceData, meta interface{}, project, region, name string) error { d.SetId("projects/" + project + "/regions/" + region + "/instanceTemplates/" + name) - return resourceComputeRegionInstanceTemplateRead(d, meta) + if err := resourceComputeRegionInstanceTemplateRead(d, meta); err != nil { + return err + } + return tpgresource.SetDataSourceLabels(d) } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template_test.go.erb index 6c32fddcb0d6..73a4d1fa09f0 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_instance_template_test.go.erb @@ -91,6 +91,9 @@ resource "google_compute_region_instance_template" "default" { network_interface { network = "default" } + labels = { + my-label = "my-label-value" + } } data "google_compute_region_instance_template" "default" { project = "%{project}" diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_network_endpoint_group.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_network_endpoint_group.go index 0147cd280d3d..3834a12ce9bf 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_network_endpoint_group.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_network_endpoint_group.go @@ -26,6 +26,7 @@ func DataSourceGoogleComputeRegionNetworkEndpointGroup() *schema.Resource { func dataSourceComputeRegionNetworkEndpointGroupRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) + id := "" if name, ok := d.GetOk("name"); ok { project, err := tpgresource.GetProject(d, config) if err != nil { @@ -36,7 +37,7 @@ func dataSourceComputeRegionNetworkEndpointGroupRead(d *schema.ResourceData, met return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", project, region, name.(string))) + id = fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", project, region, name.(string)) } else if selfLink, ok := d.GetOk("self_link"); ok { parsed, err := tpgresource.ParseNetworkEndpointGroupRegionalFieldValue(selfLink.(string), d, config) if err != nil { @@ -52,10 +53,19 @@ func dataSourceComputeRegionNetworkEndpointGroupRead(d *schema.ResourceData, met return fmt.Errorf("Error setting region: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", parsed.Project, parsed.Region, parsed.Name)) + id = fmt.Sprintf("projects/%s/regions/%s/networkEndpointGroups/%s", parsed.Project, parsed.Region, parsed.Name) } else { return errors.New("Must provide either `self_link` or `region/name`") } + d.SetId(id) + err := resourceComputeRegionNetworkEndpointGroupRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } - return resourceComputeRegionNetworkEndpointGroupRead(d, meta) + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_ssl_certificate.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_ssl_certificate.go index a42e9bc85491..17305595d0a6 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_ssl_certificate.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_ssl_certificate.go @@ -33,7 +33,16 @@ func dataSourceComputeRegionSslCertificateRead(d *schema.ResourceData, meta inte return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/sslCertificates/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/regions/%s/sslCertificates/%s", project, region, name) + d.SetId(id) - return resourceComputeRegionSslCertificateRead(d, meta) + err = resourceComputeRegionSslCertificateRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_resource_policy.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_resource_policy.go.erb index 3485a7051fe3..ae8d93646032 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_resource_policy.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_resource_policy.go.erb @@ -36,7 +36,17 @@ func dataSourceGoogleComputeResourcePolicyRead(d *schema.ResourceData, meta inte return err } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/resourcePolicies/%s", project, region, name)) + id := fmt.Sprintf("projects/%s/regions/%s/resourcePolicies/%s", project, region, name) + d.SetId(id) - return resourceComputeResourcePolicyRead(d, meta) + err = resourceComputeResourcePolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_router.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_router.go index 01f1ab0218e6..af235d576544 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_router.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_router.go @@ -1,6 +1,8 @@ package compute import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google/google/tpgresource" ) @@ -22,5 +24,13 @@ func dataSourceComputeRouterRead(d *schema.ResourceData, meta interface{}) error routerName := d.Get("name").(string) d.SetId(routerName) - return resourceComputeRouterRead(d, meta) + err := resourceComputeRouterRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", routerName) + } + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_router_nat.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_router_nat.go index b9f8fd1dae48..b74823b94b21 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_router_nat.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_router_nat.go @@ -31,5 +31,14 @@ func dataSourceGoogleComputeRouterNatRead(d *schema.ResourceData, meta interface } d.SetId(id) - return resourceComputeRouterNatRead(d, meta) + err = resourceComputeRouterNatRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot.go.erb index ea1d893715c2..a226612788c3 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_snapshot.go.erb @@ -107,7 +107,10 @@ func dataSourceGoogleComputeSnapshotRead(d *schema.ResourceData, meta interface{ func retrieveSnapshot(d *schema.ResourceData, meta interface{}, project, name string) error { d.SetId("projects/" + project + "/global/snapshots/" + name) d.Set("name", name) - return resourceComputeSnapshotRead(d, meta) + if err := resourceComputeSnapshotRead(d, meta); err != nil { + return err + } + return tpgresource.SetDataSourceLabels(d) } // ByCreationTimestamp implements sort.Interface for []*Snapshot based on diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_certificate.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_certificate.go index 20e9bf9d4110..31cc3426988d 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_certificate.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_certificate.go @@ -33,7 +33,17 @@ func dataSourceComputeSslCertificateRead(d *schema.ResourceData, meta interface{ } certificateName := d.Get("name").(string) - d.SetId(fmt.Sprintf("projects/%s/global/sslCertificates/%s", project, certificateName)) + id := fmt.Sprintf("projects/%s/global/sslCertificates/%s", project, certificateName) + d.SetId(id) - return resourceComputeSslCertificateRead(d, meta) + err = resourceComputeSslCertificateRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_policy.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_policy.go index 8710928be8e4..1266e7370867 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_policy.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_ssl_policy.go @@ -33,7 +33,17 @@ func datasourceComputeSslPolicyRead(d *schema.ResourceData, meta interface{}) er } policyName := d.Get("name").(string) - d.SetId(fmt.Sprintf("projects/%s/global/sslPolicies/%s", project, policyName)) + id := fmt.Sprintf("projects/%s/global/sslPolicies/%s", project, policyName) + d.SetId(id) - return resourceComputeSslPolicyRead(d, meta) + err = resourceComputeSslPolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_subnetwork.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_subnetwork.go.erb index 5652ba319f87..5af117f5893d 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_subnetwork.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_subnetwork.go.erb @@ -90,10 +90,11 @@ func dataSourceGoogleComputeSubnetworkRead(d *schema.ResourceData, meta interfac if err != nil { return err } + id := fmt.Sprintf("projects/%s/regions/%s/subnetworks/%s", project, region, name) subnetwork, err := config.NewComputeClient(userAgent).Subnetworks.Get(project, region, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Subnetwork Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Subnetwork Not Found : %s", name), id) } if err := d.Set("ip_cidr_range", subnetwork.IpCidrRange); err != nil { @@ -127,7 +128,7 @@ func dataSourceGoogleComputeSubnetworkRead(d *schema.ResourceData, meta interfac return fmt.Errorf("Error setting secondary_ip_range: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/subnetworks/%s", project, region, name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_vpn_gateway.go.erb b/mmv1/third_party/terraform/services/compute/data_source_google_compute_vpn_gateway.go.erb index e11c1711211b..ba7f79403e9d 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_compute_vpn_gateway.go.erb +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_vpn_gateway.go.erb @@ -72,12 +72,13 @@ func dataSourceGoogleComputeVpnGatewayRead(d *schema.ResourceData, meta interfac } name := d.Get("name").(string) + id := fmt.Sprintf("projects/%s/regions/%s/targetVpnGateways/%s", project, region, name) vpnGatewaysService := compute.NewTargetVpnGatewaysService(config.NewComputeClient(userAgent)) gateway, err := vpnGatewaysService.Get(project, region, name).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("VPN Gateway Not Found : %s", name)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("VPN Gateway Not Found : %s", name), id) } if err := d.Set("network", tpgresource.ConvertSelfLinkToV1(gateway.Network)); err != nil { return fmt.Errorf("Error setting network: %s", err) @@ -94,6 +95,6 @@ func dataSourceGoogleComputeVpnGatewayRead(d *schema.ResourceData, meta interfac if err := d.Set("project", project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/regions/%s/targetVpnGateways/%s", project, region, name)) + d.SetId(id) return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go index 1b25c01babef..24b840a9383e 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule.go @@ -33,7 +33,21 @@ func dataSourceGoogleComputeGlobalForwardingRuleRead(d *schema.ResourceData, met return err } - d.SetId(fmt.Sprintf("projects/%s/global/forwardingRules/%s", project, name)) + id := fmt.Sprintf("projects/%s/global/forwardingRules/%s", project, name) + d.SetId(id) - return resourceComputeGlobalForwardingRuleRead(d, meta) + err = resourceComputeGlobalForwardingRuleRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil } diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule_test.go index 70e2f3e6099d..bfb94ba7d822 100644 --- a/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule_test.go +++ b/mmv1/third_party/terraform/services/compute/data_source_google_global_compute_forwarding_rule_test.go @@ -32,6 +32,9 @@ resource "google_compute_global_forwarding_rule" "foobar-fr" { name = "%s" target = google_compute_target_http_proxy.default.id port_range = "80" + labels = { + my-label = "my-label-value" + } } resource "google_compute_target_http_proxy" "default" { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go b/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go deleted file mode 100644 index c9b07ec7579c..000000000000 --- a/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go +++ /dev/null @@ -1,162 +0,0 @@ -package compute_test - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-provider-google/google/acctest" -) - -func TestAccComputeAddress_networkTier(t *testing.T) { - t.Parallel() - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), - }, - { - ResourceName: "google_compute_address.foobar", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccComputeAddress_internal(t *testing.T) { - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccComputeAddress_internal(acctest.RandString(t, 10)), - }, - { - ResourceName: "google_compute_address.internal", - ImportState: true, - ImportStateVerify: true, - }, - - { - ResourceName: "google_compute_address.internal_with_subnet", - ImportState: true, - ImportStateVerify: true, - }, - - { - ResourceName: "google_compute_address.internal_with_subnet_and_address", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccComputeAddress_internal(i string) string { - return fmt.Sprintf(` -resource "google_compute_address" "internal" { - name = "tf-test-address-internal-%s" - address_type = "INTERNAL" - region = "us-east1" -} - -resource "google_compute_network" "default" { - name = "tf-test-network-test-%s" -} - -resource "google_compute_subnetwork" "foo" { - name = "subnetwork-test-%s" - ip_cidr_range = "10.0.0.0/16" - region = "us-east1" - network = google_compute_network.default.self_link -} - -resource "google_compute_address" "internal_with_subnet" { - name = "tf-test-address-internal-with-subnet-%s" - subnetwork = google_compute_subnetwork.foo.self_link - address_type = "INTERNAL" - region = "us-east1" -} - -// We can't test the address alone, because we don't know what IP range the -// default subnetwork uses. -resource "google_compute_address" "internal_with_subnet_and_address" { - name = "tf-test-address-internal-with-subnet-and-address-%s" - subnetwork = google_compute_subnetwork.foo.self_link - address_type = "INTERNAL" - address = "10.0.42.42" - region = "us-east1" -} -`, - i, // google_compute_address.internal name - i, // google_compute_network.default name - i, // google_compute_subnetwork.foo name - i, // google_compute_address.internal_with_subnet_name - i, // google_compute_address.internal_with_subnet_and_address name - ) -} - -func testAccComputeAddress_networkTier(i string) string { - return fmt.Sprintf(` -resource "google_compute_address" "foobar" { - name = "tf-test-address-%s" - network_tier = "STANDARD" -} -`, i) -} - -func TestAccComputeAddress_internalIpv6(t *testing.T) { - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccComputeAddress_internalIpv6(acctest.RandString(t, 10)), - }, - { - ResourceName: "google_compute_address.ipv6", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccComputeAddress_internalIpv6(i string) string { - return fmt.Sprintf(` -resource "google_compute_network" "default" { - name = "tf-test-network-test-%s" - enable_ula_internal_ipv6 = true - auto_create_subnetworks = false -} - -resource "google_compute_subnetwork" "foo" { - name = "subnetwork-test-%s" - ip_cidr_range = "10.0.0.0/16" - region = "us-east1" - network = google_compute_network.default.self_link - stack_type = "IPV4_IPV6" - ipv6_access_type = "INTERNAL" -} - -resource "google_compute_address" "ipv6" { - name = "tf-test-address-internal-ipv6-%s" - subnetwork = google_compute_subnetwork.foo.self_link - region = "us-east1" - address_type = "INTERNAL" - purpose = "GCE_ENDPOINT" - ip_version = "IPV6" -} -`, - i, // google_compute_network.default name - i, // google_compute_subnetwork.foo name - i, // google_compute_address.ipv6 - ) -} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go.erb new file mode 100644 index 000000000000..7f1ba5837901 --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/resource_compute_address_test.go.erb @@ -0,0 +1,481 @@ +<% autogen_exception -%> + +package compute_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccComputeAddress_networkTier(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + }, + }) +} + +func TestAccComputeAddress_internal(t *testing.T) { + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_internal(acctest.RandString(t, 10)), + }, + { + ResourceName: "google_compute_address.internal", + ImportState: true, + ImportStateVerify: true, + }, + + { + ResourceName: "google_compute_address.internal_with_subnet", + ImportState: true, + ImportStateVerify: true, + }, + + { + ResourceName: "google_compute_address.internal_with_subnet_and_address", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +<% unless version == "ga" -%> +func TestAccComputeAddress_networkTier_withLabels(t *testing.T) { + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeAddress_networkTier_withLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.default_expiration_ms", "3600000"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + // The labels field in the state is decided by the configuration. + // During importing, the configuration is unavailable, so the labels field in the state after importing is empty. + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_networkTier_withLabelsUpdate(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "bar"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "7200000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.env", "bar"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.default_expiration_ms", "7200000"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccComputeAddress_networkTier_withProvider5(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.75.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + ExternalProviders: oldVersion, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + { + Config: testAccComputeAddress_networkTier_withLabels(acctest.RandString(t, 10)), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.default_expiration_ms", "3600000"), + ), + }, + }, + }) +} + +func TestAccComputeAddress_withProviderDefaultLabels(t *testing.T) { + // The test failed if VCR testing is enabled, because the cached provider config is used. + // With the cached provider config, any changes in the provider default labels will not be applied. + acctest.SkipIfVcr(t) + t.Parallel() + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_withProviderDefaultLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_key1", "default_value1"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + // The labels field in the state is decided by the configuration. + // During importing, the configuration is unavailable, so the labels field in the state after importing is empty. + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_moveResourceLabelToProviderDefaultLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "2"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_expiration_ms", "3600000"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "labels.default_key1", "value1"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.%", "3"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_key1", "value1"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.env", "foo"), + resource.TestCheckResourceAttr("google_compute_address.foobar", "terraform_labels.default_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_compute_address.foobar", "effective_labels.%", "3"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_networkTier(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "labels.%"), + resource.TestCheckNoResourceAttr("google_compute_address.foobar", "effective_labels.%"), + ), + }, + { + ResourceName: "google_compute_address.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeAddress_networkTier_withLabels(i string) string { + return fmt.Sprintf(` +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + env = "foo" + default_expiration_ms = 3600000 + } +} +`, i) +} + +func testAccComputeAddress_networkTier_withLabelsUpdate(i string) string { + return fmt.Sprintf(` +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + env = "bar" + default_expiration_ms = 7200000 + } +} +`, i) +} + +func testAccComputeAddress_withProviderDefaultLabels(i string) string { + return fmt.Sprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + env = "foo" + default_expiration_ms = 3600000 + } +} +`, i) +} + +func testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(i string) string { + return fmt.Sprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + env = "foo" + default_expiration_ms = 3600000 + default_key1 = "value1" + } +} +`, i) +} + +func testAccComputeAddress_moveResourceLabelToProviderDefaultLabels(i string) string { + return fmt.Sprintf(` +provider "google" { + default_labels = { + default_key1 = "default_value1" + env = "foo" + } +} + +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" + + labels = { + default_expiration_ms = 3600000 + default_key1 = "value1" + } +} +`, i) +} +<% end -%> + +func testAccComputeAddress_internal(i string) string { + return fmt.Sprintf(` +resource "google_compute_address" "internal" { + name = "tf-test-address-internal-%s" + address_type = "INTERNAL" + region = "us-east1" +} + +resource "google_compute_network" "default" { + name = "tf-test-network-test-%s" +} + +resource "google_compute_subnetwork" "foo" { + name = "subnetwork-test-%s" + ip_cidr_range = "10.0.0.0/16" + region = "us-east1" + network = google_compute_network.default.self_link +} + +resource "google_compute_address" "internal_with_subnet" { + name = "tf-test-address-internal-with-subnet-%s" + subnetwork = google_compute_subnetwork.foo.self_link + address_type = "INTERNAL" + region = "us-east1" +} + +// We can't test the address alone, because we don't know what IP range the +// default subnetwork uses. +resource "google_compute_address" "internal_with_subnet_and_address" { + name = "tf-test-address-internal-with-subnet-and-address-%s" + subnetwork = google_compute_subnetwork.foo.self_link + address_type = "INTERNAL" + address = "10.0.42.42" + region = "us-east1" +} +`, + i, // google_compute_address.internal name + i, // google_compute_network.default name + i, // google_compute_subnetwork.foo name + i, // google_compute_address.internal_with_subnet_name + i, // google_compute_address.internal_with_subnet_and_address name + ) +} + +func testAccComputeAddress_networkTier(i string) string { + return fmt.Sprintf(` +resource "google_compute_address" "foobar" { + name = "tf-test-address-%s" + network_tier = "STANDARD" +} +`, i) +} + +func TestAccComputeAddress_internalIpv6(t *testing.T) { + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeAddress_internalIpv6(acctest.RandString(t, 10)), + }, + { + ResourceName: "google_compute_address.ipv6", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccComputeAddress_internalIpv6(i string) string { + return fmt.Sprintf(` +resource "google_compute_network" "default" { + name = "tf-test-network-test-%s" + enable_ula_internal_ipv6 = true + auto_create_subnetworks = false +} +resource "google_compute_subnetwork" "foo" { + name = "subnetwork-test-%s" + ip_cidr_range = "10.0.0.0/16" + region = "us-east1" + network = google_compute_network.default.self_link + stack_type = "IPV4_IPV6" + ipv6_access_type = "INTERNAL" +} +resource "google_compute_address" "ipv6" { + name = "tf-test-address-internal-ipv6-%s" + subnetwork = google_compute_subnetwork.foo.self_link + region = "us-east1" + address_type = "INTERNAL" + purpose = "GCE_ENDPOINT" + ip_version = "IPV6" +} +`, + i, // google_compute_network.default name + i, // google_compute_subnetwork.foo name + i, // google_compute_address.ipv6 + ) +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_attached_disk.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_attached_disk.go.erb index cec13a19f1da..9725498a1f7a 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_attached_disk.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_attached_disk.go.erb @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -35,6 +36,11 @@ func ResourceComputeAttachedDisk() *schema.Resource { Delete: schema.DefaultTimeout(300 * time.Second), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderZone, + ), + Schema: map[string]*schema.Schema{ "disk": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_disk_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_disk_test.go.erb index fb144f76c5bf..bfa49ae22ba2 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_disk_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_disk_test.go.erb @@ -343,6 +343,7 @@ func TestAccComputeDisk_update(t *testing.T) { ResourceName: "google_compute_disk.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeDisk_updated(diskName), @@ -351,6 +352,7 @@ func TestAccComputeDisk_update(t *testing.T) { ResourceName: "google_compute_disk.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -820,6 +822,7 @@ func TestAccComputeDisk_cloneDisk(t *testing.T) { ResourceName: "google_compute_disk.disk-clone", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -841,6 +844,7 @@ func TestAccComputeDisk_featuresUpdated(t *testing.T) { ResourceName: "google_compute_disk.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeDisk_featuresUpdated(diskName), @@ -849,6 +853,7 @@ func TestAccComputeDisk_featuresUpdated(t *testing.T) { ResourceName: "google_compute_disk.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_external_vpn_gateway_test.go b/mmv1/third_party/terraform/services/compute/resource_compute_external_vpn_gateway_test.go index 5f34bac1a1d4..808c39b5c08d 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_external_vpn_gateway_test.go +++ b/mmv1/third_party/terraform/services/compute/resource_compute_external_vpn_gateway_test.go @@ -26,9 +26,10 @@ func TestAccComputeExternalVPNGateway_updateLabels(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeExternalVPNGateway_updateLabels(rnd, "test-updated", "test-updated"), @@ -38,9 +39,10 @@ func TestAccComputeExternalVPNGateway_updateLabels(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_forwarding_rule_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_forwarding_rule_test.go.erb index c1445b640f3c..070d59e72f7c 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_forwarding_rule_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_forwarding_rule_test.go.erb @@ -27,6 +27,7 @@ func TestAccComputeForwardingRule_update(t *testing.T) { ResourceName: "google_compute_forwarding_rule.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, resource.TestStep{ Config: testAccComputeForwardingRule_update(poolName, ruleName), @@ -35,6 +36,7 @@ func TestAccComputeForwardingRule_update(t *testing.T) { ResourceName: "google_compute_forwarding_rule.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.erb index 364a2583e48c..e4f0036ae180 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_global_forwarding_rule_test.go.erb @@ -108,7 +108,7 @@ func TestAccComputeGlobalForwardingRule_labels(t *testing.T) { ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"port_range", "target"}, + ImportStateVerifyIgnore: []string{"port_range", "target", "labels", "terraform_labels"}, }, { Config: testAccComputeGlobalForwardingRule_labelsUpdated(fr, proxy, backend, hc, urlmap), @@ -117,7 +117,7 @@ func TestAccComputeGlobalForwardingRule_labels(t *testing.T) { ResourceName: "google_compute_global_forwarding_rule.forwarding_rule", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"port_range", "target"}, + ImportStateVerifyIgnore: []string{"port_range", "target", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_image_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_image_test.go.erb index 1bc622d85561..c75321a445c8 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_image_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_image_test.go.erb @@ -34,6 +34,7 @@ func TestAccComputeImage_withLicense(t *testing.T) { ResourceName: "google_compute_image.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -57,7 +58,6 @@ func TestAccComputeImage_update(t *testing.T) { testAccCheckComputeImageExists( t, "google_compute_image.foobar", &image), testAccCheckComputeImageContainsLabel(&image, "my-label", "my-label-value"), - testAccCheckComputeImageContainsLabel(&image, "empty-label", ""), ), }, { @@ -74,7 +74,7 @@ func TestAccComputeImage_update(t *testing.T) { ResourceName: "google_compute_image.foobar", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"raw_disk"}, + ImportStateVerifyIgnore: []string{"raw_disk", "labels", "terraform_labels"}, }, }, }) @@ -370,7 +370,6 @@ resource "google_compute_image" "foobar" { } labels = { my-label = "my-label-value" - empty-label = "" } } `, name) @@ -396,7 +395,6 @@ resource "google_compute_image" "foobar" { labels = { my-label = "my-label-value" - empty-label = "" } licenses = [ "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/licenses/debian-11-bullseye", diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb index 5cfc9ac2e394..f5081942521e 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb @@ -646,7 +646,24 @@ func ResourceComputeInstance() *schema.Resource { Type: schema.TypeMap, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, - Description: `A set of key/value label pairs assigned to the instance.`, + Description: `A set of key/value label pairs assigned to the instance. + + **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.`, + }, + + "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}, + }, + + "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}, }, "metadata": { @@ -1082,6 +1099,8 @@ be from 0 to 999,999,999 inclusive.`, }, }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderZone, customdiff.If( func(_ context.Context, d *schema.ResourceDiff, meta interface{}) bool { return d.HasChange("guest_accelerator") @@ -1090,6 +1109,7 @@ be from 0 to 999,999,999 inclusive.`, ), desiredStatusDiff, forceNewIfNetworkIPNotUpdatable, + tpgresource.SetLabelsDiff, ), UseJSONNumber: true, } @@ -1223,7 +1243,7 @@ func expandComputeInstance(project string, d *schema.ResourceData, config *trans NetworkPerformanceConfig: networkPerformanceConfig, Tags: resourceInstanceTags(d), Params: params, - Labels: tpgresource.ExpandLabels(d), + Labels: tpgresource.ExpandEffectiveLabels(d), ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})), GuestAccelerators: accels, MinCpuPlatform: d.Get("min_cpu_platform").(string), @@ -1437,7 +1457,15 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error } } - if err := d.Set("labels", instance.Labels); err != nil { + if err := tpgresource.SetLabels(instance.Labels, d, "labels"); err != nil { + return err + } + + if err := tpgresource.SetLabels(instance.Labels, d, "terraform_labels"); err != nil { + return err + } + + if err := d.Set("effective_labels", instance.Labels); err != nil { return err } @@ -1716,8 +1744,8 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err } } - if d.HasChange("labels") { - labels := tpgresource.ExpandLabels(d) + if d.HasChange("effective_labels") { + labels := tpgresource.ExpandEffectiveLabels(d) labelFingerprint := d.Get("label_fingerprint").(string) req := compute.InstancesSetLabelsRequest{Labels: labels, LabelFingerprint: labelFingerprint} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template.go.erb index 5d624b4b797e..fc61dd0c02c5 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_from_template.go.erb @@ -7,6 +7,7 @@ import ( "log" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -32,7 +33,10 @@ func ResourceComputeInstanceFromTemplate() *schema.Resource { Timeouts: ResourceComputeInstance().Timeouts, Schema: computeInstanceFromTemplateSchema(), - CustomizeDiff: ResourceComputeInstance().CustomizeDiff, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ResourceComputeInstance().CustomizeDiff, + ), UseJSONNumber: true, } } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group.go.erb index 856c24d3b6aa..e577bf497906 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group.go.erb @@ -12,6 +12,7 @@ import ( "google.golang.org/api/googleapi" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -36,6 +37,11 @@ func ResourceComputeInstanceGroup() *schema.Resource { Update: schema.DefaultTimeout(6 * time.Minute), Delete: schema.DefaultTimeout(6 * time.Minute), }, + + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderZone, + ), SchemaVersion: 2, MigrateState: resourceComputeInstanceGroupMigrateState, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb index ff22d40c0662..af04ff68e08d 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb @@ -9,6 +9,7 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -36,6 +37,10 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { Update: schema.DefaultTimeout(15 * time.Minute), Delete: schema.DefaultTimeout(15 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderZone, + ), Schema: map[string]*schema.Schema{ "base_instance_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb index c12cecaec2d9..d20b70d5b532 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb @@ -62,9 +62,11 @@ func ResourceComputeInstanceTemplate() *schema.Resource { }, SchemaVersion: 1, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, resourceComputeInstanceTemplateSourceImageCustomizeDiff, resourceComputeInstanceTemplateScratchDiskCustomizeDiff, resourceComputeInstanceTemplateBootDiskCustomizeDiff, + tpgresource.SetLabelsDiff, ), MigrateState: resourceComputeInstanceTemplateMigrateState, @@ -920,7 +922,27 @@ be from 0 to 999,999,999 inclusive.`, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, - Description: `A set of key/value label pairs to assign to instances created from this template,`, + Description: `A set of key/value label pairs to assign to instances created from this template. + + **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.`, + }, + + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Set: schema.HashString, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + ForceNew: true, + Set: schema.HashString, + 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}, }, "resource_policies": { @@ -1309,8 +1331,8 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac ReservationAffinity: reservationAffinity, } - if _, ok := d.GetOk("labels"); ok { - instanceProperties.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + instanceProperties.Labels = tpgresource.ExpandEffectiveLabels(d) } var itName string @@ -1634,10 +1656,16 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{ } } if instanceTemplate.Properties.Labels != nil { - if err := d.Set("labels", instanceTemplate.Properties.Labels); err != nil { + if err := tpgresource.SetLabels(instanceTemplate.Properties.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } } + if err := tpgresource.SetLabels(instanceTemplate.Properties.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + if err := d.Set("effective_labels", instanceTemplate.Properties.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err = d.Set("self_link", instanceTemplate.SelfLink); err != nil { return fmt.Errorf("Error setting self_link: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb index 97125daf0409..d5e7c5470303 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb @@ -51,6 +51,7 @@ func TestAccComputeInstanceTemplate_basic(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -77,6 +78,7 @@ func TestAccComputeInstanceTemplate_imageShorthand(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -133,6 +135,7 @@ func TestAccComputeInstanceTemplate_maintenance_interval(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeInstanceTemplate_basic(acctest.RandString(t, 10)), @@ -609,6 +612,7 @@ func TestAccComputeInstanceTemplate_EncryptKMS(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -940,6 +944,7 @@ func TestAccComputeInstanceTemplate_diskResourcePolicies(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -1017,6 +1022,7 @@ func TestAccComputeInstanceTemplate_managedEnvoy(t *testing.T) { ResourceName: "google_compute_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -1726,7 +1732,6 @@ resource "google_compute_image" "foobar" { } labels = { my-label = "my-label-value" - empty-label = "" } timeouts { create = "5m" diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb index c7c28b68bcf7..189f47d6d0d2 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb @@ -139,7 +139,7 @@ func TestAccComputeInstance_basic1(t *testing.T) { testAccCheckComputeInstanceHasConfiguredDeletionProtection(&instance, false), ), }, - computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status"}), + computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status", "labels", "terraform_labels"}), }, }) } @@ -1426,7 +1426,7 @@ func TestAccComputeInstance_forceChangeMachineTypeManually(t *testing.T) { ), ExpectNonEmptyPlan: true, }, - computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status"}), + computeInstanceImportStep("us-central1-a", instanceName, []string{"metadata.baz", "metadata.foo", "desired_status", "current_status", "labels", "terraform_labels"}), }, }) } @@ -6451,7 +6451,7 @@ resource "google_compute_node_group" "nodes" { name = "%s" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.nodetmpl.self_link } `, instance, nodeTemplate, nodeGroup) @@ -6520,7 +6520,7 @@ resource "google_compute_node_group" "nodes" { name = "%s" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.nodetmpl.self_link } `, instance, nodeTemplate, nodeGroup) @@ -6589,7 +6589,7 @@ resource "google_compute_node_group" "nodes" { name = "%s" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.nodetmpl.self_link } `, instance, nodeTemplate, nodeGroup) @@ -6652,7 +6652,7 @@ resource "google_compute_node_group" "nodes" { name = "%s" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.nodetmpl.self_link } `, instance, nodeTemplate, nodeGroup) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_node_group_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_node_group_test.go.erb index a09008450907..a713c5e78e49 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_node_group_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_node_group_test.go.erb @@ -8,12 +8,14 @@ import ( "strings" "time" + "regexp" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "github.com/hashicorp/terraform-provider-google/google/acctest" ) -func TestAccComputeNodeGroup_updateNodeTemplate(t *testing.T) { +func TestAccComputeNodeGroup_update(t *testing.T) { t.Parallel() groupName := fmt.Sprintf("group--%d", acctest.RandInt(t)) @@ -26,26 +28,47 @@ func TestAccComputeNodeGroup_updateNodeTemplate(t *testing.T) { CheckDestroy: testAccCheckComputeNodeGroupDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComputeNodeGroup_updateNodeTemplate(groupName, tmplPrefix, "tmpl1"), + Config: testAccComputeNodeGroup_update(groupName, tmplPrefix, "tmpl1"), Check: resource.ComposeTestCheckFunc( testAccCheckComputeNodeGroupCreationTimeBefore(&timeCreated), ), }, { - ResourceName: "google_compute_node_group.nodes", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_compute_node_group.nodes", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_size"}, }, { - Config: testAccComputeNodeGroup_updateNodeTemplate(groupName, tmplPrefix, "tmpl2"), + Config: testAccComputeNodeGroup_update2(groupName, tmplPrefix, "tmpl2"), Check: resource.ComposeTestCheckFunc( testAccCheckComputeNodeGroupCreationTimeBefore(&timeCreated), ), }, { - ResourceName: "google_compute_node_group.nodes", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_compute_node_group.nodes", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_size"}, + }, + }, + }) +} + +func TestAccComputeNodeGroup_fail(t *testing.T) { + t.Parallel() + + groupName := fmt.Sprintf("group--%d", acctest.RandInt(t)) + tmplPrefix := fmt.Sprintf("tmpl--%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeNodeGroupDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeNodeGroup_fail(groupName, tmplPrefix, "tmpl1"), + ExpectError: regexp.MustCompile("An initial_size or autoscaling_policy must be configured on node group creation."), }, }, }) @@ -86,7 +109,7 @@ func testAccCheckComputeNodeGroupCreationTimeBefore(prevTimeCreated *time.Time) } } -func testAccComputeNodeGroup_updateNodeTemplate(groupName, tmplPrefix, tmplToUse string) string { +func testAccComputeNodeGroup_update(groupName, tmplPrefix, tmplToUse string) string { return fmt.Sprintf(` resource "google_compute_node_template" "tmpl1" { name = "%s-first" @@ -105,8 +128,58 @@ resource "google_compute_node_group" "nodes" { zone = "us-central1-a" description = "example google_compute_node_group for Terraform Google Provider" - size = 0 + initial_size = 1 node_template = google_compute_node_template.%s.self_link } + `, tmplPrefix, tmplPrefix, groupName, tmplToUse) } + +func testAccComputeNodeGroup_update2(groupName, tmplPrefix, tmplToUse string) string { + return fmt.Sprintf(` +resource "google_compute_node_template" "tmpl1" { + name = "%s-first" + region = "us-central1" + node_type = "n1-node-96-624" +} + +resource "google_compute_node_template" "tmpl2" { + name = "%s-second" + region = "us-central1" + node_type = "n1-node-96-624" +} + +resource "google_compute_node_group" "nodes" { + name = "%s" + zone = "us-central1-a" + description = "example google_compute_node_group for Terraform Google Provider" + + autoscaling_policy { + mode = "ONLY_SCALE_OUT" + min_nodes = 1 + max_nodes = 10 + } + node_template = google_compute_node_template.%s.self_link +} + +`, tmplPrefix, tmplPrefix, groupName, tmplToUse) +} + +func testAccComputeNodeGroup_fail(groupName, tmplPrefix, tmplToUse string) string { + return fmt.Sprintf(` +resource "google_compute_node_template" "tmpl1" { + name = "%s-first" + region = "us-central1" + node_type = "n1-node-96-624" +} + +resource "google_compute_node_group" "nodes" { + name = "%s" + zone = "us-central1-a" + description = "example google_compute_node_group for Terraform Google Provider" + + node_template = google_compute_node_template.%s.self_link +} + +`, tmplPrefix, groupName, tmplToUse) +} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_project_default_network_tier.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_project_default_network_tier.go.erb index 2b838cd1bcad..3f1830c4c210 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_project_default_network_tier.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_project_default_network_tier.go.erb @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -34,6 +35,10 @@ func ResourceComputeProjectDefaultNetworkTier() *schema.Resource { Create: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + SchemaVersion: 0, Schema: map[string]*schema.Schema{ diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata.go.erb index 8186762eb938..8e8560b592f2 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata.go.erb @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -33,6 +34,10 @@ func ResourceComputeProjectMetadata() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + SchemaVersion: 0, Schema: map[string]*schema.Schema{ diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata_item.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata_item.go.erb index 5cf62dc29590..957476bb24fb 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata_item.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_project_metadata_item.go.erb @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -35,6 +36,10 @@ func ResourceComputeProjectMetadataItem() *schema.Resource { State: schema.ImportStatePassthrough, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "key": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_disk_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_disk_test.go.erb index 56b630b12777..f59bb99bcd46 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_disk_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_disk_test.go.erb @@ -44,6 +44,7 @@ func TestAccComputeRegionDisk_basic(t *testing.T) { ResourceName: "google_compute_region_disk.regiondisk", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeRegionDisk_basic(diskName, "name"), @@ -56,6 +57,7 @@ func TestAccComputeRegionDisk_basic(t *testing.T) { ResourceName: "google_compute_region_disk.regiondisk", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -84,6 +86,7 @@ func TestAccComputeRegionDisk_basicUpdate(t *testing.T) { ResourceName: "google_compute_region_disk.regiondisk", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeRegionDisk_basicUpdated(diskName, "self_link"), @@ -100,6 +103,7 @@ func TestAccComputeRegionDisk_basicUpdate(t *testing.T) { ResourceName: "google_compute_region_disk.regiondisk", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb index 9ac36c5455a8..d95ed976e020 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb @@ -9,6 +9,7 @@ import ( "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -37,6 +38,11 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Delete: schema.DefaultTimeout(15 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + ), + Schema: map[string]*schema.Schema{ "base_instance_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb index 9b34e90d6462..e2a2182a2e6f 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb @@ -34,9 +34,12 @@ func ResourceComputeRegionInstanceTemplate() *schema.Resource { }, SchemaVersion: 1, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, resourceComputeInstanceTemplateSourceImageCustomizeDiff, resourceComputeInstanceTemplateScratchDiskCustomizeDiff, resourceComputeInstanceTemplateBootDiskCustomizeDiff, + tpgresource.SetLabelsDiff, ), Timeouts: &schema.ResourceTimeout{ @@ -875,7 +878,27 @@ be from 0 to 999,999,999 inclusive.`, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, - Description: `A set of key/value label pairs to assign to instances created from this template,`, + Description: `A set of key/value label pairs to assign to instances created from this template, + + **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.`, + }, + + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Set: schema.HashString, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + ForceNew: true, + Set: schema.HashString, + 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}, }, "resource_policies": { @@ -1008,8 +1031,8 @@ func resourceComputeRegionInstanceTemplateCreate(d *schema.ResourceData, meta in ReservationAffinity: reservationAffinity, } - if _, ok := d.GetOk("labels"); ok { - instanceProperties.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + instanceProperties.Labels = tpgresource.ExpandEffectiveLabels(d) } var itName string @@ -1135,10 +1158,16 @@ func resourceComputeRegionInstanceTemplateRead(d *schema.ResourceData, meta inte } } if instanceProperties.Labels != nil { - if err := d.Set("labels", instanceProperties.Labels); err != nil { + if err := tpgresource.SetLabels(instanceProperties.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } } + if err := tpgresource.SetLabels(instanceProperties.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + if err := d.Set("effective_labels", instanceProperties.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err = d.Set("self_link", instanceTemplate["selfLink"]); err != nil { return fmt.Errorf("Error setting self_link: %s", err) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb index 1f05349a2411..bef9e29f4526 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template_test.go.erb @@ -50,6 +50,7 @@ func TestAccComputeRegionInstanceTemplate_basic(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -76,6 +77,7 @@ func TestAccComputeRegionInstanceTemplate_imageShorthand(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -767,6 +769,7 @@ func TestAccComputeRegionInstanceTemplate_maintenance_interval(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccComputeRegionInstanceTemplate_basic(acctest.RandString(t, 10)), @@ -894,6 +897,7 @@ func TestAccComputeRegionInstanceTemplate_diskResourcePolicies(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -971,6 +975,7 @@ func TestAccComputeRegionInstanceTemplate_managedEnvoy(t *testing.T) { ResourceName: "google_compute_region_instance_template.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -1657,7 +1662,6 @@ resource "google_compute_image" "foobar" { } labels = { my-label = "my-label-value" - empty-label = "" } timeouts { create = "5m" diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_router_interface.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_router_interface.go.erb index b8f48d98cffc..807a9c443d4d 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_router_interface.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_router_interface.go.erb @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "google.golang.org/api/googleapi" @@ -35,6 +36,11 @@ func ResourceComputeRouterInterface() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb index a96ca1fe6a8e..1d2c67fb7ab4 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_security_policy.go.erb @@ -12,6 +12,7 @@ import ( "time" "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -35,7 +36,10 @@ func ResourceComputeSecurityPolicy() *schema.Resource { Importer: &schema.ResourceImporter{ State: resourceSecurityPolicyStateImporter, }, - CustomizeDiff: rulesCustomizeDiff, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + rulesCustomizeDiff, + ), Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(8 * time.Minute), @@ -268,7 +272,6 @@ func ResourceComputeSecurityPolicy() *schema.Resource { "enforce_on_key": { Type: schema.TypeString, Optional: true, - Default: "ALL", Description: `Determines the key to enforce the rateLimitThreshold on`, ValidateFunc: validation.StringInSlice([]string{"ALL", "IP", "HTTP_HEADER", "XFF_IP", "HTTP_COOKIE", "HTTP_PATH", "SNI", "REGION_CODE", ""}, false), }, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_shared_vpc_service_project.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_shared_vpc_service_project.go.erb index 2ce95299eb93..3f5f9d7f74d2 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_shared_vpc_service_project.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_shared_vpc_service_project.go.erb @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "google.golang.org/api/googleapi" @@ -36,6 +37,10 @@ func ResourceComputeSharedVpcServiceProject() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "host_project": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_target_pool.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_target_pool.go.erb index 7a0bb638024f..ceb79c114082 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_target_pool.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_target_pool.go.erb @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "google.golang.org/api/googleapi" @@ -39,6 +40,11 @@ func ResourceComputeTargetPool() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.DefaultProviderRegion, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_vpn_tunnel_test.go b/mmv1/third_party/terraform/services/compute/resource_compute_vpn_tunnel_test.go index 5c23da0895eb..1f67d5adf3b5 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_vpn_tunnel_test.go +++ b/mmv1/third_party/terraform/services/compute/resource_compute_vpn_tunnel_test.go @@ -31,7 +31,6 @@ func TestAccComputeVpnTunnel_regionFromGateway(t *testing.T) { ResourceName: "google_compute_vpn_tunnel.foobar", ImportState: true, ImportStateVerify: true, - ImportStateIdPrefix: fmt.Sprintf("%s/%s/", envvar.GetTestProjectFromEnv(), region), ImportStateVerifyIgnore: []string{"shared_secret", "detailed_status"}, }, }, diff --git a/mmv1/third_party/terraform/services/compute/resource_usage_export_bucket.go.erb b/mmv1/third_party/terraform/services/compute/resource_usage_export_bucket.go.erb index e15258a3cc79..da1205fc1dca 100644 --- a/mmv1/third_party/terraform/services/compute/resource_usage_export_bucket.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_usage_export_bucket.go.erb @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" <% if version == "ga" -%> @@ -32,6 +33,10 @@ func ResourceProjectUsageBucket() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "bucket_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/container/data_source_google_container_cluster_test.go b/mmv1/third_party/terraform/services/container/data_source_google_container_cluster_test.go index a4725f5c2a61..81fa64c14c9f 100644 --- a/mmv1/third_party/terraform/services/container/data_source_google_container_cluster_test.go +++ b/mmv1/third_party/terraform/services/container/data_source_google_container_cluster_test.go @@ -26,6 +26,7 @@ func TestAccContainerClusterDatasource_zonal(t *testing.T) { "enable_autopilot": {}, "enable_tpu": {}, "pod_security_policy_config.#": {}, + "deletion_protection": {}, }, ), ), @@ -52,6 +53,7 @@ func TestAccContainerClusterDatasource_regional(t *testing.T) { "enable_autopilot": {}, "enable_tpu": {}, "pod_security_policy_config.#": {}, + "deletion_protection": {}, }, ), ), @@ -66,6 +68,7 @@ resource "google_container_cluster" "kubes" { name = "tf-test-cluster-%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } data "google_container_cluster" "kubes" { @@ -81,6 +84,7 @@ resource "google_container_cluster" "kubes" { name = "tf-test-cluster-%s" location = "us-central1" initial_node_count = 1 + deletion_protection = false } data "google_container_cluster" "kubes" { diff --git a/mmv1/third_party/terraform/services/container/node_config.go.erb b/mmv1/third_party/terraform/services/container/node_config.go.erb index e11ebef03c11..2c215fc8315c 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.erb +++ b/mmv1/third_party/terraform/services/container/node_config.go.erb @@ -32,8 +32,8 @@ func schemaLoggingVariant() *schema.Schema { return &schema.Schema{ Type: schema.TypeString, Optional: true, + Computed: true, Description: `Type of logging agent that is used as the default value for node pools in the cluster. Valid values include DEFAULT and MAX_THROUGHPUT.`, - Default: "DEFAULT", ValidateFunc: validation.StringInSlice([]string{"DEFAULT", "MAX_THROUGHPUT"}, false), } } @@ -411,18 +411,10 @@ func schemaNodeConfig() *schema.Schema { }, "taint": { - Type: schema.TypeList, - Optional: true, - // Computed=true because GKE Sandbox will automatically add taints to nodes that can/cannot run sandboxed pods. - Computed: true, - ForceNew: true, - // Legacy config mode allows explicitly defining an empty taint. - // See https://www.terraform.io/docs/configuration/attr-as-blocks.html - ConfigMode: schema.SchemaConfigModeAttr, + Type: schema.TypeList, + Optional: true, + ForceNew: true, Description: `List of Kubernetes taints to be applied to each node.`, - <% unless version.nil? || version == 'ga' -%> - DiffSuppressFunc: containerNodePoolTaintSuppress, - <% end -%> Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "key": { @@ -448,6 +440,31 @@ func schemaNodeConfig() *schema.Schema { }, }, + "effective_taints": { + Type: schema.TypeList, + Computed: true, + Description: `List of kubernetes taints applied to each node.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "key": { + Type: schema.TypeString, + Computed: true, + Description: `Key for taint.`, + }, + "value": { + Type: schema.TypeString, + Computed: true, + Description: `Value for taint.`, + }, + "effect": { + Type: schema.TypeString, + Computed: true, + Description: `Effect for taint.`, + }, + }, + }, + }, + "workload_metadata_config": { Computed: true, Type: schema.TypeList, @@ -897,12 +914,13 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { Value: data["value"].(string), Effect: data["effect"].(string), } + nodeTaints = append(nodeTaints, taint) } + nc.Taints = nodeTaints } - if v, ok := nodeConfig["workload_metadata_config"]; ok { nc.WorkloadMetadataConfig = expandWorkloadMetadataConfig(v) } @@ -1084,11 +1102,11 @@ func expandConfidentialNodes(configured interface{}) *container.ConfidentialNode } func flattenNodeConfigDefaults(c *container.NodeConfigDefaults) []map[string]interface{} { - result := make([]map[string]interface{}, 0, 1) + result := make([]map[string]interface{}, 0, 1) - if c == nil { - return result - } + if c == nil { + return result + } result = append(result, map[string]interface{}{}) @@ -1097,16 +1115,27 @@ func flattenNodeConfigDefaults(c *container.NodeConfigDefaults) []map[string]int <% unless version == 'ga' -%> result[0]["gcfs_config"] = flattenGcfsConfig(c.GcfsConfig) <% end -%> - return result + return result } -func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} { +// v == old state of `node_config` +func flattenNodeConfig(c *container.NodeConfig, v interface{}) []map[string]interface{} { config := make([]map[string]interface{}, 0, 1) if c == nil { return config } + // default to no prior taint state if there are any issues + oldTaints := []interface{}{} + oldNodeConfigSchemaContainer := v.([]interface{}) + if len(oldNodeConfigSchemaContainer) != 0 { + oldNodeConfigSchema := oldNodeConfigSchemaContainer[0].(map[string]interface{}) + if vt, ok := oldNodeConfigSchema["taint"]; ok && len(vt.([]interface{})) > 0 { + oldTaints = vt.([]interface{}) + } + } + config = append(config, map[string]interface{}{ "machine_type": c.MachineType, "disk_size_gb": c.DiskSizeGb, @@ -1126,26 +1155,27 @@ func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} { "metadata": c.Metadata, "image_type": c.ImageType, "labels": c.Labels, - "resource_labels": c.ResourceLabels, + "resource_labels": c.ResourceLabels, "tags": c.Tags, "preemptible": c.Preemptible, "spot": c.Spot, "min_cpu_platform": c.MinCpuPlatform, "shielded_instance_config": flattenShieldedInstanceConfig(c.ShieldedInstanceConfig), - "taint": flattenTaints(c.Taints), + "taint": flattenTaints(c.Taints, oldTaints), + "effective_taints": flattenEffectiveTaints(c.Taints), "workload_metadata_config": flattenWorkloadMetadataConfig(c.WorkloadMetadataConfig), <% unless version == 'ga' -%> - "sandbox_config": flattenSandboxConfig(c.SandboxConfig), + "sandbox_config": flattenSandboxConfig(c.SandboxConfig), "host_maintenance_policy": flattenHostMaintenancePolicy(c.HostMaintenancePolicy), <% end -%> "confidential_nodes": flattenConfidentialNodes(c.ConfidentialNodes), - "boot_disk_kms_key": c.BootDiskKmsKey, - "kubelet_config": flattenKubeletConfig(c.KubeletConfig), - "linux_node_config": flattenLinuxNodeConfig(c.LinuxNodeConfig), - "node_group": c.NodeGroup, + "boot_disk_kms_key": c.BootDiskKmsKey, + "kubelet_config": flattenKubeletConfig(c.KubeletConfig), + "linux_node_config": flattenLinuxNodeConfig(c.LinuxNodeConfig), + "node_group": c.NodeGroup, "advanced_machine_features": flattenAdvancedMachineFeaturesConfig(c.AdvancedMachineFeatures), - "sole_tenant_config": flattenSoleTenantConfig(c.SoleTenantConfig), - "fast_socket": flattenFastSocket(c.FastSocket), + "sole_tenant_config": flattenSoleTenantConfig(c.SoleTenantConfig), + "fast_socket": flattenFastSocket(c.FastSocket), }) if len(c.OauthScopes) > 0 { @@ -1276,7 +1306,31 @@ func flattenGKEReservationAffinity(c *container.ReservationAffinity) []map[strin return result } -func flattenTaints(c []*container.NodeTaint) []map[string]interface{} { +// flattenTaints records the set of taints already present in state. +func flattenTaints(c []*container.NodeTaint, oldTaints []interface{}) []map[string]interface{} { + taintKeys := map[string]struct{}{} + for _, raw := range oldTaints { + data := raw.(map[string]interface{}) + taintKey := data["key"].(string) + taintKeys[taintKey] = struct{}{} + } + + result := []map[string]interface{}{} + for _, taint := range c { + if _, ok := taintKeys[taint.Key]; ok { + result = append(result, map[string]interface{}{ + "key": taint.Key, + "value": taint.Value, + "effect": taint.Effect, + }) + } + } + + return result +} + +// flattenEffectiveTaints records the complete set of taints returned from GKE. +func flattenEffectiveTaints(c []*container.NodeTaint) []map[string]interface{} { result := []map[string]interface{}{} for _, taint := range c { result = append(result, map[string]interface{}{ @@ -1285,10 +1339,10 @@ func flattenTaints(c []*container.NodeTaint) []map[string]interface{} { "effect": taint.Effect, }) } + return result } - func flattenWorkloadMetadataConfig(c *container.WorkloadMetadataConfig) []map[string]interface{} { result := []map[string]interface{}{} if c != nil { @@ -1355,74 +1409,6 @@ func containerNodePoolLabelsSuppress(k, old, new string, d *schema.ResourceData) return true } - -func containerNodePoolTaintSuppress(k, old, new string, d *schema.ResourceData) bool { - // Node configs are embedded into multiple resources (container cluster and - // container node pool) so we determine the node config key dynamically. - idx := strings.Index(k, ".taint.") - if idx < 0 { - return false - } - - root := k[:idx] - - // Right now, GKE only applies its own out-of-band labels when you enable - // Sandbox. We only need to perform diff suppression in this case; - // otherwise, the default Terraform behavior is fine. - o, n := d.GetChange(root + ".sandbox_config.0.sandbox_type") - if o == nil || n == nil { - return false - } - - // Pull the entire changeset as a list rather than trying to deal with each - // element individually. - o, n = d.GetChange(root + ".taint") - if o == nil || n == nil { - return false - } - - type taintType struct { - Key, Value, Effect string - } - - taintSet := make(map[taintType]struct{}) - - // Add all new taints to set. - for _, raw := range n.([]interface{}) { - data := raw.(map[string]interface{}) - taint := taintType{ - Key: data["key"].(string), - Value: data["value"].(string), - Effect: data["effect"].(string), - } - taintSet[taint] = struct{}{} - } - - // Remove all current taints, skipping GKE-managed keys if not present in - // the new configuration. - for _, raw := range o.([]interface{}) { - data := raw.(map[string]interface{}) - taint := taintType{ - Key: data["key"].(string), - Value: data["value"].(string), - Effect: data["effect"].(string), - } - if _, ok := taintSet[taint]; ok { - delete(taintSet, taint) - } else if !strings.HasPrefix(taint.Key, "sandbox.gke.io/") && taint.Key != "kubernetes.io/arch" { - // User-provided taint removed in new configuration. - return false - } - } - - // If, at this point, the set still has elements, the new configuration - // added an additional taint. - if len(taintSet) > 0 { - return false - } - - return true -} <% end -%> func flattenKubeletConfig(c *container.NodeKubeletConfig) []map[string]interface{} { @@ -1497,4 +1483,4 @@ func flattenHostMaintenancePolicy(c *container.HostMaintenancePolicy) []map[stri return result } -<% end -%> \ No newline at end of file +<% end -%> diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index 422e35dc67fb..9adf200ff9e8 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -205,8 +205,15 @@ func ResourceContainerCluster() *schema.Resource { Delete: schema.DefaultTimeout(40 * time.Minute), }, - SchemaVersion: 1, + SchemaVersion: 2, MigrateState: resourceContainerClusterMigrateState, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceContainerClusterResourceV1().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceContainerClusterUpgradeV1, + Version: 1, + }, + }, Importer: &schema.ResourceImporter{ State: resourceContainerClusterStateImporter, @@ -262,6 +269,13 @@ func ResourceContainerCluster() *schema.Resource { Description: `The list of zones in which the cluster's nodes are located. Nodes must be in the region of their regional cluster or in the same region as their cluster's zone for zonal clusters. If this is specified for a zonal cluster, omit the cluster's zone.`, }, + "deletion_protection": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: `Whether or not to allow Terraform to destroy the instance. Defaults to true. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the cluster will fail.`, + }, + "addons_config": { Type: schema.TypeList, Optional: true, @@ -779,40 +793,31 @@ func ResourceContainerCluster() *schema.Resource { Description: ` Description of the cluster.`, }, - "enable_binary_authorization": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Deprecated: "Deprecated in favor of binary_authorization.", - Description: `Enable Binary Authorization for this cluster. If enabled, all container images will be validated by Google Binary Authorization.`, - ConflictsWith: []string{"enable_autopilot", "binary_authorization"}, - }, - "binary_authorization": { - Type: schema.TypeList, - Optional: true, - DiffSuppressFunc: BinaryAuthorizationDiffSuppress, - MaxItems: 1, - Description: "Configuration options for the Binary Authorization feature.", - ConflictsWith: []string{"enable_binary_authorization"}, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "enabled": { - Type: schema.TypeBool, - Optional: true, - Deprecated: "Deprecated in favor of evaluation_mode.", - Description: "Enable Binary Authorization for this cluster.", - ConflictsWith: []string{"enable_autopilot", "binary_authorization.0.evaluation_mode"}, - }, - "evaluation_mode": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validation.StringInSlice([]string{"DISABLED", "PROJECT_SINGLETON_POLICY_ENFORCE"}, false), - Description: "Mode of operation for Binary Authorization policy evaluation.", - ConflictsWith: []string{"binary_authorization.0.enabled"}, - }, - }, - }, - }, + "binary_authorization": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: BinaryAuthorizationDiffSuppress, + MaxItems: 1, + Description: "Configuration options for the Binary Authorization feature.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Deprecated: "Deprecated in favor of evaluation_mode.", + Description: "Enable Binary Authorization for this cluster.", + ConflictsWith: []string{"enable_autopilot", "binary_authorization.0.evaluation_mode"}, + }, + "evaluation_mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "PROJECT_SINGLETON_POLICY_ENFORCE"}, false), + Description: "Mode of operation for Binary Authorization policy evaluation.", + ConflictsWith: []string{"binary_authorization.0.enabled"}, + }, + }, + }, + }, "enable_kubernetes_alpha": { Type: schema.TypeBool, @@ -1376,11 +1381,10 @@ func ResourceContainerCluster() *schema.Resource { }, "provider": { Type: schema.TypeString, - Default: "PROVIDER_UNSPECIFIED", Optional: true, ValidateFunc: validation.StringInSlice([]string{"PROVIDER_UNSPECIFIED", "CALICO"}, false), DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("PROVIDER_UNSPECIFIED"), - Description: `The selected network policy provider. Defaults to PROVIDER_UNSPECIFIED.`, + Description: `The selected network policy provider.`, }, }, }, @@ -2151,7 +2155,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er PodSecurityPolicyConfig: expandPodSecurityPolicyConfig(d.Get("pod_security_policy_config")), <% end -%> Autoscaling: expandClusterAutoscaling(d.Get("cluster_autoscaling"), d), - BinaryAuthorization: expandBinaryAuthorization(d.Get("binary_authorization"), d.Get("enable_binary_authorization").(bool)), + BinaryAuthorization: expandBinaryAuthorization(d.Get("binary_authorization")), Autopilot: &container.Autopilot{ Enabled: d.Get("enable_autopilot").(bool), WorkloadPolicyConfig: workloadPolicyConfig, @@ -2328,12 +2332,11 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er } // For now PSC based cluster don't support `enable_private_endpoint` on `create`, but only on `update` API call. - // If cluster is PSC based and enable_private_endpoint is set to true we will ignore it on `create` call and update cluster right after creation. + // If cluster is PSC based and enable_private_endpoint is set to true we will ignore it on `create` call and update cluster right after creation. enablePrivateEndpointPSCCluster := isEnablePrivateEndpointPSCCluster(cluster) if enablePrivateEndpointPSCCluster { cluster.PrivateClusterConfig.EnablePrivateEndpoint = false } - req := &container.CreateClusterRequest{ Cluster: cluster, @@ -2373,29 +2376,26 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er if err := d.Set("operation", op.Name); err != nil { return fmt.Errorf("Error setting operation: %s", err) } + return nil default: // leaving default case to ensure this is non blocking } + // Try a GET on the cluster so we can see the state in debug logs. This will help classify error states. clusterGetCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.Get(containerClusterFullName(project, location, clusterName)) if config.UserProjectOverride { clusterGetCall.Header().Add("X-Goog-User-Project", project) } + _, getErr := clusterGetCall.Do() if getErr != nil { log.Printf("[WARN] Cluster %s was created in an error state and not found", clusterName) d.SetId("") } - if deleteErr := cleanFailedContainerCluster(d, meta); deleteErr != nil { - log.Printf("[WARN] Unable to clean up cluster from failed creation: %s", deleteErr) - // Leave ID set as the cluster likely still exists and should not be removed from state yet. - } else { - log.Printf("[WARN] Verified failed creation of cluster %s was cleaned up", d.Id()) - d.SetId("") - } - // The resource didn't actually create + // Don't clear cluster id, this will taint the resource + log.Printf("[WARN] GKE cluster %s was created in an error state, and has been marked as tainted", clusterName) return waitErr } @@ -2540,14 +2540,8 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro d.SetId("") } - if deleteErr := cleanFailedContainerCluster(d, meta); deleteErr != nil { - log.Printf("[WARN] Unable to clean up cluster from failed creation: %s", deleteErr) - // Leave ID set as the cluster likely still exists and should not be removed from state yet. - } else { - log.Printf("[WARN] Verified failed creation of cluster %s was cleaned up", d.Id()) - d.SetId("") - } - // The resource didn't actually create + // Don't clear cluster id, this will taint the resource + log.Printf("[WARN] GKE cluster %s was created in an error state, and has been marked as tainted", clusterName) return waitErr } } @@ -2633,19 +2627,10 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro } if err := d.Set("cluster_autoscaling", flattenClusterAutoscaling(cluster.Autoscaling)); err != nil { return err - } - binauthz_enabled := d.Get("binary_authorization.0.enabled").(bool) - legacy_binauthz_enabled := d.Get("enable_binary_authorization").(bool) - if !binauthz_enabled { - if err := d.Set("enable_binary_authorization", cluster.BinaryAuthorization != nil && cluster.BinaryAuthorization.Enabled); err != nil { - return fmt.Errorf("Error setting enable_binary_authorization: %s", err) - } - } - if !legacy_binauthz_enabled { - if err := d.Set("binary_authorization", flattenBinaryAuthorization(cluster.BinaryAuthorization)); err != nil { - return err - } - } + } + if err := d.Set("binary_authorization", flattenBinaryAuthorization(cluster.BinaryAuthorization)); err != nil { + return err + } if autopilot := cluster.Autopilot; autopilot != nil { if err := d.Set("enable_autopilot", autopilot.Enabled); err != nil { return fmt.Errorf("Error setting enable_autopilot: %s", err) @@ -2710,7 +2695,7 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error setting default_max_pods_per_node: %s", err) } } - if err := d.Set("node_config", flattenNodeConfig(cluster.NodeConfig)); err != nil { + if err := d.Set("node_config", flattenNodeConfig(cluster.NodeConfig, d.Get("node_config"))); err != nil { return err } if err := d.Set("project", project); err != nil { @@ -2997,7 +2982,7 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er if d.HasChange("binary_authorization") { req := &container.UpdateClusterRequest{ Update: &container.ClusterUpdate{ - DesiredBinaryAuthorization: expandBinaryAuthorization(d.Get("binary_authorization"), d.Get("enable_binary_authorization").(bool)), + DesiredBinaryAuthorization: expandBinaryAuthorization(d.Get("binary_authorization")), }, } @@ -4092,6 +4077,9 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er } func resourceContainerClusterDelete(d *schema.ResourceData, meta interface{}) error { + if d.Get("deletion_protection").(bool) { + return fmt.Errorf("Cannot destroy cluster because deletion_protection is set to true. Set it to false to proceed with instance deletion.") + } config := meta.(*transport_tpg.Config) userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { @@ -4162,52 +4150,6 @@ func resourceContainerClusterDelete(d *schema.ResourceData, meta interface{}) er return nil } -// cleanFailedContainerCluster deletes clusters that failed but were -// created in an error state. Similar to resourceContainerClusterDelete -// but implemented in separate function as it doesn't try to lock already -// locked cluster state, does different error handling, and doesn't do retries. -func cleanFailedContainerCluster(d *schema.ResourceData, meta interface{}) error { - config := meta.(*transport_tpg.Config) - - project, err := tpgresource.GetProject(d, config) - if err != nil { - return err - } - - location, err := tpgresource.GetLocation(d, config) - if err != nil { - return err - } - - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) - if err != nil { - return err - } - - clusterName := d.Get("name").(string) - fullName := containerClusterFullName(project, location, clusterName) - - log.Printf("[DEBUG] Cleaning up failed GKE cluster %s", d.Get("name").(string)) - clusterDeleteCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.Delete(fullName) - if config.UserProjectOverride { - clusterDeleteCall.Header().Add("X-Goog-User-Project", project) - } - op, err := clusterDeleteCall.Do() - if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Container Cluster %q", d.Get("name").(string))) - } - - // Wait until it's deleted - waitErr := ContainerOperationWait(config, op, project, location, "deleting GKE cluster", userAgent, d.Timeout(schema.TimeoutDelete)) - if waitErr != nil { - return waitErr - } - - log.Printf("[INFO] GKE cluster %s has been deleted", d.Id()) - d.SetId("") - return nil -} - var containerClusterRestingStates = RestingStates{ "RUNNING": ReadyState, "DEGRADED": ErrorState, @@ -4821,11 +4763,11 @@ func expandNotificationConfig(configured interface{}) *container.NotificationCon } } -func expandBinaryAuthorization(configured interface{}, legacy_enabled bool) *container.BinaryAuthorization { +func expandBinaryAuthorization(configured interface{}) *container.BinaryAuthorization { l := configured.([]interface{}) if len(l) == 0 || l[0] == nil { return &container.BinaryAuthorization{ - Enabled: legacy_enabled, + Enabled: false, ForceSendFields: []string{"Enabled"}, } } @@ -6092,6 +6034,11 @@ func resourceContainerClusterStateImporter(d *schema.ResourceData, meta interfac if err := d.Set("location", location); err != nil { return nil, fmt.Errorf("Error setting location: %s", err) } + + if err := d.Set("deletion_protection", true); err != nil { + return nil, fmt.Errorf("Error setting deletion_protection: %s", err) + } + if _, err := containerClusterAwaitRestingState(config, project, location, clusterName, userAgent, d.Timeout(schema.TimeoutCreate)); err != nil { return nil, err } diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_migrate.go b/mmv1/third_party/terraform/services/container/resource_container_cluster_migrate.go index 2b088ce0321f..58f986e29309 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_migrate.go +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_migrate.go @@ -21,6 +21,9 @@ func resourceContainerClusterMigrateState( case 0: log.Println("[INFO] Found Container Cluster State v0; migrating to v1") return migrateClusterStateV0toV1(is) + case 1: + log.Println("[INFO] Found Container Cluster State v1 in legacy migration function; returning as non-op") + return is, nil default: return is, fmt.Errorf("Unexpected schema version: %d", v) } diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb new file mode 100644 index 000000000000..2693e43a8f54 --- /dev/null +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb @@ -0,0 +1,1844 @@ +<% autogen_exception -%> +package container + +import ( + "context" + "fmt" + "log" + "regexp" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + "github.com/hashicorp/terraform-provider-google/google/verify" +) + +func ResourceContainerClusterUpgradeV1(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + log.Printf("[DEBUG] Applying container cluster migration to schema version V2.") + + rawState["deletion_protection"] = true + return rawState, nil +} + + +func resourceContainerClusterResourceV1() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the cluster, unique within the project and location.`, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if len(value) > 40 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 40 characters", k)) + } + if !regexp.MustCompile("^[a-z0-9-]+$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q can only contain lowercase letters, numbers and hyphens", k)) + } + if !regexp.MustCompile("^[a-z]").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must start with a letter", k)) + } + if !regexp.MustCompile("[a-z0-9]$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must end with a number or a letter", k)) + } + return + }, + }, + + "operation": { + Type: schema.TypeString, + Computed: true, + }, + + "location": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The location (region or zone) in which the cluster master will be created, as well as the default node location. If you specify a zone (such as us-central1-a), the cluster will be a zonal cluster with a single cluster master. If you specify a region (such as us-west1), the cluster will be a regional cluster with multiple masters spread across zones in the region, and with default node locations in those zones as well.`, + }, + + "node_locations": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The list of zones in which the cluster's nodes are located. Nodes must be in the region of their regional cluster or in the same region as their cluster's zone for zonal clusters. If this is specified for a zonal cluster, omit the cluster's zone.`, + }, + + "addons_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The configuration for addons supported by GKE.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "http_load_balancing": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the HTTP (L7) load balancing controller addon, which makes it easy to set up HTTP load balancers for services in a cluster. It is enabled by default; set disabled = true to disable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "horizontal_pod_autoscaling": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Horizontal Pod Autoscaling addon, which increases or decreases the number of replica pods a replication controller has based on the resource usage of the existing pods. It ensures that a Heapster pod is running in the cluster, which is also used by the Cloud Monitoring service. It is enabled by default; set disabled = true to disable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "network_policy_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `Whether we should enable the network policy addon for the master. This must be enabled in order to enable network policy for the nodes. To enable this, you must also define a network_policy block, otherwise nothing will happen. It can only be disabled if the nodes already do not have network policies enabled. Defaults to disabled; set disabled = false to enable.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "gcp_filestore_csi_driver_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Filestore CSI driver addon, which allows the usage of filestore instance as volumes. Defaults to disabled; set enabled = true to enable.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "cloudrun_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the CloudRun addon. It is disabled by default. Set disabled = false to enable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + "load_balancer_type": { + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"LOAD_BALANCER_TYPE_INTERNAL"}, false), + Optional: true, + }, + }, + }, + }, + "dns_cache_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the NodeLocal DNSCache addon. It is disabled by default. Set enabled = true to enable.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "gce_persistent_disk_csi_driver_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `Whether this cluster should enable the Google Compute Engine Persistent Disk Container Storage Interface (CSI) Driver. Set enabled = true to enable. The Compute Engine persistent disk CSI Driver is enabled by default on newly created clusters for the following versions: Linux clusters: GKE version 1.18.10-gke.2100 or later, or 1.19.3-gke.2100 or later.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "gke_backup_agent_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Backup for GKE Agent addon. It is disabled by default. Set enabled = true to enable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "gcs_fuse_csi_driver_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the GCS Fuse CSI driver addon, which allows the usage of gcs bucket as volumes. Defaults to disabled; set enabled = true to enable.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + <% unless version == 'ga' -%> + "istio_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The status of the Istio addon.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + Description: `The status of the Istio addon, which makes it easy to set up Istio for services in a cluster. It is disabled by default. Set disabled = false to enable.`, + }, + "auth": { + Type: schema.TypeString, + Optional: true, + // We can't use a Terraform-level default because it won't be true when the block is disabled: true + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("AUTH_NONE"), + ValidateFunc: validation.StringInSlice([]string{"AUTH_NONE", "AUTH_MUTUAL_TLS"}, false), + Description: `The authentication type between services in Istio. Available options include AUTH_MUTUAL_TLS.`, + }, + }, + }, + }, + "kalm_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `Configuration for the KALM addon, which manages the lifecycle of k8s. It is disabled by default; Set enabled = true to enable.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + <% end -%> + "config_connector_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + AtLeastOneOf: addonsConfigKeys, + MaxItems: 1, + Description: `The of the Config Connector addon.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + }, + }, + }, + + "cluster_autoscaling": { + Type: schema.TypeList, + MaxItems: 1, + // This field is Optional + Computed because we automatically set the + // enabled value to false if the block is not returned in API responses. + Optional: true, + Computed: true, + Description: `Per-cluster configuration of Node Auto-Provisioning with Cluster Autoscaler to automatically adjust the size of the cluster and create/delete node pools based on the current needs of the cluster's workload. See the guide to using Node Auto-Provisioning for more details.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + ConflictsWith: []string{"enable_autopilot"}, + Description: `Whether node auto-provisioning is enabled. Resource limits for cpu and memory must be defined to enable node auto-provisioning.`, + }, + "resource_limits": { + Type: schema.TypeList, + Optional: true, + ConflictsWith: []string{"enable_autopilot"}, + DiffSuppressFunc: suppressDiffForAutopilot, + Description: `Global constraints for machine resources in the cluster. Configuring the cpu and memory types is required if node auto-provisioning is enabled. These limits will apply to node pool autoscaling in addition to node auto-provisioning.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resource_type": { + Type: schema.TypeString, + Required: true, + Description: `The type of the resource. For example, cpu and memory. See the guide to using Node Auto-Provisioning for a list of types.`, + }, + "minimum": { + Type: schema.TypeInt, + Optional: true, + Description: `Minimum amount of the resource in the cluster.`, + }, + "maximum": { + Type: schema.TypeInt, + Optional: true, + Description: `Maximum amount of the resource in the cluster.`, + }, + }, + }, + }, + "auto_provisioning_defaults": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Contains defaults for a node pool created by NAP.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "oauth_scopes": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + DiffSuppressFunc: containerClusterAddedScopesSuppress, + Description: `Scopes that are used by NAP when creating node pools.`, + }, + "service_account": { + Type: schema.TypeString, + Optional: true, + Default: "default", + Description: `The Google Cloud Platform Service Account to be used by the node VMs.`, + }, + "disk_size": { + Type: schema.TypeInt, + Optional: true, + Default: 100, + Description: `Size of the disk attached to each node, specified in GB. The smallest allowed disk size is 10GB.`, + DiffSuppressFunc: suppressDiffForAutopilot, + ValidateFunc: validation.IntAtLeast(10), + }, + "disk_type": { + Type: schema.TypeString, + Optional: true, + Default: "pd-standard", + Description: `Type of the disk attached to each node.`, + DiffSuppressFunc: suppressDiffForAutopilot, + ValidateFunc: validation.StringInSlice([]string{"pd-standard", "pd-ssd", "pd-balanced"}, false), + }, + "image_type": { + Type: schema.TypeString, + Optional: true, + Default: "COS_CONTAINERD", + Description: `The default image type used by NAP once a new node pool is being created.`, + DiffSuppressFunc: suppressDiffForAutopilot, + ValidateFunc: validation.StringInSlice([]string{"COS_CONTAINERD", "COS", "UBUNTU_CONTAINERD", "UBUNTU"}, false), + }, + "min_cpu_platform": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("automatic"), + Description: `Minimum CPU platform to be used by this instance. The instance may be scheduled on the specified or newer CPU platform. Applicable values are the friendly names of CPU platforms, such as Intel Haswell.`, + }, + "boot_disk_kms_key": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `The Customer Managed Encryption Key used to encrypt the boot disk attached to each node in the node pool.`, + }, + "shielded_instance_config": &schema.Schema{ + Type: schema.TypeList, + Optional: true, + Description: `Shielded Instance options.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `Defines whether the instance has Secure Boot enabled.`, + AtLeastOneOf: []string{ + "cluster_autoscaling.0.auto_provisioning_defaults.0.shielded_instance_config.0.enable_secure_boot", + "cluster_autoscaling.0.auto_provisioning_defaults.0.shielded_instance_config.0.enable_integrity_monitoring", + }, + }, + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: `Defines whether the instance has integrity monitoring enabled.`, + AtLeastOneOf: []string{ + "cluster_autoscaling.0.auto_provisioning_defaults.0.shielded_instance_config.0.enable_secure_boot", + "cluster_autoscaling.0.auto_provisioning_defaults.0.shielded_instance_config.0.enable_integrity_monitoring", + }, + }, + }, + }, + }, + "management": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `NodeManagement configuration for this NodePool.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_upgrade": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Specifies whether node auto-upgrade is enabled for the node pool. If enabled, node auto-upgrade helps keep the nodes in your node pool up to date with the latest release version of Kubernetes.`, + }, + "auto_repair": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Specifies whether the node auto-repair is enabled for the node pool. If enabled, the nodes in this node pool will be monitored and, if they fail health checks too many times, an automatic repair action will be triggered.`, + }, + "upgrade_options": { + Type: schema.TypeList, + Computed: true, + Description: `Specifies the Auto Upgrade knobs for the node pool.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "auto_upgrade_start_time": { + Type: schema.TypeString, + Computed: true, + Description: `This field is set when upgrades are about to commence with the approximate start time for the upgrades, in RFC3339 text format.`, + }, + "description": { + Type: schema.TypeString, + Computed: true, + Description: `This field is set when upgrades are about to commence with the description of the upgrade.`, + }, + }, + }, + }, + }, + }, + }, + "upgrade_settings": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the upgrade settings for NAP created node pools`, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "max_surge": { + Type: schema.TypeInt, + Optional: true, + Description: `The maximum number of nodes that can be created beyond the current size of the node pool during the upgrade process.`, + }, + "max_unavailable": { + Type: schema.TypeInt, + Optional: true, + Description: `The maximum number of nodes that can be simultaneously unavailable during the upgrade process.`, + }, + "strategy": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Update strategy of the node pool.`, + ValidateFunc: validation.StringInSlice([]string{"NODE_POOL_UPDATE_STRATEGY_UNSPECIFIED", "BLUE_GREEN", "SURGE"}, false), + }, + "blue_green_settings": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Settings for blue-green upgrade strategy.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_pool_soak_duration": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Time needed after draining entire blue pool. After this period, blue pool will be cleaned up. + + A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s".`, + }, + "standard_rollout_policy": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Standard policy for the blue-green upgrade.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "batch_percentage": { + Type: schema.TypeFloat, + Optional: true, + Computed: true, + ValidateFunc: validation.FloatBetween(0.0, 1.0), + ExactlyOneOf: []string{ + "cluster_autoscaling.0.auto_provisioning_defaults.0.upgrade_settings.0.blue_green_settings.0.standard_rollout_policy.0.batch_percentage", + "cluster_autoscaling.0.auto_provisioning_defaults.0.upgrade_settings.0.blue_green_settings.0.standard_rollout_policy.0.batch_node_count", + }, + Description: `Percentage of the bool pool nodes to drain in a batch. The range of this field should be (0.0, 1.0].`, + }, + "batch_node_count": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + ExactlyOneOf: []string{ + "cluster_autoscaling.0.auto_provisioning_defaults.0.upgrade_settings.0.blue_green_settings.0.standard_rollout_policy.0.batch_percentage", + "cluster_autoscaling.0.auto_provisioning_defaults.0.upgrade_settings.0.blue_green_settings.0.standard_rollout_policy.0.batch_node_count", + }, + Description: `Number of blue nodes to drain in a batch.`, + }, + "batch_soak_duration": { + Type: schema.TypeString, + Optional: true, + Default: "0s", + Description: `Soak time after each batch gets drained. + + A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s".`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + <% unless version == 'ga' -%> + "autoscaling_profile": { + Type: schema.TypeString, + Default: "BALANCED", + Optional: true, + DiffSuppressFunc: suppressDiffForAutopilot, + ValidateFunc: validation.StringInSlice([]string{"BALANCED", "OPTIMIZE_UTILIZATION"}, false), + Description: `Configuration options for the Autoscaling profile feature, which lets you choose whether the cluster autoscaler should optimize for resource utilization or resource availability when deciding to remove nodes from a cluster. Can be BALANCED or OPTIMIZE_UTILIZATION. Defaults to BALANCED.`, + }, + <% end -%> + }, + }, + }, + + "cluster_ipv4_cidr": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: verify.OrEmpty(verify.ValidateRFC1918Network(8, 32)), + ConflictsWith: []string{"ip_allocation_policy"}, + Description: `The IP address range of the Kubernetes pods in this cluster in CIDR notation (e.g. 10.96.0.0/14). Leave blank to have one automatically chosen or specify a /14 block in 10.0.0.0/8. This field will only work for routes-based clusters, where ip_allocation_policy is not defined.`, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: ` Description of the cluster.`, + }, + + "binary_authorization": { + Type: schema.TypeList, + Optional: true, + DiffSuppressFunc: BinaryAuthorizationDiffSuppress, + MaxItems: 1, + Description: "Configuration options for the Binary Authorization feature.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Deprecated: "Deprecated in favor of evaluation_mode.", + Description: "Enable Binary Authorization for this cluster.", + ConflictsWith: []string{"enable_autopilot", "binary_authorization.0.evaluation_mode"}, + }, + "evaluation_mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "PROJECT_SINGLETON_POLICY_ENFORCE"}, false), + Description: "Mode of operation for Binary Authorization policy evaluation.", + ConflictsWith: []string{"binary_authorization.0.enabled"}, + }, + }, + }, + }, + + "enable_kubernetes_alpha": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Default: false, + Description: `Whether to enable Kubernetes Alpha features for this cluster. Note that when this option is enabled, the cluster cannot be upgraded and will be automatically deleted after 30 days.`, + }, + + "enable_k8s_beta_apis": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Configuration for Kubernetes Beta APIs.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled_apis": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `Enabled Kubernetes Beta APIs.`, + }, + }, + }, + }, + + "enable_tpu": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Whether to enable Cloud TPU resources in this cluster.`, +<% unless version == 'ga' -%> + ConflictsWith: []string{"tpu_config"}, + Computed: true, + // TODO: deprecate when tpu_config is correctly returned by the API + // Deprecated: "Deprecated in favor of tpu_config", +<% end -%> + }, + +<% unless version == 'ga' -%> + "tpu_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `TPU configuration for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `Whether Cloud TPU integration is enabled or not`, + }, + "ipv4_cidr_block": { + Type: schema.TypeString, + Computed: true, + Description: `IPv4 CIDR block reserved for Cloud TPU in the VPC.`, + }, + "use_service_networking": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Whether to use service networking for Cloud TPU or not`, + }, + }, + }, + }, +<% end -%> + + "enable_legacy_abac": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `Whether the ABAC authorizer is enabled for this cluster. When enabled, identities in the system, including service accounts, nodes, and controllers, will have statically granted permissions beyond those provided by the RBAC configuration or IAM. Defaults to false.`, + }, + + "enable_shielded_nodes": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: `Enable Shielded Nodes features on all nodes in this cluster. Defaults to true.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + + "enable_autopilot": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Enable Autopilot for this cluster.`, + // ConflictsWith: many fields, see https://cloud.google.com/kubernetes-engine/docs/concepts/autopilot-overview#comparison. The conflict is only set one-way, on other fields w/ this field. + }, + + "allow_net_admin": { + Type: schema.TypeBool, + Optional: true, + Description: `Enable NET_ADMIN for this cluster.`, + }, + + "authenticator_groups_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Configuration for the Google Groups for GKE feature.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "security_group": { + Type: schema.TypeString, + Required: true, + Description: `The name of the RBAC security group for use with Google security groups in Kubernetes RBAC. Group name must be in format gke-security-groups@yourdomain.com.`, + }, + }, + }, + }, + + "initial_node_count": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `The number of nodes to create in this cluster's default node pool. In regional or multi-zonal clusters, this is the number of nodes per zone. Must be set if node_pool is not set. If you're using google_container_node_pool objects with no default node pool, you'll need to set this to a value of at least 1, alongside setting remove_default_node_pool to true.`, + }, + + "logging_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Logging configuration for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_components": { + Type: schema.TypeList, + Required: true, + Description: `GKE components exposing logs. Valid values include SYSTEM_COMPONENTS, APISERVER, CONTROLLER_MANAGER, SCHEDULER, and WORKLOADS.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER", "WORKLOADS"}, false), + }, + }, + }, + }, + }, + + "logging_service": { + Type: schema.TypeString, + Optional: true, + Computed: true, +<% unless version == 'ga' -%> + ConflictsWith: []string{"cluster_telemetry"}, +<% end -%> + ValidateFunc: validation.StringInSlice([]string{"logging.googleapis.com", "logging.googleapis.com/kubernetes", "none"}, false), + Description: `The logging service that the cluster should write logs to. Available options include logging.googleapis.com(Legacy Stackdriver), logging.googleapis.com/kubernetes(Stackdriver Kubernetes Engine Logging), and none. Defaults to logging.googleapis.com/kubernetes.`, + }, + + "maintenance_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `The maintenance policy to use for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "daily_maintenance_window": { + Type: schema.TypeList, + Optional: true, + ExactlyOneOf: []string{ + "maintenance_policy.0.daily_maintenance_window", + "maintenance_policy.0.recurring_window", + }, + MaxItems: 1, + Description: `Time window specified for daily maintenance operations. Specify start_time in RFC3339 format "HH:MM”, where HH : [00-23] and MM : [00-59] GMT.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Time, + DiffSuppressFunc: tpgresource.Rfc3339TimeDiffSuppress, + }, + "duration": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "recurring_window": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + ExactlyOneOf: []string{ + "maintenance_policy.0.daily_maintenance_window", + "maintenance_policy.0.recurring_window", + }, + Description: `Time window for recurring maintenance operations.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "start_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Date, + }, + "end_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Date, + }, + "recurrence": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: rfc5545RecurrenceDiffSuppress, + }, + }, + }, + }, + "maintenance_exclusion": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 20, + Description: `Exceptions to maintenance window. Non-emergency maintenance should not occur in these windows.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "exclusion_name": { + Type: schema.TypeString, + Required: true, + }, + "start_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Date, + }, + "end_time": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateRFC3339Date, + }, + "exclusion_options": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Maintenance exclusion related options.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "scope": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"NO_UPGRADES", "NO_MINOR_UPGRADES", "NO_MINOR_OR_NODE_UPGRADES"}, false), + Description: `The scope of automatic upgrades to restrict in the exclusion window.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + +<% unless version == 'ga' -%> + "protect_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Enable/Disable Protect API features for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "workload_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `WorkloadConfig defines which actions are enabled for a cluster's workload configurations.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "audit_mode": { + Type: schema.TypeString, + Required: true, + Description: `Sets which mode of auditing should be used for the cluster's workloads. Accepted values are DISABLED, BASIC.`, + }, + }, + }, + AtLeastOneOf: []string{ + "protect_config.0.workload_config", + "protect_config.0.workload_vulnerability_mode", + }, + }, + "workload_vulnerability_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Sets which mode to use for Protect workload vulnerability scanning feature. Accepted values are DISABLED, BASIC.`, + AtLeastOneOf: []string{ + "protect_config.0.workload_config", + "protect_config.0.workload_vulnerability_mode", + }, + }, + }, + }, + }, +<% end -%> + + "security_posture_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Computed: true, + Description: `Defines the config needed to enable/disable features for the Security Posture API`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "BASIC", "MODE_UNSPECIFIED"}, false), + Description: `Sets the mode of the Kubernetes security posture API's off-cluster features. Available options include DISABLED and BASIC.`, + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("MODE_UNSPECIFIED"), + }, + "vulnerability_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice([]string{"VULNERABILITY_DISABLED", "VULNERABILITY_BASIC", "VULNERABILITY_MODE_UNSPECIFIED"}, false), + Description: `Sets the mode of the Kubernetes security posture API's workload vulnerability scanning. Available options include VULNERABILITY_DISABLED and VULNERABILITY_BASIC.`, + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("VULNERABILITY_MODE_UNSPECIFIED"), + }, + }, + }, + }, + "monitoring_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Monitoring configuration for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_components": { + Type: schema.TypeList, + Optional: true, + Computed: true, +<% if version == "ga" -%> + Description: `GKE components exposing metrics. Valid values include SYSTEM_COMPONENTS, APISERVER, SCHEDULER, CONTROLLER_MANAGER, STORAGE, HPA, POD, DAEMONSET, DEPLOYMENT and STATEFULSET.`, +<% else -%> + Description: `GKE components exposing metrics. Valid values include SYSTEM_COMPONENTS, APISERVER, SCHEDULER, CONTROLLER_MANAGER, STORAGE, HPA, POD, DAEMONSET, DEPLOYMENT, STATEFULSET and WORKLOADS.`, +<% end -%> + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "managed_prometheus": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Configuration for Google Cloud Managed Services for Prometheus.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether or not the managed collection is enabled.`, + }, + }, + }, + }, + "advanced_datapath_observability_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 2, + Description: `Configuration of Advanced Datapath Observability features.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_metrics": { + Type: schema.TypeBool, + Required: true, + Description: `Whether or not the advanced datapath metrics are enabled.`, + }, + "relay_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Mode used to make Relay available.`, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "INTERNAL_VPC_LB", "EXTERNAL_LB"}, false), + }, + }, + }, + }, + }, + }, + }, + + "notification_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The notification config for sending cluster upgrade notifications`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "pubsub": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Description: `Notification config for Cloud Pub/Sub`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether or not the notification config is enabled`, + }, + "topic": { + Type: schema.TypeString, + Optional: true, + Description: `The pubsub topic to push upgrade notifications to. Must be in the same project as the cluster. Must be in the format: projects/{project}/topics/{topic}.`, + }, + "filter": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Allows filtering to one or more specific event types. If event types are present, those and only those event types will be transmitted to the cluster. Other types will be skipped. If no filter is specified, or no event types are present, all event types will be sent`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "event_type": { + Type: schema.TypeList, + Required: true, + Description: `Can be used to filter what notifications are sent. Valid values include include UPGRADE_AVAILABLE_EVENT, UPGRADE_EVENT and SECURITY_BULLETIN_EVENT`, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"UPGRADE_AVAILABLE_EVENT", "UPGRADE_EVENT", "SECURITY_BULLETIN_EVENT"}, false), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + + "confidential_nodes": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + MaxItems: 1, + Description: `Configuration for the confidential nodes feature, which makes nodes run on confidential VMs. Warning: This configuration can't be changed (or added/removed) after cluster creation without deleting and recreating the entire cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `Whether Confidential Nodes feature is enabled for all nodes in this cluster.`, + }, + }, + }, + }, + + "master_auth": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Computed: true, + Description: `The authentication information for accessing the Kubernetes master. Some values in this block are only returned by the API if your service account has permission to get credentials for your GKE cluster. If you see an unexpected diff unsetting your client cert, ensure you have the container.clusters.getCredentials permission.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "client_certificate_config": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + ForceNew: true, + Description: `Whether client certificate authorization is enabled for this cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "issue_client_certificate": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `Whether client certificate authorization is enabled for this cluster.`, + }, + }, + }, + }, + + "client_certificate": { + Type: schema.TypeString, + Computed: true, + Description: `Base64 encoded public certificate used by clients to authenticate to the cluster endpoint.`, + }, + + "client_key": { + Type: schema.TypeString, + Computed: true, + Sensitive: true, + Description: `Base64 encoded private key used by clients to authenticate to the cluster endpoint.`, + }, + + "cluster_ca_certificate": { + Type: schema.TypeString, + Computed: true, + Description: `Base64 encoded public certificate that is the root of trust for the cluster.`, + }, + }, + }, + }, + + "master_authorized_networks_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: masterAuthorizedNetworksConfig, + Description: `The desired configuration options for master authorized networks. Omit the nested cidr_blocks attribute to disallow external access (except the cluster node IPs, which GKE automatically whitelists).`, + }, + + "min_master_version": { + Type: schema.TypeString, + Optional: true, + Description: `The minimum version of the master. GKE will auto-update the master to new versions, so this does not guarantee the current master version--use the read-only master_version field to obtain that. If unset, the cluster's version will be set by GKE to the version of the most recent official release (which is not necessarily the latest version).`, + }, + + "monitoring_service": { + Type: schema.TypeString, + Optional: true, + Computed: true, +<% unless version == 'ga' -%> + ConflictsWith: []string{"cluster_telemetry"}, +<% end -%> + ValidateFunc: validation.StringInSlice([]string{"monitoring.googleapis.com", "monitoring.googleapis.com/kubernetes", "none"}, false), + Description: `The monitoring service that the cluster should write metrics to. Automatically send metrics from pods in the cluster to the Google Cloud Monitoring API. VM metrics will be collected by Google Compute Engine regardless of this setting Available options include monitoring.googleapis.com(Legacy Stackdriver), monitoring.googleapis.com/kubernetes(Stackdriver Kubernetes Engine Monitoring), and none. Defaults to monitoring.googleapis.com/kubernetes.`, + }, + + "network": { + Type: schema.TypeString, + Optional: true, + Default: "default", + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name or self_link of the Google Compute Engine network to which the cluster is connected. For Shared VPC, set this to the self link of the shared network.`, + }, + + "network_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Configuration options for the NetworkPolicy feature.`, + ConflictsWith: []string{"enable_autopilot"}, + DiffSuppressFunc: containerClusterNetworkPolicyDiffSuppress, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether network policy is enabled on the cluster.`, + }, + "provider": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"PROVIDER_UNSPECIFIED", "CALICO"}, false), + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("PROVIDER_UNSPECIFIED"), + Description: `The selected network policy provider.`, + }, + }, + }, + }, + + "node_config": clusterSchemaNodeConfig(), + + "node_pool": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, // TODO: Add ability to add/remove nodePools + Elem: &schema.Resource{ + Schema: schemaNodePool, + }, + Description: `List of node pools associated with this cluster. See google_container_node_pool for schema. Warning: node pools defined inside a cluster can't be changed (or added/removed) after cluster creation without deleting and recreating the entire cluster. Unless you absolutely need the ability to say "these are the only node pools associated with this cluster", use the google_container_node_pool resource instead of this property.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + + "node_pool_defaults": clusterSchemaNodePoolDefaults(), + + "node_pool_auto_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Node pool configs that apply to all auto-provisioned node pools in autopilot clusters and node auto-provisioning enabled clusters.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_tags": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Collection of Compute Engine network tags that can be applied to a node's underlying VM instance.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tags": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `List of network tags applied to auto-provisioned node pools.`, + }, + }, + }, + }, + }, + }, + }, + + "node_version": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The Kubernetes version on the nodes. Must either be unset or set to the same value as min_master_version on create. Defaults to the default version set by GKE which is not necessarily the latest version. This only affects nodes in the default node pool. While a fuzzy version can be specified, it's recommended that you specify explicit versions as Terraform will see spurious diffs when fuzzy versions are used. See the google_container_engine_versions data source's version_prefix field to approximate fuzzy versions in a Terraform-compatible way. To update nodes in other node pools, use the version attribute on the node pool.`, + }, + +<% unless version == "ga" -%> + "pod_security_policy_config": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration for the PodSecurityPolicy feature.`, + MaxItems: 1, + DiffSuppressFunc: podSecurityPolicyCfgSuppress, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Enable the PodSecurityPolicy controller for this cluster. If enabled, pods must be valid under a PodSecurityPolicy to be created.`, + }, + }, + }, + }, +<% end -%> + + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The ID of the project in which the resource belongs. If it is not provided, the provider project is used.`, + }, + + "subnetwork": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name or self_link of the Google Compute Engine subnetwork in which the cluster's instances are launched.`, + }, + + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `Server-defined URL for the resource.`, + }, + + "endpoint": { + Type: schema.TypeString, + Computed: true, + Description: `The IP address of this cluster's Kubernetes master.`, + }, + + "master_version": { + Type: schema.TypeString, + Computed: true, + Description: `The current version of the master in the cluster. This may be different than the min_master_version set in the config if the master has been updated by GKE.`, + }, + + "services_ipv4_cidr": { + Type: schema.TypeString, + Computed: true, + Description: `The IP address range of the Kubernetes services in this cluster, in CIDR notation (e.g. 1.2.3.4/29). Service addresses are typically put in the last /16 from the container CIDR.`, + }, + + "ip_allocation_policy": { + Type: schema.TypeList, + MaxItems: 1, + ForceNew: true, + Computed: true, + Optional: true, + ConflictsWith: []string{"cluster_ipv4_cidr"}, + Description: `Configuration of cluster IP allocation for VPC-native clusters. Adding this block enables IP aliasing, making the cluster VPC-native instead of routes-based.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + // GKE creates/deletes secondary ranges in VPC + "cluster_ipv4_cidr_block": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: ipAllocationRangeFields, + DiffSuppressFunc: tpgresource.CidrOrSizeDiffSuppress, + Description: `The IP address range for the cluster pod IPs. Set to blank to have a range chosen with the default size. Set to /netmask (e.g. /14) to have a range chosen with a specific netmask. Set to a CIDR notation (e.g. 10.96.0.0/14) from the RFC-1918 private networks (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use.`, + }, + + "services_ipv4_cidr_block": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: ipAllocationRangeFields, + DiffSuppressFunc: tpgresource.CidrOrSizeDiffSuppress, + Description: `The IP address range of the services IPs in this cluster. Set to blank to have a range chosen with the default size. Set to /netmask (e.g. /14) to have a range chosen with a specific netmask. Set to a CIDR notation (e.g. 10.96.0.0/14) from the RFC-1918 private networks (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use.`, + }, + + // User manages secondary ranges manually + "cluster_secondary_range_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: ipAllocationCidrBlockFields, + Description: `The name of the existing secondary range in the cluster's subnetwork to use for pod IP addresses. Alternatively, cluster_ipv4_cidr_block can be used to automatically create a GKE-managed one.`, + }, + + "services_secondary_range_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ConflictsWith: ipAllocationCidrBlockFields, + Description: `The name of the existing secondary range in the cluster's subnetwork to use for service ClusterIPs. Alternatively, services_ipv4_cidr_block can be used to automatically create a GKE-managed one.`, + }, + + "stack_type": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "IPV4", + ValidateFunc: validation.StringInSlice([]string{"IPV4", "IPV4_IPV6"}, false), + Description: `The IP Stack type of the cluster. Choose between IPV4 and IPV4_IPV6. Default type is IPV4 Only if not set`, + }, + "pod_cidr_overprovision_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + ForceNew: true, + MaxItems: 1, + Description: `Configuration for cluster level pod cidr overprovision. Default is disabled=false.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "disabled": { + Type: schema.TypeBool, + Required: true, + }, + }, + }, + }, + "additional_pod_ranges_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: `AdditionalPodRangesConfig is the configuration for additional pod secondary ranges supporting the ClusterUpdate message.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "pod_range_names": { + Type: schema.TypeSet, + MinItems: 1, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `Name for pod secondary ipv4 range which has the actual range defined ahead.`, + }, + }, + }, + }, + }, + }, + }, + + "networking_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"VPC_NATIVE", "ROUTES"}, false), + Description: `Determines whether alias IPs or routes will be used for pod IPs in the cluster.`, + }, + + "remove_default_node_pool": { + Type: schema.TypeBool, + Optional: true, + Description: `If true, deletes the default node pool upon cluster creation. If you're using google_container_node_pool resources with no default node pool, this should be set to true, alongside setting initial_node_count to at least 1.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + + "private_cluster_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress, + Description: `Configuration for private clusters, clusters with private nodes.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + // enable_private_endpoint is orthogonal to private_endpoint_subnetwork. + // User can create a private_cluster_config block without including + // either one of those two fields. Both fields are optional. + // At the same time, we use 'AtLeastOneOf' to prevent an empty block + // like 'private_cluster_config{}' + "enable_private_endpoint": { + Type: schema.TypeBool, + Optional: true, + AtLeastOneOf: privateClusterConfigKeys, + DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress, + Description: `When true, the cluster's private endpoint is used as the cluster endpoint and access through the public endpoint is disabled. When false, either endpoint can be used.`, + }, + "enable_private_nodes": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + AtLeastOneOf: privateClusterConfigKeys, + DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress, + Description: `Enables the private cluster feature, creating a private endpoint on the cluster. In a private cluster, nodes only have RFC 1918 private addresses and communicate with the master's private endpoint via private networking.`, + }, + "master_ipv4_cidr_block": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + AtLeastOneOf: privateClusterConfigKeys, + ValidateFunc: verify.OrEmpty(validation.IsCIDRNetwork(28, 28)), + Description: `The IP range in CIDR notation to use for the hosted master network. This range will be used for assigning private IP addresses to the cluster master(s) and the ILB VIP. This range must not overlap with any other ranges in use within the cluster's network, and it must be a /28 subnet. See Private Cluster Limitations for more details. This field only applies to private clusters, when enable_private_nodes is true.`, + }, + "peering_name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of the peering between this cluster and the Google owned VPC.`, + }, + "private_endpoint": { + Type: schema.TypeString, + Computed: true, + Description: `The internal IP address of this cluster's master endpoint.`, + }, + "private_endpoint_subnetwork": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: privateClusterConfigKeys, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `Subnetwork in cluster's network where master's endpoint will be provisioned.`, + }, + "public_endpoint": { + Type: schema.TypeString, + Computed: true, + Description: `The external IP address of this cluster's master endpoint.`, + }, + "master_global_access_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + AtLeastOneOf: privateClusterConfigKeys, + Description: "Controls cluster master global access settings.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether the cluster master is accessible globally or not.`, + }, + }, + }, + }, + }, + }, + }, + + "resource_labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The GCE resource labels (a map of key/value pairs) to be applied to the cluster.`, + }, + + "label_fingerprint": { + Type: schema.TypeString, + Computed: true, + Description: `The fingerprint of the set of labels for this cluster.`, + }, + + "default_max_pods_per_node": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Computed: true, + Description: `The default maximum number of pods per node in this cluster. This doesn't work on "routes-based" clusters, clusters that don't have IP Aliasing enabled.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + + "vertical_pod_autoscaling": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Vertical Pod Autoscaling automatically adjusts the resources of pods controlled by it.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Enables vertical pod autoscaling.`, + }, + }, + }, + }, + "workload_identity_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + // Computed is unsafe to remove- this API may return `"workloadIdentityConfig": {},` or omit the key entirely + // and both will be valid. Note that we don't handle the case where the API returns nothing & the user has defined + // workload_identity_config today. + Computed: true, + Description: `Configuration for the use of Kubernetes Service Accounts in GCP IAM policies.`, + ConflictsWith: []string{"enable_autopilot"}, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "workload_pool": { + Type: schema.TypeString, + Optional: true, + Description: "The workload pool to attach all Kubernetes service accounts to.", + }, + }, + }, + }, + +<% unless version == 'ga' -%> + "identity_service_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Configuration for Identity Service which allows customers to use external identity providers with the K8S API.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Optional: true, + Description: "Whether to enable the Identity Service component.", + }, + }, + }, + }, +<% end -%> + + "service_external_ips_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `If set, and enabled=true, services with external ips field will not be blocked`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `When enabled, services with exterenal ips specified will be allowed.`, + }, + }, + }, + }, + + "mesh_certificates": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `If set, and enable_certificates=true, the GKE Workload Identity Certificates controller and node agent will be deployed in the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_certificates": { + Type: schema.TypeBool, + Required: true, + Description: `When enabled the GKE Workload Identity Certificates controller and node agent will be deployed in the cluster.`, + }, + }, + }, + }, + + "database_encryption": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Application-layer Secrets Encryption settings. The object format is {state = string, key_name = string}. Valid values of state are: "ENCRYPTED"; "DECRYPTED". key_name is the name of a CloudKMS key.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "state": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"ENCRYPTED", "DECRYPTED"}, false), + Description: `ENCRYPTED or DECRYPTED.`, + }, + "key_name": { + Type: schema.TypeString, + Optional: true, + Description: `The key to use to encrypt/decrypt secrets.`, + }, + }, + }, + }, + + "release_channel": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Configuration options for the Release channel feature, which provide more control over automatic upgrades of your GKE clusters. Note that removing this field from your config will not unenroll it. Instead, use the "UNSPECIFIED" channel.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "channel": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"UNSPECIFIED", "RAPID", "REGULAR", "STABLE"}, false), + Description: `The selected release channel. Accepted values are: +* UNSPECIFIED: Not set. +* RAPID: Weekly upgrade cadence; Early testers and developers who requires new features. +* REGULAR: Multiple per month upgrade cadence; Production users who need features not yet offered in the Stable channel. +* STABLE: Every few months upgrade cadence; Production users who need stability above all else, and for whom frequent upgrades are too risky.`, + }, + }, + }, + }, + + "tpu_ipv4_cidr_block": { + Computed: true, + Type: schema.TypeString, + Description: `The IP address range of the Cloud TPUs in this cluster, in CIDR notation (e.g. 1.2.3.4/29).`, + }, + +<% unless version == 'ga' -%> + "cluster_telemetry": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: `Telemetry integration for the cluster.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"DISABLED","ENABLED","SYSTEM_ONLY"}, false), + Description: `Type of the integration.`, + }, + }, + }, + }, +<% end -%> + + "default_snat_status": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Whether the cluster disables default in-node sNAT rules. In-node sNAT rules will be disabled when defaultSnatStatus is disabled.`, + Elem: &schema.Resource { + Schema: map[string]*schema.Schema { + "disabled": { + Type: schema.TypeBool, + Required: true, + Description: `When disabled is set to false, default IP masquerade rules will be applied to the nodes to prevent sNAT on cluster internal traffic.`, + }, + }, + }, + }, + + "datapath_provider": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + Description: `The desired datapath provider for this cluster. By default, uses the IPTables-based kube-proxy implementation.`, + ValidateFunc: validation.StringInSlice([]string{"DATAPATH_PROVIDER_UNSPECIFIED", "LEGACY_DATAPATH", "ADVANCED_DATAPATH"}, false), + DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("DATAPATH_PROVIDER_UNSPECIFIED"), + }, + + "enable_intranode_visibility": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Whether Intra-node visibility is enabled for this cluster. This makes same node pod to pod traffic visible for VPC network.`, + ConflictsWith: []string{"enable_autopilot"}, + }, + "enable_l4_ilb_subsetting": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether L4ILB Subsetting is enabled for this cluster.`, + Default: false, + }, +<% unless version == 'ga' -%> + "enable_multi_networking": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Whether multi-networking is enabled for this cluster.`, + Default: false, + }, + "enable_fqdn_network_policy": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether FQDN Network Policy is enabled on this cluster.`, + Default: false, + }, +<% end -%> + "private_ipv6_google_access": { + Type: schema.TypeString, + Optional: true, + Description: `The desired state of IPv6 connectivity to Google Services. By default, no private IPv6 access to or from Google Services (all access will be via IPv4).`, + Computed: true, + }, + + "cost_management_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `Cost management configuration for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether to enable GKE cost allocation. When you enable GKE cost allocation, the cluster name and namespace of your GKE workloads appear in the labels field of the billing export to BigQuery. Defaults to false.`, + }, + }, + }, + }, + + "resource_usage_export_config": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Description: `Configuration for the ResourceUsageExportConfig feature.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_network_egress_metering": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `Whether to enable network egress metering for this cluster. If enabled, a daemonset will be created in the cluster to meter network egress traffic.`, + }, + "enable_resource_consumption_metering": { + Type: schema.TypeBool, + Optional: true, + Default: true, + Description: `Whether to enable resource consumption metering on this cluster. When enabled, a table will be created in the resource export BigQuery dataset to store resource consumption data. The resulting table can be joined with the resource usage table or with BigQuery billing export. Defaults to true.`, + }, + "bigquery_destination": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Description: `Parameters for using BigQuery as the destination of resource usage export.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dataset_id": { + Type: schema.TypeString, + Required: true, + Description: `The ID of a BigQuery Dataset.`, + }, + }, + }, + }, + }, + }, + }, + "dns_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + ForceNew: true, + DiffSuppressFunc: suppressDiffForAutopilot, + Description: `Configuration for Cloud DNS for Kubernetes Engine.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cluster_dns": { + Type: schema.TypeString, + Default: "PROVIDER_UNSPECIFIED", + ValidateFunc: validation.StringInSlice([]string{"PROVIDER_UNSPECIFIED", "PLATFORM_DEFAULT", "CLOUD_DNS"}, false), + Description: `Which in-cluster DNS provider should be used.`, + Optional: true, + }, + "cluster_dns_scope": { + Type: schema.TypeString, + Default: "DNS_SCOPE_UNSPECIFIED", + ValidateFunc: validation.StringInSlice([]string{"DNS_SCOPE_UNSPECIFIED", "CLUSTER_SCOPE", "VPC_SCOPE"}, false), + Description: `The scope of access to cluster DNS records.`, + Optional: true, + }, + "cluster_dns_domain": { + Type: schema.TypeString, + Description: `The suffix used for all cluster service records.`, + Optional: true, + }, + }, + }, + }, + "gateway_api_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Configuration for GKE Gateway API controller.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "channel": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{"CHANNEL_DISABLED", "CHANNEL_EXPERIMENTAL", "CHANNEL_STANDARD"}, false), + Description: `The Gateway API release channel to use for Gateway API.`, + }, + }, + }, + }, + }, + } +} diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index fc9635d20137..08f43aa6063a 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -34,17 +34,20 @@ func TestAccContainerCluster_basic(t *testing.T) { ImportStateId: fmt.Sprintf("us-central1-a/%s", clusterName), ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { ResourceName: "google_container_cluster.primary", ImportStateId: fmt.Sprintf("%s/us-central1-a/%s", envvar.GetTestProjectFromEnv(), clusterName), ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -66,6 +69,7 @@ func TestAccContainerCluster_networkingModeRoutes(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -91,7 +95,7 @@ func TestAccContainerCluster_misc(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_misc_update(clusterName), @@ -100,7 +104,7 @@ func TestAccContainerCluster_misc(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, }, }) @@ -125,7 +129,7 @@ func TestAccContainerCluster_withAddons(t *testing.T) { ImportState: true, ImportStateVerify: true, // TODO: clean up this list in `4.0.0`, remove both `workload_identity_config` fields (same for below) - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_updateAddons(pid, clusterName), @@ -134,7 +138,7 @@ func TestAccContainerCluster_withAddons(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, // Issue with cloudrun_config addon: https://github.com/hashicorp/terraform-provider-google/issues/11943 // { @@ -144,12 +148,44 @@ func TestAccContainerCluster_withAddons(t *testing.T) { // ResourceName: "google_container_cluster.primary", // ImportState: true, // ImportStateVerify: true, - // ImportStateVerifyIgnore: []string{"min_master_version"}, + // ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, // }, }, }) } +func TestAccContainerCluster_withDeletionProtection(t *testing.T) { + t.Parallel() + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withDeletionProtection(clusterName, "false"), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testAccContainerCluster_withDeletionProtection(clusterName, "true"), + }, + { + Config: testAccContainerCluster_withDeletionProtection(clusterName, "true"), + Destroy: true, + ExpectError: regexp.MustCompile("Cannot destroy cluster because deletion_protection is set to true. Set it to false to proceed with instance deletion."), + }, + { + Config: testAccContainerCluster_withDeletionProtection(clusterName, "false"), + }, + }, + }) +} + func TestAccContainerCluster_withNotificationConfig(t *testing.T) { t.Parallel() @@ -169,6 +205,7 @@ func TestAccContainerCluster_withNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNotificationConfig(clusterName, newTopic), @@ -177,6 +214,7 @@ func TestAccContainerCluster_withNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_disableNotificationConfig(clusterName), @@ -185,6 +223,7 @@ func TestAccContainerCluster_withNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNotificationConfig(clusterName, newTopic), @@ -193,6 +232,7 @@ func TestAccContainerCluster_withNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -217,6 +257,7 @@ func TestAccContainerCluster_withFilteredNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.filtered_notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withFilteredNotificationConfigUpdate(clusterName, newTopic), @@ -225,6 +266,7 @@ func TestAccContainerCluster_withFilteredNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.filtered_notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_disableFilteredNotificationConfig(clusterName, newTopic), @@ -233,6 +275,7 @@ func TestAccContainerCluster_withFilteredNotificationConfig(t *testing.T) { ResourceName: "google_container_cluster.filtered_notification_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -256,6 +299,7 @@ func TestAccContainerCluster_withConfidentialNodes(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_disableConfidentialNodes(clusterName, npName), @@ -264,6 +308,7 @@ func TestAccContainerCluster_withConfidentialNodes(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withConfidentialNodes(clusterName, npName), @@ -272,6 +317,7 @@ func TestAccContainerCluster_withConfidentialNodes(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -295,6 +341,7 @@ func TestAccContainerCluster_withILBSubsetting(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withILBSubSetting(clusterName, npName), @@ -303,6 +350,7 @@ func TestAccContainerCluster_withILBSubsetting(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_disableILBSubSetting(clusterName, npName), @@ -311,6 +359,7 @@ func TestAccContainerCluster_withILBSubsetting(t *testing.T) { ResourceName: "google_container_cluster.confidential_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -334,6 +383,7 @@ func TestAccContainerCluster_withMultiNetworking(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -358,7 +408,7 @@ func TestAccContainerCluster_withFQDNNetworkPolicy(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withFQDNNetworkPolicy(clusterName, true), @@ -367,7 +417,7 @@ func TestAccContainerCluster_withFQDNNetworkPolicy(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -394,6 +444,7 @@ func TestAccContainerCluster_withMasterAuthConfig_NoCert(t *testing.T) { ResourceName: "google_container_cluster.with_master_auth_no_cert", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -419,6 +470,7 @@ func TestAccContainerCluster_withAuthenticatorGroupsConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withAuthenticatorGroupsConfigUpdate(clusterName, orgDomain), @@ -431,6 +483,7 @@ func TestAccContainerCluster_withAuthenticatorGroupsConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withAuthenticatorGroupsConfigUpdate2(clusterName), @@ -443,6 +496,7 @@ func TestAccContainerCluster_withAuthenticatorGroupsConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -502,6 +556,7 @@ resource "google_container_cluster" "cluster" { } enable_multi_networking = true datapath_provider = "ADVANCED_DATAPATH" + deletion_protection = false } `, clusterName, clusterName) } @@ -565,6 +620,7 @@ resource "google_container_cluster" "cluster" { enable_fqdn_network_policy = %t datapath_provider = "ADVANCED_DATAPATH" + deletion_protection = false } `, clusterName, clusterName, enabled) } @@ -591,7 +647,7 @@ func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { ResourceName: "google_container_cluster.with_network_policy_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_removeNetworkPolicy(clusterName), @@ -604,7 +660,7 @@ func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { ResourceName: "google_container_cluster.with_network_policy_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_withNetworkPolicyDisabled(clusterName), @@ -617,7 +673,7 @@ func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { ResourceName: "google_container_cluster.with_network_policy_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_withNetworkPolicyConfigDisabled(clusterName), @@ -630,7 +686,7 @@ func TestAccContainerCluster_withNetworkPolicyEnabled(t *testing.T) { ResourceName: "google_container_cluster.with_network_policy_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_withNetworkPolicyConfigDisabled(clusterName), @@ -658,7 +714,7 @@ func TestAccContainerCluster_withReleaseChannelEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withReleaseChannelEnabled(clusterName, "UNSPECIFIED"), @@ -668,7 +724,7 @@ func TestAccContainerCluster_withReleaseChannelEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -690,7 +746,7 @@ func TestAccContainerCluster_withReleaseChannelEnabledDefaultVersion(t *testing. ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withReleaseChannelEnabled(clusterName, "REGULAR"), @@ -700,7 +756,7 @@ func TestAccContainerCluster_withReleaseChannelEnabledDefaultVersion(t *testing. ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withReleaseChannelEnabled(clusterName, "UNSPECIFIED"), @@ -710,7 +766,7 @@ func TestAccContainerCluster_withReleaseChannelEnabledDefaultVersion(t *testing. ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -751,7 +807,7 @@ func TestAccContainerCluster_withTelemetryEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withTelemetryEnabled(clusterName, "DISABLED"), @@ -761,7 +817,7 @@ func TestAccContainerCluster_withTelemetryEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withTelemetryEnabled(clusterName, "SYSTEM_ONLY"), @@ -771,7 +827,7 @@ func TestAccContainerCluster_withTelemetryEnabled(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -805,17 +861,19 @@ func TestAccContainerCluster_withMasterAuthorizedNetworksConfig(t *testing.T) { ), }, { - ResourceName: "google_container_cluster.with_master_authorized_networks", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_master_authorized_networks", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName, []string{"10.0.0.0/8", "8.8.8.8/32"}, ""), }, { - ResourceName: "google_container_cluster.with_master_authorized_networks", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_master_authorized_networks", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withMasterAuthorizedNetworksConfig(clusterName, []string{}, ""), @@ -825,17 +883,19 @@ func TestAccContainerCluster_withMasterAuthorizedNetworksConfig(t *testing.T) { ), }, { - ResourceName: "google_container_cluster.with_master_authorized_networks", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_master_authorized_networks", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_removeMasterAuthorizedNetworksConfig(clusterName), }, { - ResourceName: "google_container_cluster.with_master_authorized_networks", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_master_authorized_networks", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -862,7 +922,7 @@ func TestAccContainerCluster_withGcpPublicCidrsAccessEnabledToggle(t *testing.T) ResourceName: "google_container_cluster.with_gcp_public_cidrs_access_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withGcpPublicCidrsAccessEnabled(clusterName, "false"), @@ -875,7 +935,7 @@ func TestAccContainerCluster_withGcpPublicCidrsAccessEnabledToggle(t *testing.T) ResourceName: "google_container_cluster.with_gcp_public_cidrs_access_enabled", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withGcpPublicCidrsAccessEnabled(clusterName, "true"), @@ -904,6 +964,7 @@ resource "google_container_cluster" "with_gcp_public_cidrs_access_enabled" { master_authorized_networks_config { gcp_public_cidrs_access_enabled = %s } + deletion_protection = false } `, clusterName, flag) } @@ -920,6 +981,7 @@ resource "google_container_cluster" "with_gcp_public_cidrs_access_enabled" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -941,6 +1003,7 @@ func TestAccContainerCluster_regional(t *testing.T) { ResourceName: "google_container_cluster.regional", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -964,6 +1027,7 @@ func TestAccContainerCluster_regionalWithNodePool(t *testing.T) { ResourceName: "google_container_cluster.regional", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -986,6 +1050,7 @@ func TestAccContainerCluster_regionalWithNodeLocations(t *testing.T) { ResourceName: "google_container_cluster.with_node_locations", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_regionalUpdateNodeLocations(clusterName), @@ -994,6 +1059,7 @@ func TestAccContainerCluster_regionalWithNodeLocations(t *testing.T) { ResourceName: "google_container_cluster.with_node_locations", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1021,6 +1087,7 @@ func TestAccContainerCluster_withTpu(t *testing.T) { ResourceName: "google_container_cluster.with_tpu", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1045,6 +1112,7 @@ func TestAccContainerCluster_withPrivateClusterConfigBasic(t *testing.T) { ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withPrivateClusterConfig(containerNetName, clusterName, true), @@ -1053,6 +1121,7 @@ func TestAccContainerCluster_withPrivateClusterConfigBasic(t *testing.T) { ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1095,6 +1164,7 @@ func TestAccContainerCluster_withPrivateClusterConfigMissingCidrBlock_withAutopi ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1117,6 +1187,7 @@ func TestAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(t * ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(clusterName, false), @@ -1125,6 +1196,7 @@ func TestAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(t * ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1150,6 +1222,7 @@ func TestAccContainerCluster_withIntraNodeVisibility(t *testing.T) { ResourceName: "google_container_cluster.with_intranode_visibility", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_updateIntraNodeVisibility(clusterName), @@ -1161,6 +1234,7 @@ func TestAccContainerCluster_withIntraNodeVisibility(t *testing.T) { ResourceName: "google_container_cluster.with_intranode_visibility", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1183,7 +1257,7 @@ func TestAccContainerCluster_withVersion(t *testing.T) { ResourceName: "google_container_cluster.with_version", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1206,7 +1280,7 @@ func TestAccContainerCluster_updateVersion(t *testing.T) { ResourceName: "google_container_cluster.with_version", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_updateVersion(clusterName), @@ -1215,7 +1289,7 @@ func TestAccContainerCluster_updateVersion(t *testing.T) { ResourceName: "google_container_cluster.with_version", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1235,17 +1309,19 @@ func TestAccContainerCluster_withNodeConfig(t *testing.T) { Config: testAccContainerCluster_withNodeConfig(clusterName), }, { - ResourceName: "google_container_cluster.with_node_config", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_node_config", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"node_config.0.taint", "deletion_protection"}, }, { Config: testAccContainerCluster_withNodeConfigUpdate(clusterName), }, { - ResourceName: "google_container_cluster.with_node_config", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_node_config", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"node_config.0.taint", "deletion_protection"}, }, }, }) @@ -1266,6 +1342,7 @@ func TestAccContainerCluster_withLoggingVariantInNodeConfig(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_in_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1287,6 +1364,7 @@ func TestAccContainerCluster_withLoggingVariantInNodePool(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_in_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1307,6 +1385,7 @@ func TestAccContainerCluster_withLoggingVariantUpdates(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_node_pool_default", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingVariantNodePoolDefault(clusterName, "MAX_THROUGHPUT"), @@ -1315,6 +1394,7 @@ func TestAccContainerCluster_withLoggingVariantUpdates(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_node_pool_default", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingVariantNodePoolDefault(clusterName, "DEFAULT"), @@ -1323,6 +1403,7 @@ func TestAccContainerCluster_withLoggingVariantUpdates(t *testing.T) { ResourceName: "google_container_cluster.with_logging_variant_node_pool_default", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1349,6 +1430,7 @@ func TestAccContainerCluster_withNodePoolDefaults(t *testing.T) { ImportStateId: fmt.Sprintf("us-central1-a/%s", clusterName), ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNodePoolDefaults(clusterName, "true"), @@ -1363,6 +1445,7 @@ func TestAccContainerCluster_withNodePoolDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_defaults", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNodePoolDefaults(clusterName, "false"), @@ -1377,6 +1460,7 @@ func TestAccContainerCluster_withNodePoolDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_defaults", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1400,6 +1484,7 @@ func TestAccContainerCluster_withNodeConfigScopeAlias(t *testing.T) { ResourceName: "google_container_cluster.with_node_config_scope_alias", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1422,6 +1507,7 @@ func TestAccContainerCluster_withNodeConfigShieldedInstanceConfig(t *testing.T) ResourceName: "google_container_cluster.with_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1450,6 +1536,7 @@ func TestAccContainerCluster_withNodeConfigReservationAffinity(t *testing.T) { ResourceName: "google_container_cluster.with_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1485,6 +1572,7 @@ func TestAccContainerCluster_withNodeConfigReservationAffinitySpecific(t *testin ResourceName: "google_container_cluster.with_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1511,7 +1599,7 @@ func TestAccContainerCluster_withWorkloadMetadataConfig(t *testing.T) { ResourceName: "google_container_cluster.with_workload_metadata_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1541,7 +1629,7 @@ func TestAccContainerCluster_withSandboxConfig(t *testing.T) { ResourceName: "google_container_cluster.with_sandbox_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "node_config.0.taint", "deletion_protection"}, }, { // GKE sets automatic labels and taints on nodes. This makes @@ -1596,7 +1684,7 @@ func TestAccContainerCluster_withBootDiskKmsKey(t *testing.T) { ResourceName: "google_container_cluster.with_boot_disk_kms_key", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1617,14 +1705,16 @@ func TestAccContainerCluster_network(t *testing.T) { Config: testAccContainerCluster_networkRef(clusterName, network), }, { - ResourceName: "google_container_cluster.with_net_ref_by_url", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_net_ref_by_url", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - ResourceName: "google_container_cluster.with_net_ref_by_name", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.with_net_ref_by_name", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1647,6 +1737,7 @@ func TestAccContainerCluster_backend(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1670,6 +1761,7 @@ func TestAccContainerCluster_withNodePoolBasic(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1693,7 +1785,7 @@ func TestAccContainerCluster_withNodePoolUpdateVersion(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withNodePoolUpdateVersion(clusterName, npName), @@ -1702,7 +1794,7 @@ func TestAccContainerCluster_withNodePoolUpdateVersion(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1728,6 +1820,7 @@ func TestAccContainerCluster_withNodePoolResize(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withNodePoolResize(clusterName, npName), @@ -1739,6 +1832,7 @@ func TestAccContainerCluster_withNodePoolResize(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1766,6 +1860,7 @@ func TestAccContainerCluster_withNodePoolAutoscaling(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, resource.TestStep{ Config: testAccContainerCluster_withNodePoolUpdateAutoscaling(clusterName, npName), @@ -1778,6 +1873,7 @@ func TestAccContainerCluster_withNodePoolAutoscaling(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, resource.TestStep{ Config: testAccContainerCluster_withNodePoolBasic(clusterName, npName), @@ -1790,6 +1886,7 @@ func TestAccContainerCluster_withNodePoolAutoscaling(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1820,7 +1917,7 @@ func TestAccContainerCluster_withNodePoolCIA(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, resource.TestStep{ Config: testAccContainerRegionalClusterUpdate_withNodePoolCIA(clusterName, npName), @@ -1836,7 +1933,7 @@ func TestAccContainerCluster_withNodePoolCIA(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, resource.TestStep{ Config: testAccContainerRegionalCluster_withNodePoolBasic(clusterName, npName), @@ -1851,7 +1948,7 @@ func TestAccContainerCluster_withNodePoolCIA(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -1877,7 +1974,7 @@ func TestAccContainerCluster_withNodePoolNamePrefix(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_name_prefix", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"node_pool.0.name_prefix"}, + ImportStateVerifyIgnore: []string{"node_pool.0.name_prefix", "deletion_protection"}, }, }, }) @@ -1901,6 +1998,7 @@ func TestAccContainerCluster_withNodePoolMultiple(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_multiple", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1943,6 +2041,7 @@ func TestAccContainerCluster_withNodePoolNodeConfig(t *testing.T) { ResourceName: "google_container_cluster.with_node_pool_node_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1966,6 +2065,7 @@ func TestAccContainerCluster_withMaintenanceWindow(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withMaintenanceWindow(clusterName, ""), @@ -1980,7 +2080,7 @@ func TestAccContainerCluster_withMaintenanceWindow(t *testing.T) { ImportStateVerify: true, // maintenance_policy.# = 0 is equivalent to no maintenance policy at all, // but will still cause an import diff - ImportStateVerifyIgnore: []string{"maintenance_policy.#"}, + ImportStateVerifyIgnore: []string{"maintenance_policy.#", "deletion_protection"}, }, }, }) @@ -2008,6 +2108,8 @@ func TestAccContainerCluster_withRecurringMaintenanceWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, { Config: testAccContainerCluster_withRecurringMaintenanceWindow(cluster, "", ""), @@ -2025,7 +2127,7 @@ func TestAccContainerCluster_withRecurringMaintenanceWindow(t *testing.T) { ImportStateVerify: true, // maintenance_policy.# = 0 is equivalent to no maintenance policy at all, // but will still cause an import diff - ImportStateVerifyIgnore: []string{"maintenance_policy.#"}, + ImportStateVerifyIgnore: []string{"maintenance_policy.#", "deletion_protection"}, }, }, }) @@ -2049,6 +2151,7 @@ func TestAccContainerCluster_withMaintenanceExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExclusion_DailyMaintenanceWindow(cluster, "2020-01-01T00:00:00Z", "2020-01-02T00:00:00Z"), @@ -2058,6 +2161,7 @@ func TestAccContainerCluster_withMaintenanceExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2088,6 +2192,7 @@ func TestAccContainerCluster_withMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2118,6 +2223,7 @@ func TestAccContainerCluster_deleteMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_NoExclusionOptions_RecurringMaintenanceWindow( @@ -2134,6 +2240,7 @@ func TestAccContainerCluster_deleteMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2167,6 +2274,7 @@ func TestAccContainerCluster_updateMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExclusionOptions_RecurringMaintenanceWindow( @@ -2183,6 +2291,7 @@ func TestAccContainerCluster_updateMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_updateExclusionOptions_RecurringMaintenanceWindow( @@ -2199,6 +2308,7 @@ func TestAccContainerCluster_updateMaintenanceExclusionOptions(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2223,6 +2333,7 @@ func TestAccContainerCluster_deleteExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExclusion_RecurringMaintenanceWindow(cluster, "2019-01-01T00:00:00Z", "2019-01-02T00:00:00Z", "2019-05-01T00:00:00Z", "2019-05-02T00:00:00Z"), @@ -2232,6 +2343,7 @@ func TestAccContainerCluster_deleteExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExclusion_NoMaintenanceWindow(cluster, "2020-01-01T00:00:00Z", "2020-01-02T00:00:00Z"), @@ -2241,6 +2353,7 @@ func TestAccContainerCluster_deleteExclusionWindow(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2263,6 +2376,7 @@ func TestAccContainerCluster_withIPAllocationPolicy_existingSecondaryRanges(t *t ResourceName: "google_container_cluster.with_ip_allocation_policy", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2285,6 +2399,7 @@ func TestAccContainerCluster_withIPAllocationPolicy_specificIPRanges(t *testing. ResourceName: "google_container_cluster.with_ip_allocation_policy", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2307,6 +2422,7 @@ func TestAccContainerCluster_withIPAllocationPolicy_specificSizes(t *testing.T) ResourceName: "google_container_cluster.with_ip_allocation_policy", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2334,7 +2450,7 @@ func TestAccContainerCluster_stackType_withDualStack(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2362,7 +2478,7 @@ func TestAccContainerCluster_stackType_withSingleStack(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2390,7 +2506,7 @@ func TestAccContainerCluster_with_PodCIDROverprovisionDisabled(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2417,7 +2533,7 @@ func TestAccContainerCluster_nodeAutoprovisioning(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioning(clusterName, false, false), @@ -2430,7 +2546,7 @@ func TestAccContainerCluster_nodeAutoprovisioning(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2458,7 +2574,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaults(clusterName, true), @@ -2472,7 +2588,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsMinCpuPlatform(clusterName, !includeMinCpuPlatform), @@ -2481,7 +2597,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaults(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2504,6 +2620,7 @@ func TestAccContainerCluster_autoprovisioningDefaultsUpgradeSettings(t *testing. ResourceName: "google_container_cluster.with_autoprovisioning_upgrade_settings", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsUpgradeSettings(clusterName, 2, 1, "BLUE_GREEN"), @@ -2516,6 +2633,7 @@ func TestAccContainerCluster_autoprovisioningDefaultsUpgradeSettings(t *testing. ResourceName: "google_container_cluster.with_autoprovisioning_upgrade_settings", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2542,7 +2660,7 @@ func TestAccContainerCluster_nodeAutoprovisioningNetworkTags(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2565,6 +2683,7 @@ func TestAccContainerCluster_withShieldedNodes(t *testing.T) { ResourceName: "google_container_cluster.with_shielded_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withShieldedNodes(clusterName, false), @@ -2573,6 +2692,7 @@ func TestAccContainerCluster_withShieldedNodes(t *testing.T) { ResourceName: "google_container_cluster.with_shielded_nodes", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2597,7 +2717,7 @@ func TestAccContainerCluster_withAutopilot(t *testing.T) { ResourceName: "google_container_cluster.with_autopilot", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2632,7 +2752,7 @@ func TestAccContainerClusterCustomServiceAccount_withAutopilot(t *testing.T) { ResourceName: "google_container_cluster.with_autopilot", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2677,7 +2797,7 @@ func TestAccContainerCluster_withAutopilotNetworkTags(t *testing.T) { ResourceName: "google_container_cluster.with_autopilot", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2701,7 +2821,7 @@ func TestAccContainerCluster_withWorkloadIdentityConfig(t *testing.T) { ResourceName: "google_container_cluster.with_workload_identity_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_updateWorkloadIdentityConfig(pid, clusterName, false), @@ -2710,7 +2830,7 @@ func TestAccContainerCluster_withWorkloadIdentityConfig(t *testing.T) { ResourceName: "google_container_cluster.with_workload_identity_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_updateWorkloadIdentityConfig(pid, clusterName, true), @@ -2719,7 +2839,7 @@ func TestAccContainerCluster_withWorkloadIdentityConfig(t *testing.T) { ResourceName: "google_container_cluster.with_workload_identity_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, }, }) @@ -2742,6 +2862,7 @@ func TestAccContainerCluster_withIdentityServiceConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withIdentityServiceConfigEnabled(clusterName), @@ -2750,6 +2871,7 @@ func TestAccContainerCluster_withIdentityServiceConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withIdentityServiceConfigUpdated(clusterName), @@ -2758,6 +2880,7 @@ func TestAccContainerCluster_withIdentityServiceConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_basic(clusterName), @@ -2766,6 +2889,7 @@ func TestAccContainerCluster_withIdentityServiceConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2788,6 +2912,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingConfigEnabled(clusterName), @@ -2796,6 +2921,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingConfigDisabled(clusterName), @@ -2804,6 +2930,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withLoggingConfigUpdated(clusterName), @@ -2812,6 +2939,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_basic(clusterName), @@ -2820,6 +2948,7 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2841,7 +2970,7 @@ func TestAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityCo ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityConfigDisabled(clusterName), @@ -2850,7 +2979,7 @@ func TestAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityCo ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2872,7 +3001,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigEnabled(clusterName), @@ -2881,7 +3010,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigDisabled(clusterName), @@ -2890,7 +3019,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigUpdated(clusterName), @@ -2899,7 +3028,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigPrometheusUpdated(clusterName), @@ -2908,7 +3037,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, // Back to basic settings to test setting Prometheus on its own { @@ -2918,7 +3047,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigPrometheusOnly(clusterName), @@ -2927,7 +3056,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withMonitoringConfigPrometheusOnly2(clusterName), @@ -2936,7 +3065,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_basic(clusterName), @@ -2945,7 +3074,7 @@ func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -2967,6 +3096,7 @@ func TestAccContainerCluster_withSoleTenantGroup(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -2992,6 +3122,7 @@ func TestAccContainerCluster_withAutoscalingProfile(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withAutoscalingProfile(clusterName, "OPTIMIZE_UTILIZATION"), @@ -3001,6 +3132,7 @@ func TestAccContainerCluster_withAutoscalingProfile(t *testing.T) { ImportStateIdPrefix: "us-central1-a/", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3048,6 +3180,7 @@ func TestAccContainerCluster_sharedVpc(t *testing.T) { ImportStateId: fmt.Sprintf("%s-service/us-central1-a/%s", projectName, clusterName), ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3070,7 +3203,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEnabledBool(t *testing.T) { ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"enable_binary_authorization"}, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withBinaryAuthorizationEnabledBool(clusterName, false), @@ -3079,38 +3212,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEnabledBool(t *testing.T) { ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool", ImportState: true, ImportStateVerify: true, - }, - }, - }) -} - -func TestAccContainerCluster_withBinaryAuthorizationEnabledBoolLegacy(t *testing.T) { - t.Parallel() - - clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccContainerCluster_withBinaryAuthorizationEnabledBoolLegacy(clusterName, true), - }, - { - ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool_legacy", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"enable_binary_authorization", "binary_authorization.#", "binary_authorization.0.%", "binary_authorization.0.enabled", "binary_authorization.0.evaluation_mode"}, - }, - { - Config: testAccContainerCluster_withBinaryAuthorizationEnabledBoolLegacy(clusterName, false), - }, - { - ResourceName: "google_container_cluster.with_binary_authorization_enabled_bool_legacy", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"enable_binary_authorization"}, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3133,6 +3235,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeAutopilot(t *t ResourceName: "google_container_cluster.with_binary_authorization_evaluation_mode", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withBinaryAuthorizationEvaluationMode(clusterName, true, "DISABLED"), @@ -3141,6 +3244,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeAutopilot(t *t ResourceName: "google_container_cluster.with_binary_authorization_evaluation_mode", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3163,6 +3267,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeClassic(t *tes ResourceName: "google_container_cluster.with_binary_authorization_evaluation_mode", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withBinaryAuthorizationEvaluationMode(clusterName, false, "DISABLED"), @@ -3171,6 +3276,7 @@ func TestAccContainerCluster_withBinaryAuthorizationEvaluationModeClassic(t *tes ResourceName: "google_container_cluster.with_binary_authorization_evaluation_mode", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3194,6 +3300,7 @@ func TestAccContainerCluster_withFlexiblePodCIDR(t *testing.T) { ResourceName: "google_container_cluster.with_flexible_cidr", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3218,7 +3325,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsDiskSizeGb(t *testing.T ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsDiskSizeGb(clusterName, !includeDiskSizeGb), @@ -3227,7 +3334,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsDiskSizeGb(t *testing.T ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3251,7 +3358,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsDiskType(t *testing.T) ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsDiskType(clusterName, !includeDiskType), @@ -3260,7 +3367,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsDiskType(t *testing.T) ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3284,7 +3391,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsImageType(t *testing.T) ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsImageType(clusterName, !includeImageType), @@ -3293,7 +3400,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsImageType(t *testing.T) ResourceName: "google_container_cluster.with_autoprovisioning", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3323,6 +3430,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsBootDiskKmsKey(t *testi ImportStateVerify: true, ImportStateVerifyIgnore: []string{ "min_master_version", + "deletion_protection", "node_pool", // cluster_autoscaling (node auto-provisioning) creates new node pools automatically }, }, @@ -3347,7 +3455,7 @@ func TestAccContainerCluster_nodeAutoprovisioningDefaultsShieldedInstance(t *tes ResourceName: "google_container_cluster.nap_shielded_instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3370,7 +3478,7 @@ func TestAccContainerCluster_autoprovisioningDefaultsManagement(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning_management", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autoprovisioningDefaultsManagement(clusterName, true, true), @@ -3379,12 +3487,15 @@ func TestAccContainerCluster_autoprovisioningDefaultsManagement(t *testing.T) { ResourceName: "google_container_cluster.with_autoprovisioning_management", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) } +// This resource originally cleaned up the dangling cluster directly, but now +// taints it, having Terraform clean it up during the next apply. This test +// name is now inexact, but is being preserved to maintain the test history. func TestAccContainerCluster_errorCleanDanglingCluster(t *testing.T) { t.Parallel() @@ -3405,18 +3516,19 @@ func TestAccContainerCluster_errorCleanDanglingCluster(t *testing.T) { Config: initConfig, }, { - ResourceName: "google_container_cluster.cidr_error_preempt", - ImportState: true, + ResourceName: "google_container_cluster.cidr_error_preempt", + ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: overlapConfig, + Config: overlapConfig, ExpectError: regexp.MustCompile("Error waiting for creating GKE cluster"), }, - // If dangling cluster wasn't deleted, this plan will return an error + // If tainted cluster won't be deleted, this step will return an error { - Config: overlapConfig, - PlanOnly: true, + Config: overlapConfig, + PlanOnly: true, ExpectNonEmptyPlan: true, }, }, @@ -3457,6 +3569,7 @@ func TestAccContainerCluster_withExternalIpsConfig(t *testing.T) { ResourceName: "google_container_cluster.with_external_ips_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withExternalIpsConfig(pid, clusterName, false), @@ -3465,6 +3578,7 @@ func TestAccContainerCluster_withExternalIpsConfig(t *testing.T) { ResourceName: "google_container_cluster.with_external_ips_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3488,7 +3602,7 @@ func TestAccContainerCluster_withMeshCertificatesConfig(t *testing.T) { ResourceName: "google_container_cluster.with_mesh_certificates_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_updateMeshCertificatesConfig(pid, clusterName, true), @@ -3497,7 +3611,7 @@ func TestAccContainerCluster_withMeshCertificatesConfig(t *testing.T) { ResourceName: "google_container_cluster.with_mesh_certificates_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, { Config: testAccContainerCluster_updateMeshCertificatesConfig(pid, clusterName, false), @@ -3506,7 +3620,7 @@ func TestAccContainerCluster_withMeshCertificatesConfig(t *testing.T) { ResourceName: "google_container_cluster.with_mesh_certificates_config", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"remove_default_node_pool"}, + ImportStateVerifyIgnore: []string{"remove_default_node_pool", "deletion_protection"}, }, }, }) @@ -3530,6 +3644,7 @@ func TestAccContainerCluster_withCostManagementConfig(t *testing.T) { ResourceName: "google_container_cluster.with_cost_management_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_updateCostManagementConfig(pid, clusterName, false), @@ -3538,6 +3653,7 @@ func TestAccContainerCluster_withCostManagementConfig(t *testing.T) { ResourceName: "google_container_cluster.with_cost_management_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3568,6 +3684,7 @@ func TestAccContainerCluster_withDatabaseEncryption(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_basic(clusterName), @@ -3576,6 +3693,7 @@ func TestAccContainerCluster_withDatabaseEncryption(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3598,6 +3716,7 @@ func TestAccContainerCluster_withAdvancedDatapath(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3622,6 +3741,7 @@ func TestAccContainerCluster_withResourceUsageExportConfig(t *testing.T) { ResourceName: "google_container_cluster.with_resource_usage_export_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withResourceUsageExportConfig(clusterName, datesetId, "false"), @@ -3630,6 +3750,7 @@ func TestAccContainerCluster_withResourceUsageExportConfig(t *testing.T) { ResourceName: "google_container_cluster.with_resource_usage_export_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_withResourceUsageExportConfigNoConfig(clusterName, datesetId), @@ -3638,6 +3759,7 @@ func TestAccContainerCluster_withResourceUsageExportConfig(t *testing.T) { ResourceName: "google_container_cluster.with_resource_usage_export_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3664,6 +3786,7 @@ func TestAccContainerCluster_withMasterAuthorizedNetworksDisabled(t *testing.T) ResourceName: "google_container_cluster.with_private_cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3687,6 +3810,7 @@ func TestAccContainerCluster_withEnableKubernetesAlpha(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3709,7 +3833,7 @@ func TestAccContainerCluster_withEnableKubernetesBetaAPIs(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3732,7 +3856,7 @@ func TestAccContainerCluster_withEnableKubernetesBetaAPIsOnExistingCluster(t *te ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withEnableKubernetesBetaAPIs(clusterName), @@ -3741,7 +3865,7 @@ func TestAccContainerCluster_withEnableKubernetesBetaAPIsOnExistingCluster(t *te ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3781,6 +3905,7 @@ func TestAccContainerCluster_withDNSConfig(t *testing.T) { ResourceName: "google_container_cluster.with_dns_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3805,7 +3930,7 @@ func TestAccContainerCluster_withGatewayApiConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withGatewayApiConfig(clusterName, "CHANNEL_STANDARD"), @@ -3814,7 +3939,7 @@ func TestAccContainerCluster_withGatewayApiConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3839,7 +3964,7 @@ func TestAccContainerCluster_withTPUConfig(t *testing.T) { ImportState: true, ImportStateVerify: true, // TODO: remove when tpu_config can be read from the API - ImportStateVerifyIgnore: []string{"tpu_config"}, + ImportStateVerifyIgnore: []string{"tpu_config", "deletion_protection"}, }, }, }) @@ -3862,7 +3987,7 @@ func TestAccContainerCluster_withProtectConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withProtectConfigUpdated(clusterName), @@ -3871,7 +3996,7 @@ func TestAccContainerCluster_withProtectConfig(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -3895,6 +4020,7 @@ func TestAccContainerCluster_withSecurityPostureConfig(t *testing.T) { ResourceName: "google_container_cluster.with_security_posture_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_SetWorkloadVulnerabilityToStandard(clusterName), @@ -3903,6 +4029,7 @@ func TestAccContainerCluster_withSecurityPostureConfig(t *testing.T) { ResourceName: "google_container_cluster.with_security_posture_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_DisableALL(clusterName), @@ -3911,6 +4038,7 @@ func TestAccContainerCluster_withSecurityPostureConfig(t *testing.T) { ResourceName: "google_container_cluster.with_security_posture_config", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3925,6 +4053,7 @@ resource "google_container_cluster" "with_security_posture_config" { security_posture_config { mode = "BASIC" } + deletion_protection = false } `, resource_name) } @@ -3938,6 +4067,7 @@ resource "google_container_cluster" "with_security_posture_config" { security_posture_config { vulnerability_mode = "VULNERABILITY_BASIC" } + deletion_protection = false } `, resource_name) } @@ -3952,6 +4082,7 @@ resource "google_container_cluster" "with_security_posture_config" { mode = "DISABLED" vulnerability_mode = "VULNERABILITY_DISABLED" } + deletion_protection = false } `, resource_name) } @@ -3972,6 +4103,7 @@ func TestAccContainerCluster_autopilot_minimal(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -3993,7 +4125,7 @@ func TestAccContainerCluster_autopilot_net_admin(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autopilot_net_admin(clusterName, false), @@ -4002,7 +4134,7 @@ func TestAccContainerCluster_autopilot_net_admin(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_autopilot_net_admin(clusterName, true), @@ -4011,7 +4143,7 @@ func TestAccContainerCluster_autopilot_net_admin(t *testing.T) { ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -4033,6 +4165,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_create(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -4054,6 +4187,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 2), @@ -4062,6 +4196,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 0), @@ -4070,6 +4205,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 1), @@ -4078,6 +4214,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { Config: testAccContainerCluster_additional_pod_ranges_config(clusterName, 0), @@ -4086,6 +4223,7 @@ func TestAccContainerCluster_additional_pod_ranges_config_on_update(t *testing.T ResourceName: "google_container_cluster.primary", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -4142,6 +4280,7 @@ resource "google_container_cluster" "primary" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } `, name) } @@ -4153,6 +4292,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 networking_mode = "ROUTES" + deletion_protection = false } `, name) } @@ -4187,6 +4327,7 @@ resource "google_container_cluster" "primary" { <% unless version == 'ga' -%> enable_intranode_visibility = true <% end -%> +deletion_protection = false } `, name) } @@ -4222,6 +4363,7 @@ resource "google_container_cluster" "primary" { <% unless version == 'ga' -%> enable_intranode_visibility = true <% end -%> + deletion_protection = false } `, name) } @@ -4284,6 +4426,7 @@ resource "google_container_cluster" "primary" { } <% end -%> } + deletion_protection = false } `, projectID, clusterName) } @@ -4347,6 +4490,7 @@ resource "google_container_cluster" "primary" { enabled = true } <% end -%> + deletion_protection = false } } `, projectID, clusterName) @@ -4385,6 +4529,7 @@ resource "google_container_cluster" "primary" { // load_balancer_type = "LOAD_BALANCER_TYPE_INTERNAL" // } // } +// deletion_protection = false // } // `, projectID, clusterName) // } @@ -4406,6 +4551,7 @@ resource "google_container_cluster" "notification_config" { topic = google_pubsub_topic.%s.id } } + deletion_protection = false } `, topic, topic, clusterName, topic) } @@ -4421,6 +4567,7 @@ resource "google_container_cluster" "notification_config" { enabled = false } } + deletion_protection = false } `, clusterName) } @@ -4446,6 +4593,7 @@ resource "google_container_cluster" "filtered_notification_config" { } } } + deletion_protection = false } `, topic, topic, clusterName, topic) } @@ -4471,6 +4619,7 @@ resource "google_container_cluster" "filtered_notification_config" { } } } + deletion_protection = false } `, topic, topic, clusterName, topic) } @@ -4493,6 +4642,7 @@ resource "google_container_cluster" "filtered_notification_config" { topic = google_pubsub_topic.%s.id } } + deletion_protection = false } `, topic, topic, clusterName, topic) } @@ -4517,6 +4667,7 @@ resource "google_container_cluster" "confidential_nodes" { confidential_nodes { enabled = true } + deletion_protection = false } `, clusterName, npName) } @@ -4541,6 +4692,7 @@ resource "google_container_cluster" "confidential_nodes" { confidential_nodes { enabled = false } + deletion_protection = false } `, clusterName, npName) } @@ -4563,6 +4715,7 @@ resource "google_container_cluster" "confidential_nodes" { } enable_l4_ilb_subsetting = true + deletion_protection = false } `, clusterName, npName) } @@ -4585,6 +4738,7 @@ resource "google_container_cluster" "confidential_nodes" { } enable_l4_ilb_subsetting = false + deletion_protection = false } `, clusterName, npName) } @@ -4607,10 +4761,22 @@ resource "google_container_cluster" "with_network_policy_enabled" { disabled = false } } + deletion_protection = false } `, clusterName) } +func testAccContainerCluster_withDeletionProtection(clusterName string, deletionProtection string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + + deletion_protection = %s +} +`, clusterName, deletionProtection) +} func testAccContainerCluster_withReleaseChannelEnabled(clusterName string, channel string) string { return fmt.Sprintf(` @@ -4622,6 +4788,7 @@ resource "google_container_cluster" "with_release_channel" { release_channel { channel = "%s" } + deletion_protection = false } `, clusterName, channel) } @@ -4638,6 +4805,7 @@ resource "google_container_cluster" "with_release_channel" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.release_channel_default_version["%s"] + deletion_protection = false } `, clusterName, channel) } @@ -4653,6 +4821,7 @@ resource "google_container_cluster" "with_cluster_telemetry" { cluster_telemetry { type = "%s" } + deletion_protection = false } `, clusterName, telemetryType) } @@ -4665,6 +4834,7 @@ resource "google_container_cluster" "with_network_policy_enabled" { location = "us-central1-a" initial_node_count = 1 remove_default_node_pool = true + deletion_protection = false } `, clusterName) } @@ -4680,6 +4850,7 @@ resource "google_container_cluster" "with_network_policy_enabled" { network_policy { enabled = false } + deletion_protection = false } `, clusterName) } @@ -4701,6 +4872,7 @@ resource "google_container_cluster" "with_network_policy_enabled" { disabled = true } } + deletion_protection = false } `, clusterName) } @@ -4715,6 +4887,7 @@ resource "google_container_cluster" "primary" { authenticator_groups_config { security_group = "gke-security-groups@%s" } + deletion_protection = false } `, name, orgDomain) } @@ -4729,6 +4902,7 @@ resource "google_container_cluster" "primary" { authenticator_groups_config { security_group = "" } + deletion_protection = false } `, name) } @@ -4758,6 +4932,7 @@ resource "google_container_cluster" "with_master_authorized_networks" { master_authorized_networks_config { %s } + deletion_protection = false } `, clusterName, cidrBlocks) } @@ -4768,6 +4943,7 @@ resource "google_container_cluster" "with_master_authorized_networks" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -4778,6 +4954,7 @@ resource "google_container_cluster" "regional" { name = "%s" location = "us-central1" initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -4808,7 +4985,7 @@ func TestAccContainerCluster_withPrivateEndpointSubnetwork(t *testing.T) { ResourceName: "google_container_cluster.with_private_endpoint_subnetwork", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -4853,6 +5030,7 @@ resource "google_container_cluster" "with_private_endpoint_subnetwork" { private_cluster_config { private_endpoint_subnetwork = google_compute_subnetwork.container_subnetwork2.name } + deletion_protection = false } `, containerNetName, s1Name, s1Cidr, s2Name, s2Cidr, clusterName) } @@ -4877,7 +5055,7 @@ func TestAccContainerCluster_withPrivateClusterConfigPrivateEndpointSubnetwork(t ResourceName: "google_container_cluster.with_private_endpoint_subnetwork", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -4929,6 +5107,7 @@ resource "google_container_cluster" "with_private_endpoint_subnetwork" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName) } @@ -4950,7 +5129,7 @@ func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { ResourceName: "google_container_cluster.with_enable_private_endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, { Config: testAccContainerCluster_withEnablePrivateEndpoint(clusterName, "false"), @@ -4959,7 +5138,7 @@ func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { ResourceName: "google_container_cluster.with_enable_private_endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, }) @@ -5013,6 +5192,7 @@ resource "google_container_cluster" "with_enable_private_endpoint" { private_cluster_config { enable_private_endpoint = %s } + deletion_protection = false } `, clusterName, flag) } @@ -5026,6 +5206,7 @@ resource "google_container_cluster" "regional" { node_pool { name = "%s" } + deletion_protection = false } `, cluster, nodePool) } @@ -5041,6 +5222,7 @@ resource "google_container_cluster" "with_node_locations" { "us-central1-f", "us-central1-c", ] + deletion_protection = false } `, clusterName) } @@ -5056,6 +5238,7 @@ resource "google_container_cluster" "with_node_locations" { "us-central1-f", "us-central1-b", ] + deletion_protection = false } `, clusterName) } @@ -5111,6 +5294,7 @@ resource "google_container_cluster" "with_tpu" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName) } @@ -5123,6 +5307,7 @@ resource "google_container_cluster" "with_intranode_visibility" { location = "us-central1-a" initial_node_count = 1 enable_intranode_visibility = true + deletion_protection = false } `, clusterName) } @@ -5135,6 +5320,7 @@ resource "google_container_cluster" "with_intranode_visibility" { initial_node_count = 1 enable_intranode_visibility = false private_ipv6_google_access = "PRIVATE_IPV6_GOOGLE_ACCESS_BIDIRECTIONAL" + deletion_protection = false } `, clusterName) } @@ -5150,6 +5336,7 @@ resource "google_container_cluster" "with_version" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -5165,6 +5352,7 @@ resource "google_container_cluster" "with_version" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.valid_master_versions[3] initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -5180,6 +5368,7 @@ resource "google_container_cluster" "with_master_auth_no_cert" { issue_client_certificate = false } } + deletion_protection = false } `, clusterName) } @@ -5196,6 +5385,7 @@ resource "google_container_cluster" "with_version" { min_master_version = data.google_container_engine_versions.central1a.latest_master_version node_version = data.google_container_engine_versions.central1a.valid_node_versions[1] initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -5245,6 +5435,7 @@ resource "google_container_cluster" "with_node_config" { // Updatable fields image_type = "COS_CONTAINERD" } + deletion_protection = false } `, clusterName) } @@ -5259,6 +5450,7 @@ resource "google_container_cluster" "with_logging_variant_in_node_config" { node_config { logging_variant = "%s" } + deletion_protection = false } `, clusterName, loggingVariant) } @@ -5276,6 +5468,7 @@ resource "google_container_cluster" "with_logging_variant_in_node_pool" { logging_variant = "%s" } } + deletion_protection = false } `, clusterName, nodePoolName, loggingVariant) } @@ -5292,6 +5485,7 @@ resource "google_container_cluster" "with_logging_variant_node_pool_default" { logging_variant = "%s" } } + deletion_protection = false } `, clusterName, loggingVariant) } @@ -5311,6 +5505,7 @@ resource "google_container_cluster" "with_node_pool_defaults" { } } } + deletion_protection = false } `, clusterName, enabled) } @@ -5361,6 +5556,7 @@ resource "google_container_cluster" "with_node_config" { // Updatable fields image_type = "UBUNTU_CONTAINERD" } + deletion_protection = false } `, clusterName) } @@ -5377,6 +5573,7 @@ resource "google_container_cluster" "with_node_config_scope_alias" { disk_size_gb = 15 oauth_scopes = ["compute-rw", "storage-ro", "logging-write", "monitoring"] } + deletion_protection = false } `, clusterName) } @@ -5417,6 +5614,7 @@ resource "google_container_cluster" "with_node_config" { enable_integrity_monitoring = true } } + deletion_protection = false } `, clusterName) } @@ -5456,6 +5654,7 @@ resource "google_container_cluster" "with_node_config" { consume_reservation_type = "ANY_RESERVATION" } } + deletion_protection = false } `, clusterName) } @@ -5526,6 +5725,7 @@ resource "google_container_cluster" "with_node_config" { ] } } + deletion_protection = false depends_on = [google_project_service.container] } `, reservation, clusterName) @@ -5553,6 +5753,7 @@ resource "google_container_cluster" "with_workload_metadata_config" { mode = "GCE_METADATA" } } + deletion_protection = false } `, clusterName) } @@ -5593,6 +5794,7 @@ resource "google_container_cluster" "with_sandbox_config" { effect = "NO_SCHEDULE" } } + deletion_protection = false } `, clusterName) } @@ -5633,6 +5835,7 @@ resource "google_container_cluster" "with_sandbox_config" { effect = "NO_SCHEDULE" } } + deletion_protection = false } `, clusterName) } @@ -5656,6 +5859,7 @@ resource "google_container_cluster" "with_boot_disk_kms_key" { boot_disk_kms_key = "%s" } + deletion_protection = false } `, clusterName, kmsKeyName) } @@ -5673,6 +5877,7 @@ resource "google_container_cluster" "with_net_ref_by_url" { initial_node_count = 1 network = google_compute_network.container_network.self_link + deletion_protection = false } resource "google_container_cluster" "with_net_ref_by_name" { @@ -5681,6 +5886,7 @@ resource "google_container_cluster" "with_net_ref_by_name" { initial_node_count = 1 network = google_compute_network.container_network.name + deletion_protection = false } `, network, cluster, cluster) } @@ -5712,6 +5918,7 @@ resource "google_container_cluster" "with_autoprovisioning_management" { } } } + deletion_protection = false } `, clusterName, autoUpgrade, autoRepair) } @@ -5755,6 +5962,7 @@ resource "google_container_cluster" "primary" { "https://www.googleapis.com/auth/monitoring", ] } + deletion_protection = false } `, cluster, cluster, cluster) } @@ -5764,6 +5972,7 @@ func testAccContainerCluster_withNodePoolBasic(cluster, nodePool string) string resource "google_container_cluster" "with_node_pool" { name = "%s" location = "us-central1-a" + deletion_protection = false node_pool { name = "%s" @@ -5790,6 +5999,7 @@ resource "google_container_cluster" "with_node_pool" { initial_node_count = 2 version = data.google_container_engine_versions.central1a.valid_node_versions[2] } + deletion_protection = false } `, cluster, nodePool) } @@ -5811,6 +6021,7 @@ resource "google_container_cluster" "with_node_pool" { initial_node_count = 2 version = data.google_container_engine_versions.central1a.valid_node_versions[1] } + deletion_protection = false } `, cluster, nodePool) } @@ -5830,6 +6041,7 @@ resource "google_container_cluster" "with_node_pool" { name = "%s" node_count = 2 } + deletion_protection = false } `, cluster, nodePool) } @@ -5849,6 +6061,7 @@ resource "google_container_cluster" "with_node_pool" { name = "%s" node_count = 3 } + deletion_protection = false } `, cluster, nodePool) } @@ -5865,6 +6078,7 @@ resource "google_container_cluster" "autoscaling_with_profile" { enabled = false autoscaling_profile = "%s" } + deletion_protection = false } `, cluster, autoscalingProfile) return config @@ -5882,6 +6096,7 @@ resource "google_container_cluster" "with_autoprovisioning" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false `, cluster) if autoprovisioning { config += ` @@ -5926,6 +6141,7 @@ resource "google_container_cluster" "with_autoprovisioning" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false logging_service = "none" monitoring_service = "none" @@ -5994,6 +6210,7 @@ resource "google_container_cluster" "with_autoprovisioning" { %s } } + deletion_protection = false }`, cluster, minCpuPlatformCfg) } @@ -6039,6 +6256,7 @@ func testAccContainerCluster_autoprovisioningDefaultsUpgradeSettings(clusterName } } } + deletion_protection = false } `, clusterName, maxSurge, maxUnavailable, strategy, blueGreenSettings) } @@ -6076,6 +6294,7 @@ func testAccContainerCluster_autoprovisioningDefaultsUpgradeSettingsWithBlueGree } } } + deletion_protection = false } `, clusterName, strategy, duration, duration) } @@ -6109,6 +6328,7 @@ resource "google_container_cluster" "with_autoprovisioning" { %s } } + deletion_protection = false }`, cluster, DiskSizeGbCfg) } @@ -6141,6 +6361,7 @@ resource "google_container_cluster" "with_autoprovisioning" { %s } } + deletion_protection = false }`, cluster, DiskTypeCfg) } @@ -6173,6 +6394,7 @@ resource "google_container_cluster" "with_autoprovisioning" { %s } } + deletion_protection = false }`, cluster, imageTypeCfg) } @@ -6199,6 +6421,7 @@ resource "google_container_cluster" "nap_boot_disk_kms_key" { boot_disk_kms_key = "%s" } } + deletion_protection = false } `, clusterName, kmsKeyName) } @@ -6230,6 +6453,7 @@ resource "google_container_cluster" "nap_shielded_instance" { } } } + deletion_protection = false }`, cluster) } @@ -6247,6 +6471,7 @@ resource "google_container_cluster" "with_node_pool" { max_node_count = 3 } } + deletion_protection = false } `, cluster, np) } @@ -6265,6 +6490,7 @@ resource "google_container_cluster" "with_node_pool" { max_node_count = 5 } } + deletion_protection = false } `, cluster, np) } @@ -6289,6 +6515,7 @@ resource "google_container_cluster" "with_node_pool" { location_policy = "BALANCED" } } + deletion_protection = false } `, cluster, np) } @@ -6313,6 +6540,7 @@ resource "google_container_cluster" "with_node_pool" { location_policy = "ANY" } } + deletion_protection = false } `, cluster, np) } @@ -6332,6 +6560,7 @@ resource "google_container_cluster" "with_node_pool" { name = "%s" initial_node_count = 2 } + deletion_protection = false } `, cluster, nodePool) } @@ -6346,6 +6575,7 @@ resource "google_container_cluster" "with_node_pool_name_prefix" { name_prefix = "%s" node_count = 2 } + deletion_protection = false } `, cluster, npPrefix) } @@ -6365,6 +6595,7 @@ resource "google_container_cluster" "with_node_pool_multiple" { name = "%s-two" node_count = 3 } + deletion_protection = false } `, cluster, npPrefix, npPrefix) } @@ -6381,6 +6612,7 @@ resource "google_container_cluster" "with_node_pool_multiple" { name_prefix = "%s" node_count = 1 } + deletion_protection = false } `, cluster, npPrefix, npPrefix) } @@ -6415,6 +6647,7 @@ resource "google_container_cluster" "with_node_pool_node_config" { tags = ["foo", "bar"] } } + deletion_protection = false } `, cluster, np) } @@ -6436,6 +6669,7 @@ resource "google_container_cluster" "with_maintenance_window" { location = "us-central1-a" initial_node_count = 1 %s + deletion_protection = false } `, clusterName, maintenancePolicy) } @@ -6459,6 +6693,7 @@ resource "google_container_cluster" "with_recurring_maintenance_window" { location = "us-central1-a" initial_node_count = 1 %s + deletion_protection = false } `, clusterName, maintenancePolicy) @@ -6489,6 +6724,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_window" { end_time = "%s" } } + deletion_protection = false } `, clusterName, w1startTime, w1endTime, w1startTime, w1endTime, w2startTime, w2endTime) } @@ -6524,6 +6760,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_options" { } } } + deletion_protection = false } `, cclusterName, w1startTime, w1endTime, w1startTime, w1endTime, scope1, w2startTime, w2endTime, scope2) } @@ -6553,6 +6790,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_options" { end_time = "%s" } } + deletion_protection = false } `, cclusterName, w1startTime, w1endTime, w1startTime, w1endTime, w2startTime, w2endTime) } @@ -6564,6 +6802,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_options" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false maintenance_policy { recurring_window { @@ -6607,6 +6846,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_window" { recurrence = "FREQ=DAILY" } } + deletion_protection = false } `, clusterName, w1startTime, w1endTime) } @@ -6629,6 +6869,7 @@ resource "google_container_cluster" "with_maintenance_exclusion_window" { end_time = "%s" } } + deletion_protection = false } `, clusterName, w1startTime, w1endTime) } @@ -6670,6 +6911,7 @@ resource "google_container_cluster" "with_ip_allocation_policy" { cluster_secondary_range_name = "pods" services_secondary_range_name = "services" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6702,6 +6944,7 @@ resource "google_container_cluster" "with_ip_allocation_policy" { cluster_ipv4_cidr_block = "10.0.0.0/16" services_ipv4_cidr_block = "10.1.0.0/16" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6734,6 +6977,7 @@ resource "google_container_cluster" "with_ip_allocation_policy" { cluster_ipv4_cidr_block = "/16" services_ipv4_cidr_block = "/22" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6771,6 +7015,7 @@ resource "google_container_cluster" "with_stack_type" { services_ipv4_cidr_block = "10.1.0.0/16" stack_type = "IPV4_IPV6" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6805,6 +7050,7 @@ resource "google_container_cluster" "with_stack_type" { services_ipv4_cidr_block = "10.1.0.0/16" stack_type = "IPV4" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6837,10 +7083,11 @@ resource "google_container_cluster" "with_pco_disabled" { ip_allocation_policy { cluster_ipv4_cidr_block = "10.1.0.0/16" services_ipv4_cidr_block = "10.2.0.0/16" - pod_cidr_overprovision_config { - disabled = true - } + pod_cidr_overprovision_config { + disabled = true + } } + deletion_protection = false } `, containerNetName, clusterName) } @@ -6869,6 +7116,7 @@ resource "google_container_cluster" "with_resource_usage_export_config" { dataset_id = google_bigquery_dataset.default.dataset_id } } + deletion_protection = false } `, datasetId, clusterName, enableMetering) } @@ -6885,6 +7133,7 @@ resource "google_container_cluster" "with_resource_usage_export_config" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } `, datasetId, clusterName) } @@ -6936,6 +7185,7 @@ resource "google_container_cluster" "with_private_cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName, location, autopilotEnabled) } @@ -6991,6 +7241,7 @@ resource "google_container_cluster" "with_private_cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName, masterGlobalAccessEnabled) } @@ -7007,6 +7258,7 @@ resource "google_container_cluster" "with_private_cluster" { enabled = %t } } + deletion_protection = false } `, clusterName, masterGlobalAccessEnabled) } @@ -7019,6 +7271,7 @@ resource "google_container_cluster" "with_shielded_nodes" { initial_node_count = 1 enable_shielded_nodes = %v + deletion_protection = false } `, clusterName, enabled) } @@ -7038,6 +7291,7 @@ resource "google_container_cluster" "with_workload_identity_config" { workload_pool = "${data.google_project.project.project_id}.svc.id.goog" } remove_default_node_pool = true + deletion_protection = false } `, projectID, clusterName) @@ -7067,6 +7321,7 @@ resource "google_container_cluster" "with_workload_identity_config" { initial_node_count = 1 remove_default_node_pool = true %s + deletion_protection = false } `, projectID, clusterName, workloadIdentityConfig) } @@ -7175,6 +7430,7 @@ resource "google_container_cluster" "shared_vpc_cluster" { google_compute_subnetwork_iam_member.service_network_cloud_services, google_compute_subnetwork_iam_member.service_network_gke_user, ] + deletion_protection = false } `, projectName, org, billingId, projectName, org, billingId, suffix, suffix, name) } @@ -7189,18 +7445,7 @@ resource "google_container_cluster" "with_binary_authorization_enabled_bool" { binary_authorization { enabled = %v } -} -`, clusterName, enabled) -} - -func testAccContainerCluster_withBinaryAuthorizationEnabledBoolLegacy(clusterName string, enabled bool) string { - return fmt.Sprintf(` -resource "google_container_cluster" "with_binary_authorization_enabled_bool_legacy" { - name = "%s" - location = "us-central1-a" - initial_node_count = 1 - - enable_binary_authorization = %v + deletion_protection = false } `, clusterName, enabled) } @@ -7218,6 +7463,7 @@ resource "google_container_cluster" "with_binary_authorization_evaluation_mode" binary_authorization { evaluation_mode = "%s" } + deletion_protection = false } `, clusterName, autopilot_enabled, evaluation_mode) } @@ -7271,6 +7517,7 @@ resource "google_container_cluster" "with_flexible_cidr" { } default_max_pods_per_node = 100 + deletion_protection = false } `, containerNetName, clusterName) } @@ -7303,6 +7550,7 @@ resource "google_container_cluster" "cidr_error_preempt" { cluster_ipv4_cidr_block = "10.0.0.0/16" services_ipv4_cidr_block = "10.1.0.0/16" } + deletion_protection = false } `, containerNetName, clusterName) } @@ -7325,6 +7573,7 @@ resource "google_container_cluster" "cidr_error_overlap" { cluster_ipv4_cidr_block = "10.0.0.0/16" services_ipv4_cidr_block = "10.1.0.0/16" } + deletion_protection = false } `, initConfig, secondCluster) } @@ -7335,6 +7584,7 @@ resource "google_container_cluster" "with_resource_labels" { name = "invalid-gke-cluster" location = "%s" initial_node_count = 1 + deletion_protection = false } `, location) } @@ -7352,6 +7602,7 @@ func testAccContainerCluster_withExternalIpsConfig(projectID string, clusterName service_external_ips_config { enabled = %v } + deletion_protection = false }`, projectID, clusterName, enabled) } @@ -7372,6 +7623,7 @@ func testAccContainerCluster_withMeshCertificatesConfigEnabled(projectID string, mesh_certificates { enable_certificates = true } + deletion_protection = false } `, projectID, clusterName) } @@ -7390,9 +7642,10 @@ func testAccContainerCluster_updateMeshCertificatesConfig(projectID string, clus workload_identity_config { workload_pool = "${data.google_project.project.project_id}.svc.id.goog" } - mesh_certificates { + mesh_certificates { enable_certificates = %v - } + } + deletion_protection = false }`, projectID, clusterName, enabled) } @@ -7409,6 +7662,7 @@ func testAccContainerCluster_updateCostManagementConfig(projectID string, cluste cost_management_config { enabled = %v } + deletion_protection = false }`, projectID, clusterName, enabled) } @@ -7445,6 +7699,7 @@ resource "google_container_cluster" "primary" { state = "ENCRYPTED" key_name = "%[2]s" } + deletion_protection = false } `, kmsData.KeyRing.Name, kmsData.CryptoKey.Name, clusterName) } @@ -7463,6 +7718,7 @@ resource "google_container_cluster" "primary" { release_channel { channel = "RAPID" } + deletion_protection = false } `, clusterName, datapathProvider) } @@ -7511,6 +7767,7 @@ resource "google_container_cluster" "with_private_cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, containerNetName, clusterName) } @@ -7530,6 +7787,7 @@ resource "google_container_cluster" "primary" { auto_upgrade = false } } + deletion_protection = false } `, cluster, np) } @@ -7545,6 +7803,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.release_channel_latest_version["STABLE"] initial_node_count = 1 + deletion_protection = false } `, clusterName) } @@ -7560,6 +7819,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] initial_node_count = 1 + deletion_protection = false # This feature has been available since GKE 1.27, and currently the only # supported Beta API is authentication.k8s.io/v1beta1/selfsubjectreviews. @@ -7599,6 +7859,7 @@ resource "google_container_cluster" "primary" { enable_private_nodes = false master_ipv4_cidr_block = "10.42.0.0/28" } + deletion_protection = false } `, name) } @@ -7664,6 +7925,7 @@ resource "google_container_cluster" "with_autopilot" { name = "%s" location = "%s" enable_autopilot = %v + deletion_protection = false min_master_version = "latest" release_channel { channel = "RAPID" @@ -7707,6 +7969,7 @@ resource "google_container_cluster" "with_dns_config" { cluster_dns_domain = "%s" cluster_dns_scope = "%s" } + deletion_protection = false } `, clusterName, clusterDns, clusterDnsDomain, clusterDnsScope) } @@ -7725,6 +7988,7 @@ resource "google_container_cluster" "primary" { gateway_api_config { channel = "%s" } + deletion_protection = false } `, clusterName, gatewayApiChannel) } @@ -7739,6 +8003,7 @@ resource "google_container_cluster" "primary" { identity_service_config { enabled = true } + deletion_protection = false } `, name) } @@ -7752,6 +8017,7 @@ resource "google_container_cluster" "primary" { identity_service_config { enabled = false } + deletion_protection = false } `, name) } @@ -7769,6 +8035,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [ "SYSTEM_COMPONENTS" ] } + deletion_protection = false } `, name) } @@ -7782,6 +8049,7 @@ resource "google_container_cluster" "primary" { logging_config { enable_components = [] } + deletion_protection = false } `, name) } @@ -7798,6 +8066,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [ "SYSTEM_COMPONENTS" ] } + deletion_protection = false } `, name) } @@ -7815,6 +8084,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [ "SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER", "SCHEDULER" ] } + deletion_protection = false } `, name) } @@ -7828,6 +8098,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [] } + deletion_protection = false } `, name) } @@ -7841,6 +8112,7 @@ resource "google_container_cluster" "primary" { monitoring_config { enable_components = [ "SYSTEM_COMPONENTS", "APISERVER", "CONTROLLER_MANAGER" ] } + deletion_protection = false } `, name) } @@ -7857,6 +8129,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } `, name) } @@ -7873,6 +8146,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } `, name) } @@ -7888,6 +8162,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } `, name) } @@ -7937,6 +8212,7 @@ resource "google_container_cluster" "primary" { relay_mode = "INTERNAL_VPC_LB" } } + deletion_protection = false } `, name, name) } @@ -7986,6 +8262,7 @@ resource "google_container_cluster" "primary" { relay_mode = "DISABLED" } } + deletion_protection = false } `, name, name) } @@ -8003,7 +8280,7 @@ resource "google_compute_node_group" "group" { zone = "us-central1-f" description = "example google_compute_node_group for Terraform Google Provider" - size = 1 + initial_size = 1 node_template = google_compute_node_template.soletenant-tmpl.id } @@ -8017,6 +8294,7 @@ resource "google_container_cluster" "primary" { disk_type = "pd-ssd" node_group = google_compute_node_group.group.name } + deletion_protection = false } `, name, name, name) } @@ -8074,6 +8352,7 @@ resource "google_container_cluster" "with_tpu_config" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } `, network, cluster) } @@ -8094,6 +8373,7 @@ resource "google_container_cluster" "primary" { timeouts { create = "40s" } + deletion_protection = false }`, cluster, project, project) } @@ -8108,6 +8388,7 @@ resource "google_container_cluster" "primary" { workload_identity_config { workload_pool = "%s.svc.id.goog" } + deletion_protection = false }`, cluster, project, project) } @@ -8125,6 +8406,7 @@ resource "google_container_cluster" "primary" { } workload_vulnerability_mode = "BASIC" } + deletion_protection = false } `, name) } @@ -8142,6 +8424,7 @@ resource "google_container_cluster" "primary" { } workload_vulnerability_mode = "DISABLED" } + deletion_protection = false } `, name) } @@ -8154,6 +8437,7 @@ resource "google_container_cluster" "primary" { name = "%s" location = "us-central1" enable_autopilot = true + deletion_protection = false }`, name) } @@ -8165,6 +8449,7 @@ resource "google_container_cluster" "primary" { enable_autopilot = true allow_net_admin = %t min_master_version = 1.27 + deletion_protection = false }`, name, enabled) } @@ -8193,6 +8478,7 @@ func TestAccContainerCluster_customPlacementPolicy(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -8226,6 +8512,7 @@ resource "google_container_cluster" "cluster" { policy_name = google_compute_resource_policy.policy.name } } + deletion_protection = false }`, policyName, cluster, np) } @@ -8305,6 +8592,7 @@ func testAccContainerCluster_additional_pod_ranges_config(name string, nameCount services_secondary_range_name = "gke-autopilot-services" %s } + deletion_protection = false } `, name, name, name, aprc) } diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb index 1eca550efe8c..06078da73d3b 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb @@ -48,6 +48,7 @@ func ResourceContainerNodePool() *schema.Resource { }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, resourceNodeConfigEmptyGuestAccelerator, ), @@ -292,15 +293,15 @@ var schemaNodePool = map[string]*schema.Schema{ "auto_repair": { Type: schema.TypeBool, Optional: true, - Default: false, - Description: `Whether the nodes will be automatically repaired.`, + Default: true, + Description: `Whether the nodes will be automatically repaired. Enabled by default.`, }, "auto_upgrade": { Type: schema.TypeBool, Optional: true, - Default: false, - Description: `Whether the nodes will be automatically upgraded.`, + Default: true, + Description: `Whether the nodes will be automatically upgraded. Enabled by default.`, }, }, }, @@ -1111,7 +1112,7 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c "initial_node_count": np.InitialNodeCount, "node_locations": schema.NewSet(schema.HashString, tpgresource.ConvertStringArrToInterface(np.Locations)), "node_count": nodeCount, - "node_config": flattenNodeConfig(np.Config), + "node_config": flattenNodeConfig(np.Config, d.Get(prefix + "node_config")), "instance_group_urls": igmUrls, "managed_instance_group_urls": managedIgmUrls, "version": np.Version, diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb index d80c9c89ece3..0de1dfc1e04c 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb @@ -215,7 +215,7 @@ func TestAccContainerNodePool_withNodeConfig(t *testing.T) { ImportStateVerify: true, // autoscaling.# = 0 is equivalent to no autoscaling at all, // but will still cause an import diff - ImportStateVerifyIgnore: []string{"autoscaling.#"}, + ImportStateVerifyIgnore: []string{"autoscaling.#", "node_config.0.taint"}, }, resource.TestStep{ Config: testAccContainerNodePool_withNodeConfigUpdate(cluster, nodePool), @@ -226,7 +226,7 @@ func TestAccContainerNodePool_withNodeConfig(t *testing.T) { ImportStateVerify: true, // autoscaling.# = 0 is equivalent to no autoscaling at all, // but will still cause an import diff - ImportStateVerifyIgnore: []string{"autoscaling.#"}, + ImportStateVerifyIgnore: []string{"autoscaling.#", "node_config.0.taint"}, }, }, }) @@ -361,32 +361,6 @@ func TestAccContainerNodePool_withSandboxConfig(t *testing.T) { ImportState: true, ImportStateVerify: true, }, - { - // GKE sets automatic labels and taints on nodes. This makes - // sure we ignore the automatic ones and keep our own. - Config: testAccContainerNodePool_withSandboxConfig(cluster, np), - // When we use PlanOnly without ExpectNonEmptyPlan, we're - // guaranteeing that the computed fields of the resources don't - // force an unintentional change to the plan. That is, we - // expect this part of the test to pass only if the plan - // doesn't change. - PlanOnly: true, - }, - { - // Now we'll modify the taints, which should force a change to - // the plan. We make sure we don't over-suppress and end up - // eliminating the labels or taints we asked for. This will - // destroy and recreate the node pool as taints are immutable. - Config: testAccContainerNodePool_withSandboxConfig_changeTaints(cluster, np), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("google_container_node_pool.with_sandbox_config", - "node_config.0.labels.test.terraform.io/gke-sandbox", "true"), - resource.TestCheckResourceAttr("google_container_node_pool.with_sandbox_config", - "node_config.0.taint.0.key", "test.terraform.io/gke-sandbox"), - resource.TestCheckResourceAttr("google_container_node_pool.with_sandbox_config", - "node_config.0.taint.1.key", "test.terraform.io/gke-sandbox-amended"), - ), - }, }, }) } @@ -551,7 +525,7 @@ func TestAccContainerNodePool_withMultiNicNetworkConfig(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"network_config.0.create_pod_range"}, + ImportStateVerifyIgnore: []string{"network_config.0.create_pod_range", "deletion_protection"}, }, }, }) @@ -630,6 +604,7 @@ resource "google_container_cluster" "cluster" { cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name } + deletion_protection = false } resource "google_container_node_pool" "with_enable_private_nodes" { @@ -1297,6 +1272,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1352,6 +1328,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1406,6 +1383,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1453,6 +1431,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1501,6 +1480,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1566,6 +1546,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-f" initial_node_count = 1 min_master_version = "1.25" + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1610,6 +1591,7 @@ func TestAccContainerNodePool_compactPlacement(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1621,6 +1603,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1674,6 +1657,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_compute_resource_policy" "policy" { @@ -1719,6 +1703,7 @@ func TestAccContainerNodePool_threadsPerCore(t *testing.T) { ResourceName: "google_container_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, }) @@ -1730,6 +1715,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false node_config { machine_type = "c2-standard-4" @@ -1802,6 +1788,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1820,6 +1807,7 @@ resource "google_container_cluster" "with_logging_variant" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "with_logging_variant" { @@ -1845,6 +1833,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1901,6 +1890,7 @@ resource "google_container_cluster" "cluster" { master_authorized_networks_config { } + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1959,6 +1949,7 @@ resource "google_container_cluster" "cluster" { master_authorized_networks_config { } + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1977,6 +1968,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -1994,6 +1986,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2011,6 +2004,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2027,6 +2021,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2049,6 +2044,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1" initial_node_count = 3 min_master_version = "1.27" + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2072,6 +2068,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1" initial_node_count = 3 min_master_version = "1.27" + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2101,6 +2098,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1" initial_node_count = 3 min_master_version = "1.27" + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2119,6 +2117,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2140,6 +2139,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2166,6 +2166,7 @@ resource "google_container_cluster" "cluster" { "us-central1-b", "us-central1-c", ] + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2188,6 +2189,7 @@ resource "google_container_cluster" "cluster" { "us-central1-b", "us-central1-c", ] + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -2208,6 +2210,7 @@ resource "google_container_cluster" "cluster" { release_channel { channel = "UNSPECIFIED" } + deletion_protection = false } resource "google_container_node_pool" "np_with_management" { @@ -2233,6 +2236,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np_with_node_config" { @@ -2287,6 +2291,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np_with_node_config" { @@ -2348,6 +2353,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_reservation_affinity" { @@ -2380,6 +2386,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_compute_reservation" "gce_reservation" { @@ -2431,6 +2438,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_workload_metadata_config" { @@ -2472,6 +2480,7 @@ resource "google_container_cluster" "cluster" { workload_identity_config { workload_pool = "${data.google_project.project.project_id}.svc.id.goog" } + deletion_protection = false } resource "google_container_node_pool" "with_workload_metadata_config" { @@ -2505,6 +2514,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_sandbox_config" { @@ -2524,63 +2534,6 @@ resource "google_container_node_pool" "with_sandbox_config" { "test.terraform.io/gke-sandbox" = "true" } - taint { - key = "test.terraform.io/gke-sandbox" - value = "true" - effect = "NO_SCHEDULE" - } - - oauth_scopes = [ - "https://www.googleapis.com/auth/logging.write", - "https://www.googleapis.com/auth/monitoring", - ] - } -} -`, cluster, np) -} - -func testAccContainerNodePool_withSandboxConfig_changeTaints(cluster, np string) string { - return fmt.Sprintf(` -data "google_container_engine_versions" "central1a" { - location = "us-central1-a" -} - -resource "google_container_cluster" "cluster" { - name = "%s" - location = "us-central1-a" - initial_node_count = 1 - min_master_version = data.google_container_engine_versions.central1a.latest_master_version -} - -resource "google_container_node_pool" "with_sandbox_config" { - name = "%s" - location = "us-central1-a" - cluster = google_container_cluster.cluster.name - initial_node_count = 1 - node_config { - machine_type = "n1-standard-1" // can't be e2 because of gvisor - image_type = "COS_CONTAINERD" - - sandbox_config { - sandbox_type = "gvisor" - } - - labels = { - "test.terraform.io/gke-sandbox" = "true" - } - - taint { - key = "test.terraform.io/gke-sandbox" - value = "true" - effect = "NO_SCHEDULE" - } - - taint { - key = "test.terraform.io/gke-sandbox-amended" - value = "also-true" - effect = "NO_SCHEDULE" - } - oauth_scopes = [ "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring", @@ -2602,6 +2555,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } # cpu_manager_policy & cpu_cfs_quota_period cannot be blank if cpu_cfs_quota is set to true @@ -2623,6 +2577,7 @@ resource "google_container_node_pool" "with_kubelet_config" { "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring", ] + logging_variant = "DEFAULT" } } `, cluster, np, policy, quota, period, podPidsLimit) @@ -2662,6 +2617,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_linux_node_config" { @@ -2732,6 +2688,7 @@ resource "google_container_cluster" "cluster" { release_channel { channel = "RAPID" } + deletion_protection = false } resource "google_container_node_pool" "with_manual_pod_cidr" { @@ -2869,6 +2826,7 @@ resource "google_container_cluster" "cluster" { } enable_multi_networking = true datapath_provider = "ADVANCED_DATAPATH" + deletion_protection = false } resource "google_container_node_pool" "with_multi_nic" { @@ -2930,6 +2888,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_boot_disk_kms_key" { @@ -2987,6 +2946,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1" initial_node_count = 1 min_master_version = "${data.google_container_engine_versions.central1.latest_master_version}" + deletion_protection = false } resource "google_container_node_pool" "with_upgrade_settings" { @@ -3010,6 +2970,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-c" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1c.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "np_with_gpu" { @@ -3059,6 +3020,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np_with_node_config_scope_alias" { @@ -3086,6 +3048,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3110,6 +3073,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3129,6 +3093,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3154,6 +3119,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3175,6 +3141,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3200,6 +3167,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3230,6 +3198,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-f" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3265,6 +3234,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3288,6 +3258,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np1" { @@ -3312,6 +3283,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" initial_node_count = 3 + deletion_protection = false } resource "google_container_node_pool" "np1" { @@ -3347,7 +3319,7 @@ resource "google_compute_node_template" "soletenant-tmpl" { resource "google_compute_node_group" "nodes" { name = "tf-test-soletenant-group" zone = "us-central1-a" - size = 1 + initial_size = 1 node_template = google_compute_node_template.soletenant-tmpl.id } @@ -3356,6 +3328,7 @@ resource "google_container_cluster" "cluster" { location = "us-central1-a" initial_node_count = 1 min_master_version = data.google_container_engine_versions.central1a.latest_master_version + deletion_protection = false } resource "google_container_node_pool" "with_sole_tenant_config" { @@ -3432,6 +3405,7 @@ resource "google_container_cluster" "cluster" { } machine_type = "n2-standard-2" } + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3461,6 +3435,7 @@ resource "google_container_cluster" "cluster" { } machine_type = "n2-standard-2" } + deletion_protection = false } resource "google_container_node_pool" "np" { @@ -3515,6 +3490,7 @@ resource "google_container_cluster" "cluster" { name = "%s" location = "us-central2-b" initial_node_count = 1 + deletion_protection = false } resource "google_container_node_pool" "regular_pool" { @@ -3583,6 +3559,7 @@ resource "google_container_cluster" "cluster" { } machine_type = "n2-standard-2" } + deletion_protection = false } resource "google_container_node_pool" "np" { diff --git a/mmv1/third_party/terraform/services/containeranalysis/resource_container_registry.go b/mmv1/third_party/terraform/services/containeranalysis/resource_container_registry.go index f19e1389bd0b..d44bb07e105c 100644 --- a/mmv1/third_party/terraform/services/containeranalysis/resource_container_registry.go +++ b/mmv1/third_party/terraform/services/containeranalysis/resource_container_registry.go @@ -5,6 +5,7 @@ import ( "log" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "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" @@ -16,6 +17,10 @@ func ResourceContainerRegistry() *schema.Resource { Read: resourceContainerRegistryRead, Delete: resourceContainerRegistryDelete, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "location": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/containerattached/resource_container_attached_cluster_update_test.go b/mmv1/third_party/terraform/services/containerattached/resource_container_attached_cluster_update_test.go index 2b87744d4318..b5b28747a872 100644 --- a/mmv1/third_party/terraform/services/containerattached/resource_container_attached_cluster_update_test.go +++ b/mmv1/third_party/terraform/services/containerattached/resource_container_attached_cluster_update_test.go @@ -26,7 +26,7 @@ func TestAccContainerAttachedCluster_update(t *testing.T) { ResourceName: "google_container_attached_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location"}, + ImportStateVerifyIgnore: []string{"location", "annotations"}, }, { Config: testAccContainerAttachedCluster_containerAttachedCluster_update(context), @@ -35,7 +35,7 @@ func TestAccContainerAttachedCluster_update(t *testing.T) { ResourceName: "google_container_attached_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location"}, + ImportStateVerifyIgnore: []string{"location", "annotations"}, }, { Config: testAccContainerAttachedCluster_containerAttachedCluster_destroy(context), @@ -44,7 +44,7 @@ func TestAccContainerAttachedCluster_update(t *testing.T) { ResourceName: "google_container_attached_cluster.primary", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location"}, + ImportStateVerifyIgnore: []string{"location", "annotations"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/corebilling/resource_google_billing_project_info_test.go b/mmv1/third_party/terraform/services/corebilling/resource_google_billing_project_info_test.go index 67ea5ce04e93..feb75b3d7ad6 100644 --- a/mmv1/third_party/terraform/services/corebilling/resource_google_billing_project_info_test.go +++ b/mmv1/third_party/terraform/services/corebilling/resource_google_billing_project_info_test.go @@ -29,6 +29,7 @@ func TestAccBillingProjectInfo_update(t *testing.T) { ResourceName: "google_billing_project_info.info", ImportState: true, ImportStateVerify: true, + ImportStateId: fmt.Sprintf("projects/%s", projectId), }, { Config: testAccBillingProjectInfo_basic(projectId, orgId, ""), @@ -37,6 +38,7 @@ func TestAccBillingProjectInfo_update(t *testing.T) { ResourceName: "google_billing_project_info.info", ImportState: true, ImportStateVerify: true, + ImportStateId: fmt.Sprintf("projects/%s", projectId), }, { Config: testAccBillingProjectInfo_basic(projectId, orgId, billingAccount), @@ -45,6 +47,7 @@ func TestAccBillingProjectInfo_update(t *testing.T) { ResourceName: "google_billing_project_info.info", ImportState: true, ImportStateVerify: true, + ImportStateId: fmt.Sprintf("projects/%s", projectId), }, }, }) diff --git a/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go b/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go index 598da3507871..a9f9c108574a 100644 --- a/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go +++ b/mmv1/third_party/terraform/services/databasemigrationservice/resource_database_migration_service_connection_profile_test.go @@ -25,7 +25,7 @@ func TestAccDatabaseMigrationServiceConnectionProfile_update(t *testing.T) { ResourceName: "google_database_migration_service_connection_profile.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "mysql.0.password"}, + ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "mysql.0.password", "labels", "terraform_labels"}, }, { Config: testAccDatabaseMigrationServiceConnectionProfile_update(suffix), @@ -34,7 +34,7 @@ func TestAccDatabaseMigrationServiceConnectionProfile_update(t *testing.T) { ResourceName: "google_database_migration_service_connection_profile.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "mysql.0.password"}, + ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "mysql.0.password", "labels", "terraform_labels"}, }, }, }) @@ -77,3 +77,70 @@ resource "google_database_migration_service_connection_profile" "default" { } `, context) } + +func TestAccDatabaseMigrationServiceConnectionProfile_databaseMigrationServiceConnectionProfileAlloydb(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "vpc-network-1"), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDatabaseMigrationServiceConnectionProfileDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDatabaseMigrationServiceConnectionProfile_databaseMigrationServiceConnectionProfileAlloydb(context), + }, + { + ResourceName: "google_database_migration_service_connection_profile.alloydbprofile", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"connection_profile_id", "location", "alloydb.0.settings.0.initial_user.0.password", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccDatabaseMigrationServiceConnectionProfile_databaseMigrationServiceConnectionProfileAlloydb(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "%{network_name}" +} + +resource "google_database_migration_service_connection_profile" "alloydbprofile" { + location = "us-central1" + connection_profile_id = "tf-test-my-profileid%{random_suffix}" + display_name = "tf-test-my-profileid%{random_suffix}_display" + labels = { + foo = "bar" + } + alloydb { + cluster_id = "tf-test-dbmsalloycluster%{random_suffix}" + settings { + initial_user { + user = "alloyuser%{random_suffix}" + password = "alloypass%{random_suffix}" + } + vpc_network = data.google_compute_network.default.id + labels = { + alloyfoo = "alloybar" + } + primary_instance_settings { + id = "priminstid" + machine_config { + cpu_count = 2 + } + database_flags = { + } + labels = { + alloysinstfoo = "allowinstbar" + } + } + } + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb index 01632223d44b..5d3e995c83b8 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job.go.erb @@ -6,13 +6,14 @@ import ( "context" "fmt" "log" + "strconv" "strings" "time" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" - "github.com/hashicorp/terraform-provider-google/google/tpgresource" - transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" "google.golang.org/api/googleapi" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -32,11 +33,20 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { Update: resourceDataflowFlexTemplateJobUpdate, Delete: resourceDataflowFlexTemplateJobDelete, CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, resourceDataflowFlexJobTypeCustomizeDiff, ), Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, }, + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceDataflowFlexTemplateJobResourceV0().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceDataflowFlexTemplateJobStateUpgradeV0, + Version: 0, + }, + }, Schema: map[string]*schema.Schema{ "container_spec_gcs_path": { @@ -74,8 +84,22 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "labels": { Type: schema.TypeMap, Optional: true, - DiffSuppressFunc: resourceDataflowJobLabelDiffSuppress, - Description: `User labels to be specified for the job. Keys and values should follow the restrictions specified in the labeling restrictions page. NOTE: Google-provided Dataflow templates often provide default labels that begin with goog-dataflow-provided. Unless explicitly set in config, these labels will be ignored to prevent diffs on re-apply.`, + Description: `User labels to be specified for the job. Keys and values should follow the restrictions specified in the labeling restrictions page. 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.`, + }, + + "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}, + }, + + "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}, }, "parameters": { @@ -111,6 +135,7 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { Optional: true, // ForceNew applies to both stream and batch jobs ForceNew: true, + Computed: true, Description: `The initial number of Google Compute Engine instances for the job.`, }, @@ -119,6 +144,7 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { Optional: true, // ForceNew applies to both stream and batch jobs ForceNew: true, + Computed: true, Description: `The maximum number of Google Compute Engine instances to be made available to your pipeline during execution, from 1 to 1000.`, }, @@ -146,12 +172,14 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "sdk_container_image": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `Docker registry location of container image to use for the 'worker harness. Default is the container for the version of the SDK. Note this field is only valid for portable pipelines.`, }, "network": { Type: schema.TypeString, Optional: true, + Computed: true, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The network to which VMs will be assigned. If it is not provided, "default" will be used.`, }, @@ -159,6 +187,7 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "subnetwork": { Type: schema.TypeString, Optional: true, + Computed: true, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The subnetwork to which VMs will be assigned. Should be of the form "regions/REGION/subnetworks/SUBNETWORK".`, }, @@ -166,12 +195,14 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "machine_type": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `The machine type to use for the job.`, }, "kms_key_name": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `The name for the Cloud KMS key for the job. Key format is: projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY`, }, @@ -202,12 +233,14 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { "autoscaling_algorithm": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `The algorithm to use for autoscaling`, }, "launcher_machine_type": { Type: schema.TypeString, Optional: true, + Computed: true, Description: `The machine type to use for launching the job. The default is n1-standard-1.`, }, @@ -225,7 +258,7 @@ func ResourceDataflowFlexTemplateJob() *schema.Resource { // resourceDataflowFlexTemplateJobCreate creates a Flex Template Job from TF code. func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -240,7 +273,7 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac return err } - env, err := resourceDataflowFlexJobSetupEnv(d, config) + env, updatedParameters, err := resourceDataflowFlexJobSetupEnv(d, config) if err != nil { return err } @@ -249,7 +282,7 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac LaunchParameter: &dataflow.LaunchFlexTemplateParameter{ ContainerSpecGcsPath: d.Get("container_spec_gcs_path").(string), JobName: d.Get("name").(string), - Parameters: tpgresource.ExpandStringMap(d, "parameters"), + Parameters: updatedParameters, Environment: &env, }, } @@ -275,35 +308,98 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac return resourceDataflowFlexTemplateJobRead(d, meta) } -func resourceDataflowFlexJobSetupEnv(d *schema.ResourceData, config *transport_tpg.Config) (dataflow.FlexTemplateRuntimeEnvironment, error) { +func resourceDataflowFlexJobSetupEnv(d *schema.ResourceData, config *transport_tpg.Config) (dataflow.FlexTemplateRuntimeEnvironment, map[string]string, error) { + + updatedParameters := tpgresource.ExpandStringMap(d, "parameters") additionalExperiments := tpgresource.ConvertStringSet(d.Get("additional_experiments").(*schema.Set)) + var autoscalingAlgorithm string + autoscalingAlgorithm, updatedParameters = dataflowFlexJobTypeTransferVar("autoscaling_algorithm", "autoscalingAlgorithm", updatedParameters, d) + + var numWorkers int + if p, ok := d.GetOk("parameters.numWorkers"); ok { + number, err := strconv.Atoi(p.(string)) + if err != nil { + return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, fmt.Errorf("parameters.numWorkers must have a valid integer assigned to it, current value is %s", p.(string)) + } + delete(updatedParameters, "numWorkers") + numWorkers = number + } else { + if v, ok := d.GetOk("num_workers"); ok { + numWorkers = v.(int) + } + } + + var maxNumWorkers int + if p, ok := d.GetOk("parameters.maxNumWorkers"); ok { + number, err := strconv.Atoi(p.(string)) + if err != nil { + return dataflow.FlexTemplateRuntimeEnvironment{}, updatedParameters, fmt.Errorf("parameters.maxNumWorkers must have a valid integer assigned to it, current value is %s", p.(string)) + } + delete(updatedParameters, "maxNumWorkers") + maxNumWorkers = number + } else { + if v, ok := d.GetOk("max_workers"); ok { + maxNumWorkers = v.(int) + } + } + + network, updatedParameters := dataflowFlexJobTypeTransferVar("network", "network", updatedParameters, d) + + serviceAccountEmail, updatedParameters := dataflowFlexJobTypeTransferVar("service_account_email", "serviceAccountEmail", updatedParameters, d) + + subnetwork, updatedParameters := dataflowFlexJobTypeTransferVar("subnetwork", "subnetwork", updatedParameters, d) + + tempLocation, updatedParameters := dataflowFlexJobTypeTransferVar("temp_location", "tempLocation", updatedParameters, d) + + stagingLocation, updatedParameters := dataflowFlexJobTypeTransferVar("staging_location", "stagingLocation", updatedParameters, d) + + machineType, updatedParameters := dataflowFlexJobTypeTransferVar("machine_type", "workerMachineType", updatedParameters, d) + + kmsKeyName, updatedParameters := dataflowFlexJobTypeTransferVar("kms_key_name", "kmsKeyName", updatedParameters, d) + + ipConfiguration, updatedParameters := dataflowFlexJobTypeTransferVar("ip_configuration", "ipConfiguration", updatedParameters, d) + + var enableStreamingEngine bool + if p, ok := d.GetOk("parameters.enableStreamingEngine"); ok { + delete(updatedParameters, "enableStreamingEngine") + enableStreamingEngine = p.(bool) + } else { + if v, ok := d.GetOk("enable_streaming_engine"); ok { + enableStreamingEngine = v.(bool) + } + } + + sdkContainerImage, updatedParameters := dataflowFlexJobTypeTransferVar("sdk_container_image", "sdkContainerImage", updatedParameters, d) + + launcherMachineType, updatedParameters := dataflowFlexJobTypeTransferVar("launcher_machine_type", "launcherMachineType", updatedParameters, d) + env := dataflow.FlexTemplateRuntimeEnvironment{ - AdditionalUserLabels: tpgresource.ExpandStringMap(d, "labels"), - AutoscalingAlgorithm: d.Get("autoscaling_algorithm").(string), - NumWorkers: int64(d.Get("num_workers").(int)), - MaxWorkers: int64(d.Get("max_workers").(int)), - Network: d.Get("network").(string), - ServiceAccountEmail: d.Get("service_account_email").(string), - Subnetwork: d.Get("subnetwork").(string), - TempLocation: d.Get("temp_location").(string), - StagingLocation: d.Get("staging_location").(string), - MachineType: d.Get("machine_type").(string), - KmsKeyName: d.Get("kms_key_name").(string), - IpConfiguration: d.Get("ip_configuration").(string), - EnableStreamingEngine: d.Get("enable_streaming_engine").(bool), + AdditionalUserLabels: tpgresource.ExpandStringMap(d, "effective_labels"), + AutoscalingAlgorithm: autoscalingAlgorithm, + NumWorkers: int64(numWorkers), + MaxWorkers: int64(maxNumWorkers), + Network: network, + ServiceAccountEmail: serviceAccountEmail, + Subnetwork: subnetwork, + TempLocation: tempLocation, + StagingLocation: stagingLocation, + MachineType: machineType, + KmsKeyName: kmsKeyName, + IpConfiguration: ipConfiguration, + EnableStreamingEngine: enableStreamingEngine, AdditionalExperiments: additionalExperiments, - SdkContainerImage: d.Get("sdk_container_image").(string), - LauncherMachineType: d.Get("launcher_machine_type").(string), + SdkContainerImage: sdkContainerImage, + LauncherMachineType: launcherMachineType, } - return env, nil + return env, updatedParameters, nil } // resourceDataflowFlexTemplateJobRead reads a Flex Template Job resource. func resourceDataflowFlexTemplateJobRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -340,9 +436,15 @@ func resourceDataflowFlexTemplateJobRead(d *schema.ResourceData, meta interface{ if err := d.Set("project", project); err != nil { return fmt.Errorf("Error setting project: %s", err) } - if err := d.Set("labels", job.Labels); err != nil { + if err := tpgresource.SetLabels(job.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(job.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + if err := d.Set("effective_labels", job.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err := d.Set("kms_key_name", job.Environment.ServiceKmsKeyName); err != nil { return fmt.Errorf("Error setting kms_key_name: %s", err) } @@ -365,7 +467,7 @@ func resourceDataflowFlexTemplateJobRead(d *schema.ResourceData, meta interface{ if err := d.Set("num_workers", optionsMap["numWorkers"]); err != nil { return fmt.Errorf("Error setting num_workers: %s", err) } - if err := d.Set("max_workers", optionsMap["maxWorkers"]); err != nil { + if err := d.Set("max_workers", optionsMap["maxNumWorkers"]); err != nil { return fmt.Errorf("Error setting max_workers: %s", err) } if err := d.Set("staging_location", optionsMap["stagingLocation"]); err != nil { @@ -439,7 +541,7 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac } config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -456,7 +558,7 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac tnamemapping := tpgresource.ExpandStringMap(d, "transform_name_mapping") - env, err := resourceDataflowFlexJobSetupEnv(d, config) + env, updatedParameters, err := resourceDataflowFlexJobSetupEnv(d, config) if err != nil { return err } @@ -470,12 +572,12 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac request := dataflow.LaunchFlexTemplateRequest{ LaunchParameter: &dataflow.LaunchFlexTemplateParameter{ - ContainerSpecGcsPath: d.Get("container_spec_gcs_path").(string), - JobName: d.Get("name").(string), - Parameters: tpgresource.ExpandStringMap(d, "parameters"), + ContainerSpecGcsPath: d.Get("container_spec_gcs_path").(string), + JobName: d.Get("name").(string), + Parameters: updatedParameters, TransformNameMappings: tnamemapping, - Environment: &env, - Update: true, + Environment: &env, + Update: true, }, } @@ -503,7 +605,7 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac func resourceDataflowFlexTemplateJobDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -585,6 +687,100 @@ func resourceDataflowFlexTemplateJobDelete(d *schema.ResourceData, meta interfac } func resourceDataflowFlexJobTypeCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + + err := dataflowFlexJobTypeParameterOverride("autoscaling_algorithm", "autoscalingAlgorithm", d) + if err != nil { + return err + } + + if p, ok := d.GetOk("parameters.numWorkers"); ok { + if d.HasChange("num_workers") { + e := d.Get("num_workers") + return fmt.Errorf("Error setting num_workers, value is supplied twice: num_workers=%d, parameters.numWorkers=%d", e.(int), p.(int)) + } else { + p := d.Get("parameters.numWorkers") + number, err := strconv.Atoi(p.(string)) + if err != nil { + return fmt.Errorf("parameters.maxNumWorkers must have a valid integer assigned to it, current value is %s", p.(string)) + } + d.SetNew("num_workers", number) + } + } + + if p, ok := d.GetOk("parameters.maxNumWorkers"); ok { + if d.HasChange("max_workers") { + e := d.Get("max_workers") + return fmt.Errorf("Error setting max_workers, value is supplied twice: max_workers=%d, parameters.maxNumWorkers=%d", e.(int), p.(int)) + } else { + p := d.Get("parameters.maxNumWorkers") + number, err := strconv.Atoi(p.(string)) + if err != nil { + return fmt.Errorf("parameters.maxNumWorkers must have a valid integer assigned to it, current value is %s", p.(string)) + } + d.SetNew("max_workers", number) + } + } + + err = dataflowFlexJobTypeParameterOverride("network", "network", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("service_account_email", "serviceAccountEmail", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("subnetwork", "subnetwork", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("temp_location", "tempLocation", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("staging_location", "stagingLocation", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("machine_type", "workerMachineType", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("kms_key_name", "kmsKeyName", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("ip_configuration", "ipConfiguration", d) + if err != nil { + return err + } + + if p, ok := d.GetOk("parameters.enableStreamingEngine"); ok { + if d.HasChange("enable_streaming_engine") { + e := d.Get("enable_streaming_engine") + return fmt.Errorf("Error setting enable_streaming_engine, value is supplied twice: enable_streaming_engine=%t, parameters.enableStreamingEngine=%t", e.(bool), p.(bool)) + } else { + p := d.Get("parameters.enableStreamingEngine") + d.SetNew("enable_streaming_engine", p.(string)) + } + } + + err = dataflowFlexJobTypeParameterOverride("sdk_container_image", "sdkContainerImage", d) + if err != nil { + return err + } + + err = dataflowFlexJobTypeParameterOverride("launcher_machine_type", "launcherMachineType", d) + if err != nil { + return err + } + // All non-virtual fields are ForceNew for batch jobs if d.Get("type") == "JOB_TYPE_BATCH" { resourceSchema := ResourceDataflowFlexTemplateJob().Schema @@ -592,12 +788,8 @@ func resourceDataflowFlexJobTypeCustomizeDiff(_ context.Context, d *schema.Resou if field == "on_delete" { continue } - // Labels map will likely have suppressed changes, so we check each key instead of the parent field - if field == "labels" { - if err := resourceDataflowJobIterateMapForceNew(field, d); err != nil { - return err - } - } else if d.HasChange(field) { + + if field != "labels" && field != "terraform_labels" && d.HasChange(field) { if err := d.ForceNew(field); err != nil { return err } @@ -608,4 +800,36 @@ func resourceDataflowFlexJobTypeCustomizeDiff(_ context.Context, d *schema.Resou return nil } +func dataflowFlexJobTypeTransferVar(ename, pname string, updatedParameters map[string]string, d *schema.ResourceData) (string, map[string]string) { + + pstring := fmt.Sprintf("parameters.%s", pname) + + if p, ok := d.GetOk(pstring); ok { + delete(updatedParameters, pname) + return p.(string), updatedParameters + } else { + if v, ok := d.GetOk(ename); ok { + return v.(string), updatedParameters + } else { + return "", updatedParameters + } + } +} + +func dataflowFlexJobTypeParameterOverride(ename, pname string, d *schema.ResourceDiff) error { + + pstring := fmt.Sprintf("parameters.%s", pname) + + if p, ok := d.GetOk(pstring); ok { + if d.HasChange(ename) { + e := d.Get(ename) + return fmt.Errorf("Error setting %s, value is supplied twice: %s=\"%s\", %s=\"%s\"", ename, ename, e.(string), pstring, p.(string)) + } else { + p := d.Get(pstring) + d.SetNew(ename, p.(string)) + } + } + return nil +} + <% end -%> diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_migrate.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_migrate.go.erb new file mode 100644 index 000000000000..aa0c11361713 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_migrate.go.erb @@ -0,0 +1,205 @@ +<% autogen_exception -%> +package dataflow +<% unless version == 'ga' -%> + +import ( + "context" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceDataflowFlexTemplateJobResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "container_spec_gcs_path": { + Type: schema.TypeString, + Required: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "region": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + Description: `The region in which the created job should run.`, + }, + + "transform_name_mapping": { + Type: schema.TypeMap, + Optional: true, + Description: `Only applicable when updating a pipeline. Map of transform name prefixes of the job to be replaced with the corresponding name prefixes of the new job.`, + }, + + "on_delete": { + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{"cancel", "drain"}, false), + Optional: true, + Default: "cancel", + }, + + "labels": { + Type: schema.TypeMap, + Optional: true, + DiffSuppressFunc: resourceDataflowJobLabelDiffSuppress, + Description: `User labels to be specified for the job. Keys and values should follow the restrictions specified in the labeling restrictions page. NOTE: Google-provided Dataflow templates often provide default labels that begin with goog-dataflow-provided. Unless explicitly set in config, these labels will be ignored to prevent diffs on re-apply.`, + }, + + "parameters": { + Type: schema.TypeMap, + Optional: true, + }, + + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + + "job_id": { + Type: schema.TypeString, + Computed: true, + }, + + "state": { + Type: schema.TypeString, + Computed: true, + }, + + "type": { + Type: schema.TypeString, + Computed: true, + Description: `The type of this job, selected from the JobType enum.`, + }, + + "num_workers": { + Type: schema.TypeInt, + Optional: true, + // ForceNew applies to both stream and batch jobs + ForceNew: true, + Description: `The initial number of Google Compute Engine instances for the job.`, + }, + + "max_workers": { + Type: schema.TypeInt, + Optional: true, + // ForceNew applies to both stream and batch jobs + ForceNew: true, + Description: `The maximum number of Google Compute Engine instances to be made available to your pipeline during execution, from 1 to 1000.`, + }, + + "service_account_email": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The Service Account email used to create the job.`, + }, + + "temp_location": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The Cloud Storage path to use for temporary files. Must be a valid Cloud Storage URL, beginning with gs://.`, + }, + + "staging_location": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The Cloud Storage path to use for staging files. Must be a valid Cloud Storage URL, beginning with gs://.`, + }, + + "sdk_container_image": { + Type: schema.TypeString, + Optional: true, + Description: `Docker registry location of container image to use for the 'worker harness. Default is the container for the version of the SDK. Note this field is only valid for portable pipelines.`, + }, + + "network": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The network to which VMs will be assigned. If it is not provided, "default" will be used.`, + }, + + "subnetwork": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The subnetwork to which VMs will be assigned. Should be of the form "regions/REGION/subnetworks/SUBNETWORK".`, + }, + + "machine_type": { + Type: schema.TypeString, + Optional: true, + Description: `The machine type to use for the job.`, + }, + + "kms_key_name": { + Type: schema.TypeString, + Optional: true, + Description: `The name for the Cloud KMS key for the job. Key format is: projects/PROJECT_ID/locations/LOCATION/keyRings/KEY_RING/cryptoKeys/KEY`, + }, + + "ip_configuration": { + Type: schema.TypeString, + Optional: true, + Description: `The configuration for VM IPs. Options are "WORKER_IP_PUBLIC" or "WORKER_IP_PRIVATE".`, + ValidateFunc: validation.StringInSlice([]string{"WORKER_IP_PUBLIC", "WORKER_IP_PRIVATE"}, false), + }, + + "additional_experiments": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + Description: `List of experiments that should be used by the job. An example value is ["enable_stackdriver_agent_metrics"].`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "enable_streaming_engine": { + Type: schema.TypeBool, + Optional: true, + ForceNew: true, + Description: `Indicates if the job should use the streaming engine feature.`, + }, + + "autoscaling_algorithm": { + Type: schema.TypeString, + Optional: true, + Description: `The algorithm to use for autoscaling`, + }, + + "launcher_machine_type": { + Type: schema.TypeString, + Optional: true, + Description: `The machine type to use for launching the job. The default is n1-standard-1.`, + }, + + "skip_wait_on_job_termination": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `If true, treat DRAINING and CANCELLING as terminal job states and do not wait for further changes before removing from terraform state and moving on. WARNING: this will lead to job name conflicts if you do not ensure that the job names are different, e.g. by embedding a release ID or by using a random_id.`, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceDataflowFlexTemplateJobStateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return tpgresource.LabelsStateUpgrade(rawState, resourceDataflowJobGoogleLabelPrefix) +} + +<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb index 577ec7f63de8..2c29df864833 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_flex_template_job_test.go.erb @@ -44,7 +44,7 @@ func TestAccDataflowFlexTemplateJob_basic(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -83,7 +83,7 @@ func TestAccDataflowFlexTemplateJob_streamUpdate(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "transform_name_mapping", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "transform_name_mapping", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -145,7 +145,7 @@ func TestAccDataflowFlexTemplateJob_FullUpdate(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, { Config: testAccDataflowFlexTemplateJob_dataflowFlexTemplateJobFullUpdate(job, bucket, topic), @@ -154,7 +154,7 @@ func TestAccDataflowFlexTemplateJob_FullUpdate(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -189,7 +189,7 @@ func TestAccDataflowFlexTemplateJob_withNetwork(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_network", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, { Config: testAccDataflowFlexTemplateJob_networkUpdate(job, network1, network2, bucket, topic), @@ -202,7 +202,7 @@ func TestAccDataflowFlexTemplateJob_withNetwork(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_network", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -238,7 +238,7 @@ func TestAccDataflowFlexTemplateJob_withSubNetwork(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_subnetwork", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, { Config: testAccDataflowFlexTemplateJob_subnetworkUpdate(job, network, subnetwork1, subnetwork2, bucket, topic), @@ -251,7 +251,7 @@ func TestAccDataflowFlexTemplateJob_withSubNetwork(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_subnetwork", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -285,7 +285,7 @@ func TestAccDataflowFlexTemplateJob_withIpConfig(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_ipconfig", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "ip_configuration", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "ip_configuration", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -319,7 +319,7 @@ func TestAccDataflowFlexTemplateJob_withKmsKey(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_kms", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -353,7 +353,87 @@ func TestAccDataflowFlexTemplateJob_withAdditionalExperiments(t *testing.T) { ResourceName: "google_dataflow_flex_template_job.flex_job_experiments", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "additional_experiments", "container_spec_gcs_path"}, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "additional_experiments", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + }, + }) +} + +func TestAccDataflowFlexTemplateJob_withProviderDefaultLabels(t *testing.T) { + // This resource uses custom retry logic that cannot be sped up without + // modifying the actual resource + acctest.SkipIfVcr(t) + t.Parallel() + + randStr := acctest.RandString(t, 10) + job := "tf-test-dataflow-job-" + randStr + bucket := "tf-test-dataflow-bucket-" + randStr + topic := "tf-test-topic" + randStr + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckDataflowJobDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataflowFlexTemplateJob_withProviderDefaultLabels(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_moveResourceLabelToProviderDefaultLabels(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + { + Config: testAccComputeAddress_resourceLabelsOverridesProviderDefaultLabels(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, + }, + { + Config: testAccDataflowFlexTemplateJob_dataflowFlexTemplateJobFull(job, bucket, topic), + Check: resource.ComposeTestCheckFunc( + testAccDataflowFlexJobExists(t, "google_dataflow_flex_template_job.flex_job_fullupdate", false), + ), + }, + { + ResourceName: "google_dataflow_flex_template_job.flex_job_fullupdate", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"on_delete", "parameters", "skip_wait_on_job_termination", "state", "container_spec_gcs_path", "labels", "terraform_labels"}, }, }, }) @@ -635,12 +715,13 @@ resource "google_dataflow_flex_template_job" "flex_job_fullupdate" { schemaLocation = "gs://${google_storage_bucket_object.schema.bucket}/schema.json" qps = "1" topic = google_pubsub_topic.example.id + workerMachineType = "n1-standard-2" + maxNumWorkers = 2 } labels = { "my_labels" = "value-1" } service_account_email = google_service_account.dataflow-sa[0].email - machine_type = "n1-standard-2" } `, topicName, bucket, job) } @@ -705,16 +786,17 @@ resource "google_dataflow_flex_template_job" "flex_job_fullupdate" { name = "%s" container_spec_gcs_path = "gs://${data.google_storage_bucket_object.flex_template.bucket}/${data.google_storage_bucket_object.flex_template.name}" on_delete = "cancel" + machine_type = "n2-standard-2" parameters = { schemaLocation = "gs://${google_storage_bucket_object.schema.bucket}/schema.json" qps = "1" topic = google_pubsub_topic.example.id + maxNumWorkers = 3 } labels = { "my_labels" = "value-update" } service_account_email = google_service_account.dataflow-sa[1].email - machine_type = "n2-standard-2" } `, topicName, bucket, job) } @@ -1185,6 +1267,260 @@ resource "google_dataflow_flex_template_job" "flex_job_experiments" { `, topicName, bucket, job, strings.Join(experiments, `", "`)) } +func testAccDataflowFlexTemplateJob_withProviderDefaultLabels(job, bucket, topicName string) string { + return fmt.Sprintf(` + +provider "google" { + default_labels = { + default_key1 = "default_value1" + } +} + +data "google_project" "project" {} + +resource "google_pubsub_topic" "example" { + name = "%s" +} + +resource "google_service_account" "dataflow-sa" { + count = 2 + account_id = "dataflow-sa-${count.index}" + display_name = "DataFlow Service Account" +} + +resource "google_project_iam_member" "dataflow-worker" { + count = 2 + project = data.google_project.project.project_id + role = "roles/dataflow.worker" + member = "serviceAccount:${google_service_account.dataflow-sa[count.index].email}" +} + +resource "google_project_iam_member" "dataflow-storage" { + count = 2 + project = data.google_project.project.project_id + role = "roles/storage.admin" + member = "serviceAccount:${google_service_account.dataflow-sa[count.index].email}" +} + +data "google_storage_bucket_object" "flex_template" { + name = "latest/flex/Streaming_Data_Generator" + bucket = "dataflow-templates" +} + +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "US-CENTRAL1" + force_destroy = true + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "schema" { + name = "schema.json" + bucket = google_storage_bucket.bucket.name + content = < package dataproc import ( @@ -10,6 +9,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -116,7 +116,8 @@ var ( } ) -const resourceDataprocGoogleProvidedLabelPrefix = "labels.goog-dataproc" +const resourceDataprocGoogleLabelPrefix = "goog-dataproc" +const resourceDataprocGoogleProvidedLabelPrefix = "labels." + resourceDataprocGoogleLabelPrefix func resourceDataprocLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { if strings.HasPrefix(k, resourceDataprocGoogleProvidedLabelPrefix) && new == "" { @@ -162,6 +163,20 @@ func ResourceDataprocCluster() *schema.Resource { Delete: schema.DefaultTimeout(45 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.SetLabelsDiff, + ), + + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceDataprocClusterResourceV0().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceDataprocClusterStateUpgradeV0, + Version: 0, + }, + }, + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -218,10 +233,24 @@ func ResourceDataprocCluster() *schema.Resource { Type: schema.TypeMap, Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, - // GCP automatically adds labels - DiffSuppressFunc: resourceDataprocLabelDiffSuppress, + Description: `The list of the labels (key/value pairs) configured on the resource and to be applied to instances in the cluster. + + **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.`, + }, + + "terraform_labels": { + Type: schema.TypeMap, Computed: true, - Description: `The list of labels (key/value pairs) to be applied to instances in the cluster. GCP generates some itself including goog-dataproc-cluster-name which is the name of the cluster.`, + Description: `The combination of labels configured directly on the resource and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "effective_labels": { + Type: schema.TypeMap, + Elem: &schema.Schema{Type: schema.TypeString}, + 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.`, }, "virtual_cluster_config": { @@ -696,10 +725,10 @@ func ResourceDataprocCluster() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "node_group_uri": { - Type: schema.TypeString, - ForceNew: true, - Required: true, - Description: `The URI of a sole-tenant that the cluster will be created on.`, + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: `The URI of a sole-tenant that the cluster will be created on.`, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, }, }, @@ -738,8 +767,8 @@ func ResourceDataprocCluster() *schema.Resource { // "machine_type": { ... } // "min_cpu_platform": { ... } "preemptibility": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, Description: `Specifies the preemptibility of the secondary nodes. Defaults to PREEMPTIBLE.`, AtLeastOneOf: []string{ "cluster_config.0.preemptible_worker_config.0.num_instances", @@ -1020,22 +1049,22 @@ by Dataproc`, }, }, "metastore_config": { - Type: schema.TypeList, - Optional: true, - AtLeastOneOf: clusterConfigKeys, - MaxItems: 1, - Description: `Specifies a Metastore configuration.`, + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + MaxItems: 1, + Description: `Specifies a Metastore configuration.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "dataproc_metastore_service": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - Description: `Resource name of an existing Dataproc Metastore service.`, + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Resource name of an existing Dataproc Metastore service.`, }, }, }, - }, + }, "lifecycle_config": { Type: schema.TypeList, Optional: true, @@ -1100,18 +1129,18 @@ by Dataproc`, }, "dataproc_metric_config": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: `The config for Dataproc metrics.`, + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `The config for Dataproc metrics.`, AtLeastOneOf: clusterConfigKeys, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "metrics": { - Type: schema.TypeList, - Required: true, - Description: `Metrics sources to enable.`, - Elem: metricsSchema(), + Type: schema.TypeList, + Required: true, + Description: `Metrics sources to enable.`, + Elem: metricsSchema(), }, }, }, @@ -1126,7 +1155,7 @@ by Dataproc`, // We need to pull metrics' schema out so we can use it to make a set hash func func metricsSchema() *schema.Resource { - return &schema.Resource{ + return &schema.Resource{ Schema: map[string]*schema.Schema{ "metric_source": { Type: schema.TypeString, @@ -1136,11 +1165,11 @@ func metricsSchema() *schema.Resource { Description: `A source for the collection of Dataproc OSS metrics (see [available OSS metrics] (https://cloud.google.com//dataproc/docs/guides/monitoring#available_oss_metrics)).`, }, "metric_overrides": { - Type: schema.TypeSet, - Elem: &schema.Schema{Type: schema.TypeString}, - Optional: true, - ForceNew: true, - Description: `Specify one or more [available OSS metrics] (https://cloud.google.com/dataproc/docs/guides/monitoring#available_oss_metrics) to collect.`, + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + ForceNew: true, + Description: `Specify one or more [available OSS metrics] (https://cloud.google.com/dataproc/docs/guides/monitoring#available_oss_metrics) to collect.`, }, }, } @@ -1247,8 +1276,8 @@ func instanceConfigSchema(parent string) *schema.Schema { "cluster_config.0." + parent + ".0.disk_config.0.boot_disk_size_gb", "cluster_config.0." + parent + ".0.disk_config.0.boot_disk_type", }, - ForceNew: true, - Default: "pd-standard", + ForceNew: true, + Default: "pd-standard", }, }, }, @@ -1298,7 +1327,7 @@ func acceleratorsSchema() *schema.Resource { func resourceDataprocClusterCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -1324,8 +1353,8 @@ func resourceDataprocClusterCreate(d *schema.ResourceData, meta interface{}) err return err } - if _, ok := d.GetOk("labels"); ok { - cluster.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + cluster.Labels = tpgresource.ExpandEffectiveLabels(d) } // Checking here caters for the case where the user does not specify cluster_config @@ -1829,7 +1858,7 @@ func expandDataprocMetricConfig(cfg map[string]interface{}) *dataproc.DataprocMe for _, raw := range metricsConfigs { data := raw.(map[string]interface{}) metric := dataproc.Metric{ - MetricSource: data["metric_source"].(string), + MetricSource: data["metric_source"].(string), MetricOverrides: tpgresource.ConvertStringSet(data["metric_overrides"].(*schema.Set)), } metricsSet = append(metricsSet, &metric) @@ -1948,7 +1977,7 @@ func expandAccelerators(configured []interface{}) []*dataproc.AcceleratorConfig func resourceDataprocClusterUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -1969,8 +1998,8 @@ func resourceDataprocClusterUpdate(d *schema.ResourceData, meta interface{}) err updMask := []string{} - if d.HasChange("labels") { - v := d.Get("labels") + if d.HasChange("effective_labels") { + v := d.Get("effective_labels") m := make(map[string]string) for k, val := range v.(map[string]interface{}) { m[k] = val.(string) @@ -2055,7 +2084,7 @@ func resourceDataprocClusterUpdate(d *schema.ResourceData, meta interface{}) err func resourceDataprocClusterRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } @@ -2083,10 +2112,19 @@ func resourceDataprocClusterRead(d *schema.ResourceData, meta interface{}) error if err := d.Set("region", region); err != nil { return fmt.Errorf("Error setting region: %s", err) } - if err := d.Set("labels", cluster.Labels); err != nil { + + if err := tpgresource.SetLabels(cluster.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(cluster.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + + if err := d.Set("effective_labels", cluster.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } + var cfg []map[string]interface{} cfg, err = flattenClusterConfig(d, cluster.Config) @@ -2367,7 +2405,7 @@ func flattenDataprocMetricConfig(d *schema.ResourceData, dmc *dataproc.DataprocM metricsTypeList := schema.NewSet(schema.HashResource(metricsSchema()), []interface{}{}).List() for _, metric := range dmc.Metrics { data := map[string]interface{}{ - "metric_source": metric.MetricSource, + "metric_source": metric.MetricSource, "metric_overrides": metric.MetricOverrides, } @@ -2459,16 +2497,16 @@ func flattenGceClusterConfig(d *schema.ResourceData, gcc *dataproc.GceClusterCon if gcc.ReservationAffinity != nil { gceConfig["reservation_affinity"] = []map[string]interface{}{ { - "consume_reservation_type": gcc.ReservationAffinity.ConsumeReservationType, - "key": gcc.ReservationAffinity.Key, - "values": gcc.ReservationAffinity.Values, + "consume_reservation_type": gcc.ReservationAffinity.ConsumeReservationType, + "key": gcc.ReservationAffinity.Key, + "values": gcc.ReservationAffinity.Values, }, } } if gcc.NodeGroupAffinity != nil { gceConfig["node_group_affinity"] = []map[string]interface{}{ { - "node_group_uri": gcc.NodeGroupAffinity.NodeGroupUri, + "node_group_uri": gcc.NodeGroupAffinity.NodeGroupUri, }, } } @@ -2544,7 +2582,7 @@ func extractInitTimeout(t string) (int, error) { func resourceDataprocClusterDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) - userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) if err != nil { return err } diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_migrate.go b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_migrate.go new file mode 100644 index 000000000000..11a640e76c69 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_migrate.go @@ -0,0 +1,981 @@ +package dataproc + +import ( + "context" + "fmt" + "regexp" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" +) + +func resourceDataprocClusterResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the cluster, unique within the project and zone.`, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + + if len(value) > 55 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 55 characters", k)) + } + if !regexp.MustCompile("^[a-z0-9-]+$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q can only contain lowercase letters, numbers and hyphens", k)) + } + if !regexp.MustCompile("^[a-z]").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must start with a letter", k)) + } + if !regexp.MustCompile("[a-z0-9]$").MatchString(value) { + errors = append(errors, fmt.Errorf( + "%q must end with a number or a letter", k)) + } + return + }, + }, + + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The ID of the project in which the cluster will exist. If it is not provided, the provider project is used.`, + }, + + "region": { + Type: schema.TypeString, + Optional: true, + Default: "global", + ForceNew: true, + Description: `The region in which the cluster and associated nodes will be created in. Defaults to global.`, + }, + + "graceful_decommission_timeout": { + Type: schema.TypeString, + Optional: true, + Default: "0s", + Description: `The timeout duration which allows graceful decomissioning when you change the number of worker nodes directly through a terraform apply`, + }, + + "labels": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + // GCP automatically adds labels + DiffSuppressFunc: resourceDataprocLabelDiffSuppress, + Computed: true, + Description: `The list of labels (key/value pairs) to be applied to instances in the cluster. GCP generates some itself including goog-dataproc-cluster-name which is the name of the cluster.`, + }, + + "virtual_cluster_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The virtual cluster config is used when creating a Dataproc cluster that does not directly control the underlying compute resources, for example, when creating a Dataproc-on-GKE cluster. Dataproc may set default values, and values may change when clusters are updated. Exactly one of config or virtualClusterConfig must be specified.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "staging_bucket": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: virtualClusterConfigKeys, + ForceNew: true, + Description: `A Cloud Storage bucket used to stage job dependencies, config files, and job driver console output. If you do not specify a staging bucket, Cloud Dataproc will determine a Cloud Storage location (US, ASIA, or EU) for your cluster's staging bucket according to the Compute Engine zone where your cluster is deployed, and then create and manage this project-level, per-location bucket.`, + }, + + "auxiliary_services_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + AtLeastOneOf: virtualClusterConfigKeys, + Description: `Auxiliary services configuration for a Cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "metastore_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + AtLeastOneOf: auxiliaryServicesConfigKeys, + Description: `The Hive Metastore configuration for this workload.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "dataproc_metastore_service": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: auxiliaryServicesMetastoreConfigKeys, + Description: `The Hive Metastore configuration for this workload.`, + }, + }, + }, + }, + + "spark_history_server_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + AtLeastOneOf: auxiliaryServicesConfigKeys, + Description: `The Spark History Server configuration for the workload.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "dataproc_cluster": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: auxiliaryServicesSparkHistoryServerConfigKeys, + Description: `Resource name of an existing Dataproc Cluster to act as a Spark History Server for the workload.`, + }, + }, + }, + }, + }, + }, + }, + + "kubernetes_cluster_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + AtLeastOneOf: virtualClusterConfigKeys, + Description: `The configuration for running the Dataproc cluster on Kubernetes.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "kubernetes_namespace": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + AtLeastOneOf: kubernetesClusterConfigKeys, + Description: `A namespace within the Kubernetes cluster to deploy into. If this namespace does not exist, it is created. If it exists, Dataproc verifies that another Dataproc VirtualCluster is not installed into it. If not specified, the name of the Dataproc Cluster is used.`, + }, + + "kubernetes_software_config": { + Type: schema.TypeList, + MaxItems: 1, + Required: true, + Description: `The software configuration for this Dataproc cluster running on Kubernetes.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "component_version": { + Type: schema.TypeMap, + Required: true, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The components that should be installed in this Dataproc cluster. The key must be a string from the KubernetesComponent enumeration. The value is the version of the software to be installed.`, + }, + + "properties": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + DiffSuppressFunc: resourceDataprocPropertyDiffSuppress, + Elem: &schema.Schema{Type: schema.TypeString}, + Computed: true, + Description: `The properties to set on daemon config files. Property keys are specified in prefix:property format, for example spark:spark.kubernetes.container.image.`, + }, + }, + }, + }, + + "gke_cluster_config": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Description: `The configuration for running the Dataproc cluster on GKE.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "gke_cluster_target": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + AtLeastOneOf: gkeClusterConfigKeys, + Description: `A target GKE cluster to deploy to. It must be in the same project and region as the Dataproc cluster (the GKE cluster can be zonal or regional). Format: 'projects/{project}/locations/{location}/clusters/{cluster_id}'`, + }, + + "node_pool_target": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: gkeClusterConfigKeys, + MinItems: 1, + Description: `GKE node pools where workloads will be scheduled. At least one node pool must be assigned the DEFAULT GkeNodePoolTarget.Role. If a GkeNodePoolTarget is not specified, Dataproc constructs a DEFAULT GkeNodePoolTarget.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "node_pool": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: `The target GKE node pool. Format: 'projects/{project}/locations/{location}/clusters/{cluster}/nodePools/{nodePool}'`, + }, + + "roles": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + ForceNew: true, + Required: true, + Description: `The roles associated with the GKE node pool.`, + }, + + "node_pool_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Input only. The configuration for the GKE node pool.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The node pool configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "machine_type": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Description: `The name of a Compute Engine machine type.`, + }, + + "local_ssd_count": { + Type: schema.TypeInt, + ForceNew: true, + Optional: true, + Description: `The minimum number of nodes in the node pool. Must be >= 0 and <= maxNodeCount.`, + }, + + "preemptible": { + Type: schema.TypeBool, + ForceNew: true, + Optional: true, + Description: `Whether the nodes are created as preemptible VM instances. Preemptible nodes cannot be used in a node pool with the CONTROLLER role or in the DEFAULT node pool if the CONTROLLER role is not assigned (the DEFAULT node pool will assume the CONTROLLER role).`, + }, + + "min_cpu_platform": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + Description: `Minimum CPU platform to be used by this instance. The instance may be scheduled on the specified or a newer CPU platform. Specify the friendly names of CPU platforms, such as "Intel Haswell" or "Intel Sandy Bridge".`, + }, + + "spot": { + Type: schema.TypeBool, + ForceNew: true, + Optional: true, + Description: `Spot flag for enabling Spot VM, which is a rebrand of the existing preemptible flag.`, + }, + }, + }, + }, + + "locations": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + ForceNew: true, + Required: true, + Description: `The list of Compute Engine zones where node pool nodes associated with a Dataproc on GKE virtual cluster will be located.`, + }, + + "autoscaling": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The autoscaler configuration for this node pool. The autoscaler is enabled only when a valid configuration is present.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "min_node_count": { + Type: schema.TypeInt, + ForceNew: true, + Optional: true, + Description: `The minimum number of nodes in the node pool. Must be >= 0 and <= maxNodeCount.`, + }, + + "max_node_count": { + Type: schema.TypeInt, + ForceNew: true, + Optional: true, + Description: `The maximum number of nodes in the node pool. Must be >= minNodeCount, and must be > 0.`, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + + "cluster_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Allows you to configure various aspects of the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "staging_bucket": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + ForceNew: true, + Description: `The Cloud Storage staging bucket used to stage files, such as Hadoop jars, between client machines and the cluster. Note: If you don't explicitly specify a staging_bucket then GCP will auto create / assign one for you. However, you are not guaranteed an auto generated bucket which is solely dedicated to your cluster; it may be shared with other clusters in the same region/zone also choosing to use the auto generation option.`, + }, + // If the user does not specify a staging bucket, GCP will allocate one automatically. + // The staging_bucket field provides a way for the user to supply their own + // staging bucket. The bucket field is purely a computed field which details + // the definitive bucket allocated and in use (either the user supplied one via + // staging_bucket, or the GCP generated one) + "bucket": { + Type: schema.TypeString, + Computed: true, + Description: ` The name of the cloud storage bucket ultimately used to house the staging data for the cluster. If staging_bucket is specified, it will contain this value, otherwise it will be the auto generated name.`, + }, + + "temp_bucket": { + Type: schema.TypeString, + Optional: true, + Computed: true, + AtLeastOneOf: clusterConfigKeys, + ForceNew: true, + Description: `The Cloud Storage temp bucket used to store ephemeral cluster and jobs data, such as Spark and MapReduce history files. Note: If you don't explicitly specify a temp_bucket then GCP will auto create / assign one for you.`, + }, + + "gce_cluster_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `Common config settings for resources of Google Compute Engine cluster instances, applicable to all instances in the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "zone": { + Type: schema.TypeString, + Optional: true, + Computed: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Description: `The GCP zone where your data is stored and used (i.e. where the master and the worker nodes will be created in). If region is set to 'global' (default) then zone is mandatory, otherwise GCP is able to make use of Auto Zone Placement to determine this automatically for you. Note: This setting additionally determines and restricts which computing resources are available for use with other configs such as cluster_config.master_config.machine_type and cluster_config.worker_config.machine_type.`, + }, + + "network": { + Type: schema.TypeString, + Optional: true, + Computed: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + ConflictsWith: []string{"cluster_config.0.gce_cluster_config.0.subnetwork"}, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name or self_link of the Google Compute Engine network to the cluster will be part of. Conflicts with subnetwork. If neither is specified, this defaults to the "default" network.`, + }, + + "subnetwork": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + ConflictsWith: []string{"cluster_config.0.gce_cluster_config.0.network"}, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name or self_link of the Google Compute Engine subnetwork the cluster will be part of. Conflicts with network.`, + }, + + "tags": { + Type: schema.TypeSet, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `The list of instance tags applied to instances in the cluster. Tags are used to identify valid sources or targets for network firewalls.`, + }, + + "service_account": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Description: `The service account to be used by the Node VMs. If not specified, the "default" service account is used.`, + }, + + "service_account_scopes": { + Type: schema.TypeSet, + Optional: true, + Computed: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Description: `The set of Google API scopes to be made available on all of the node VMs under the service_account specified. These can be either FQDNs, or scope aliases.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + StateFunc: func(v interface{}) string { + return tpgresource.CanonicalizeServiceScope(v.(string)) + }, + }, + Set: tpgresource.StringScopeHashcode, + }, + + "internal_ip_only": { + Type: schema.TypeBool, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + ForceNew: true, + Default: false, + Description: `By default, clusters are not restricted to internal IP addresses, and will have ephemeral external IP addresses assigned to each instance. If set to true, all instances in the cluster will only have internal IP addresses. Note: Private Google Access (also known as privateIpGoogleAccess) must be enabled on the subnetwork that the cluster will be launched in.`, + }, + + "metadata": { + Type: schema.TypeMap, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + Elem: &schema.Schema{Type: schema.TypeString}, + ForceNew: true, + Description: `A map of the Compute Engine metadata entries to add to all instances`, + }, + + "shielded_instance_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `Shielded Instance Config for clusters using Compute Engine Shielded VMs.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_secure_boot": { + Type: schema.TypeBool, + Optional: true, + Default: false, + AtLeastOneOf: schieldedInstanceConfigKeys, + ForceNew: true, + Description: `Defines whether instances have Secure Boot enabled.`, + }, + "enable_vtpm": { + Type: schema.TypeBool, + Optional: true, + Default: false, + AtLeastOneOf: schieldedInstanceConfigKeys, + ForceNew: true, + Description: `Defines whether instances have the vTPM enabled.`, + }, + "enable_integrity_monitoring": { + Type: schema.TypeBool, + Optional: true, + Default: false, + AtLeastOneOf: schieldedInstanceConfigKeys, + ForceNew: true, + Description: `Defines whether instances have integrity monitoring enabled.`, + }, + }, + }, + }, + + "reservation_affinity": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `Reservation Affinity for consuming Zonal reservation.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "consume_reservation_type": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: reservationAffinityKeys, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"NO_RESERVATION", "ANY_RESERVATION", "SPECIFIC_RESERVATION"}, false), + Description: `Type of reservation to consume.`, + }, + "key": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: reservationAffinityKeys, + ForceNew: true, + Description: `Corresponds to the label key of reservation resource.`, + }, + "values": { + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + AtLeastOneOf: reservationAffinityKeys, + ForceNew: true, + Description: `Corresponds to the label values of reservation resource.`, + }, + }, + }, + }, + + "node_group_affinity": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: gceClusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `Node Group Affinity for sole-tenant clusters.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "node_group_uri": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + Description: `The URI of a sole-tenant that the cluster will be created on.`, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + }, + }, + }, + }, + }, + }, + }, + + "master_config": instanceConfigSchema("master_config"), + "worker_config": instanceConfigSchema("worker_config"), + // preemptible_worker_config has a slightly different config + "preemptible_worker_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `The Google Compute Engine config settings for the additional (aka preemptible) instances in a cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "num_instances": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + Description: `Specifies the number of preemptible nodes to create. Defaults to 0.`, + AtLeastOneOf: []string{ + "cluster_config.0.preemptible_worker_config.0.num_instances", + "cluster_config.0.preemptible_worker_config.0.preemptibility", + "cluster_config.0.preemptible_worker_config.0.disk_config", + }, + }, + + // API does not honour this if set ... + // It always uses whatever is specified for the worker_config + // "machine_type": { ... } + // "min_cpu_platform": { ... } + "preemptibility": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies the preemptibility of the secondary nodes. Defaults to PREEMPTIBLE.`, + AtLeastOneOf: []string{ + "cluster_config.0.preemptible_worker_config.0.num_instances", + "cluster_config.0.preemptible_worker_config.0.preemptibility", + "cluster_config.0.preemptible_worker_config.0.disk_config", + }, + ForceNew: true, + ValidateFunc: validation.StringInSlice([]string{"PREEMPTIBILITY_UNSPECIFIED", "NON_PREEMPTIBLE", "PREEMPTIBLE", "SPOT"}, false), + Default: "PREEMPTIBLE", + }, + + "disk_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Description: `Disk Config`, + AtLeastOneOf: []string{ + "cluster_config.0.preemptible_worker_config.0.num_instances", + "cluster_config.0.preemptible_worker_config.0.preemptibility", + "cluster_config.0.preemptible_worker_config.0.disk_config", + }, + MaxItems: 1, + + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "num_local_ssds": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + AtLeastOneOf: preemptibleWorkerDiskConfigKeys, + ForceNew: true, + Description: `The amount of local SSD disks that will be attached to each preemptible worker node. Defaults to 0.`, + }, + + "boot_disk_size_gb": { + Type: schema.TypeInt, + Optional: true, + Computed: true, + AtLeastOneOf: preemptibleWorkerDiskConfigKeys, + ForceNew: true, + ValidateFunc: validation.IntAtLeast(10), + Description: `Size of the primary disk attached to each preemptible worker node, specified in GB. The smallest allowed disk size is 10GB. GCP will default to a predetermined computed value if not set (currently 500GB). Note: If SSDs are not attached, it also contains the HDFS data blocks and Hadoop working directories.`, + }, + + "boot_disk_type": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: preemptibleWorkerDiskConfigKeys, + ForceNew: true, + Default: "pd-standard", + Description: `The disk type of the primary disk attached to each preemptible worker node. Such as "pd-ssd" or "pd-standard". Defaults to "pd-standard".`, + }, + }, + }, + }, + + "instance_names": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `List of preemptible instance names which have been assigned to the cluster.`, + }, + }, + }, + }, + + "security_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Security related configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "kerberos_config": { + Type: schema.TypeList, + Required: true, + Description: "Kerberos related configuration", + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "cross_realm_trust_admin_server": { + Type: schema.TypeString, + Optional: true, + Description: `The admin server (IP or hostname) for the remote trusted realm in a cross realm trust relationship.`, + }, + "cross_realm_trust_kdc": { + Type: schema.TypeString, + Optional: true, + Description: `The KDC (IP or hostname) for the remote trusted realm in a cross realm trust relationship.`, + }, + "cross_realm_trust_realm": { + Type: schema.TypeString, + Optional: true, + Description: `The remote realm the Dataproc on-cluster KDC will trust, should the user enable cross realm trust.`, + }, + "cross_realm_trust_shared_password_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing the shared password between the on-cluster +Kerberos realm and the remote trusted realm, in a cross realm trust relationship.`, + }, + "enable_kerberos": { + Type: schema.TypeBool, + Optional: true, + Description: `Flag to indicate whether to Kerberize the cluster.`, + }, + "kdc_db_key_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing the master key of the KDC database.`, + }, + "key_password_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing the password to the user provided key. For the self-signed certificate, this password is generated by Dataproc.`, + }, + "keystore_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of the keystore file used for SSL encryption. If not provided, Dataproc will provide a self-signed certificate.`, + }, + "keystore_password_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing +the password to the user provided keystore. For the self-signed certificate, this password is generated +by Dataproc`, + }, + "kms_key_uri": { + Type: schema.TypeString, + Required: true, + Description: `The uri of the KMS key used to encrypt various sensitive files.`, + }, + "realm": { + Type: schema.TypeString, + Optional: true, + Description: `The name of the on-cluster Kerberos realm. If not specified, the uppercased domain of hostnames will be the realm.`, + }, + "root_principal_password_uri": { + Type: schema.TypeString, + Required: true, + Description: `The cloud Storage URI of a KMS encrypted file containing the root principal password.`, + }, + "tgt_lifetime_hours": { + Type: schema.TypeInt, + Optional: true, + Description: `The lifetime of the ticket granting ticket, in hours.`, + }, + "truststore_password_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of a KMS encrypted file containing the password to the user provided truststore. For the self-signed certificate, this password is generated by Dataproc.`, + }, + "truststore_uri": { + Type: schema.TypeString, + Optional: true, + Description: `The Cloud Storage URI of the truststore file used for SSL encryption. If not provided, Dataproc will provide a self-signed certificate.`, + }, + }, + }, + }, + }, + }, + }, + + "software_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + Computed: true, + MaxItems: 1, + Description: `The config settings for software inside the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "image_version": { + Type: schema.TypeString, + Optional: true, + Computed: true, + AtLeastOneOf: clusterSoftwareConfigKeys, + ForceNew: true, + DiffSuppressFunc: dataprocImageVersionDiffSuppress, + Description: `The Cloud Dataproc image version to use for the cluster - this controls the sets of software versions installed onto the nodes when you create clusters. If not specified, defaults to the latest version.`, + }, + "override_properties": { + Type: schema.TypeMap, + Optional: true, + AtLeastOneOf: clusterSoftwareConfigKeys, + ForceNew: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A list of override and additional properties (key/value pairs) used to modify various aspects of the common configuration files used when creating a cluster.`, + }, + + "properties": { + Type: schema.TypeMap, + Computed: true, + Description: `A list of the properties used to set the daemon config files. This will include any values supplied by the user via cluster_config.software_config.override_properties`, + }, + + // We have two versions of the properties field here because by default + // dataproc will set a number of default properties for you out of the + // box. If you want to override one or more, if we only had one field, + // you would need to add in all these values as well otherwise you would + // get a diff. To make this easier, 'properties' simply contains the computed + // values (including overrides) for all properties, whilst override_properties + // is only for properties the user specifically wants to override. If nothing + // is overridden, this will be empty. + + "optional_components": { + Type: schema.TypeSet, + Optional: true, + AtLeastOneOf: clusterSoftwareConfigKeys, + Description: `The set of optional components to activate on the cluster.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "initialization_action": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + ForceNew: true, + Description: `Commands to execute on each node after config is completed. You can specify multiple versions of these.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "script": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The script to be executed during initialization of the cluster. The script must be a GCS file with a gs:// prefix.`, + }, + + "timeout_sec": { + Type: schema.TypeInt, + Optional: true, + Default: 300, + ForceNew: true, + Description: `The maximum duration (in seconds) which script is allowed to take to execute its action. GCP will default to a predetermined computed value if not set (currently 300).`, + }, + }, + }, + }, + "encryption_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + MaxItems: 1, + Description: `The Customer managed encryption keys settings for the cluster.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "kms_key_name": { + Type: schema.TypeString, + Required: true, + Description: `The Cloud KMS key name to use for PD disk encryption for all instances in the cluster.`, + }, + }, + }, + }, + "autoscaling_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + MaxItems: 1, + Description: `The autoscaling policy config associated with the cluster.`, + DiffSuppressFunc: tpgresource.EmptyOrUnsetBlockDiffSuppress, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "policy_uri": { + Type: schema.TypeString, + Required: true, + Description: `The autoscaling policy used by the cluster.`, + DiffSuppressFunc: tpgresource.LocationDiffSuppress, + }, + }, + }, + }, + "metastore_config": { + Type: schema.TypeList, + Optional: true, + AtLeastOneOf: clusterConfigKeys, + MaxItems: 1, + Description: `Specifies a Metastore configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dataproc_metastore_service": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Resource name of an existing Dataproc Metastore service.`, + }, + }, + }, + }, + "lifecycle_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + AtLeastOneOf: clusterConfigKeys, + Description: `The settings for auto deletion cluster schedule.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "idle_delete_ttl": { + Type: schema.TypeString, + Optional: true, + Description: `The duration to keep the cluster alive while idling (no jobs running). After this TTL, the cluster will be deleted. Valid range: [10m, 14d].`, + AtLeastOneOf: []string{ + "cluster_config.0.lifecycle_config.0.idle_delete_ttl", + "cluster_config.0.lifecycle_config.0.auto_delete_time", + }, + }, + "idle_start_time": { + Type: schema.TypeString, + Computed: true, + Description: `Time when the cluster became idle (most recent job finished) and became eligible for deletion due to idleness.`, + }, + // the API also has the auto_delete_ttl option in its request, however, + // the value is not returned in the response, rather the auto_delete_time + // after calculating ttl with the update time is returned, thus, for now + // we will only allow auto_delete_time to updated. + "auto_delete_time": { + Type: schema.TypeString, + Optional: true, + Description: `The time when cluster will be auto-deleted. A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z".`, + DiffSuppressFunc: tpgresource.TimestampDiffSuppress(time.RFC3339Nano), + AtLeastOneOf: []string{ + "cluster_config.0.lifecycle_config.0.idle_delete_ttl", + "cluster_config.0.lifecycle_config.0.auto_delete_time", + }, + }, + }, + }, + }, + "endpoint_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `The config settings for port access on the cluster. Structure defined below.`, + AtLeastOneOf: clusterConfigKeys, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_http_port_access": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `The flag to enable http access to specific ports on the cluster from external sources (aka Component Gateway). Defaults to false.`, + }, + "http_ports": { + Type: schema.TypeMap, + Computed: true, + Description: `The map of port descriptions to URLs. Will only be populated if enable_http_port_access is true.`, + }, + }, + }, + }, + + "dataproc_metric_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `The config for Dataproc metrics.`, + AtLeastOneOf: clusterConfigKeys, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "metrics": { + Type: schema.TypeList, + Required: true, + Description: `Metrics sources to enable.`, + Elem: metricsSchema(), + }, + }, + }, + }, + }, + }, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceDataprocClusterStateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return tpgresource.LabelsStateUpgrade(rawState, resourceDataprocGoogleLabelPrefix) +} diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb index 4e0f97060275..db170c912973 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb @@ -686,14 +686,46 @@ func TestAccDataprocCluster_withLabels(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckDataprocClusterDestroy(t), Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withoutLabels(rnd), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // We don't provide any, but GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), + ), + }, { Config: testAccDataprocCluster_withLabels(rnd), Check: resource.ComposeTestCheckFunc( testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), - // We only provide one, but GCP adds three and we added goog-dataproc-autozone internally, so expect 5. - resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + { + Config: testAccDataprocCluster_withLabelsUpdate(rnd), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + // We only provide two, so expect 2. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key2", "value2"), + ), + }, + { + Config: testAccDataprocCluster_withoutLabels(rnd), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // We don't provide any, but GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), ), }, }, @@ -1133,6 +1165,7 @@ resource "google_container_cluster" "primary" { workload_identity_config { workload_pool = "${data.google_project.project.project_id}.svc.id.goog" } + deletion_protection = false } resource "google_project_iam_binding" "workloadidentity" { @@ -1397,7 +1430,7 @@ resource "google_compute_node_group" "nodes" { name = "test-nodegroup-%s" zone = "us-central1-f" - size = 3 + initial_size = 3 node_template = google_compute_node_template.nodetmpl.self_link } @@ -1723,6 +1756,28 @@ resource "google_dataproc_cluster" "with_labels" { `, rnd) } +func testAccDataprocCluster_withLabelsUpdate(rnd string) string { + return fmt.Sprintf(` +resource "google_dataproc_cluster" "with_labels" { + name = "tf-test-dproc-%s" + region = "us-central1" + + labels = { + key2 = "value2" + } +} +`, rnd) +} + +func testAccDataprocCluster_withoutLabels(rnd string) string { + return fmt.Sprintf(` +resource "google_dataproc_cluster" "with_labels" { + name = "tf-test-dproc-%s" + region = "us-central1" +} +`, rnd) +} + func testAccDataprocCluster_withEndpointConfig(rnd string) string { return fmt.Sprintf(` resource "google_dataproc_cluster" "with_endpoint_config" { diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_upgrade_test.go b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_upgrade_test.go new file mode 100644 index 000000000000..57e11de4a1b8 --- /dev/null +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_upgrade_test.go @@ -0,0 +1,212 @@ +package dataproc_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "google.golang.org/api/dataproc/v1" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +// Tests schema version migration by creating a cluster with an old version of the provider (4.65.0) +// and then updating it with the current version the provider. +func TestAccDataprocClusterLabelsMigration_withoutLabels_withoutChanges(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.65.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ExternalProviders: oldVersion, + }, + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), + ), + }, + { + Config: testAccDataprocCluster_withLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + }, + }) +} + +func TestAccDataprocClusterLabelsMigration_withLabels_withoutChanges(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.65.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withLabels(rnd), + ExternalProviders: oldVersion, + }, + { + Config: testAccDataprocCluster_withLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + { + Config: testAccDataprocCluster_withLabelsUpdate(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + // We only provide one, so expect 1. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key2", "value2"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key2", "value2"), + ), + }, + }, + }) +} + +func TestAccDataprocClusterLabelsMigration_withUpdate(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.65.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ExternalProviders: oldVersion, + }, + { + Config: testAccDataprocCluster_withLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), + ), + }, + }, + }) +} + +func TestAccDataprocClusterLabelsMigration_withRemoval(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + rnd := acctest.RandString(t, 10) + var cluster dataproc.Cluster + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.65.0", // a version that doesn't separate user defined labels and system labels + Source: "registry.terraform.io/hashicorp/google", + }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckDataprocClusterDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocCluster_withLabels(rnd), + ExternalProviders: oldVersion, + }, + { + Config: testAccDataprocCluster_withoutLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckNoResourceAttr("google_dataproc_cluster.with_labels", "labels.%"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 4. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "4"), + ), + }, + { + Config: testAccDataprocCluster_withLabels(rnd), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Check: resource.ComposeTestCheckFunc( + testAccCheckDataprocClusterExists(t, "google_dataproc_cluster.with_labels", &cluster), + + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.%", "1"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "labels.key1", "value1"), + // We only provide one, but GCP adds three and goog-dataproc-autozone is added internally, so expect 5. + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.%", "5"), + resource.TestCheckResourceAttr("google_dataproc_cluster.with_labels", "effective_labels.key1", "value1"), + ), + }, + }, + }) +} diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb index 94cd75a6ed99..c51e7f5d19c5 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_job.go.erb @@ -11,6 +11,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "google.golang.org/api/dataproc/v1" @@ -30,6 +31,11 @@ func ResourceDataprocJob() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + tpgresource.SetLabelsDiff, + ), + Schema: map[string]*schema.Schema{ "project": { Type: schema.TypeString, @@ -144,12 +150,30 @@ func ResourceDataprocJob() *schema.Resource { "labels": { Type: schema.TypeMap, - Description: "Optional. The labels to associate with this job.", + Description: `Optional. The labels to associate with this job. + + **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.`, Optional: true, ForceNew: true, Elem: &schema.Schema{Type: schema.TypeString}, }, + "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}, + }, + + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + ForceNew: 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}, + }, + "scheduling": { Type: schema.TypeList, Description: "Optional. Job scheduling configuration.", @@ -230,8 +254,8 @@ func resourceDataprocJobCreate(d *schema.ResourceData, meta interface{}) error { submitReq.Job.Scheduling = expandJobScheduling(config) } - if _, ok := d.GetOk("labels"); ok { - submitReq.Job.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + submitReq.Job.Labels = tpgresource.ExpandEffectiveLabels(d) } if v, ok := d.GetOk("pyspark_config"); ok { @@ -311,9 +335,15 @@ func resourceDataprocJobRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("force_delete", d.Get("force_delete")); err != nil { return fmt.Errorf("Error setting force_delete: %s", err) } - if err := d.Set("labels", job.Labels); err != nil { + if err := tpgresource.SetLabels(job.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(job.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + if err := d.Set("effective_labels", job.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if err := d.Set("driver_output_resource_uri", job.DriverOutputResourceUri); err != nil { return fmt.Errorf("Error setting driver_output_resource_uri: %s", err) } diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_test.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_test.go.erb index 65afbe1c1026..21988d0cb673 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_test.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_workflow_template_test.go.erb @@ -37,6 +37,10 @@ func TestAccDataprocWorkflowTemplate_basic(t *testing.T) { { ImportState: true, ImportStateVerify: true, + // The "labels" field in the state are decided by the configuration. + // During importing, as the configuration is unavailable, the "labels" field in the state will be empty. + // So add the "labels" to the ImportStateVerifyIgnore list. + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, ResourceName: "google_dataproc_workflow_template.template", }, }, @@ -124,6 +128,11 @@ resource "google_dataproc_workflow_template" "template" { query_file_uri = "someuri" } } + + labels = { + env = "foo" + somekey = "somevalue" + } } `, context) } diff --git a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb index 6a351893759d..38225a1d54ad 100644 --- a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb +++ b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service.go.erb @@ -28,5 +28,17 @@ func dataSourceDataprocMetastoreServiceRead(d *schema.ResourceData, meta interfa return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceDataprocMetastoreServiceRead(d, meta) + err = resourceDataprocMetastoreServiceRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service_test.go.erb b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service_test.go.erb index 23832fffb79c..bb8ef1bcabdc 100644 --- a/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service_test.go.erb +++ b/mmv1/third_party/terraform/services/dataprocmetastore/data_source_dataproc_metastore_service_test.go.erb @@ -38,6 +38,10 @@ resource "google_dataproc_metastore_service" "my_metastore" { hive_metastore_config { version = "2.3.6" } + + labels = { + env = "test" + } } data "google_dataproc_metastore_service" "my_metastore" { diff --git a/mmv1/third_party/terraform/services/datastream/resource_datastream_stream_test.go b/mmv1/third_party/terraform/services/datastream/resource_datastream_stream_test.go index dde019ab0af1..ad71b868cd22 100644 --- a/mmv1/third_party/terraform/services/datastream/resource_datastream_stream_test.go +++ b/mmv1/third_party/terraform/services/datastream/resource_datastream_stream_test.go @@ -33,7 +33,7 @@ func TestAccDatastreamStream_update(t *testing.T) { ResourceName: "google_datastream_stream.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state"}, + ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state", "labels", "terraform_labels"}, }, { Config: testAccDatastreamStream_datastreamStreamBasicUpdate(context, "RUNNING", true), @@ -43,7 +43,7 @@ func TestAccDatastreamStream_update(t *testing.T) { ResourceName: "google_datastream_stream.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state"}, + ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state", "labels", "terraform_labels"}, }, { Config: testAccDatastreamStream_datastreamStreamBasicUpdate(context, "PAUSED", true), @@ -53,7 +53,7 @@ func TestAccDatastreamStream_update(t *testing.T) { ResourceName: "google_datastream_stream.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state"}, + ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state", "labels", "terraform_labels"}, }, { Config: testAccDatastreamStream_datastreamStreamBasicUpdate(context, "RUNNING", true), @@ -63,7 +63,7 @@ func TestAccDatastreamStream_update(t *testing.T) { ResourceName: "google_datastream_stream.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state"}, + ImportStateVerifyIgnore: []string{"stream_id", "location", "desired_state", "labels", "terraform_labels"}, }, { // Disable prevent_destroy diff --git a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_environment.go b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_environment.go index 086883aa0d4d..3953c21bb38d 100644 --- a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_environment.go +++ b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_environment.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -32,6 +33,10 @@ func ResourceDialogflowCXEnvironment() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "display_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_version.go b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_version.go index 980387b9eb16..98d22ff459ed 100644 --- a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_version.go +++ b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflow_cx_version.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -33,6 +34,10 @@ func ResourceDialogflowCXVersion() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "display_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_intent_test.go b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_intent_test.go index eba882c85830..e19b497bc825 100644 --- a/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_intent_test.go +++ b/mmv1/third_party/terraform/services/dialogflowcx/resource_dialogflowcx_intent_test.go @@ -25,17 +25,19 @@ func TestAccDialogflowCXIntent_update(t *testing.T) { Config: testAccDialogflowCXIntent_basic(context), }, { - ResourceName: "google_dialogflow_cx_intent.my_intent", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_dialogflow_cx_intent.my_intent", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDialogflowCXIntent_full(context), }, { - ResourceName: "google_dialogflow_cx_intent.my_intent", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_dialogflow_cx_intent.my_intent", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/dns/data_source_dns_keys.go b/mmv1/third_party/terraform/services/dns/data_source_dns_keys.go index 1cc9c8af095f..470815cdc2d0 100644 --- a/mmv1/third_party/terraform/services/dns/data_source_dns_keys.go +++ b/mmv1/third_party/terraform/services/dns/data_source_dns_keys.go @@ -16,7 +16,6 @@ import ( "github.com/hashicorp/terraform-provider-google/google/fwmodels" "github.com/hashicorp/terraform-provider-google/google/fwresource" "github.com/hashicorp/terraform-provider-google/google/fwtransport" - transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) // Ensure the implementation satisfies the expected interfaces @@ -179,9 +178,7 @@ func (d *GoogleDnsKeysDataSource) Read(ctx context.Context, req datasource.ReadR clientResp, err := d.client.DnsKeys.List(data.Project.ValueString(), data.ManagedZone.ValueString()).Do() if err != nil { - if !transport_tpg.IsGoogleApiErrorWithCode(err, 404) { - resp.Diagnostics.AddError(fmt.Sprintf("Error when reading or editing dataSourceDnsKeys"), err.Error()) - } + resp.Diagnostics.AddError(fmt.Sprintf("Error when reading or editing dataSourceDnsKeys"), err.Error()) // Save data into Terraform state resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) return diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb b/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb index 5b6fdd6f76ba..fbbd8ad3bbcf 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb +++ b/mmv1/third_party/terraform/services/dns/resource_dns_managed_zone_test.go.erb @@ -32,6 +32,7 @@ func TestAccDNSManagedZone_update(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDnsManagedZone_basic(zoneSuffix, "description2", map[string]string{"foo": "bar"}), @@ -40,6 +41,7 @@ func TestAccDNSManagedZone_update(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -174,6 +176,7 @@ func TestAccDNSManagedZone_cloudLoggingConfigUpdate(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDnsManagedZone_cloudLoggingConfig_update(zoneSuffix, true), @@ -182,6 +185,7 @@ func TestAccDNSManagedZone_cloudLoggingConfigUpdate(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccDnsManagedZone_cloudLoggingConfig_update(zoneSuffix, false), @@ -190,6 +194,7 @@ func TestAccDNSManagedZone_cloudLoggingConfigUpdate(t *testing.T) { ResourceName: "google_dns_managed_zone.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -438,6 +443,7 @@ resource "google_container_cluster" "cluster-1" { name = "tf-test-cluster-1-%s" location = "us-central1-c" initial_node_count = 1 + deletion_protection = false networking_mode = "VPC_NATIVE" default_snat_status { diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go b/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go index 38d53ebc4b39..4a4d90eaa5a0 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go +++ b/mmv1/third_party/terraform/services/dns/resource_dns_record_set.go @@ -8,6 +8,7 @@ import ( "net" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -81,6 +82,10 @@ func ResourceDnsRecordSet() *schema.Resource { State: resourceDnsRecordSetImportState, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "managed_zone": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/dns/resource_dns_response_policy_test.go.erb b/mmv1/third_party/terraform/services/dns/resource_dns_response_policy_test.go.erb index 3bc78da05c1a..5029770f1cef 100644 --- a/mmv1/third_party/terraform/services/dns/resource_dns_response_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/dns/resource_dns_response_policy_test.go.erb @@ -125,6 +125,7 @@ resource "google_container_cluster" "cluster-1" { cluster_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[1].range_name } + deletion_protection = false } `, suffix, network, suffix, suffix, suffix) } @@ -203,6 +204,7 @@ resource "google_container_cluster" "cluster-1" { cluster_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[0].range_name services_secondary_range_name = google_compute_subnetwork.subnetwork-1.secondary_ip_range[1].range_name } + deletion_protection = false } `, suffix, suffix, suffix, suffix) } diff --git a/mmv1/third_party/terraform/services/filestore/resource_filestore_backup_test.go b/mmv1/third_party/terraform/services/filestore/resource_filestore_backup_test.go index fc024f291721..768b61b89f8f 100644 --- a/mmv1/third_party/terraform/services/filestore/resource_filestore_backup_test.go +++ b/mmv1/third_party/terraform/services/filestore/resource_filestore_backup_test.go @@ -35,7 +35,7 @@ func TestAccFilestoreBackup_update(t *testing.T) { ResourceName: "google_filestore_backup.backup", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"labels", "description", "location"}, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels", "description", "location"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go b/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go index 96d44c1c8244..6f52889d72ae 100644 --- a/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go +++ b/mmv1/third_party/terraform/services/filestore/resource_filestore_instance_test.go @@ -56,7 +56,7 @@ func TestAccFilestoreInstance_update(t *testing.T) { ResourceName: "google_filestore_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"zone", "location"}, + ImportStateVerifyIgnore: []string{"zone", "location", "labels", "terraform_labels"}, }, { Config: testAccFilestoreInstance_update2(name), diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app.go.erb b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app.go.erb index e9167e5d8d3e..1c8ca39a6f46 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app.go.erb +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_android_app.go.erb @@ -37,6 +37,14 @@ func dataSourceGoogleFirebaseAndroidAppRead(d *schema.ResourceData, meta interfa if err := d.Set("name", name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - return resourceFirebaseAndroidAppRead(d, meta) + err = resourceFirebaseAndroidAppRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", name) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app.go.erb b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app.go.erb index 9d2351c22011..8737c2800b1a 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app.go.erb +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_apple_app.go.erb @@ -37,6 +37,14 @@ func dataSourceGoogleFirebaseAppleAppRead(d *schema.ResourceData, meta interface if err := d.Set("name", name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - return resourceFirebaseAppleAppRead(d, meta) + err = resourceFirebaseAppleAppRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", name) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app.go.erb b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app.go.erb index d6da3622e83c..4c5616580314 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app.go.erb +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app.go.erb @@ -37,6 +37,14 @@ func dataSourceGoogleFirebaseWebAppRead(d *schema.ResourceData, meta interface{} if err := d.Set("name", name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - return resourceFirebaseWebAppRead(d, meta) + err = resourceFirebaseWebAppRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", name) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_test.go.erb b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_test.go.erb index 6d387d96fe0b..2314f6bd26c1 100644 --- a/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_test.go.erb +++ b/mmv1/third_party/terraform/services/firebase/data_source_google_firebase_web_app_test.go.erb @@ -44,7 +44,6 @@ func testAccDataSourceGoogleFirebaseWebApp(context map[string]interface{}) strin resource "google_firebase_web_app" "my_app" { project = "%{project_id}" display_name = "%{display_name}" - deletion_policy = "DELETE" } data "google_firebase_web_app" "my_app" { diff --git a/mmv1/third_party/terraform/services/firebase/resource_firebase_web_app_test.go.erb b/mmv1/third_party/terraform/services/firebase/resource_firebase_web_app_test.go.erb index 540580925560..c0b25c6d74a4 100644 --- a/mmv1/third_party/terraform/services/firebase/resource_firebase_web_app_test.go.erb +++ b/mmv1/third_party/terraform/services/firebase/resource_firebase_web_app_test.go.erb @@ -22,13 +22,14 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "org_id": envvar.GetTestOrgFromEnv(t), + "project_id": envvar.GetTestProjectFromEnv(), "random_suffix": acctest.RandString(t, 10), "display_name": "tf-test Display Name N", } acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), Steps: []resource.TestStep{ { Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "", "key1"), @@ -42,11 +43,9 @@ func TestAccFirebaseWebApp_firebaseWebAppFull(t *testing.T) { ), }, { - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "", "key1"), }, { - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Config: testAccFirebaseWebApp_firebaseWebAppFull(context, "2", "key2"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("data.google_firebase_web_app_config.default", "api_key"), @@ -62,27 +61,11 @@ func testAccFirebaseWebApp_firebaseWebAppFull(context map[string]interface{}, up context["display_name"] = context["display_name"].(string) + update context["api_key_label"] = apiKeyLabel return acctest.Nprintf(` -resource "google_project" "default" { - provider = google-beta - - project_id = "tf-test%{random_suffix}" - name = "tf-test%{random_suffix}" - org_id = "%{org_id}" - labels = { - "firebase" = "enabled" - } -} - -resource "google_firebase_project" "default" { - provider = google-beta - project = google_project.default.project_id -} - resource "google_apikeys_key" "key1" { provider = google-beta name = "tf-test-api-key1%{random_suffix}" display_name = "Test api key 1" - project = google_project.default.project_id + project = "%{project_id}" restrictions { browser_key_restrictions { @@ -106,11 +89,10 @@ resource "google_apikeys_key" "key2" { resource "google_firebase_web_app" "default" { provider = google-beta - project = google_project.default.project_id + project = "%{project_id}" display_name = "%{display_name} %{random_suffix}" api_key_id = google_apikeys_key.%{api_key_label}.uid - - depends_on = [google_firebase_project.default] + deletion_policy = "DELETE" } data "google_firebase_web_app_config" "default" { @@ -124,7 +106,7 @@ func TestAccFirebaseWebApp_firebaseWebAppSkipDelete(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "project_id": envvar.GetTestProjectFromEnv(), + "org_id": envvar.GetTestOrgFromEnv(t), "random_suffix": acctest.RandString(t, 10), "display_name": "tf-test Display Name N", } @@ -148,11 +130,29 @@ func TestAccFirebaseWebApp_firebaseWebAppSkipDelete(t *testing.T) { } func testAccFirebaseWebApp_firebaseWebAppSkipDelete(context map[string]interface{}, update string) string { + // Create a new project so we can clean up the project entirely return acctest.Nprintf(` +resource "google_project" "default" { + provider = google-beta + + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + labels = { + "firebase" = "enabled" + } +} + +resource "google_firebase_project" "default" { + provider = google-beta + project = google_project.default.project_id +} + resource "google_firebase_web_app" "skip_delete" { provider = google-beta - project = "%{project_id}" + project = google_firebase_project.default.project display_name = "%{display_name} %{random_suffix}" + deletion_policy = "ABANDON" } `, context) } diff --git a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb index c8cd9e60a3a1..1a888cbd4f6c 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb +++ b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel.go.erb @@ -31,6 +31,18 @@ func dataSourceGoogleFirebaseHostingChannelRead(d *schema.ResourceData, meta int } d.SetId(id) - return resourceFirebaseHostingChannelRead(d, meta) + err = resourceFirebaseHostingChannelRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel_test.go.erb b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel_test.go.erb index ecb0f42ddd07..dc9adf02ea9e 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel_test.go.erb +++ b/mmv1/third_party/terraform/services/firebasehosting/data_source_google_firebase_hosting_channel_test.go.erb @@ -44,6 +44,10 @@ resource "google_firebase_hosting_site" "default" { resource "google_firebase_hosting_channel" "channel" { site_id = google_firebase_hosting_site.default.site_id channel_id = "tf-test-channel%{random_suffix}" + + labels = { + foo = "bar" + } } data "google_firebase_hosting_channel" "channel" { diff --git a/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_channel_test.go.erb b/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_channel_test.go.erb index 97dfe64fa86e..93169502da64 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_channel_test.go.erb +++ b/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_channel_test.go.erb @@ -75,7 +75,7 @@ func TestAccFirebaseHostingChannel_firebasehostingChannelUpdate(t *testing.T) { ResourceName: "google_firebase_hosting_channel.update", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl", "site_id", "channel_id"}, + ImportStateVerifyIgnore: []string{"ttl", "site_id", "channel_id", "labels", "terraform_labels"}, }, { Config: testAccFirebaseHostingChannel_firebasehostingChannelMultipleFields(context), @@ -84,7 +84,7 @@ func TestAccFirebaseHostingChannel_firebasehostingChannelUpdate(t *testing.T) { ResourceName: "google_firebase_hosting_channel.update", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl", "site_id", "channel_id"}, + ImportStateVerifyIgnore: []string{"ttl", "site_id", "channel_id", "labels", "terraform_labels"}, }, { Config: testAccFirebaseHostingChannel_firebasehostingChannelBasic(context), diff --git a/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_site_test.go.erb b/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_site_test.go.erb index 0bdd29754f5d..c12e002acaa2 100644 --- a/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_site_test.go.erb +++ b/mmv1/third_party/terraform/services/firebasehosting/resource_firebase_hosting_site_test.go.erb @@ -52,7 +52,6 @@ resource "google_firebase_web_app" "before" { provider = google-beta project = "%{project_id}" display_name = "tf-test Test web app before for Firebase Hosting" - deletion_policy = "DELETE" } resource "google_firebase_hosting_site" "update" { @@ -70,7 +69,6 @@ resource "google_firebase_web_app" "after" { provider = google-beta project = "%{project_id}" display_name = "tf-test Test web app after for Firebase Hosting" - deletion_policy = "DELETE" } resource "google_firebase_hosting_site" "update" { diff --git a/mmv1/third_party/terraform/services/gameservices/data_source_google_game_services_game_server_deployment_rollout.go b/mmv1/third_party/terraform/services/gameservices/data_source_google_game_services_game_server_deployment_rollout.go deleted file mode 100644 index ab8d406cafdb..000000000000 --- a/mmv1/third_party/terraform/services/gameservices/data_source_google_game_services_game_server_deployment_rollout.go +++ /dev/null @@ -1,33 +0,0 @@ -package gameservices - -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 DataSourceGameServicesGameServerDeploymentRollout() *schema.Resource { - - dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceGameServicesGameServerDeploymentRollout().Schema) - tpgresource.AddRequiredFieldsToSchema(dsSchema, "deployment_id") - - return &schema.Resource{ - Read: dataSourceGameServicesGameServerDeploymentRolloutRead, - Schema: dsSchema, - } -} - -func dataSourceGameServicesGameServerDeploymentRolloutRead(d *schema.ResourceData, meta interface{}) error { - config := meta.(*transport_tpg.Config) - - id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout") - if err != nil { - return fmt.Errorf("Error constructing id: %s", err) - } - - d.SetId(id) - - return resourceGameServicesGameServerDeploymentRolloutRead(d, meta) -} diff --git a/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb b/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb index ea1059fd8dac..9c8b4886b507 100644 --- a/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb +++ b/mmv1/third_party/terraform/services/gkebackup/resource_gke_backup_backup_plan_test.go.erb @@ -30,6 +30,7 @@ func TestAccGKEBackupBackupPlan_update(t *testing.T) { ResourceName: "google_gke_backup_backup_plan.backupplan", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccGKEBackupBackupPlan_full(context), @@ -38,6 +39,7 @@ func TestAccGKEBackupBackupPlan_update(t *testing.T) { ResourceName: "google_gke_backup_backup_plan.backupplan", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -57,6 +59,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } resource "google_gke_backup_backup_plan" "backupplan" { @@ -68,6 +71,9 @@ resource "google_gke_backup_backup_plan" "backupplan" { include_secrets = false all_namespaces = true } + labels = { + "some-key-1": "some-value-1" + } } `, context) } @@ -86,6 +92,7 @@ resource "google_container_cluster" "primary" { enabled = true } } + deletion_protection = false } resource "google_gke_backup_backup_plan" "backupplan" { @@ -113,6 +120,9 @@ resource "google_gke_backup_backup_plan" "backupplan" { } } } + labels = { + "some-key-2": "some-value-2" + } } `, context) } diff --git a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb index 8d905fadbf77..66015707cc14 100644 --- a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb @@ -387,6 +387,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" 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] } @@ -452,6 +453,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" 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] } @@ -518,6 +520,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" 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] } @@ -817,6 +820,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.container, google_project_service.gkehub] } @@ -869,6 +873,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.container, google_project_service.gkehub] } @@ -920,6 +925,7 @@ resource "google_container_cluster" "primary" { name = "tf-test-cl%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false depends_on = [google_project_service.container, google_project_service.gkehub] } @@ -971,6 +977,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" 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] } @@ -979,6 +986,7 @@ resource "google_container_cluster" "secondary" { location = "us-central1-a" 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] } @@ -987,6 +995,7 @@ resource "google_container_cluster" "tertiary" { location = "us-central1-a" 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] } @@ -996,6 +1005,7 @@ resource "google_container_cluster" "quarternary" { location = "us-central1-a" 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] } @@ -1069,6 +1079,7 @@ resource "google_container_cluster" "container_acmoci" { initial_node_count = 1 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] } diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb index b9d2dce61ccf..616bebb70a6b 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb @@ -231,7 +231,7 @@ func TestAccGKEHubFeature_gkehubFeatureMciUpdate(t *testing.T) { ResourceName: "google_gke_hub_feature.feature", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"update_time"}, + ImportStateVerifyIgnore: []string{"update_time", "labels", "terraform_labels"}, }, }, }) @@ -245,6 +245,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -253,6 +254,7 @@ resource "google_container_cluster" "secondary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -296,6 +298,7 @@ resource "google_container_cluster" "primary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -304,6 +307,7 @@ resource "google_container_cluster" "secondary" { location = "us-central1-a" initial_node_count = 1 project = google_project.project.project_id + deletion_protection = false depends_on = [google_project_service.mci, google_project_service.container, google_project_service.container, google_project_service.gkehub] } @@ -366,7 +370,7 @@ func TestAccGKEHubFeature_gkehubFeatureMcsd(t *testing.T) { ResourceName: "google_gke_hub_feature.feature", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"project"}, + ImportStateVerifyIgnore: []string{"project", "labels", "terraform_labels"}, }, { Config: testAccGKEHubFeature_gkehubFeatureMcsdUpdate(context), @@ -375,6 +379,7 @@ func TestAccGKEHubFeature_gkehubFeatureMcsd(t *testing.T) { ResourceName: "google_gke_hub_feature.feature", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go index 5834df3cb576..8f1a7bc10787 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_membership_binding_test.go @@ -29,7 +29,7 @@ func TestAccGKEHub2MembershipBinding_gkehubMembershipBindingBasicExample_update( ResourceName: "google_gke_hub_membership_binding.example", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"membership_binding_id", "scope", "membership_id", "location"}, + ImportStateVerifyIgnore: []string{"membership_binding_id", "scope", "membership_id", "location", "labels", "terraform_labels"}, }, { Config: testAccGKEHub2MembershipBinding_gkehubMembershipBindingBasicExample_update(context), @@ -38,7 +38,7 @@ func TestAccGKEHub2MembershipBinding_gkehubMembershipBindingBasicExample_update( ResourceName: "google_gke_hub_membership_binding.example", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"membership_binding_id", "scope", "membership_id", "location"}, + ImportStateVerifyIgnore: []string{"membership_binding_id", "scope", "membership_id", "location", "labels", "terraform_labels"}, }, }, }) @@ -50,6 +50,7 @@ resource "google_container_cluster" "primary" { name = "basiccluster%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_gke_hub_membership" "example" { @@ -91,6 +92,7 @@ resource "google_container_cluster" "primary" { name = "basiccluster%{random_suffix}" location = "us-central1-a" initial_node_count = 1 + deletion_protection = false } resource "google_gke_hub_membership" "example" { diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_namespace_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_namespace_test.go index 5dcc01cd2b83..a80cb1393807 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_namespace_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_namespace_test.go @@ -28,7 +28,7 @@ func TestAccGKEHub2Namespace_gkehubNamespaceBasicExample_update(t *testing.T) { ResourceName: "google_gke_hub_namespace.namespace", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_namespace_id", "scope", "scope_id", "scope"}, + ImportStateVerifyIgnore: []string{"scope_namespace_id", "scope", "scope_id", "scope", "labels", "terraform_labels"}, }, { Config: testAccGKEHub2Namespace_gkehubNamespaceBasicExample_update(context), @@ -37,7 +37,7 @@ func TestAccGKEHub2Namespace_gkehubNamespaceBasicExample_update(t *testing.T) { ResourceName: "google_gke_hub_namespace.namespace", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_namespace_id", "scope", "scope_id", "scope"}, + ImportStateVerifyIgnore: []string{"scope_namespace_id", "scope", "scope_id", "scope", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_rbac_role_binding_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_rbac_role_binding_test.go index a1f9e6f5742e..5756e6c2a8b3 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_rbac_role_binding_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_rbac_role_binding_test.go @@ -28,7 +28,7 @@ func TestAccGKEHub2ScopeRBACRoleBinding_gkehubScopeRbacRoleBindingBasicExample_u ResourceName: "google_gke_hub_scope_rbac_role_binding.scoperbacrolebinding", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_rbac_role_binding_id", "scope_id"}, + ImportStateVerifyIgnore: []string{"scope_rbac_role_binding_id", "scope_id", "labels", "terraform_labels"}, }, { Config: testAccGKEHub2ScopeRBACRoleBinding_gkehubScopeRbacRoleBindingBasicExample_update(context), @@ -37,7 +37,7 @@ func TestAccGKEHub2ScopeRBACRoleBinding_gkehubScopeRbacRoleBindingBasicExample_u ResourceName: "google_gke_hub_scope_rbac_role_binding.scoperbacrolebinding", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_rbac_role_binding_id", "scope_id"}, + ImportStateVerifyIgnore: []string{"scope_rbac_role_binding_id", "scope_id", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go index 0c3c84e598ab..967fe08c4bc2 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go @@ -28,7 +28,7 @@ func TestAccGKEHub2Scope_gkehubScopeBasicExample_update(t *testing.T) { ResourceName: "google_gke_hub_scope.scope", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_id"}, + ImportStateVerifyIgnore: []string{"scope_id", "labels", "terraform_labels"}, }, { Config: testAccGKEHub2Scope_gkehubScopeBasicExample_update(context), @@ -37,7 +37,7 @@ func TestAccGKEHub2Scope_gkehubScopeBasicExample_update(t *testing.T) { ResourceName: "google_gke_hub_scope.scope", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"scope_id"}, + ImportStateVerifyIgnore: []string{"scope_id", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_cluster_test.go.erb b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_cluster_test.go.erb index be8905f2f378..9664b054d931 100644 --- a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_cluster_test.go.erb @@ -27,6 +27,7 @@ func TestAccGkeonpremBareMetalCluster_bareMetalClusterUpdateBasic(t *testing.T) ResourceName: "google_gkeonprem_bare_metal_cluster.cluster-metallb", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, { Config: testAccGkeonpremBareMetalCluster_bareMetalClusterUpdateMetalLb(context), @@ -35,6 +36,7 @@ func TestAccGkeonpremBareMetalCluster_bareMetalClusterUpdateBasic(t *testing.T) ResourceName: "google_gkeonprem_bare_metal_cluster.cluster-metallb", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, }, }) @@ -111,6 +113,9 @@ func testAccGkeonpremBareMetalCluster_bareMetalClusterUpdateMetalLbStart(context provider = google-beta name = "cluster-metallb%{random_suffix}" location = "us-west1" + annotations = { + env = "test" + } admin_cluster_membership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test" bare_metal_version = "1.12.3" network_config { @@ -187,6 +192,9 @@ func testAccGkeonpremBareMetalCluster_bareMetalClusterUpdateMetalLb(context map[ provider = google-beta name = "cluster-metallb%{random_suffix}" location = "us-west1" + annotations = { + env = "test-update" + } admin_cluster_membership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test" bare_metal_version = "1.12.3" network_config { diff --git a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_node_pool_test.go.erb b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_node_pool_test.go.erb index 2819f8f66a34..866021db160f 100644 --- a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_bare_metal_node_pool_test.go.erb @@ -27,6 +27,7 @@ func TestAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdate(t *testing.T) { ResourceName: "google_gkeonprem_bare_metal_node_pool.nodepool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, { Config: testAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdate(context), @@ -35,6 +36,7 @@ func TestAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdate(t *testing.T) { ResourceName: "google_gkeonprem_bare_metal_node_pool.nodepool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, }, }) @@ -121,7 +123,9 @@ func testAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdateStart(context map[ name = "tf-test-nodepool-%{random_suffix}" location = "us-west1" bare_metal_cluster = google_gkeonprem_bare_metal_cluster.cluster.name - annotations = {} + annotations = { + env = "test" + } node_pool_config { operating_system = "LINUX" labels = {} @@ -215,7 +219,9 @@ func testAccGkeonpremBareMetalNodePool_bareMetalNodePoolUpdate(context map[strin name = "tf-test-nodepool-%{random_suffix}" location = "us-west1" bare_metal_cluster = google_gkeonprem_bare_metal_cluster.cluster.name - annotations = {} + annotations = { + env = "test-update" + } node_pool_config { operating_system = "LINUX" labels = {} diff --git a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_cluster_test.go.erb b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_cluster_test.go.erb index a2cc7e50f7e9..3771d14f521f 100644 --- a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_cluster_test.go.erb @@ -27,6 +27,7 @@ func TestAccGkeonpremVmwareCluster_vmwareClusterUpdateBasic(t *testing.T) { ResourceName: "google_gkeonprem_vmware_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, { Config: testAccGkeonpremVmwareCluster_vmwareClusterUpdateMetalLb(context), @@ -35,6 +36,7 @@ func TestAccGkeonpremVmwareCluster_vmwareClusterUpdateBasic(t *testing.T) { ResourceName: "google_gkeonprem_vmware_cluster.cluster", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, }, }) @@ -117,7 +119,9 @@ func testAccGkeonpremVmwareCluster_vmwareClusterUpdateMetalLbStart(context map[s admin_cluster_membership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test" description = "test cluster" on_prem_version = "1.13.1-gke.35" - annotations = {} + annotations = { + env = "test" + } network_config { service_address_cidr_blocks = ["10.96.0.0/12"] pod_address_cidr_blocks = ["192.168.0.0/16"] @@ -165,7 +169,9 @@ func testAccGkeonpremVmwareCluster_vmwareClusterUpdateMetalLb(context map[string admin_cluster_membership = "projects/870316890899/locations/global/memberships/gkeonprem-terraform-test" description = "test cluster updated" on_prem_version = "1.13.1-gke.36" - annotations = {} + annotations = { + env = "test-update" + } network_config { service_address_cidr_blocks = ["10.96.0.0/16"] pod_address_cidr_blocks = ["192.168.0.0/20"] diff --git a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_node_pool_test.go.erb b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_node_pool_test.go.erb index 4be86f65a2c1..8589b95ba4e8 100644 --- a/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/gkeonprem/resource_gkeonprem_vmware_node_pool_test.go.erb @@ -27,6 +27,7 @@ func TestAccGkeonpremVmwareNodePool_vmwareNodePoolUpdate(t *testing.T) { ResourceName: "google_gkeonprem_vmware_node_pool.nodepool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, { Config: testAccGkeonpremVmwareNodePool_vmwareNodePoolUpdate(context), @@ -35,6 +36,7 @@ func TestAccGkeonpremVmwareNodePool_vmwareNodePoolUpdate(t *testing.T) { ResourceName: "google_gkeonprem_vmware_node_pool.nodepool", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, }, }, }) @@ -92,7 +94,9 @@ func testAccGkeonpremVmwareNodePool_vmwareNodePoolUpdateStart(context map[string name = "tf-test-nodepool-%{random_suffix}" location = "us-west1" vmware_cluster = google_gkeonprem_vmware_cluster.cluster.name - annotations = {} + annotations = { + env = "test" + } config { cpus = 4 memory_mb = 8196 @@ -167,7 +171,9 @@ func testAccGkeonpremVmwareNodePool_vmwareNodePoolUpdate(context map[string]inte name = "tf-test-nodepool-%{random_suffix}" location = "us-west1" vmware_cluster = google_gkeonprem_vmware_cluster.cluster.name - annotations = {} + annotations = { + env = "test-update" + } config { cpus = 5 memory_mb = 4096 diff --git a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_dicom_store_test.go b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_dicom_store_test.go index 4b7584d72d1a..39dd582532da 100644 --- a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_dicom_store_test.go +++ b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_dicom_store_test.go @@ -91,9 +91,10 @@ func TestAccHealthcareDicomStore_basic(t *testing.T) { Config: testGoogleHealthcareDicomStore_basic(dicomStoreName, datasetName), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareDicomStore_update(dicomStoreName, datasetName, pubsubTopic), @@ -102,17 +103,19 @@ func TestAccHealthcareDicomStore_basic(t *testing.T) { ), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareDicomStore_basic(dicomStoreName, datasetName), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_fhir_store_test.go.erb b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_fhir_store_test.go.erb index 16fe33421493..470d123a5cde 100644 --- a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_fhir_store_test.go.erb +++ b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_fhir_store_test.go.erb @@ -95,6 +95,7 @@ func TestAccHealthcareFhirStore_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareFhirStore_update(fhirStoreName, datasetName, pubsubTopic), @@ -106,6 +107,7 @@ func TestAccHealthcareFhirStore_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareFhirStore_basic(fhirStoreName, datasetName), @@ -114,6 +116,7 @@ func TestAccHealthcareFhirStore_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_hl7_v2_store_test.go.erb b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_hl7_v2_store_test.go.erb index e3b6468de56f..aec48d059681 100644 --- a/mmv1/third_party/terraform/services/healthcare/resource_healthcare_hl7_v2_store_test.go.erb +++ b/mmv1/third_party/terraform/services/healthcare/resource_healthcare_hl7_v2_store_test.go.erb @@ -95,6 +95,7 @@ func TestAccHealthcareHl7V2Store_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareHl7V2Store_update(hl7_v2StoreName, datasetName, pubsubTopic), @@ -106,6 +107,7 @@ func TestAccHealthcareHl7V2Store_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleHealthcareHl7V2Store_basic(hl7_v2StoreName, datasetName), @@ -114,6 +116,7 @@ func TestAccHealthcareHl7V2Store_basic(t *testing.T) { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb index 88588781b10d..6df5264d41b5 100644 --- a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb +++ b/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb @@ -31,7 +31,15 @@ func dataSourceIAMBetaWorkloadIdentityPoolRead(d *schema.ResourceData, meta inte return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceIAMBetaWorkloadIdentityPoolRead(d, meta) + err = resourceIAMBetaWorkloadIdentityPoolRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb index 0aef39e9cfbc..582cd395c5fb 100644 --- a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb +++ b/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb @@ -32,7 +32,15 @@ func dataSourceIAMBetaWorkloadIdentityPoolProviderRead(d *schema.ResourceData, m return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceIAMBetaWorkloadIdentityPoolProviderRead(d, meta) + err = resourceIAMBetaWorkloadIdentityPoolProviderRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/iap/data_source_iap_client.go b/mmv1/third_party/terraform/services/iap/data_source_iap_client.go index 6cd3a863188d..736e18da0fe3 100644 --- a/mmv1/third_party/terraform/services/iap/data_source_iap_client.go +++ b/mmv1/third_party/terraform/services/iap/data_source_iap_client.go @@ -27,5 +27,13 @@ func dataSourceGoogleIapClientRead(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceIapClientRead(d, meta) + err = resourceIapClientRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go index 84c124eba250..670d67f40e66 100644 --- a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go +++ b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key.go @@ -1,6 +1,8 @@ package kms 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" @@ -31,7 +33,20 @@ func dataSourceGoogleKmsCryptoKeyRead(d *schema.ResourceData, meta interface{}) Name: d.Get("name").(string), } - d.SetId(cryptoKeyId.CryptoKeyId()) + id := cryptoKeyId.CryptoKeyId() + d.SetId(id) + + err = resourceKMSCryptoKeyRead(d, meta) + if err != nil { + return err + } - return resourceKMSCryptoKeyRead(d, meta) + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key_version.go b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key_version.go index eb7253f2c674..21192c68ea48 100644 --- a/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key_version.go +++ b/mmv1/third_party/terraform/services/kms/data_source_google_kms_crypto_key_version.go @@ -87,7 +87,7 @@ func dataSourceGoogleKmsCryptoKeyVersionRead(d *schema.ResourceData, meta interf UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("KmsCryptoKeyVersion %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("KmsCryptoKeyVersion %q", d.Id()), url) } if err := d.Set("version", flattenKmsCryptoKeyVersionVersion(res["name"], d)); err != nil { @@ -120,7 +120,7 @@ func dataSourceGoogleKmsCryptoKeyVersionRead(d *schema.ResourceData, meta interf UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("KmsCryptoKey %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("KmsCryptoKey %q", d.Id()), url) } if res["purpose"] == "ASYMMETRIC_SIGN" || res["purpose"] == "ASYMMETRIC_DECRYPT" { diff --git a/mmv1/third_party/terraform/services/kms/data_source_google_kms_key_ring.go b/mmv1/third_party/terraform/services/kms/data_source_google_kms_key_ring.go index ae1bc4f73199..7a47f9b798ef 100644 --- a/mmv1/third_party/terraform/services/kms/data_source_google_kms_key_ring.go +++ b/mmv1/third_party/terraform/services/kms/data_source_google_kms_key_ring.go @@ -1,6 +1,8 @@ package kms 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" @@ -31,7 +33,16 @@ func dataSourceGoogleKmsKeyRingRead(d *schema.ResourceData, meta interface{}) er Location: d.Get("location").(string), Project: project, } - d.SetId(keyRingId.KeyRingId()) + id := keyRingId.KeyRingId() + d.SetId(id) + + err = resourceKMSKeyRingRead(d, meta) + if err != nil { + return err + } - return resourceKMSKeyRingRead(d, meta) + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go b/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go index 6f84c616dc29..d067dbcdb9af 100644 --- a/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go +++ b/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go @@ -152,16 +152,18 @@ func TestAccKmsCryptoKey_basic(t *testing.T) { Config: testGoogleKmsCryptoKey_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key.crypto_key", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key.crypto_key", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, // Test importing with a short id { - ResourceName: "google_kms_crypto_key.crypto_key", - ImportState: true, - ImportStateId: fmt.Sprintf("%s/%s/%s/%s", projectId, location, keyRingName, cryptoKeyName), - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key.crypto_key", + ImportState: true, + ImportStateId: fmt.Sprintf("%s/%s/%s/%s", projectId, location, keyRingName, cryptoKeyName), + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, // Use a separate TestStep rather than a CheckDestroy because we need the project to still exist. { @@ -294,9 +296,10 @@ func TestAccKmsCryptoKey_destroyDuration(t *testing.T) { Config: testGoogleKmsCryptoKey_destroyDuration(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key.crypto_key", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key.crypto_key", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, // Use a separate TestStep rather than a CheckDestroy because we need the project to still exist. { @@ -332,7 +335,7 @@ func TestAccKmsCryptoKey_importOnly(t *testing.T) { ResourceName: "google_kms_crypto_key.crypto_key", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"skip_initial_version_creation"}, + ImportStateVerifyIgnore: []string{"skip_initial_version_creation", "labels", "terraform_labels"}, }, // Use a separate TestStep rather than a CheckDestroy because we need the project to still exist. { @@ -426,9 +429,10 @@ func TestAccKmsCryptoKeyVersion_basic(t *testing.T) { Config: testGoogleKmsCryptoKeyVersion_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key_version.crypto_key_version", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleKmsCryptoKeyVersion_removed(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), @@ -454,9 +458,10 @@ func TestAccKmsCryptoKeyVersion_skipInitialVersion(t *testing.T) { Config: testGoogleKmsCryptoKeyVersion_skipInitialVersion(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key_version.crypto_key_version", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -480,17 +485,19 @@ func TestAccKmsCryptoKeyVersion_patch(t *testing.T) { Config: testGoogleKmsCryptoKeyVersion_patchInitialize(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), }, { - ResourceName: "google_kms_crypto_key_version.crypto_key_version", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleKmsCryptoKeyVersion_patch("true", projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state), }, { - ResourceName: "google_kms_crypto_key_version.crypto_key_version", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testGoogleKmsCryptoKeyVersion_patch("false", projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state), diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_cmek_settings.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_cmek_settings.go index a2b30a6e414a..f839cbe7a868 100644 --- a/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_cmek_settings.go +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_cmek_settings.go @@ -85,7 +85,7 @@ func dataSourceGoogleLoggingProjectCmekSettingsRead(d *schema.ResourceData, meta UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("LoggingProjectCmekSettings %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("LoggingProjectCmekSettings %q", d.Id()), url) } d.SetId(fmt.Sprintf("projects/%s/cmekSettings", project)) diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_sink.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_sink.go index 64788602d8d7..95cf8663a709 100644 --- a/mmv1/third_party/terraform/services/logging/data_source_google_logging_sink.go +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_sink.go @@ -33,7 +33,7 @@ func dataSourceGoogleLoggingSinkRead(d *schema.ResourceData, meta interface{}) e sink, err := config.NewLoggingClient(userAgent).Sinks.Get(sinkId).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Logging Sink %s", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Logging Sink %s", d.Id()), sinkId) } if err := flattenResourceLoggingSink(d, sink); err != nil { diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config.go b/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config.go index 9ad5ebb08f29..923d253a74d0 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config.go @@ -6,6 +6,7 @@ import ( "regexp" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "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" @@ -105,6 +106,9 @@ func ResourceLoggingBucketConfig(parentType string, parentSpecificSchema map[str }, Schema: tpgresource.MergeSchemas(loggingBucketConfigSchema, parentSpecificSchema), UseJSONNumber: true, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), } } diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go index 5968089b847a..6072816e9a1e 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go @@ -1,3 +1,5 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 package logging import ( @@ -36,8 +38,8 @@ func ResourceLoggingProjectSink() *schema.Resource { schm.Schema["unique_writer_identity"] = &schema.Schema{ Type: schema.TypeBool, Optional: true, - Default: false, - Description: `Whether or not to create a unique identity associated with this sink. If false (the default), then the writer_identity used is serviceAccount:cloud-logs@system.gserviceaccount.com. If true, then a unique service account is created and used for this sink. If you wish to publish logs across projects, you must set unique_writer_identity to true.`, + Default: true, + Description: `Whether or not to create a unique identity associated with this sink. If false (the legacy behavior), then the writer_identity used is serviceAccount:cloud-logs@system.gserviceaccount.com. If true, then a unique service account is created and used for this sink. If you wish to publish logs across projects, you must set unique_writer_identity to true.`, } return schm } diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go index f2934f4d1573..cd0dcf102a62 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go @@ -292,13 +292,11 @@ func testAccLoggingProjectSink_basic(name, project, bucketName string) string { resource "google_logging_project_sink" "basic" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" - - unique_writer_identity = false } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -310,14 +308,14 @@ func testAccLoggingProjectSink_described(name, project, bucketName string) strin resource "google_logging_project_sink" "described" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" description = "this is a description for a project level logging sink" - + unique_writer_identity = false } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -329,14 +327,14 @@ func testAccLoggingProjectSink_described_update(name, project, bucketName string resource "google_logging_project_sink" "described" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" description = "description updated" - + unique_writer_identity = true } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -348,14 +346,14 @@ func testAccLoggingProjectSink_disabled(name, project, bucketName string) string resource "google_logging_project_sink" "disabled" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" disabled = true unique_writer_identity = false } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -367,14 +365,14 @@ func testAccLoggingProjectSink_disabled_update(name, project, bucketName, disabl resource "google_logging_project_sink" "disabled" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" disabled = "%s" unique_writer_identity = true } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -385,13 +383,13 @@ func testAccLoggingProjectSink_uniqueWriter(name, bucketName string) string { return fmt.Sprintf(` resource "google_logging_project_sink" "unique_writer" { name = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=ERROR" unique_writer_identity = true } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -402,13 +400,13 @@ func testAccLoggingProjectSink_uniqueWriterUpdated(name, bucketName string) stri return fmt.Sprintf(` resource "google_logging_project_sink" "unique_writer" { name = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=WARNING" unique_writer_identity = true } -resource "google_storage_bucket" "log-bucket" { +resource "google_storage_bucket" "gcs-bucket" { name = "%s" location = "US" } @@ -420,7 +418,7 @@ func testAccLoggingProjectSink_heredoc(name, project, bucketName string) string resource "google_logging_project_sink" "heredoc" { name = "%s" project = "%s" - destination = "storage.googleapis.com/${google_storage_bucket.log-bucket.name}" + destination = "storage.googleapis.com/${google_storage_bucket.gcs-bucket.name}" filter = <=ERROR" unique_writer_identity = true @@ -454,7 +452,7 @@ resource "google_logging_project_sink" "bigquery" { } } -resource "google_bigquery_dataset" "logging_sink" { +resource "google_bigquery_dataset" "bq_dataset" { dataset_id = "%s" description = "Log sink (generated during acc test of terraform-provider-google(-beta))." } @@ -465,13 +463,13 @@ func testAccLoggingProjectSink_bigquery_after(sinkName, bqDatasetID string) stri return fmt.Sprintf(` resource "google_logging_project_sink" "bigquery" { name = "%s" - destination = "bigquery.googleapis.com/projects/%s/datasets/${google_bigquery_dataset.logging_sink.dataset_id}" + destination = "bigquery.googleapis.com/projects/%s/datasets/${google_bigquery_dataset.bq_dataset.dataset_id}" filter = "logName=\"projects/%s/logs/compute.googleapis.com%%2Factivity_log\" AND severity>=WARNING" unique_writer_identity = true } -resource "google_bigquery_dataset" "logging_sink" { +resource "google_bigquery_dataset" "bq_dataset" { dataset_id = "%s" description = "Log sink (generated during acc test of terraform-provider-google(-beta))." } @@ -495,8 +493,6 @@ resource "google_logging_project_sink" "loggingbucket" { description = "test-2" filter = "resource.type = k8s_container" } - - unique_writer_identity = true } `, name, project, project) diff --git a/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go b/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go index 51b78686511e..585f0f114603 100644 --- a/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go +++ b/mmv1/third_party/terraform/services/memcache/resource_memcache_instance_test.go @@ -13,7 +13,7 @@ func TestAccMemcacheInstance_update(t *testing.T) { prefix := fmt.Sprintf("%d", acctest.RandInt(t)) name := fmt.Sprintf("tf-test-%s", prefix) - network := acctest.BootstrapSharedTestNetwork(t, "memcache-instance-update") + network := acctest.BootstrapSharedServiceNetworkingConnection(t, "memcache-instance-update-1") acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -42,24 +42,10 @@ func TestAccMemcacheInstance_update(t *testing.T) { func testAccMemcacheInstance_update(prefix, name, network string) string { return fmt.Sprintf(` -resource "google_compute_global_address" "service_range" { - name = "tf-test%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.memcache_network.id -} - -resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.memcache_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.service_range.name] -} - resource "google_memcache_instance" "test" { name = "%s" region = "us-central1" - authorized_network = google_service_networking_connection.private_service_connection.network + authorized_network = data.google_compute_network.memcache_network.id node_config { cpu_count = 1 @@ -78,29 +64,15 @@ resource "google_memcache_instance" "test" { data "google_compute_network" "memcache_network" { name = "%s" } -`, prefix, name, network) +`, name, network) } func testAccMemcacheInstance_update2(prefix, name, network string) string { return fmt.Sprintf(` -resource "google_compute_global_address" "service_range" { - name = "tf-test%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.memcache_network.id -} - -resource "google_service_networking_connection" "private_service_connection" { - network = data.google_compute_network.memcache_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.service_range.name] -} - resource "google_memcache_instance" "test" { name = "%s" region = "us-central1" - authorized_network = google_service_networking_connection.private_service_connection.network + authorized_network = data.google_compute_network.memcache_network.id node_config { cpu_count = 1 @@ -119,5 +91,5 @@ resource "google_memcache_instance" "test" { data "google_compute_network" "memcache_network" { name = "%s" } -`, prefix, name, network) +`, name, network) } diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go index b0a06770882d..458b5cfbb1c8 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard.go @@ -8,29 +8,51 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/structure" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) -func monitoringDashboardDiffSuppress(k, old, new string, d *schema.ResourceData) bool { - computedFields := []string{"etag", "name"} +// This recursive function takes an old map and a new map and is intended to remove the computed keys +// from the old json string (stored in state) so that it doesn't show a diff if it's not defined in the +// new map's json string (defined in config) +func removeComputedKeys(old map[string]interface{}, new map[string]interface{}) map[string]interface{} { + for k, v := range old { + if _, ok := old[k]; ok && new[k] == nil { + delete(old, k) + continue + } + + if reflect.ValueOf(v).Kind() == reflect.Map { + old[k] = removeComputedKeys(v.(map[string]interface{}), new[k].(map[string]interface{})) + continue + } + + if reflect.ValueOf(v).Kind() == reflect.Slice { + for i, j := range v.([]interface{}) { + if reflect.ValueOf(j).Kind() == reflect.Map { + old[k].([]interface{})[i] = removeComputedKeys(j.(map[string]interface{}), new[k].([]interface{})[i].(map[string]interface{})) + } + } + continue + } + } + return old +} + +func monitoringDashboardDiffSuppress(k, old, new string, d *schema.ResourceData) bool { oldMap, err := structure.ExpandJsonFromString(old) if err != nil { return false } - newMap, err := structure.ExpandJsonFromString(new) if err != nil { return false } - for _, f := range computedFields { - delete(oldMap, f) - delete(newMap, f) - } - + oldMap = removeComputedKeys(oldMap, newMap) return reflect.DeepEqual(oldMap, newMap) } @@ -51,6 +73,10 @@ func ResourceMonitoringDashboard() *schema.Resource { Delete: schema.DefaultTimeout(4 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "dashboard_json": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard_test.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard_test.go index 1f8caaa86759..5c1a5d28afd7 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard_test.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_dashboard_test.go @@ -83,8 +83,6 @@ func TestAccMonitoringDashboard_rowLayout(t *testing.T) { } func TestAccMonitoringDashboard_update(t *testing.T) { - // TODO: Fix requires a breaking change https://github.com/hashicorp/terraform-provider-google/issues/9976 - t.Skip() t.Parallel() acctest.VcrTest(t, resource.TestCase{ diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_metric_descriptor_test.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_metric_descriptor_test.go index a34cc21f54db..53ad4f17478e 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_metric_descriptor_test.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_metric_descriptor_test.go @@ -9,8 +9,6 @@ import ( ) func TestAccMonitoringMetricDescriptor_update(t *testing.T) { - // TODO: Fix requires a breaking change https://github.com/hashicorp/terraform-provider-google/issues/12139 - t.Skip() t.Parallel() acctest.VcrTest(t, resource.TestCase{ @@ -19,8 +17,7 @@ func TestAccMonitoringMetricDescriptor_update(t *testing.T) { CheckDestroy: testAccCheckMonitoringMetricDescriptorDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccMonitoringMetricDescriptor_update("key1", "STRING", - "description1", "30s", "30s"), + Config: testAccMonitoringMetricDescriptor_update("30s", "30s"), }, { ResourceName: "google_monitoring_metric_descriptor.basic", @@ -29,8 +26,7 @@ func TestAccMonitoringMetricDescriptor_update(t *testing.T) { ImportStateVerifyIgnore: []string{"metadata", "launch_stage"}, }, { - Config: testAccMonitoringMetricDescriptor_update("key2", "INT64", - "description2", "60s", "60s"), + Config: testAccMonitoringMetricDescriptor_update("60s", "60s"), }, { ResourceName: "google_monitoring_metric_descriptor.basic", @@ -42,8 +38,7 @@ func TestAccMonitoringMetricDescriptor_update(t *testing.T) { }) } -func testAccMonitoringMetricDescriptor_update(key, valueType, description, - samplePeriod, ingestDelay string) string { +func testAccMonitoringMetricDescriptor_update(samplePeriod, ingestDelay string) string { return fmt.Sprintf(` resource "google_monitoring_metric_descriptor" "basic" { description = "Daily sales records from all branch stores." @@ -53,9 +48,9 @@ resource "google_monitoring_metric_descriptor" "basic" { value_type = "DOUBLE" unit = "{USD}" labels { - key = "%s" - value_type = "%s" - description = "%s" + key = "key" + value_type = "STRING" + description = "description" } launch_stage = "BETA" metadata { @@ -63,6 +58,6 @@ resource "google_monitoring_metric_descriptor" "basic" { ingest_delay = "%s" } } -`, key, valueType, description, samplePeriod, ingestDelay, +`, samplePeriod, ingestDelay, ) } diff --git a/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_service_connection_policies_test.go b/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_service_connection_policies_test.go index 6344f761585b..0894eeab35d5 100644 --- a/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_service_connection_policies_test.go +++ b/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_service_connection_policies_test.go @@ -27,25 +27,28 @@ func TestAccNetworkConnectivityServiceConnectionPolicy_update(t *testing.T) { Config: testAccNetworkConnectivityServiceConnectionPolicy_basic(context), }, { - ResourceName: "google_network_connectivity_service_connection_policy.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkConnectivityServiceConnectionPolicy_update(context), }, { - ResourceName: "google_network_connectivity_service_connection_policy.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkConnectivityServiceConnectionPolicy_basic(context), }, { - ResourceName: "google_network_connectivity_service_connection_policy.default", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_address_group_test.go b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_address_group_test.go index 106848e01d65..15d35521d161 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_address_group_test.go +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_address_group_test.go @@ -24,17 +24,19 @@ func TestAccNetworkSecurityAddressGroups_update(t *testing.T) { Config: testAccNetworkSecurityAddressGroups_basic(addressGroupsName, projectName), }, { - ResourceName: "google_network_security_address_group.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_security_address_group.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkSecurityAddressGroups_update(addressGroupsName, projectName), }, { - ResourceName: "google_network_security_address_group.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_security_address_group.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_authorization_policy_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_authorization_policy_test.go.erb index b4993f5084d8..2d1c4af67055 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_authorization_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_authorization_policy_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkSecurityAuthorizationPolicy_update(t *testing.T) { ResourceName: "google_network_security_authorization_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkSecurityAuthorizationPolicy_update(authorizationPolicyName), @@ -35,6 +36,7 @@ func TestAccNetworkSecurityAuthorizationPolicy_update(t *testing.T) { ResourceName: "google_network_security_authorization_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_client_tls_policy_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_client_tls_policy_test.go.erb index 67de18513d1d..d91d8e030965 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_client_tls_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_client_tls_policy_test.go.erb @@ -21,12 +21,13 @@ func TestAccNetworkSecurityClientTlsPolicy_update(t *testing.T) { CheckDestroy: testAccCheckNetworkSecurityClientTlsPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccNetworkSecurityClientTlsPolicy_basic(clientTlsPolicyName), + Config: testAccNetworkSecurityClientTlsPolicy_basic(clientTlsPolicyName), }, { ResourceName: "google_network_security_client_tls_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkSecurityClientTlsPolicy_update(clientTlsPolicyName), @@ -35,6 +36,7 @@ func TestAccNetworkSecurityClientTlsPolicy_update(t *testing.T) { ResourceName: "google_network_security_client_tls_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_server_tls_policy_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_server_tls_policy_test.go.erb index 00f7755bf324..f1000f4665de 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_server_tls_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_server_tls_policy_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkSecurityServerTlsPolicy_update(t *testing.T) { ResourceName: "google_network_security_server_tls_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkSecurityServerTlsPolicy_update(serverTlsPolicyName), @@ -35,6 +36,7 @@ func TestAccNetworkSecurityServerTlsPolicy_update(t *testing.T) { ResourceName: "google_network_security_server_tls_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_keyset_test.go b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_keyset_test.go index f12e0cec4b04..56b1cd8bfcd3 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_keyset_test.go +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_keyset_test.go @@ -26,7 +26,7 @@ func TestAccNetworkServicesEdgeCacheKeyset_update(t *testing.T) { ResourceName: "google_network_services_edge_cache_keyset.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, { Config: testAccNetworkServicesEdgeCacheKeyset_update(context), @@ -35,7 +35,7 @@ func TestAccNetworkServicesEdgeCacheKeyset_update(t *testing.T) { ResourceName: "google_network_services_edge_cache_keyset.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_origin_test.go b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_origin_test.go index 9e68d59853d6..6ad86ecb883f 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_origin_test.go +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_edge_cache_origin_test.go @@ -23,7 +23,7 @@ func TestAccNetworkServicesEdgeCacheOrigin_updateAndImport(t *testing.T) { ResourceName: "google_network_services_edge_cache_origin.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, { Config: testAccNetworkServicesEdgeCacheOrigin_update_1(name), @@ -32,7 +32,7 @@ func TestAccNetworkServicesEdgeCacheOrigin_updateAndImport(t *testing.T) { ResourceName: "google_network_services_edge_cache_origin.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name"}, + ImportStateVerifyIgnore: []string{"name", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_endpoint_policy_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_endpoint_policy_test.go.erb index 5ca9e8290821..3369b28dc114 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_endpoint_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_endpoint_policy_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkServicesEndpointPolicy_update(t *testing.T) { ResourceName: "google_network_services_endpoint_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesEndpointPolicy_update(endpointPolicyName), @@ -35,6 +36,7 @@ func TestAccNetworkServicesEndpointPolicy_update(t *testing.T) { ResourceName: "google_network_services_endpoint_policy.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) 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 9aae107edfc1..d572021996d1 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 @@ -23,17 +23,19 @@ func TestAccNetworkServicesGateway_update(t *testing.T) { Config: testAccNetworkServicesGateway_basic(gatewayName), }, { - ResourceName: "google_network_services_gateway.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_services_gateway.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesGateway_update(gatewayName), }, { - ResourceName: "google_network_services_gateway.foobar", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_network_services_gateway.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_grpc_route_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_grpc_route_test.go.erb index 3220d937b433..e2a10dd024e7 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_grpc_route_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_grpc_route_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkServicesGrpcRoute_update(t *testing.T) { ResourceName: "google_network_services_grpc_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesGrpcRoute_update(grpcRouteName), @@ -35,6 +36,7 @@ func TestAccNetworkServicesGrpcRoute_update(t *testing.T) { ResourceName: "google_network_services_grpc_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_http_route_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_http_route_test.go.erb index f94075ec67ee..2f0c54530c64 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_http_route_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_http_route_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkServicesHttpRoute_update(t *testing.T) { ResourceName: "google_network_services_http_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesHttpRoute_update(httpRouteName), @@ -35,6 +36,7 @@ func TestAccNetworkServicesHttpRoute_update(t *testing.T) { ResourceName: "google_network_services_http_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_mesh_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_mesh_test.go.erb index 240f5b94887e..87451e4ee1a0 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_mesh_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_mesh_test.go.erb @@ -27,6 +27,7 @@ func TestAccNetworkServicesMesh_update(t *testing.T) { ResourceName: "google_network_services_mesh.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesMesh_update(meshName), @@ -35,6 +36,7 @@ func TestAccNetworkServicesMesh_update(t *testing.T) { ResourceName: "google_network_services_mesh.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/networkservices/resource_network_services_tcp_route_test.go.erb b/mmv1/third_party/terraform/services/networkservices/resource_network_services_tcp_route_test.go.erb index 0b7aa52cfc9e..27f545faed8a 100644 --- a/mmv1/third_party/terraform/services/networkservices/resource_network_services_tcp_route_test.go.erb +++ b/mmv1/third_party/terraform/services/networkservices/resource_network_services_tcp_route_test.go.erb @@ -23,12 +23,13 @@ func TestAccNetworkServicesTcpRoute_update(t *testing.T) { CheckDestroy: testAccCheckNetworkServicesTcpRouteDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccNetworkServicesTcpRoute_basic(tcpServiceName, tcpHealthCheckName, tcpRouteName), + Config: testAccNetworkServicesTcpRoute_basic(tcpServiceName, tcpHealthCheckName, tcpRouteName), }, { ResourceName: "google_network_services_tcp_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNetworkServicesTcpRoute_update(tcpServiceName, tcpHealthCheckName, tcpRouteName), @@ -37,6 +38,7 @@ func TestAccNetworkServicesTcpRoute_update(t *testing.T) { ResourceName: "google_network_services_tcp_route.foobar", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/notebooks/resource_notebooks_instance_test.go.erb b/mmv1/third_party/terraform/services/notebooks/resource_notebooks_instance_test.go.erb index 63857df18d57..90749f4dc35e 100644 --- a/mmv1/third_party/terraform/services/notebooks/resource_notebooks_instance_test.go.erb +++ b/mmv1/third_party/terraform/services/notebooks/resource_notebooks_instance_test.go.erb @@ -56,7 +56,7 @@ func TestAccNotebooksInstance_update(t *testing.T) { ResourceName: "google_notebooks_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"vm_image", "metadata"}, + ImportStateVerifyIgnore: []string{"vm_image", "metadata", "labels", "terraform_labels"}, }, { Config: testAccNotebooksInstance_update(context, false), @@ -65,7 +65,7 @@ func TestAccNotebooksInstance_update(t *testing.T) { ResourceName: "google_notebooks_instance.instance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"vm_image", "metadata"}, + ImportStateVerifyIgnore: []string{"vm_image", "metadata", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/osconfig/resource_os_config_os_policy_assignment.go b/mmv1/third_party/terraform/services/osconfig/resource_os_config_os_policy_assignment.go index c3e8e143c89d..9ea349cdbce8 100644 --- a/mmv1/third_party/terraform/services/osconfig/resource_os_config_os_policy_assignment.go +++ b/mmv1/third_party/terraform/services/osconfig/resource_os_config_os_policy_assignment.go @@ -7,6 +7,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "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" @@ -30,6 +31,10 @@ func ResourceOSConfigOSPolicyAssignment() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "instance_filter": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go index 1c72eda30b86..062930dca191 100644 --- a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go +++ b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority.go @@ -45,6 +45,10 @@ func dataSourcePrivatecaCertificateAuthorityRead(d *schema.ResourceData, meta in return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + // pem_csr is only applicable for SUBORDINATE CertificateAuthorities when their state is AWAITING_USER_ACTIVATION if d.Get("type") == "SUBORDINATE" && d.Get("state") == "AWAITING_USER_ACTIVATION" { url, err := tpgresource.ReplaceVars(d, config, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}:fetch") @@ -73,7 +77,7 @@ func dataSourcePrivatecaCertificateAuthorityRead(d *schema.ResourceData, meta in UserAgent: userAgent, }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("PrivatecaCertificateAuthority %q", d.Id())) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("PrivatecaCertificateAuthority %q", d.Id()), url) } if err := d.Set("pem_csr", res["pemCsr"]); err != nil { return fmt.Errorf("Error fetching CertificateAuthority: %s", err) diff --git a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority_test.go b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority_test.go index 2a7cdfb4c2d1..e50ba6119073 100644 --- a/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority_test.go +++ b/mmv1/third_party/terraform/services/privateca/data_source_certificate_authority_test.go @@ -81,6 +81,9 @@ resource "google_privateca_certificate_authority" "default" { key_spec { algorithm = "RSA_PKCS1_4096_SHA256" } + labels = { + my-label = "my-label-value" + } } data "google_privateca_certificate_authority" "default" { diff --git a/mmv1/third_party/terraform/services/privateca/resource_privateca_ca_pool_test.go b/mmv1/third_party/terraform/services/privateca/resource_privateca_ca_pool_test.go index b288d24fb7cb..8466df22a917 100644 --- a/mmv1/third_party/terraform/services/privateca/resource_privateca_ca_pool_test.go +++ b/mmv1/third_party/terraform/services/privateca/resource_privateca_ca_pool_test.go @@ -26,7 +26,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolUpdate(t *testing.T) { ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCaPool_privatecaCapoolEnd(context), @@ -35,7 +35,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolUpdate(t *testing.T) { ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCaPool_privatecaCapoolStart(context), @@ -44,7 +44,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolUpdate(t *testing.T) { ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, }, }) @@ -233,7 +233,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolEmptyBaseline(t *testing.T) { ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, }, }) @@ -297,7 +297,7 @@ func TestAccPrivatecaCaPool_privatecaCapoolEmptyPublishingOptions(t *testing.T) ResourceName: "google_privateca_ca_pool.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"name", "location"}, + ImportStateVerifyIgnore: []string{"name", "location", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_authority_test.go b/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_authority_test.go index b43ca328de94..44dafcc2edd9 100644 --- a/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_authority_test.go +++ b/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_authority_test.go @@ -34,7 +34,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t ResourceName: "google_privateca_certificate_authority.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period"}, + ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityEnd(context), @@ -43,7 +43,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t ResourceName: "google_privateca_certificate_authority.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period"}, + ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicRoot(context), @@ -52,7 +52,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t ResourceName: "google_privateca_certificate_authority.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period"}, + ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection", "skip_grace_period", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_test.go b/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_test.go index 0e955d5ed745..e6c0c5f76c36 100644 --- a/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_test.go +++ b/mmv1/third_party/terraform/services/privateca/resource_privateca_certificate_test.go @@ -36,7 +36,7 @@ func TestAccPrivatecaCertificate_privatecaCertificateUpdate(t *testing.T) { ResourceName: "google_privateca_certificate.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"pool", "name", "location", "certificate_authority"}, + ImportStateVerifyIgnore: []string{"pool", "name", "location", "certificate_authority", "labels", "terraform_labels"}, }, { Config: testAccPrivatecaCertificate_privatecaCertificateStart(context), diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go index 745315ad39fd..dde9618c8327 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription.go @@ -28,5 +28,17 @@ func dataSourceGooglePubsubSubscriptionRead(d *schema.ResourceData, meta interfa return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourcePubsubSubscriptionRead(d, meta) + err = resourcePubsubSubscriptionRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription_test.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription_test.go index a5c976e9241e..ffe48a0bae3a 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription_test.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_subscription_test.go @@ -60,6 +60,9 @@ resource "google_pubsub_topic" "foo" { resource "google_pubsub_subscription" "foo" { name = "tf-test-pubsub-subscription-%{random_suffix}" topic = google_pubsub_topic.foo.name + labels = { + my-label = "my-label-value" + } } data "google_pubsub_subscription" "foo" { diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go index 9e0fbb909b11..a813bc152dca 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic.go @@ -28,5 +28,17 @@ func dataSourceGooglePubsubTopicRead(d *schema.ResourceData, meta interface{}) e return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourcePubsubTopicRead(d, meta) + err = resourcePubsubTopicRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic_test.go b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic_test.go index b5f6efa8504c..e3b4614d1ca6 100644 --- a/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic_test.go +++ b/mmv1/third_party/terraform/services/pubsub/data_source_pubsub_topic_test.go @@ -55,6 +55,9 @@ func testAccDataSourceGooglePubsubTopic_basic(context map[string]interface{}) st return acctest.Nprintf(` resource "google_pubsub_topic" "foo" { name = "tf-test-pubsub-%{random_suffix}" + labels = { + my-label = "my-label-value" + } } data "google_pubsub_topic" "foo" { 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 5ac29b2b44b3..19f15a66fd45 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 @@ -51,10 +51,11 @@ func TestAccPubsubSubscription_basic(t *testing.T) { Config: testAccPubsubSubscription_basic(topic, subscription, "bar", 20, false), }, { - ResourceName: "google_pubsub_subscription.foo", - ImportStateId: subscription, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscription, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -75,19 +76,21 @@ func TestAccPubsubSubscription_update(t *testing.T) { Config: testAccPubsubSubscription_basic(topic, subscriptionShort, "bar", 20, false), }, { - ResourceName: "google_pubsub_subscription.foo", - ImportStateId: subscriptionShort, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscriptionShort, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccPubsubSubscription_basic(topic, subscriptionShort, "baz", 30, true), }, { - ResourceName: "google_pubsub_subscription.foo", - ImportStateId: subscriptionShort, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscriptionShort, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go index 059eee101f5f..41d8e7a58182 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go @@ -22,19 +22,21 @@ func TestAccPubsubTopic_update(t *testing.T) { Config: testAccPubsubTopic_update(topic, "foo", "bar"), }, { - ResourceName: "google_pubsub_topic.foo", - ImportStateId: topic, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccPubsubTopic_updateWithRegion(topic, "wibble", "wobble", "us-central1"), }, { - ResourceName: "google_pubsub_topic.foo", - ImportStateId: topic, - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go b/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go index b3da20ecba44..1d16a177a860 100644 --- a/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go +++ b/mmv1/third_party/terraform/services/redis/data_source_redis_instance.go @@ -1,6 +1,8 @@ package redis 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" @@ -29,5 +31,17 @@ func dataSourceGoogleRedisInstanceRead(d *schema.ResourceData, meta interface{}) } d.SetId(id) - return resourceRedisInstanceRead(d, meta) + err = resourceRedisInstanceRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/redis/data_source_redis_instance_test.go b/mmv1/third_party/terraform/services/redis/data_source_redis_instance_test.go index 0c03762b0021..35942e513aec 100644 --- a/mmv1/third_party/terraform/services/redis/data_source_redis_instance_test.go +++ b/mmv1/third_party/terraform/services/redis/data_source_redis_instance_test.go @@ -30,6 +30,10 @@ func testAccRedisInstanceDatasourceConfig(suffix string) string { resource "google_redis_instance" "redis" { name = "redis-test-%s" memory_size_gb = 1 + + labels = { + my-label = "my-label-value" + } } data "google_redis_instance" "redis" { diff --git a/mmv1/third_party/terraform/services/redis/resource_redis_instance_test.go b/mmv1/third_party/terraform/services/redis/resource_redis_instance_test.go index f5f4e9fe8821..dd5579c54cf2 100644 --- a/mmv1/third_party/terraform/services/redis/resource_redis_instance_test.go +++ b/mmv1/third_party/terraform/services/redis/resource_redis_instance_test.go @@ -23,17 +23,19 @@ func TestAccRedisInstance_update(t *testing.T) { Config: testAccRedisInstance_update(name, true), }, { - ResourceName: "google_redis_instance.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_instance.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccRedisInstance_update2(name, true), }, { - ResourceName: "google_redis_instance.test", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_redis_instance.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccRedisInstance_update2(name, false), diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder.go index fa3099bb8bd5..fb95137a83cc 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder.go @@ -61,13 +61,14 @@ func dataSourceFolderRead(d *schema.ResourceData, meta interface{}) error { return err } - d.SetId(canonicalFolderName(d.Get("folder").(string))) + id := canonicalFolderName(d.Get("folder").(string)) + d.SetId(id) if err := resourceGoogleFolderRead(d, meta); err != nil { return err } // If resource doesn't exist, read will not set ID and we should return error. if d.Id() == "" { - return nil + return fmt.Errorf("%s not found", id) } if v, ok := d.GetOk("lookup_organization"); ok && v.(bool) { diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder_organization_policy.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder_organization_policy.go index a0bbf3fbd779..aa7249c8e99b 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder_organization_policy.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_folder_organization_policy.go @@ -22,7 +22,16 @@ func DataSourceGoogleFolderOrganizationPolicy() *schema.Resource { func datasourceGoogleFolderOrganizationPolicyRead(d *schema.ResourceData, meta interface{}) error { - d.SetId(fmt.Sprintf("%s/%s", d.Get("folder"), d.Get("constraint"))) + id := fmt.Sprintf("%s/%s", d.Get("folder"), d.Get("constraint")) + d.SetId(id) - return resourceGoogleFolderOrganizationPolicyRead(d, meta) + err := resourceGoogleFolderOrganizationPolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_iam_role.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_iam_role.go index 83639d864e95..aad1818e1624 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_iam_role.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_iam_role.go @@ -43,7 +43,7 @@ func dataSourceGoogleIamRoleRead(d *schema.ResourceData, meta interface{}) error roleName := d.Get("name").(string) role, err := config.NewIamClient(userAgent).Roles.Get(roleName).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Error reading IAM Role %s: %s", roleName, err)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Error reading IAM Role %s: %s", roleName, err), roleName) } d.SetId(role.Name) diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_organization.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_organization.go index d600eebddaa9..294a1b652aef 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_organization.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_organization.go @@ -103,7 +103,7 @@ func dataSourceOrganizationRead(d *schema.ResourceData, meta interface{}) error Timeout: d.Timeout(schema.TimeoutRead), }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Organization Not Found : %s", v)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Organization Not Found : %s", v), canonicalOrganizationName(v.(string))) } organization = resp diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project.go index 03584ed4b02a..d5cd9c738087 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project.go @@ -42,6 +42,10 @@ func datasourceGoogleProjectRead(d *schema.ResourceData, meta interface{}) error return err } + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + if d.Id() == "" { return fmt.Errorf("%s not found or not in ACTIVE state", id) } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_organization_policy.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_organization_policy.go index 597b51beb943..6aaa7d54dcfc 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_organization_policy.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_organization_policy.go @@ -22,7 +22,16 @@ func DataSourceGoogleProjectOrganizationPolicy() *schema.Resource { func datasourceGoogleProjectOrganizationPolicyRead(d *schema.ResourceData, meta interface{}) error { - d.SetId(fmt.Sprintf("%s:%s", d.Get("project"), d.Get("constraint"))) + id := fmt.Sprintf("%s:%s", d.Get("project"), d.Get("constraint")) + d.SetId(id) - return resourceGoogleProjectOrganizationPolicyRead(d, meta) + err := resourceGoogleProjectOrganizationPolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_service.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_service.go index d056b6489828..7bcaa985ca2d 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_service.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_service.go @@ -28,5 +28,13 @@ func dataSourceGoogleProjectServiceRead(d *schema.ResourceData, meta interface{} return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceGoogleProjectServiceRead(d, meta) + err = resourceGoogleProjectServiceRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_test.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_test.go index 033ce759d4fb..513be054caaa 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_test.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_project_test.go @@ -41,6 +41,9 @@ resource "google_project" "project" { project_id = "%s" name = "%s" org_id = "%s" + labels = { + my-label = "my-label-value" + } } data "google_project" "project" { diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account.go index c917c396dfbc..15b075a1e763 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account.go @@ -59,7 +59,7 @@ func dataSourceGoogleServiceAccountRead(d *schema.ResourceData, meta interface{} sa, err := config.NewIamClient(userAgent).Projects.ServiceAccounts.Get(serviceAccountName).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Service Account %q", serviceAccountName), serviceAccountName) } d.SetId(sa.Name) diff --git a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account_key.go b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account_key.go index d3ab027a8cf0..95b47a88cc79 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account_key.go +++ b/mmv1/third_party/terraform/services/resourcemanager/data_source_google_service_account_key.go @@ -66,7 +66,7 @@ func dataSourceGoogleServiceAccountKeyRead(d *schema.ResourceData, meta interfac // Confirm the service account key exists sak, err := config.NewIamClient(userAgent).Projects.ServiceAccounts.Keys.Get(keyName).PublicKeyType(publicKeyType).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Service Account Key %q", keyName)) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Service Account Key %q", keyName), keyName) } d.SetId(sak.Name) 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 cb88fc4c14f8..acf1db96fa56 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go @@ -11,6 +11,7 @@ import ( "time" "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" tpgcompute "github.com/hashicorp/terraform-provider-google/google/services/compute" @@ -40,6 +41,10 @@ func ResourceGoogleProject() *schema.Resource { Update: resourceGoogleProjectUpdate, Delete: resourceGoogleProjectDelete, + CustomizeDiff: customdiff.All( + tpgresource.SetLabelsDiff, + ), + Importer: &schema.ResourceImporter{ State: resourceProjectImportState, }, @@ -103,10 +108,27 @@ func ResourceGoogleProject() *schema.Resource { Description: `The alphanumeric ID of the billing account this project belongs to. The user or service account performing this operation with Terraform must have Billing Account Administrator privileges (roles/billing.admin) in the organization. See Google Cloud Billing API Access Control for more details.`, }, "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.`, + }, + + "terraform_labels": { Type: schema.TypeMap, - Optional: true, + 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}, + }, + + "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}, - Description: `A set of key/value label pairs to assign to the project.`, }, }, UseJSONNumber: true, @@ -137,8 +159,8 @@ func resourceGoogleProjectCreate(d *schema.ResourceData, meta interface{}) error return err } - if _, ok := d.GetOk("labels"); ok { - project.Labels = tpgresource.ExpandLabels(d) + if _, ok := d.GetOk("effective_labels"); ok { + project.Labels = tpgresource.ExpandEffectiveLabels(d) } var op *cloudresourcemanager.Operation @@ -286,9 +308,15 @@ func resourceGoogleProjectRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("name", p.Name); err != nil { return fmt.Errorf("Error setting name: %s", err) } - if err := d.Set("labels", p.Labels); err != nil { + if err := tpgresource.SetLabels(p.Labels, d, "labels"); err != nil { return fmt.Errorf("Error setting labels: %s", err) } + if err := tpgresource.SetLabels(p.Labels, d, "terraform_labels"); err != nil { + return fmt.Errorf("Error setting terraform_labels: %s", err) + } + if err := d.Set("effective_labels", p.Labels); err != nil { + return fmt.Errorf("Error setting effective_labels: %s", err) + } if p.Parent != nil { switch p.Parent.Type { @@ -431,8 +459,8 @@ func resourceGoogleProjectUpdate(d *schema.ResourceData, meta interface{}) error } // Project Labels have changed - if ok := d.HasChange("labels"); ok { - p.Labels = tpgresource.ExpandLabels(d) + if ok := d.HasChange("effective_labels"); ok { + p.Labels = tpgresource.ExpandEffectiveLabels(d) // Do Update on project if p, err = updateProject(config, d, project_name, userAgent, p); err != nil { diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_iam_custom_role.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_iam_custom_role.go index 121919258376..ef27f2aacb9a 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_iam_custom_role.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_iam_custom_role.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "github.com/hashicorp/terraform-provider-google/google/tpgresource" @@ -23,6 +24,10 @@ func ResourceGoogleProjectIamCustomRole() *schema.Resource { State: resourceGoogleProjectIamCustomRoleImport, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "role_id": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_service.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_service.go index a24765e16f6d..94d5d4873e18 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_service.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_service.go @@ -6,6 +6,7 @@ import ( "strings" "time" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" tpgserviceusage "github.com/hashicorp/terraform-provider-google/google/services/serviceusage" @@ -93,6 +94,10 @@ func ResourceGoogleProjectService() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "service": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_test.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_test.go index 5bb17b86c28e..12489e663f6e 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_test.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_test.go @@ -136,7 +136,7 @@ func TestAccProject_labels(t *testing.T) { ResourceName: "google_project.acceptance", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"skip_delete"}, + ImportStateVerifyIgnore: []string{"skip_delete", "labels", "terraform_labels"}, }, // update project with labels { diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_service_account.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_service_account.go index cb7113fea0aa..e2a9531732f3 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_service_account.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_service_account.go @@ -9,6 +9,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" "google.golang.org/api/iam/v1" @@ -26,6 +27,9 @@ func ResourceGoogleServiceAccount() *schema.Resource { Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(5 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), Schema: map[string]*schema.Schema{ "email": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_project_service_identity.go.erb b/mmv1/third_party/terraform/services/resourcemanager/resource_project_service_identity.go.erb index 9a22928cca5f..351fa637401c 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_project_service_identity.go.erb +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_project_service_identity.go.erb @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) @@ -26,6 +27,10 @@ func ResourceProjectServiceIdentity() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "service": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_config.go.erb b/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_config.go.erb index 1d2ae6c688e4..eca8279a8ae3 100644 --- a/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_config.go.erb +++ b/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_config.go.erb @@ -31,6 +31,14 @@ func dataSourceGoogleRuntimeconfigConfigRead(d *schema.ResourceData, meta interf return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceRuntimeconfigConfigRead(d, meta) + err = resourceRuntimeconfigConfigRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end %> diff --git a/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_variable.go.erb b/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_variable.go.erb index 3d3538dca306..9531af6cda41 100644 --- a/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_variable.go.erb +++ b/mmv1/third_party/terraform/services/runtimeconfig/data_source_runtimeconfig_variable.go.erb @@ -33,7 +33,15 @@ func dataSourceGoogleRuntimeconfigVariableRead(d *schema.ResourceData, meta inte return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceRuntimeconfigVariableRead(d, meta) + err = resourceRuntimeconfigVariableRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> diff --git a/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_config.go.erb b/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_config.go.erb index 273ec7dc010b..f0d1aa31a902 100644 --- a/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_config.go.erb +++ b/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_config.go.erb @@ -10,6 +10,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" runtimeconfig "google.golang.org/api/runtimeconfig/v1beta1" ) @@ -27,6 +28,10 @@ func ResourceRuntimeconfigConfig() *schema.Resource { State: resourceRuntimeconfigConfigImport, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_variable.go.erb b/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_variable.go.erb index fbabc5d7ee00..01c98fc45724 100644 --- a/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_variable.go.erb +++ b/mmv1/third_party/terraform/services/runtimeconfig/resource_runtimeconfig_variable.go.erb @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" runtimeconfig "google.golang.org/api/runtimeconfig/v1beta1" ) @@ -24,6 +25,10 @@ func ResourceRuntimeconfigVariable() *schema.Resource { State: resourceRuntimeconfigVariableImport, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go index 6f424b7cd691..007bd1e2a8f1 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret.go @@ -26,5 +26,21 @@ func dataSourceSecretManagerSecretRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceSecretManagerSecretRead(d, meta) + 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 + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go index 413f69d98c7e..d175df4012a8 100644 --- a/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go +++ b/mmv1/third_party/terraform/services/secretmanager/data_source_secret_manager_secret_test.go @@ -22,7 +22,11 @@ func TestAccDataSourceSecretManagerSecret_basic(t *testing.T) { { Config: testAccDataSourceSecretManagerSecret_basic(context), Check: resource.ComposeTestCheckFunc( - acctest.CheckDataSourceStateMatchesResourceState("data.google_secret_manager_secret.foo", "google_secret_manager_secret.bar"), + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores( + "data.google_secret_manager_secret.foo", + "google_secret_manager_secret.bar", + map[string]struct{}{"zone": {}}, + ), ), }, }, @@ -38,6 +42,10 @@ resource "google_secret_manager_secret" "bar" { label = "my-label" } + annotations = { + annotation = "my-annotation" + } + replication { user_managed { replicas { diff --git a/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb b/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb index b672a3d607cc..63581e85487b 100644 --- a/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb +++ b/mmv1/third_party/terraform/services/secretmanager/resource_secret_manager_secret_test.go.erb @@ -29,7 +29,7 @@ func TestAccSecretManagerSecret_import(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -58,7 +58,7 @@ func TestAccSecretManagerSecret_cmek(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -83,7 +83,7 @@ func TestAccSecretManagerSecret_annotationsUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-with-annotations", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels", "annotations"}, }, { Config: testAccSecretManagerSecret_annotationsUpdate(context), @@ -92,7 +92,7 @@ func TestAccSecretManagerSecret_annotationsUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-with-annotations", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels", "annotations"}, }, { Config: testAccSecretManagerSecret_annotationsBasic(context), @@ -101,7 +101,7 @@ func TestAccSecretManagerSecret_annotationsUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-with-annotations", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels", "annotations"}, }, }, }) @@ -126,7 +126,7 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretManagerSecret_versionAliasesBasic(context), @@ -135,7 +135,7 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretManagerSecret_versionAliasesUpdate(context), @@ -144,7 +144,7 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretManagerSecret_basicWithSecretVersions(context), @@ -153,7 +153,7 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -184,7 +184,7 @@ func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_userManagedCmekUpdate(context), @@ -193,7 +193,7 @@ func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_userManagedCmekUpdate2(context), @@ -202,7 +202,7 @@ func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_userManagedCmekBasic(context), @@ -211,7 +211,7 @@ func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -234,15 +234,6 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckSecretManagerSecretDestroyProducer(t), Steps: []resource.TestStep{ - { - Config: testAccSecretMangerSecret_automaticBasic(context), - }, - { - ResourceName: "google_secret_manager_secret.secret-basic", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl", "replication.0.automatic", "replication.0.auto"}, - }, { Config: testAccSecretMangerSecret_automaticCmekBasic(context), }, @@ -250,7 +241,7 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_automaticCmekUpdate(context), @@ -259,7 +250,7 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_automaticCmekUpdate2(context), @@ -268,7 +259,7 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, { Config: testAccSecretMangerSecret_automaticCmekBasic(context), @@ -277,7 +268,7 @@ func TestAccSecretManagerSecret_automaticCmekUpdate(t *testing.T) { ResourceName: "google_secret_manager_secret.secret-basic", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"ttl"}, + ImportStateVerifyIgnore: []string{"ttl", "labels", "terraform_labels"}, }, }, }) @@ -751,38 +742,6 @@ resource "google_secret_manager_secret" "secret-basic" { `, context) } -func testAccSecretMangerSecret_automaticBasic(context map[string]interface{}) string { - return acctest.Nprintf(` -data "google_project" "project" { - project_id = "%{pid}" -} -resource "google_kms_crypto_key_iam_member" "kms-secret-binding-1" { - crypto_key_id = "%{kms_key_name_1}" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com" -} -resource "google_kms_crypto_key_iam_member" "kms-secret-binding-2" { - crypto_key_id = "%{kms_key_name_2}" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com" -} -resource "google_secret_manager_secret" "secret-basic" { - secret_id = "tf-test-secret-%{random_suffix}" - - labels = { - label = "my-label" - } - replication { - automatic = true - } - depends_on = [ - google_kms_crypto_key_iam_member.kms-secret-binding-1, - google_kms_crypto_key_iam_member.kms-secret-binding-2, - ] -} -`, context) -} - func testAccSecretMangerSecret_automaticCmekBasic(context map[string]interface{}) string { return acctest.Nprintf(` data "google_project" "project" { diff --git a/mmv1/third_party/terraform/services/servicedirectory/resource_service_directory_namespace_test.go.erb b/mmv1/third_party/terraform/services/servicedirectory/resource_service_directory_namespace_test.go.erb index d056b18d33e7..5bf8e8868df9 100644 --- a/mmv1/third_party/terraform/services/servicedirectory/resource_service_directory_namespace_test.go.erb +++ b/mmv1/third_party/terraform/services/servicedirectory/resource_service_directory_namespace_test.go.erb @@ -53,6 +53,7 @@ func TestAccServiceDirectoryNamespace_serviceDirectoryNamespaceUpdateExample(t * ResourceName: "google_service_directory_namespace.example", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/servicenetworking/resource_google_service_networking_peered_dns_domain.go b/mmv1/third_party/terraform/services/servicenetworking/resource_google_service_networking_peered_dns_domain.go index 108d5d343588..bb9aba314e34 100644 --- a/mmv1/third_party/terraform/services/servicenetworking/resource_google_service_networking_peered_dns_domain.go +++ b/mmv1/third_party/terraform/services/servicenetworking/resource_google_service_networking_peered_dns_domain.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "google.golang.org/api/servicenetworking/v1" ) @@ -30,6 +31,10 @@ func ResourceGoogleServiceNetworkingPeeredDNSDomain() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "project": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go index ac1ff4a07912..8482083fbdd7 100644 --- a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go +++ b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection.go @@ -8,13 +8,11 @@ import ( "strings" "time" - tpgcompute "github.com/hashicorp/terraform-provider-google/google/services/compute" "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "google.golang.org/api/compute/v1" "google.golang.org/api/servicenetworking/v1" ) @@ -94,27 +92,16 @@ func resourceServiceNetworkingConnectionCreate(d *schema.ResourceData, meta inte project := networkFieldValue.Project parentService := formatParentService(d.Get("service").(string)) - // We use Patch instead of Create, because we're getting - // "Error waiting for Create Service Networking Connection: - // Error code 9, message: Cannot modify allocated ranges in - // CreateConnection. Please use UpdateConnection." - // if we're creating peerings to more than one VPC (like two - // CloudSQL instances within one project, peered with two - // clusters.) - // - // This is a workaround for: - // https://issuetracker.google.com/issues/131908322 - // - // The API docs don't specify that you can do connections/-, - // but that's what gcloud does, and it's easier than grabbing - // the connection name. + + // There is no blocker to use Create method, as the bug in CloudSQL has been fixed (https://b.corp.google.com/issues/123276199). + // Read more in https://stackoverflow.com/questions/55135559/unable-to-recreate-private-service-access-on-gcp // err == nil indicates that the billing_project value was found if bp, err := tpgresource.GetBillingProject(d, config); err == nil { project = bp } - createCall := config.NewServiceNetworkingClient(userAgent).Services.Connections.Patch(parentService+"/connections/-", connection).UpdateMask("reservedPeeringRanges").Force(true) + createCall := config.NewServiceNetworkingClient(userAgent).Services.Connections.Create(parentService, connection) if config.UserProjectOverride { createCall.Header().Add("X-Goog-User-Project", project) } @@ -272,42 +259,35 @@ func resourceServiceNetworkingConnectionDelete(d *schema.ResourceData, meta inte return err } - obj := make(map[string]interface{}) - peering := d.Get("peering").(string) - obj["name"] = peering - url := fmt.Sprintf("%s%s/removePeering", config.ComputeBasePath, serviceNetworkingNetworkName) - networkFieldValue, err := tpgresource.ParseNetworkFieldValue(network, d, config) if err != nil { return errwrap.Wrapf("Failed to retrieve network field value, err: {{err}}", err) } project := networkFieldValue.Project - res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ - Config: config, - Method: "POST", - Project: project, - RawURL: url, - UserAgent: userAgent, - Body: obj, - Timeout: d.Timeout(schema.TimeoutDelete), - }) + connectionId, err := parseConnectionId(d.Id()) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ServiceNetworkingConnection %q", d.Id())) + return errwrap.Wrapf("Unable to parse Service Networking Connection id, err: {{err}}", err) } + parentService := formatParentService(connectionId.Service) - op := &compute.Operation{} - err = tpgresource.Convert(res, op) - if err != nil { - return err + deleteConnectionRequest := &servicenetworking.DeleteConnectionRequest{ + ConsumerNetwork: serviceNetworkingNetworkName, } - err = tpgcompute.ComputeOperationWaitTime( - config, op, project, "Updating Network", userAgent, d.Timeout(schema.TimeoutDelete)) + deleteCall := config.NewServiceNetworkingClient(userAgent).Services.Connections.DeleteConnection(parentService+"/connections/servicenetworking-googleapis-com", deleteConnectionRequest) + if config.UserProjectOverride { + deleteCall.Header().Add("X-Goog-User-Project", project) + } + op, err := deleteCall.Do() if err != nil { return err } + if err := ServiceNetworkingOperationWaitTime(config, op, "Delete Service Networking Connection", userAgent, project, d.Timeout(schema.TimeoutCreate)); err != nil { + return errwrap.Wrapf("Unable to remove Service Networking Connection, err: {{err}}", err) + } + d.SetId("") log.Printf("[INFO] Service network connection removed.") diff --git a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection_test.go b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection_test.go index 374a8be52ac5..e5ee28383379 100644 --- a/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection_test.go +++ b/mmv1/third_party/terraform/services/servicenetworking/resource_service_networking_connection_test.go @@ -13,7 +13,7 @@ import ( func TestAccServiceNetworkingConnection_create(t *testing.T) { t.Parallel() - network := acctest.BootstrapSharedTestNetwork(t, "service-networking-connection-create") + network := fmt.Sprintf("tf-test-service-networking-connection-create-%s", acctest.RandString(t, 10)) addr := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) service := "servicenetworking.googleapis.com" @@ -37,7 +37,7 @@ func TestAccServiceNetworkingConnection_create(t *testing.T) { func TestAccServiceNetworkingConnection_update(t *testing.T) { t.Parallel() - network := acctest.BootstrapSharedTestNetwork(t, "service-networking-connection-update") + network := fmt.Sprintf("tf-test-service-networking-connection-update-%s", acctest.RandString(t, 10)) addr1 := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) addr2 := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) service := "servicenetworking.googleapis.com" @@ -94,7 +94,7 @@ func testServiceNetworkingConnectionDestroy(t *testing.T, parent, network string func testAccServiceNetworkingConnection(networkName, addressRangeName, serviceName string) string { return fmt.Sprintf(` -data "google_compute_network" "servicenet" { +resource "google_compute_network" "servicenet" { name = "%s" } @@ -103,11 +103,11 @@ resource "google_compute_global_address" "foobar" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link } resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link + network = google_compute_network.servicenet.self_link service = "%s" reserved_peering_ranges = [google_compute_global_address.foobar.name] } diff --git a/mmv1/third_party/terraform/services/sourcerepo/data_source_sourcerepo_repository.go b/mmv1/third_party/terraform/services/sourcerepo/data_source_sourcerepo_repository.go index 5fa2a433c7bf..03dd46452142 100644 --- a/mmv1/third_party/terraform/services/sourcerepo/data_source_sourcerepo_repository.go +++ b/mmv1/third_party/terraform/services/sourcerepo/data_source_sourcerepo_repository.go @@ -31,5 +31,13 @@ func dataSourceGoogleSourceRepoRepositoryRead(d *schema.ResourceData, meta inter } d.SetId(id) - return resourceSourceRepoRepositoryRead(d, meta) + err = resourceSourceRepoRepositoryRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go b/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go index 26dff8a17c7d..afdbce7f040d 100644 --- a/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go +++ b/mmv1/third_party/terraform/services/spanner/data_source_spanner_instance.go @@ -32,5 +32,17 @@ func dataSourceSpannerInstanceRead(d *schema.ResourceData, meta interface{}) err } d.SetId(id) - return resourceSpannerInstanceRead(d, meta) + err = resourceSpannerInstanceRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } 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 53a531ed99e4..9d753eaf7e79 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 @@ -95,17 +95,19 @@ func TestAccSpannerInstance_update(t *testing.T) { Config: testAccSpannerInstance_update(dName1, 1, false), }, { - ResourceName: "google_spanner_instance.updater", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_spanner_instance.updater", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccSpannerInstance_update(dName2, 2, true), }, { - ResourceName: "google_spanner_instance.updater", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_spanner_instance.updater", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/sql/data_source_sql_database.go b/mmv1/third_party/terraform/services/sql/data_source_sql_database.go index 264cde5a1f4f..5c4696314c59 100644 --- a/mmv1/third_party/terraform/services/sql/data_source_sql_database.go +++ b/mmv1/third_party/terraform/services/sql/data_source_sql_database.go @@ -27,11 +27,15 @@ func dataSourceSqlDatabaseRead(d *schema.ResourceData, meta interface{}) error { if err != nil { return fmt.Errorf("Error fetching project for Database: %s", err) } - d.SetId(fmt.Sprintf("projects/%s/instances/%s/databases/%s", project, d.Get("instance").(string), d.Get("name").(string))) + id := fmt.Sprintf("projects/%s/instances/%s/databases/%s", project, d.Get("instance").(string), d.Get("name").(string)) + d.SetId(id) err = resourceSQLDatabaseRead(d, meta) if err != nil { return err } + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } if err := d.Set("deletion_policy", nil); err != nil { return fmt.Errorf("Error setting deletion_policy: %s", err) } diff --git a/mmv1/third_party/terraform/services/sql/data_source_sql_database_instance.go b/mmv1/third_party/terraform/services/sql/data_source_sql_database_instance.go index 9aac126ad1e9..e9135ba07723 100644 --- a/mmv1/third_party/terraform/services/sql/data_source_sql_database_instance.go +++ b/mmv1/third_party/terraform/services/sql/data_source_sql_database_instance.go @@ -1,6 +1,8 @@ package sql import ( + "fmt" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google/google/tpgresource" ) @@ -18,7 +20,15 @@ func DataSourceSqlDatabaseInstance() *schema.Resource { } func dataSourceSqlDatabaseInstanceRead(d *schema.ResourceData, meta interface{}) error { + id := d.Get("name").(string) + err := resourceSqlDatabaseInstanceRead(d, meta) + if err != nil { + return err + } - return resourceSqlDatabaseInstanceRead(d, meta) + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/sql/data_source_sql_databases.go b/mmv1/third_party/terraform/services/sql/data_source_sql_databases.go index ed4ecc4f4f9d..1662765ab489 100644 --- a/mmv1/third_party/terraform/services/sql/data_source_sql_databases.go +++ b/mmv1/third_party/terraform/services/sql/data_source_sql_databases.go @@ -60,7 +60,7 @@ func dataSourceSqlDatabasesRead(d *schema.ResourceData, meta interface{}) error }) if err != nil { - return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Databases in %q instance", d.Get("instance").(string))) + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("Databases in %q instance", d.Get("instance").(string)), fmt.Sprintf("Databases in %q instance", d.Get("instance").(string))) } flattenedDatabases := flattenDatabases(databases.Items) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb index 254161f9e9ee..511c62aacd09 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb @@ -46,6 +46,21 @@ var sqlDatabaseAuthorizedNetWorkSchemaElem *schema.Resource = &schema.Resource{ }, } +var sqlDatabaseFlagSchemaElem *schema.Resource = &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Required: true, + Description: `Value of the flag.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + Description: `Name of the flag.`, + }, + }, +} + var ( backupConfigurationKeys = []string{ "settings.0.backup_configuration.0.binary_log_enabled", @@ -119,6 +134,7 @@ func ResourceSqlDatabaseInstance() *schema.Resource { }, CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, customdiff.ForceNewIfChange("settings.0.disk_size", compute.IsDiskShrinkage), customdiff.ForceNewIfChange("master_instance_name", isMasterInstanceNameSet), customdiff.IfValueChange("instance_type", isReplicaPromoteRequested, checkPromoteConfigurationsAndUpdateDiff), @@ -362,22 +378,10 @@ is set to true. Defaults to ZONAL.`, Description: `The name of server instance collation.`, }, "database_flags": { - Type: schema.TypeList, + Type: schema.TypeSet, Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "value": { - Type: schema.TypeString, - Required: true, - Description: `Value of the flag.`, - }, - "name": { - Type: schema.TypeString, - Required: true, - Description: `Name of the flag.`, - }, - }, - }, + Set: schema.HashResource(sqlDatabaseFlagSchemaElem), + Elem: sqlDatabaseFlagSchemaElem, }, "disk_autoresize": { Type: schema.TypeBool, @@ -1266,7 +1270,7 @@ func expandSqlDatabaseInstanceSettings(configured []interface{}, databaseVersion DeletionProtectionEnabled: _settings["deletion_protection_enabled"].(bool), UserLabels: tpgresource.ConvertStringMap(_settings["user_labels"].(map[string]interface{})), BackupConfiguration: expandBackupConfiguration(_settings["backup_configuration"].([]interface{})), - DatabaseFlags: expandDatabaseFlags(_settings["database_flags"].([]interface{})), + DatabaseFlags: expandDatabaseFlags(_settings["database_flags"].(*schema.Set).List()), IpConfiguration: expandIpConfiguration(_settings["ip_configuration"].([]interface{}), databaseVersion), LocationPreference: expandLocationPreference(_settings["location_preference"].([]interface{})), MaintenanceWindow: expandMaintenanceWindow(_settings["maintenance_window"].([]interface{})), 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 f20ece069f2f..4c3bcb7e0ac8 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 @@ -178,8 +178,12 @@ func TestAccSqlDatabaseInstance_deleteDefaultUserBeforeSubsequentApiCalls(t *tes t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-clone-2") + testId := "sql-instance-clone-2" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + projectNumber := envvar.GetTestProjectNumberFromEnv() + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) // 1. Create an instance. // 2. Add a root@'%' user. @@ -191,7 +195,7 @@ func TestAccSqlDatabaseInstance_deleteDefaultUserBeforeSubsequentApiCalls(t *tes CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, false, false), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, false, false), }, { PreConfig: func() { @@ -736,8 +740,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network") + networkName := acctest.BootstrapSharedServiceNetworkingConnection(t, "sql-instance-1") acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -745,7 +748,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, false, false), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, false, false), }, { ResourceName: "google_sql_database_instance.instance", @@ -754,7 +757,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, true, false), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, true, false), }, { ResourceName: "google_sql_database_instance.instance", @@ -763,7 +766,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, true, true), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, true, true), }, { ResourceName: "google_sql_database_instance.instance", @@ -772,7 +775,7 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(t *te ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { - Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressName, true, false), + Config: testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, true, false), }, { ResourceName: "google_sql_database_instance.instance", @@ -975,10 +978,19 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(t *testi t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-allocated") - addressName_update := "tf-test-" + acctest.RandString(t, 10) + "update" - networkName_update := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-allocated-update") + + projectNumber := envvar.GetTestProjectNumberFromEnv() + testId := "sql-instance-allocated-1" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) + + updateTestId := "sql-instance-allocated-update-1" + networkName_update := acctest.BootstrapSharedTestNetwork(t, updateTestId) + networkId_update := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName_update) + addressName_update := acctest.BootstrapSharedTestGlobalAddress(t, updateTestId, networkId_update) + acctest.BootstrapSharedServiceNetworkingConnection(t, updateTestId) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1012,8 +1024,13 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(t t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-replica") + + projectNumber := envvar.GetTestProjectNumberFromEnv() + testId := "sql-instance-replica-1" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1044,8 +1061,12 @@ func TestAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(t * t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - addressName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-network-clone") + projectNumber := envvar.GetTestProjectNumberFromEnv() + testId := "sql-instance-clone-1" + networkName := acctest.BootstrapSharedTestNetwork(t, testId) + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectNumber, networkName) + addressName := acctest.BootstrapSharedTestGlobalAddress(t, testId, networkId) + acctest.BootstrapSharedServiceNetworkingConnection(t, testId) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1445,8 +1466,7 @@ func TestAccSqlDatabaseInstance_ActiveDirectory(t *testing.T) { t.Parallel() databaseName := "tf-test-" + acctest.RandString(t, 10) - networkName := acctest.BootstrapSharedTestNetwork(t, "sql-instance-private-test-ad") - addressName := "tf-test-" + acctest.RandString(t, 10) + networkName := acctest.BootstrapSharedServiceNetworkingConnection(t, "sql-instance-ad-1") rootPassword := acctest.RandString(t, 15) adDomainName := acctest.BootstrapSharedTestADDomain(t, "test-domain", networkName) @@ -1456,7 +1476,7 @@ func TestAccSqlDatabaseInstance_ActiveDirectory(t *testing.T) { CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testGoogleSqlDatabaseInstance_ActiveDirectoryConfig(databaseName, networkName, addressName, rootPassword, adDomainName), + Config: testGoogleSqlDatabaseInstance_ActiveDirectoryConfig(databaseName, networkName, rootPassword, adDomainName), }, { ResourceName: "google_sql_database_instance.instance-with-ad", @@ -1677,6 +1697,34 @@ func TestAccSqlDatabaseInstance_Timezone(t *testing.T) { }) } +func TestAccSqlDatabaseInstance_updateDifferentFlagOrder(t *testing.T) { + t.Parallel() + + instance := "tf-test-" + acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testGoogleSqlDatabaseInstance_flags(instance), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testGoogleSqlDatabaseInstance_flags_update(instance), + PlanOnly: true, + ExpectNonEmptyPlan: false, + }, + }, + }) +} + func TestAccSqlDatabaseInstance_sqlMysqlInstancePvpExample(t *testing.T) { t.Parallel() @@ -2146,28 +2194,13 @@ resource "google_sql_database_instance" "instance" { } ` -func testGoogleSqlDatabaseInstance_ActiveDirectoryConfig(databaseName, networkName, addressRangeName, rootPassword, adDomainName string) string { +func testGoogleSqlDatabaseInstance_ActiveDirectoryConfig(databaseName, networkName, rootPassword, adDomainName string) string { return fmt.Sprintf(` data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance-with-ad" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "SQLSERVER_2017_STANDARD" @@ -2184,7 +2217,7 @@ resource "google_sql_database_instance" "instance-with-ad" { domain = "%s" } } -}`, networkName, addressRangeName, databaseName, rootPassword, adDomainName) +}`, networkName, databaseName, rootPassword, adDomainName) } func testGoogleSqlDatabaseInstance_DenyMaintenancePeriodConfig(databaseName, endDate, startDate, time string) string { @@ -2775,7 +2808,7 @@ func verifyPscOperation(resourceName string, isPscConfigExpected bool, expectedP } } -func testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName, addressRangeName string, specifyPrivatePathOption bool, enablePrivatePath bool) string { +func testAccSqlDatabaseInstance_withPrivateNetwork_withoutAllocatedIpRange(databaseName, networkName string, specifyPrivatePathOption bool, enablePrivatePath bool) string { privatePathOption := "" if specifyPrivatePathOption { privatePathOption = fmt.Sprintf("enable_private_path_for_google_cloud_services = %t", enablePrivatePath) @@ -2786,22 +2819,7 @@ data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -2815,7 +2833,7 @@ resource "google_sql_database_instance" "instance" { } } } -`, networkName, addressRangeName, databaseName, privatePathOption) +`, networkName, databaseName, privatePathOption) } func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRange(databaseName, networkName, addressRangeName string) string { @@ -2824,22 +2842,7 @@ data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -2849,11 +2852,11 @@ resource "google_sql_database_instance" "instance" { ip_configuration { ipv4_enabled = "false" private_network = data.google_compute_network.servicenet.self_link - allocated_ip_range = google_compute_global_address.foobar.name + allocated_ip_range = "%s" } } } -`, networkName, addressRangeName, databaseName) +`, networkName, databaseName, addressRangeName) } func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeReplica(databaseName, networkName, addressRangeName string) string { @@ -2862,22 +2865,7 @@ data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -2896,7 +2884,6 @@ resource "google_sql_database_instance" "instance" { } } resource "google_sql_database_instance" "replica1" { - depends_on = [google_service_networking_connection.foobar] name = "%s-replica1" region = "us-central1" database_version = "MYSQL_5_7" @@ -2906,7 +2893,7 @@ resource "google_sql_database_instance" "replica1" { ip_configuration { ipv4_enabled = "false" private_network = data.google_compute_network.servicenet.self_link - allocated_ip_range = google_compute_global_address.foobar.name + allocated_ip_range = "%s" } } @@ -2921,7 +2908,7 @@ resource "google_sql_database_instance" "replica1" { verify_server_certificate = false } } -`, networkName, addressRangeName, databaseName, databaseName) +`, networkName, databaseName, databaseName, addressRangeName) } func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone(databaseName, networkName, addressRangeName string) string { @@ -2930,22 +2917,7 @@ data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -2972,11 +2944,11 @@ resource "google_sql_database_instance" "clone1" { clone { source_instance_name = google_sql_database_instance.instance.name - allocated_ip_range = google_compute_global_address.foobar.name + allocated_ip_range = "%s" } } -`, networkName, addressRangeName, databaseName, databaseName) +`, networkName, databaseName, databaseName, addressRangeName) } func testAccSqlDatabaseInstance_withPrivateNetwork_withAllocatedIpRangeClone_withSettings(databaseName, networkName, addressRangeName string) string { @@ -2985,22 +2957,7 @@ data "google_compute_network" "servicenet" { name = "%s" } -resource "google_compute_global_address" "foobar" { - name = "%s" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = data.google_compute_network.servicenet.self_link -} - -resource "google_service_networking_connection" "foobar" { - network = data.google_compute_network.servicenet.self_link - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.foobar.name] -} - resource "google_sql_database_instance" "instance" { - depends_on = [google_service_networking_connection.foobar] name = "%s" region = "us-central1" database_version = "MYSQL_5_7" @@ -3027,7 +2984,7 @@ resource "google_sql_database_instance" "clone1" { clone { source_instance_name = google_sql_database_instance.instance.name - allocated_ip_range = google_compute_global_address.foobar.name + allocated_ip_range = "%s" } settings { @@ -3037,7 +2994,7 @@ resource "google_sql_database_instance" "clone1" { } } } -`, networkName, addressRangeName, databaseName, databaseName) +`, networkName, databaseName, databaseName, addressRangeName) } var testGoogleSqlDatabaseInstance_settings = ` @@ -3843,6 +3800,50 @@ func checkInstanceTypeIsPresent(resourceName string) func(*terraform.State) erro } } +func testGoogleSqlDatabaseInstance_flags(instance string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "instance" { + name = "%s" + region = "us-central1" + database_version = "MYSQL_5_7" + deletion_protection = false + settings { + tier = "db-f1-micro" + + database_flags { + name = "character_set_server" + value = "utf8mb4" + } + database_flags { + name = "auto_increment_increment" + value = "2" + } + } +}`, instance) +} + +func testGoogleSqlDatabaseInstance_flags_update(instance string) string { + return fmt.Sprintf(` +resource "google_sql_database_instance" "instance" { + name = "%s" + region = "us-central1" + database_version = "MYSQL_5_7" + deletion_protection = false + settings { + tier = "db-f1-micro" + + database_flags { + name = "auto_increment_increment" + value = "2" + } + database_flags { + name = "character_set_server" + value = "utf8mb4" + } + } +}`, instance) +} + func testGoogleSqlDatabaseInstance_readReplica(instance string) string { return fmt.Sprintf(` resource "google_sql_database_instance" "master" { diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_ssl_cert.go b/mmv1/third_party/terraform/services/sql/resource_sql_ssl_cert.go index 116a9b682f86..374230343810 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_ssl_cert.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_ssl_cert.go @@ -8,6 +8,7 @@ import ( "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" sqladmin "google.golang.org/api/sqladmin/v1beta4" ) @@ -25,6 +26,10 @@ func ResourceSqlSslCert() *schema.Resource { Delete: schema.DefaultTimeout(10 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "common_name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user.go b/mmv1/third_party/terraform/services/sql/resource_sql_user.go index d0ee4d85bc0b..599e55df39f7 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user.go @@ -10,6 +10,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" sqladmin "google.golang.org/api/sqladmin/v1beta4" @@ -56,6 +57,10 @@ func ResourceSqlUser() *schema.Resource { Delete: schema.DefaultTimeout(10 * time.Minute), }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + SchemaVersion: 1, MigrateState: resourceSqlUserMigrateState, diff --git a/mmv1/third_party/terraform/services/storage/data_source_google_storage_project_service_account.go b/mmv1/third_party/terraform/services/storage/data_source_google_storage_project_service_account.go index 0b248d5b53ca..188627eb2838 100644 --- a/mmv1/third_party/terraform/services/storage/data_source_google_storage_project_service_account.go +++ b/mmv1/third_party/terraform/services/storage/data_source_google_storage_project_service_account.go @@ -55,7 +55,7 @@ func dataSourceGoogleStorageProjectServiceAccountRead(d *schema.ResourceData, me serviceAccount, err := serviceAccountGetRequest.Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, "GCS service account not found") + return transport_tpg.HandleDataSourceNotFoundError(err, d, "GCS service account not found", fmt.Sprintf("Project %q GCS service account", project)) } if err := d.Set("project", project); err != nil { diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb index fcfc331523d7..b823ef308c30 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb @@ -37,6 +37,7 @@ func ResourceStorageBucket() *schema.Resource { }, CustomizeDiff: customdiff.All( customdiff.ForceNewIfChange("retention_policy.0.is_locked", isPolicyLocked), + tpgresource.SetLabelsDiff, ), Timeouts: &schema.ResourceTimeout{ @@ -45,6 +46,15 @@ func ResourceStorageBucket() *schema.Resource { Read: schema.DefaultTimeout(4 * time.Minute), }, + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceStorageBucketV0().CoreConfigSchema().ImpliedType(), + Upgrade: ResourceStorageBucketStateUpgradeV0, + Version: 0, + }, + }, + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -85,13 +95,24 @@ func ResourceStorageBucket() *schema.Resource { "labels": { Type: schema.TypeMap, Optional: true, - Computed: true, - // GCP (Dataplex) automatically adds labels - DiffSuppressFunc: resourceDataplexLabelDiffSuppress, Elem: &schema.Schema{Type: schema.TypeString}, Description: `A set of key/value label pairs to assign to the bucket.`, }, + "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}, + }, + + "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}, + }, + "location": { Type: schema.TypeString, Required: true, @@ -442,7 +463,8 @@ func ResourceStorageBucket() *schema.Resource { } } -const resourceDataplexGoogleProvidedLabelPrefix = "labels.goog-dataplex" +const resourceDataplexGoogleLabelPrefix = "goog-dataplex" +const resourceDataplexGoogleProvidedLabelPrefix = "labels." + resourceDataplexGoogleLabelPrefix func resourceDataplexLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { if strings.HasPrefix(k, resourceDataplexGoogleProvidedLabelPrefix) && new == "" { @@ -494,7 +516,7 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error // Create a bucket, setting the labels, location and name. sb := &storage.Bucket{ Name: bucket, - Labels: tpgresource.ExpandLabels(d), + Labels: tpgresource.ExpandEffectiveLabels(d), Location: location, IamConfiguration: expandIamConfiguration(d), } @@ -695,15 +717,15 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error } } - if d.HasChange("labels") { - sb.Labels = tpgresource.ExpandLabels(d) + if d.HasChange("effective_labels") { + sb.Labels = tpgresource.ExpandEffectiveLabels(d) if len(sb.Labels) == 0 { sb.NullFields = append(sb.NullFields, "Labels") } // To delete a label using PATCH, we have to explicitly set its value // to null. - old, _ := d.GetChange("labels") + old, _ := d.GetChange("effective_labels") for k := range old.(map[string]interface{}) { if _, ok := sb.Labels[k]; !ok { sb.NullFields = append(sb.NullFields, fmt.Sprintf("Labels.%s", k)) @@ -1597,7 +1619,13 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res if err := d.Set("lifecycle_rule", flattenBucketLifecycle(res.Lifecycle)); err != nil { return fmt.Errorf("Error setting lifecycle_rule: %s", err) } - if err := d.Set("labels", res.Labels); err != nil { + 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 labels: %s", err) } if err := d.Set("website", flattenBucketWebsite(res.Website)); err != nil { diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_migrate.go b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_migrate.go new file mode 100644 index 000000000000..f59f8adba0c8 --- /dev/null +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_migrate.go @@ -0,0 +1,415 @@ +package storage + +import ( + "context" + "math" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" +) + +func resourceStorageBucketV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The name of the bucket.`, + }, + + "encryption": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "default_kms_key_name": { + Type: schema.TypeString, + Required: true, + Description: `A Cloud KMS key that will be used to encrypt objects inserted into this bucket, if no encryption method is specified. You must pay attention to whether the crypto key is available in the location that this bucket is created in. See the docs for more details.`, + }, + }, + }, + Description: `The bucket's encryption configuration.`, + }, + + "requester_pays": { + Type: schema.TypeBool, + Optional: true, + Description: `Enables Requester Pays on a storage bucket.`, + }, + + "force_destroy": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `When deleting a bucket, this boolean option will delete all contained objects. If you try to delete a bucket that contains objects, Terraform will fail that run.`, + }, + + "labels": { + Type: schema.TypeMap, + Optional: true, + Computed: true, + // GCP (Dataplex) automatically adds labels + DiffSuppressFunc: resourceDataplexLabelDiffSuppress, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `A set of key/value label pairs to assign to the bucket.`, + }, + + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: func(s interface{}) string { + return strings.ToUpper(s.(string)) + }, + Description: `The Google Cloud Storage location`, + }, + + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The ID of the project in which the resource belongs. If it is not provided, the provider project is used.`, + }, + + "self_link": { + Type: schema.TypeString, + Computed: true, + Description: `The URI of the created resource.`, + }, + + "url": { + Type: schema.TypeString, + Computed: true, + Description: `The base URL of the bucket, in the format gs://.`, + }, + + "storage_class": { + Type: schema.TypeString, + Optional: true, + Default: "STANDARD", + Description: `The Storage Class of the new bucket. Supported values include: STANDARD, MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE.`, + }, + + "lifecycle_rule": { + Type: schema.TypeList, + Optional: true, + MaxItems: 100, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + MaxItems: 1, + Set: resourceGCSBucketLifecycleRuleActionHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Required: true, + Description: `The type of the action of this Lifecycle Rule. Supported values include: Delete, SetStorageClass and AbortIncompleteMultipartUpload.`, + }, + "storage_class": { + Type: schema.TypeString, + Optional: true, + Description: `The target Storage Class of objects affected by this Lifecycle Rule. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE.`, + }, + }, + }, + Description: `The Lifecycle Rule's action configuration. A single block of this type is supported.`, + }, + "condition": { + Type: schema.TypeSet, + Required: true, + MinItems: 1, + MaxItems: 1, + Set: resourceGCSBucketLifecycleRuleConditionHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "age": { + Type: schema.TypeInt, + Optional: true, + Description: `Minimum age of an object in days to satisfy this condition.`, + }, + "created_before": { + Type: schema.TypeString, + Optional: true, + Description: `Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.`, + }, + "custom_time_before": { + Type: schema.TypeString, + Optional: true, + Description: `Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.`, + }, + "days_since_custom_time": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of days elapsed since the user-specified timestamp set on an object.`, + }, + "days_since_noncurrent_time": { + Type: schema.TypeInt, + Optional: true, + Description: `Number of days elapsed since the noncurrent timestamp of an object. This + condition is relevant only for versioned objects.`, + }, + "noncurrent_time_before": { + Type: schema.TypeString, + Optional: true, + Description: `Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.`, + }, + "with_state": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"LIVE", "ARCHIVED", "ANY", ""}, false), + Description: `Match to live and/or archived objects. Unversioned buckets have only live objects. Supported values include: "LIVE", "ARCHIVED", "ANY".`, + }, + "matches_storage_class": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE, STANDARD, DURABLE_REDUCED_AVAILABILITY.`, + }, + "num_newer_versions": { + Type: schema.TypeInt, + Optional: true, + Description: `Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition.`, + }, + "matches_prefix": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `One or more matching name prefixes to satisfy this condition.`, + }, + "matches_suffix": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `One or more matching name suffixes to satisfy this condition.`, + }, + }, + }, + Description: `The Lifecycle Rule's condition configuration.`, + }, + }, + }, + Description: `The bucket's Lifecycle Rules configuration.`, + }, + + "versioning": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `While set to true, versioning is fully enabled for this bucket.`, + }, + }, + }, + Description: `The bucket's Versioning configuration.`, + }, + + "autoclass": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `While set to true, autoclass automatically transitions objects in your bucket to appropriate storage classes based on each object's access pattern.`, + }, + }, + }, + Description: `The bucket's autoclass configuration.`, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + _, n := d.GetChange(strings.TrimSuffix(k, ".#")) + if !strings.HasSuffix(k, ".#") { + return false + } + var l []interface{} + if new == "1" && old == "0" { + l = n.([]interface{}) + contents, ok := l[0].(map[string]interface{}) + if !ok { + return false + } + if contents["enabled"] == false { + return true + } + } + return false + }, + }, + "website": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "main_page_suffix": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: []string{"website.0.not_found_page", "website.0.main_page_suffix"}, + Description: `Behaves as the bucket's directory index where missing objects are treated as potential directories.`, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return old != "" && new == "" + }, + }, + "not_found_page": { + Type: schema.TypeString, + Optional: true, + AtLeastOneOf: []string{"website.0.main_page_suffix", "website.0.not_found_page"}, + Description: `The custom object to return when a requested resource is not found.`, + DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool { + return old != "" && new == "" + }, + }, + }, + }, + Description: `Configuration if the bucket acts as a website.`, + }, + + "retention_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_locked": { + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: `If set to true, the bucket will be locked and permanently restrict edits to the bucket's retention policy. Caution: Locking a bucket is an irreversible action.`, + }, + "retention_period": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, math.MaxInt32), + Description: `The period of time, in seconds, that objects in the bucket must be retained and cannot be deleted, overwritten, or archived. The value must be less than 3,155,760,000 seconds.`, + }, + }, + }, + Description: `Configuration of the bucket's data retention policy for how long objects in the bucket should be retained.`, + }, + + "cors": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "origin": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The list of Origins eligible to receive CORS response headers. Note: "*" is permitted in the list of origins, and means "any Origin".`, + }, + "method": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The list of HTTP methods on which to include CORS response headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in the list of methods, and means "any method".`, + }, + "response_header": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The list of HTTP headers other than the simple response headers to give permission for the user-agent to share across domains.`, + }, + "max_age_seconds": { + Type: schema.TypeInt, + Optional: true, + Description: `The value, in seconds, to return in the Access-Control-Max-Age header used in preflight responses.`, + }, + }, + }, + Description: `The bucket's Cross-Origin Resource Sharing (CORS) configuration.`, + }, + + "default_event_based_hold": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether or not to automatically apply an eventBasedHold to new objects added to the bucket.`, + }, + + "logging": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "log_bucket": { + Type: schema.TypeString, + Required: true, + Description: `The bucket that will receive log objects.`, + }, + "log_object_prefix": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `The object prefix for log objects. If it's not provided, by default Google Cloud Storage sets this to this bucket's name.`, + }, + }, + }, + Description: `The bucket's Access & Storage Logs configuration.`, + }, + "uniform_bucket_level_access": { + Type: schema.TypeBool, + Optional: true, + Computed: true, + Description: `Enables uniform bucket-level access on a bucket.`, + }, + "custom_placement_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "data_locations": { + Type: schema.TypeSet, + Required: true, + ForceNew: true, + MaxItems: 2, + MinItems: 2, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Description: `The list of individual regions that comprise a dual-region bucket. See the docs for a list of acceptable regions. Note: If any of the data_locations changes, it will recreate the bucket.`, + }, + }, + }, + Description: `The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated a single or multi-region, the parameters are empty.`, + }, + "public_access_prevention": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Prevents public access to a bucket.`, + }, + }, + UseJSONNumber: true, + } +} + +func ResourceStorageBucketStateUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + return tpgresource.LabelsStateUpgrade(rawState, resourceDataplexGoogleLabelPrefix) +} diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb index fb04f1bfa88c..ec4802c16148 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb @@ -978,7 +978,7 @@ func TestAccStorageBucket_labels(t *testing.T) { ResourceName: "google_storage_bucket.bucket", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"force_destroy"}, + ImportStateVerifyIgnore: []string{"force_destroy", "labels", "terraform_labels"}, }, // Down to only one label (test single label deletion) { @@ -988,7 +988,7 @@ func TestAccStorageBucket_labels(t *testing.T) { ResourceName: "google_storage_bucket.bucket", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"force_destroy"}, + ImportStateVerifyIgnore: []string{"force_destroy", "labels", "terraform_labels"}, }, // And make sure deleting all labels work { @@ -998,7 +998,7 @@ func TestAccStorageBucket_labels(t *testing.T) { ResourceName: "google_storage_bucket.bucket", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"force_destroy"}, + ImportStateVerifyIgnore: []string{"force_destroy", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/storagetransfer/data_source_google_storage_transfer_project_service_account.go b/mmv1/third_party/terraform/services/storagetransfer/data_source_google_storage_transfer_project_service_account.go index 4dc7ec9413b1..584791693df6 100644 --- a/mmv1/third_party/terraform/services/storagetransfer/data_source_google_storage_transfer_project_service_account.go +++ b/mmv1/third_party/terraform/services/storagetransfer/data_source_google_storage_transfer_project_service_account.go @@ -47,7 +47,7 @@ func dataSourceGoogleStorageTransferProjectServiceAccountRead(d *schema.Resource serviceAccount, err := config.NewStorageTransferClient(userAgent).GoogleServiceAccounts.Get(project).Do() if err != nil { - return transport_tpg.HandleNotFoundError(err, d, "Google Cloud Storage Transfer service account not found") + return transport_tpg.HandleDataSourceNotFoundError(err, d, "Google Cloud Storage Transfer service account not found", fmt.Sprintf("Project %q Google Cloud Storage Transfer account", project)) } d.SetId(serviceAccount.AccountEmail) diff --git a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go index cac0b57affa9..f0e1747ce96b 100644 --- a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go +++ b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go @@ -11,6 +11,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/terraform-provider-google/google/verify" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" @@ -61,6 +62,10 @@ func ResourceStorageTransferJob() *schema.Resource { State: resourceStorageTransferJobStateImporter, }, + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, diff --git a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go index 50e58e12c221..8353f7598327 100644 --- a/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go +++ b/mmv1/third_party/terraform/services/vertexai/data_source_vertex_ai_index.go @@ -29,5 +29,17 @@ func dataSourceVertexAIIndexRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceVertexAIIndexRead(d, meta) + err = resourceVertexAIIndexRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go index 2cde7c0a6862..09ca7ccc3c05 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_endpoint_test.go @@ -18,7 +18,7 @@ func TestAccVertexAIEndpoint_vertexAiEndpointNetwork(t *testing.T) { context := map[string]interface{}{ "endpoint_name": fmt.Sprint(acctest.RandInt(t) % 9999999999), "kms_key_name": acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name, - "network_name": acctest.BootstrapSharedTestNetwork(t, "vertex-ai-endpoint-update"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "vertex-ai-endpoint-update-1"), "random_suffix": acctest.RandString(t, 10), } @@ -34,7 +34,7 @@ func TestAccVertexAIEndpoint_vertexAiEndpointNetwork(t *testing.T) { ResourceName: "google_vertex_ai_endpoint.endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "location", "region"}, + ImportStateVerifyIgnore: []string{"etag", "location", "region", "labels", "terraform_labels"}, }, { Config: testAccVertexAIEndpoint_vertexAiEndpointNetworkUpdate(context), @@ -43,7 +43,7 @@ func TestAccVertexAIEndpoint_vertexAiEndpointNetwork(t *testing.T) { ResourceName: "google_vertex_ai_endpoint.endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "location", "region"}, + ImportStateVerifyIgnore: []string{"etag", "location", "region", "labels", "terraform_labels"}, }, }, }) @@ -64,23 +64,6 @@ resource "google_vertex_ai_endpoint" "endpoint" { encryption_spec { kms_key_name = "%{kms_key_name}" } - depends_on = [ - google_service_networking_connection.vertex_vpc_connection - ] -} - -resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.vertex_range.name] -} - -resource "google_compute_global_address" "vertex_range" { - name = "tf-test-address-name%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 24 - network = data.google_compute_network.vertex_network.id } data "google_compute_network" "vertex_network" { @@ -112,23 +95,6 @@ resource "google_vertex_ai_endpoint" "endpoint" { encryption_spec { kms_key_name = "%{kms_key_name}" } - depends_on = [ - google_service_networking_connection.vertex_vpc_connection - ] -} - -resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.vertex_range.name] -} - -resource "google_compute_global_address" "vertex_range" { - name = "tf-test-address-name%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 24 - network = data.google_compute_network.vertex_network.id } data "google_compute_network" "vertex_network" { diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_endpoint_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_endpoint_test.go index 1e9aa0eb6f22..aac5eb5eeb8d 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_endpoint_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_endpoint_test.go @@ -12,7 +12,7 @@ func TestAccVertexAIIndexEndpoint_updated(t *testing.T) { t.Parallel() context := map[string]interface{}{ - "network_name": acctest.BootstrapSharedTestNetwork(t, "vertex-ai-index-endpoint-update"), + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "vertex-ai-index-endpoint-update-1"), "random_suffix": acctest.RandString(t, 10), } @@ -28,7 +28,7 @@ func TestAccVertexAIIndexEndpoint_updated(t *testing.T) { ResourceName: "google_vertex_ai_index_endpoint.index_endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "region"}, + ImportStateVerifyIgnore: []string{"etag", "region", "labels", "terraform_labels"}, }, { Config: testAccVertexAIIndexEndpoint_updated(context), @@ -37,7 +37,7 @@ func TestAccVertexAIIndexEndpoint_updated(t *testing.T) { ResourceName: "google_vertex_ai_index_endpoint.index_endpoint", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "region"}, + ImportStateVerifyIgnore: []string{"etag", "region", "labels", "terraform_labels"}, }, }, }) @@ -53,15 +53,8 @@ resource "google_vertex_ai_index_endpoint" "index_endpoint" { label-one = "value-one" } network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" - depends_on = [ - google_service_networking_connection.vertex_vpc_connection - ] -} -resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.vertex_range.name] } + resource "google_compute_global_address" "vertex_range" { name = "tf-test-address-name%{random_suffix}" purpose = "VPC_PEERING" @@ -87,22 +80,8 @@ resource "google_vertex_ai_index_endpoint" "index_endpoint" { label-two = "value-two" } network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" - depends_on = [ - google_service_networking_connection.vertex_vpc_connection - ] -} -resource "google_service_networking_connection" "vertex_vpc_connection" { - network = data.google_compute_network.vertex_network.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.vertex_range.name] -} -resource "google_compute_global_address" "vertex_range" { - name = "tf-test-address-name%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 24 - network = data.google_compute_network.vertex_network.id } + data "google_compute_network" "vertex_network" { name = "%{network_name}" } diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_test.go index 09964869d97a..bd8f8d7e005c 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_index_test.go @@ -34,7 +34,7 @@ func TestAccVertexAIIndex_updated(t *testing.T) { ResourceName: "google_vertex_ai_index.index", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "region", "metadata.0.contents_delta_uri", "metadata.0.is_complete_overwrite"}, + ImportStateVerifyIgnore: []string{"etag", "region", "metadata.0.contents_delta_uri", "metadata.0.is_complete_overwrite", "labels", "terraform_labels"}, }, { Config: testAccVertexAIIndex_updated(context), @@ -43,7 +43,7 @@ func TestAccVertexAIIndex_updated(t *testing.T) { ResourceName: "google_vertex_ai_index.index", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag", "region", "metadata.0.contents_delta_uri", "metadata.0.is_complete_overwrite"}, + ImportStateVerifyIgnore: []string{"etag", "region", "metadata.0.contents_delta_uri", "metadata.0.is_complete_overwrite", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_tensorboard_test.go b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_tensorboard_test.go index d620fdfdeee7..a684ba95b623 100644 --- a/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_tensorboard_test.go +++ b/mmv1/third_party/terraform/services/vertexai/resource_vertex_ai_tensorboard_test.go @@ -25,7 +25,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix+"new", random_suffix, random_suffix, random_suffix), @@ -34,7 +34,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix+"new", random_suffix+"new", random_suffix, random_suffix), @@ -43,7 +43,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix+"new", random_suffix+"new", random_suffix+"new", random_suffix), @@ -52,7 +52,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix+"new", random_suffix+"new", random_suffix+"new", random_suffix+"new"), @@ -61,7 +61,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, { Config: testAccVertexAITensorboard_Update(random_suffix, random_suffix, random_suffix, random_suffix), @@ -70,7 +70,7 @@ func TestAccVertexAITensorboard_Update(t *testing.T) { ResourceName: "google_vertex_ai_tensorboard.tensorboard", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region", "project"}, + ImportStateVerifyIgnore: []string{"region", "project", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb index b5668f99aaee..cdeff513d0e0 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb @@ -28,6 +28,14 @@ func dataSourceVmwareengineClusterRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceVmwareengineClusterRead(d, meta) + err = resourceVmwareengineClusterRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb index dbbdfa4f2fd8..87465bef390a 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb @@ -30,6 +30,14 @@ func dataSourceVmwareengineNetworkRead(d *schema.ResourceData, meta interface{}) return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceVmwareengineNetworkRead(d, meta) + err = resourceVmwareengineNetworkRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb index 800536162504..915240857698 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb @@ -30,6 +30,14 @@ func dataSourceVmwareenginePrivateCloudRead(d *schema.ResourceData, meta interfa return fmt.Errorf("Error constructing id: %s", err) } d.SetId(id) - return resourceVmwareenginePrivateCloudRead(d, meta) + err = resourceVmwareenginePrivateCloudRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } <% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vpcaccess/data_source_vpc_access_connector.go b/mmv1/third_party/terraform/services/vpcaccess/data_source_vpc_access_connector.go index 7caa852d8ee7..b8b79401c819 100644 --- a/mmv1/third_party/terraform/services/vpcaccess/data_source_vpc_access_connector.go +++ b/mmv1/third_party/terraform/services/vpcaccess/data_source_vpc_access_connector.go @@ -30,5 +30,13 @@ func dataSourceVPCAccessConnectorRead(d *schema.ResourceData, meta interface{}) d.SetId(id) - return resourceVPCAccessConnectorRead(d, meta) + err = resourceVPCAccessConnectorRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil } diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb index af09534de104..57f5de6e6381 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_cluster_test.go.erb @@ -28,7 +28,7 @@ func TestAccWorkstationsWorkstationCluster_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationCluster_update(context), @@ -37,7 +37,7 @@ func TestAccWorkstationsWorkstationCluster_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, }, }) @@ -62,7 +62,7 @@ func TestAccWorkstationsWorkstationCluster_Private_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationCluster_private_update(context), @@ -71,7 +71,7 @@ func TestAccWorkstationsWorkstationCluster_Private_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb index f1272a8f7560..be4492fcff75 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb @@ -28,7 +28,7 @@ func TestAccWorkstationsWorkstationConfig_basic(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, }, }) @@ -95,7 +95,7 @@ func TestAccWorkstationsWorkstationConfig_displayName(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationConfig_displayName(context, "2"), @@ -104,7 +104,7 @@ func TestAccWorkstationsWorkstationConfig_displayName(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, }, }) @@ -172,7 +172,7 @@ func TestAccWorkstationsWorkstationConfig_persistentDirectories(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, }, }) @@ -317,7 +317,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationConfig_update(context), @@ -326,7 +326,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstationConfig_workstationConfigBasicExample(context), @@ -335,7 +335,7 @@ func TestAccWorkstationsWorkstationConfig_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "annotations", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_test.go.erb index 9e06368ceb1a..f1de41975189 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_test.go.erb @@ -28,7 +28,7 @@ func TestAccWorkstationsWorkstation_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, { Config: testAccWorkstationsWorkstation_modified(context), @@ -37,7 +37,7 @@ func TestAccWorkstationsWorkstation_update(t *testing.T) { ResourceName: "google_workstations_workstation_cluster.default", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"etag"}, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, }, }, }) diff --git a/mmv1/third_party/terraform/tpgresource/annotations.go b/mmv1/third_party/terraform/tpgresource/annotations.go new file mode 100644 index 000000000000..410fbd2355d4 --- /dev/null +++ b/mmv1/third_party/terraform/tpgresource/annotations.go @@ -0,0 +1,95 @@ +package tpgresource + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func SetAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + raw := d.Get("annotations") + if raw == nil { + return nil + } + + if d.Get("effective_annotations") == nil { + return fmt.Errorf("`effective_annotations` field is not present in the resource schema.") + } + + o, n := d.GetChange("annotations") + effectiveAnnotations := d.Get("effective_annotations").(map[string]interface{}) + + for k, v := range n.(map[string]interface{}) { + effectiveAnnotations[k] = v.(string) + } + + for k := range o.(map[string]interface{}) { + if _, ok := n.(map[string]interface{})[k]; !ok { + delete(effectiveAnnotations, k) + } + } + + if err := d.SetNew("effective_annotations", effectiveAnnotations); err != nil { + return fmt.Errorf("error setting new effective_annotations diff: %w", err) + } + + return nil +} + +func SetMetadataAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + l := d.Get("metadata").([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil + } + + raw := d.Get("metadata.0.annotations") + if raw == nil { + return nil + } + + if d.Get("metadata.0.effective_annotations") == nil { + return fmt.Errorf("`metadata.0.effective_annotations` field is not present in the resource schema.") + } + + o, n := d.GetChange("metadata.0.annotations") + effectiveAnnotations := d.Get("metadata.0.effective_annotations").(map[string]interface{}) + + for k, v := range n.(map[string]interface{}) { + effectiveAnnotations[k] = v.(string) + } + + for k := range o.(map[string]interface{}) { + if _, ok := n.(map[string]interface{})[k]; !ok { + delete(effectiveAnnotations, k) + } + } + + original := l[0].(map[string]interface{}) + original["effective_annotations"] = effectiveAnnotations + + if err := d.SetNew("metadata", []interface{}{original}); err != nil { + return fmt.Errorf("error setting new metadata diff: %w", err) + } + + return nil +} + +// Sets the "annotations" field with the value of the field "effective_annotations" for data sources. +// When reading data source, as the annotations field is unavailable in the configuration of the data source, +// the "annotations" field will be empty. With this funciton, the labels "annotations" will have all of annotations in the resource. +func SetDataSourceAnnotations(d *schema.ResourceData) error { + effectiveAnnotations := d.Get("effective_annotations") + if effectiveAnnotations == nil { + return nil + } + + if d.Get("annotations") == nil { + return fmt.Errorf("`annotations` field is not present in the resource schema.") + } + if err := d.Set("annotations", effectiveAnnotations); err != nil { + return fmt.Errorf("Error setting annotations in data source: %s", err) + } + + return nil +} diff --git a/mmv1/third_party/terraform/tpgresource/field_helpers.go b/mmv1/third_party/terraform/tpgresource/field_helpers.go index a6e700c71ba4..919b04cd6898 100644 --- a/mmv1/third_party/terraform/tpgresource/field_helpers.go +++ b/mmv1/third_party/terraform/tpgresource/field_helpers.go @@ -387,7 +387,8 @@ func GetRegionFromSchema(regionSchemaField, zoneSchemaField string, d TerraformR return GetResourceNameFromSelfLink(v.(string)), nil } if v, ok := d.GetOk(zoneSchemaField); ok && zoneSchemaField != "" { - return GetRegionFromZone(v.(string)), nil + zone := GetResourceNameFromSelfLink(v.(string)) + return GetRegionFromZone(zone), nil } if config.Region != "" { return config.Region, nil diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go new file mode 100644 index 000000000000..d8ff6bab6f43 --- /dev/null +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -0,0 +1,198 @@ +package tpgresource + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +// SetLabels is called in the READ method of the resources to set +// the field "labels" and "terraform_labels" in the state based on the labels field in the configuration. +// So the field "labels" and "terraform_labels" in the state will only have the user defined labels. +// param "labels" is all of labels returned from API read reqeust. +// param "lineage" is the terraform lineage of the field and could be "labels" or "terraform_labels". +func SetLabels(labels map[string]string, d *schema.ResourceData, lineage string) error { + transformed := make(map[string]interface{}) + + if v, ok := d.GetOk(lineage); ok { + if labels != nil { + for k := range v.(map[string]interface{}) { + transformed[k] = labels[k] + } + } + } + + return d.Set(lineage, transformed) +} + +// Sets the "labels" field and "terraform_labels" with the value of the field "effective_labels" for data sources. +// When reading data source, as the labels field is unavailable in the configuration of the data source, +// the "labels" field will be empty. With this funciton, the labels "field" will have all of labels in the resource. +func SetDataSourceLabels(d *schema.ResourceData) error { + effectiveLabels := d.Get("effective_labels") + if effectiveLabels == nil { + return nil + } + + if d.Get("labels") == nil { + return fmt.Errorf("`labels` field is not present in the resource schema.") + } + if err := d.Set("labels", effectiveLabels); err != nil { + return fmt.Errorf("Error setting labels in data source: %s", err) + } + + if d.Get("terraform_labels") == nil { + return fmt.Errorf("`terraform_labels` field is not present in the resource schema.") + } + if err := d.Set("terraform_labels", effectiveLabels); err != nil { + return fmt.Errorf("Error setting terraform_labels in data source: %s", err) + } + + return nil +} + +func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + raw := d.Get("labels") + if raw == nil { + return nil + } + + if d.Get("terraform_labels") == nil { + return fmt.Errorf("`terraform_labels` field is not present in the resource schema.") + } + + if d.Get("effective_labels") == nil { + return fmt.Errorf("`effective_labels` field is not present in the resource schema.") + } + + config := meta.(*transport_tpg.Config) + + // Merge provider default labels with the user defined labels in the resource to get terraform managed labels + terraformLabels := make(map[string]string) + for k, v := range config.DefaultLabels { + terraformLabels[k] = v + } + + labels := raw.(map[string]interface{}) + for k, v := range labels { + terraformLabels[k] = v.(string) + } + + if err := d.SetNew("terraform_labels", terraformLabels); err != nil { + return fmt.Errorf("error setting new terraform_labels diff: %w", err) + } + + o, n := d.GetChange("terraform_labels") + effectiveLabels := d.Get("effective_labels").(map[string]interface{}) + + for k, v := range n.(map[string]interface{}) { + effectiveLabels[k] = v.(string) + } + + for k := range o.(map[string]interface{}) { + if _, ok := n.(map[string]interface{})[k]; !ok { + delete(effectiveLabels, k) + } + } + + if err := d.SetNew("effective_labels", effectiveLabels); err != nil { + return fmt.Errorf("error setting new effective_labels diff: %w", err) + } + + return nil +} + +func SetMetadataLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + l := d.Get("metadata").([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil + } + + raw := d.Get("metadata.0.labels") + if raw == nil { + return nil + } + + if d.Get("metadata.0.terraform_labels") == nil { + return fmt.Errorf("`metadata.0.terraform_labels` field is not present in the resource schema.") + } + + if d.Get("metadata.0.effective_labels") == nil { + return fmt.Errorf("`metadata.0.effective_labels` field is not present in the resource schema.") + } + + config := meta.(*transport_tpg.Config) + + // Merge provider default labels with the user defined labels in the resource to get terraform managed labels + terraformLabels := make(map[string]string) + for k, v := range config.DefaultLabels { + terraformLabels[k] = v + } + + labels := raw.(map[string]interface{}) + for k, v := range labels { + terraformLabels[k] = v.(string) + } + + original := l[0].(map[string]interface{}) + + original["terraform_labels"] = terraformLabels + if err := d.SetNew("metadata", []interface{}{original}); err != nil { + return fmt.Errorf("error setting new metadata diff: %w", err) + } + + o, n := d.GetChange("metadata.0.terraform_labels") + effectiveLabels := d.Get("metadata.0.effective_labels").(map[string]interface{}) + + for k, v := range n.(map[string]interface{}) { + effectiveLabels[k] = v.(string) + } + + for k := range o.(map[string]interface{}) { + if _, ok := n.(map[string]interface{})[k]; !ok { + delete(effectiveLabels, k) + } + } + + original["effective_labels"] = effectiveLabels + if err := d.SetNew("metadata", []interface{}{original}); err != nil { + return fmt.Errorf("error setting new metadata diff: %w", err) + } + + return nil +} + +// Upgrade the field "labels" in the state to exclude the labels with the labels prefix +// and the field "effective_labels" to have all of labels, including the labels with the labels prefix +func LabelsStateUpgrade(rawState map[string]interface{}, labesPrefix string) (map[string]interface{}, error) { + log.Printf("[DEBUG] Attributes before migration: %#v", rawState) + log.Printf("[DEBUG] Attributes before migration labels: %#v", rawState["labels"]) + log.Printf("[DEBUG] Attributes before migration effective_labels: %#v", rawState["effective_labels"]) + + if rawState["labels"] != nil { + rawLabels := rawState["labels"].(map[string]interface{}) + labels := make(map[string]interface{}) + effectiveLabels := make(map[string]interface{}) + + for k, v := range rawLabels { + effectiveLabels[k] = v + + if !strings.HasPrefix(k, labesPrefix) { + labels[k] = v + } + } + + rawState["labels"] = labels + rawState["effective_labels"] = effectiveLabels + } + + log.Printf("[DEBUG] Attributes after migration: %#v", rawState) + log.Printf("[DEBUG] Attributes after migration labels: %#v", rawState["labels"]) + log.Printf("[DEBUG] Attributes after migration effective_labels: %#v", rawState["effective_labels"]) + + return rawState, nil +} diff --git a/mmv1/third_party/terraform/tpgresource/regional_utils.go b/mmv1/third_party/terraform/tpgresource/regional_utils.go index e9c98e615b90..b771a84c8bea 100644 --- a/mmv1/third_party/terraform/tpgresource/regional_utils.go +++ b/mmv1/third_party/terraform/tpgresource/regional_utils.go @@ -17,17 +17,25 @@ func IsZone(location string) bool { // - location argument in the resource config // - region argument in the resource config // - zone argument in the resource config +// - region argument in the provider config // - zone argument set in the provider config func GetLocation(d TerraformResourceData, config *transport_tpg.Config) (string, error) { if v, ok := d.GetOk("location"); ok { - return v.(string), nil + return GetResourceNameFromSelfLink(v.(string)), nil } else if v, isRegionalCluster := d.GetOk("region"); isRegionalCluster { - return v.(string), nil + return GetResourceNameFromSelfLink(v.(string)), nil } else { - // If region is not explicitly set, use "zone" (or fall back to the provider-level zone). - // For now, to avoid confusion, we require region to be set in the config to create a regional - // cluster rather than falling back to the provider-level region. - return GetZone(d, config) + if v, ok := d.GetOk("zone"); ok { + return GetResourceNameFromSelfLink(v.(string)), nil + } else { + if config.Region != "" { + return GetResourceNameFromSelfLink(config.Region), nil + } else if config.Zone != "" { + return GetResourceNameFromSelfLink(config.Zone), nil + } else { + return "", fmt.Errorf("Unable to determine location: region/zone not configured in resource/provider config") + } + } } } diff --git a/mmv1/third_party/terraform/tpgresource/utils.go b/mmv1/third_party/terraform/tpgresource/utils.go index 2a481d71ff06..24af3278f552 100644 --- a/mmv1/third_party/terraform/tpgresource/utils.go +++ b/mmv1/third_party/terraform/tpgresource/utils.go @@ -1,6 +1,7 @@ package tpgresource import ( + "context" "crypto/md5" "encoding/base64" "errors" @@ -18,6 +19,7 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" "github.com/hashicorp/errwrap" + "github.com/hashicorp/go-cty/cty" fwDiags "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -96,12 +98,49 @@ func GetProjectFromDiff(d *schema.ResourceDiff, config *transport_tpg.Config) (s if ok { return res.(string), nil } + if d.GetRawConfig().GetAttr("project") == cty.UnknownVal(cty.String) { + return res.(string), nil + } if config.Project != "" { return config.Project, nil } return "", fmt.Errorf("%s: required field is not set", "project") } +// getRegionFromDiff reads the "region" field from the given diff and falls +// back to the provider's value if not given. If the provider's value is not +// given, an error is returned. +func GetRegionFromDiff(d *schema.ResourceDiff, config *transport_tpg.Config) (string, error) { + res, ok := d.GetOk("region") + if ok { + return res.(string), nil + } + if d.GetRawConfig().GetAttr("region") == cty.UnknownVal(cty.String) { + return res.(string), nil + } + if config.Region != "" { + return config.Region, nil + } + return "", fmt.Errorf("%s: required field is not set", "region") +} + +// getZoneFromDiff reads the "zone" field from the given diff and falls +// back to the provider's value if not given. If the provider's value is not +// given, an error is returned. +func GetZoneFromDiff(d *schema.ResourceDiff, config *transport_tpg.Config) (string, error) { + res, ok := d.GetOk("zone") + if ok { + return res.(string), nil + } + if d.GetRawConfig().GetAttr("zone") == cty.UnknownVal(cty.String) { + return res.(string), nil + } + if config.Zone != "" { + return config.Zone, nil + } + return "", fmt.Errorf("%s: required field is not set", "zone") +} + func GetRouterLockName(region string, router string) string { return fmt.Sprintf("router/%s/%s", region, router) } @@ -165,6 +204,11 @@ func ExpandLabels(d TerraformResourceData) map[string]string { return ExpandStringMap(d, "labels") } +// ExpandEffectiveLabels pulls the value of "effective_labels" out of a TerraformResourceData as a map[string]string. +func ExpandEffectiveLabels(d TerraformResourceData) map[string]string { + return ExpandStringMap(d, "effective_labels") +} + // ExpandEnvironmentVariables pulls the value of "environment_variables" out of a schema.ResourceData as a map[string]string. func ExpandEnvironmentVariables(d *schema.ResourceData) map[string]string { return ExpandStringMap(d, "environment_variables") @@ -699,3 +743,57 @@ func GetContentMd5Hash(content []byte) string { } return base64.StdEncoding.EncodeToString(h.Sum(nil)) } + +func DefaultProviderProject(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + + config := meta.(*transport_tpg.Config) + + //project + if project := diff.Get("project"); project != nil { + project, err := GetProjectFromDiff(diff, config) + if err != nil { + return fmt.Errorf("Failed to retrieve project, pid: %s, err: %s", project, err) + } + err = diff.SetNew("project", project) + if err != nil { + return err + } + } + return nil +} + +func DefaultProviderRegion(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + + config := meta.(*transport_tpg.Config) + //region + if region := diff.Get("region"); region != nil { + region, err := GetRegionFromDiff(diff, config) + if err != nil { + return fmt.Errorf("Failed to retrieve region, pid: %s, err: %s", region, err) + } + err = diff.SetNew("region", region) + if err != nil { + return err + } + } + + return nil +} + +func DefaultProviderZone(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + + config := meta.(*transport_tpg.Config) + // zone + if zone := diff.Get("zone"); zone != nil { + zone, err := GetZoneFromDiff(diff, config) + if err != nil { + return fmt.Errorf("Failed to retrieve zone, pid: %s, err: %s", zone, err) + } + err = diff.SetNew("zone", zone) + if err != nil { + return err + } + } + + return nil +} diff --git a/mmv1/third_party/terraform/tpgresource/utils_test.go b/mmv1/third_party/terraform/tpgresource/utils_test.go index f5b5a6ccf825..b815ff762473 100644 --- a/mmv1/third_party/terraform/tpgresource/utils_test.go +++ b/mmv1/third_party/terraform/tpgresource/utils_test.go @@ -239,11 +239,11 @@ func TestGetLocation(t *testing.T) { }, ExpectedLocation: "resource-location", }, - "does not shorten the location value when it is set as a self link in the resource config": { + "shortens the location value when it is set as a self link in the resource config": { ResourceConfig: map[string]interface{}{ "location": "https://www.googleapis.com/compute/v1/projects/my-project/locations/resource-location", }, - ExpectedLocation: "https://www.googleapis.com/compute/v1/projects/my-project/locations/resource-location", // No shortening takes place + ExpectedLocation: "resource-location", }, "returns the region value set in the resource config when location is not in the schema": { ResourceConfig: map[string]interface{}{ @@ -252,11 +252,11 @@ func TestGetLocation(t *testing.T) { }, ExpectedLocation: "resource-region", }, - "does not shorten the region value when it is set as a self link in the resource config": { + "shortens the region value when it is set as a self link in the resource config": { ResourceConfig: map[string]interface{}{ "region": "https://www.googleapis.com/compute/v1/projects/my-project/region/resource-region", }, - ExpectedLocation: "https://www.googleapis.com/compute/v1/projects/my-project/region/resource-region", // No shortening takes place + ExpectedLocation: "resource-region", }, "returns the zone value set in the resource config when neither location nor region in the schema": { ResourceConfig: map[string]interface{}{ @@ -278,13 +278,23 @@ func TestGetLocation(t *testing.T) { }, ExpectedLocation: "provider-zone-a", }, - "does not shorten the zone value when it is set as a self link in the provider config": { - // This behaviour makes sense because provider config values don't originate from APIs - // Users should always configure the provider with the short names of regions/zones + "returns the region value from the provider config when none of location/region/zone are set in the resource config": { + ProviderConfig: map[string]string{ + "region": "provider-region", + }, + ExpectedLocation: "provider-region", + }, + "shortens the region value when it is set as a self link in the provider config": { + ProviderConfig: map[string]string{ + "region": "https://www.googleapis.com/compute/v1/projects/my-project/region/provider-region", + }, + ExpectedLocation: "provider-region", + }, + "shortens the zone value when it is set as a self link in the provider config": { ProviderConfig: map[string]string{ "zone": "https://www.googleapis.com/compute/v1/projects/my-project/zones/provider-zone-a", }, - ExpectedLocation: "https://www.googleapis.com/compute/v1/projects/my-project/zones/provider-zone-a", + ExpectedLocation: "provider-zone-a", }, // Handling of empty strings "returns the region value set in the resource config when location is an empty string": { @@ -313,13 +323,18 @@ func TestGetLocation(t *testing.T) { }, ExpectedLocation: "provider-zone-a", }, - // Error states - "returns an error when only a region value is set in the the provider config and none of location/region/zone are set in the resource config": { + "returns the region value when only a region value is set in the the provider config and none of location/region/zone are set in the resource config": { + ResourceConfig: map[string]interface{}{ + "location": "", + "region": "", + "zone": "", + }, ProviderConfig: map[string]string{ "region": "provider-region", }, - ExpectError: true, + ExpectedLocation: "provider-region", }, + // Error states "returns an error when none of location/region/zone are set on the resource, and neither region or zone is set on the provider": { ExpectError: true, }, @@ -498,11 +513,11 @@ func TestGetRegion(t *testing.T) { }, ExpectedRegion: "resource-zone", // is truncated }, - "does not shorten region values when derived from a zone self link set in the resource config": { + "shortens region values when derived from a zone self link set in the resource config": { ResourceConfig: map[string]interface{}{ "zone": "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a", }, - ExpectedRegion: "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1", // Value is not shortenedfrom URI to name + ExpectedRegion: "us-central1", }, "returns the value of the region field in provider config when region/zone is unset in resource config": { ProviderConfig: map[string]string{ diff --git a/mmv1/third_party/terraform/transport/config.go.erb b/mmv1/third_party/terraform/transport/config.go.erb index ee330cd4a26d..9e831c7d392b 100644 --- a/mmv1/third_party/terraform/transport/config.go.erb +++ b/mmv1/third_party/terraform/transport/config.go.erb @@ -189,6 +189,7 @@ type Config struct { UserProjectOverride bool RequestReason string RequestTimeout time.Duration + DefaultLabels map[string]string // PollInterval is passed to resource.StateChangeConf in common_operation.go // It controls the interval at which we poll for successful operations PollInterval time.Duration diff --git a/mmv1/third_party/terraform/transport/transport.go b/mmv1/third_party/terraform/transport/transport.go index 374841b34ec1..01f0fd1a1aa6 100644 --- a/mmv1/third_party/terraform/transport/transport.go +++ b/mmv1/third_party/terraform/transport/transport.go @@ -136,6 +136,15 @@ func HandleNotFoundError(err error, d *schema.ResourceData, resource string) err fmt.Sprintf("Error when reading or editing %s: {{err}}", resource), err) } +func HandleDataSourceNotFoundError(err error, d *schema.ResourceData, resource, url string) error { + if IsGoogleApiErrorWithCode(err, 404) { + return fmt.Errorf("%s not found", url) + } + + return errwrap.Wrapf( + fmt.Sprintf("Error when reading or editing %s: {{err}}", resource), err) +} + func IsGoogleApiErrorWithCode(err error, errCode int) bool { gerr, ok := errwrap.GetType(err, &googleapi.Error{}).(*googleapi.Error) return ok && gerr != nil && gerr.Code == errCode diff --git a/mmv1/third_party/terraform/utils/provider_versionfive_upgrade_test.go.erb b/mmv1/third_party/terraform/utils/provider_versionfive_upgrade_test.go.erb new file mode 100644 index 000000000000..161ec6ccf34d --- /dev/null +++ b/mmv1/third_party/terraform/utils/provider_versionfive_upgrade_test.go.erb @@ -0,0 +1,646 @@ +<% autogen_exception -%> +package google + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestProvider_versionfive_upgrade(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + org := envvar.GetTestOrgFromEnv(t) + billingId := envvar.GetTestBillingAccountFromEnv(t) + project := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + + name1 := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + name2 := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + name3 := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + name4 := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.80.0", + Source: "hashicorp/google-beta", + }, + }, + Config: testProvider_versionfive_upgrades(project, org, billingId, name1, name2, name3, name4), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Config: testProvider_versionfive_upgrades(project, org, billingId, name1, name2, name3, name4), + PlanOnly: true, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ResourceName: "google_data_fusion_instance.unset", + ImportState: true, + ImportStateVerify: true, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ResourceName: "google_data_fusion_instance.set", + ImportState: true, + ImportStateVerify: true, + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ResourceName: "google_data_fusion_instance.reference", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestProvider_versionfive_ignorereads_upgrade(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + var itName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var tpName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var igmName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var autoscalerName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + policyName := fmt.Sprintf("tf-test-policy-%s", acctest.RandString(t, 10)) + + endpointContext := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + var itNameRegion = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var tpNameRegion = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var igmNameRegion = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + var autoscalerNameRegion = fmt.Sprintf("tf-test-region-autoscaler-%s", acctest.RandString(t, 10)) + + policyContext := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + attachmentContext := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: resource.ComposeTestCheckFunc(testAccCheckComputeResourcePolicyDestroyProducer(t), + testAccCheckComputeRegionAutoscalerDestroyProducer(t), + testAccCheckComputeNetworkEndpointGroupDestroyProducer(t), + testAccCheckComputeAutoscalerDestroyProducer(t), + ), + Steps: []resource.TestStep{ + { + ExternalProviders: map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "4.80.0", + Source: "hashicorp/google-beta", + }, + }, + Config: testProvider_versionfive_upgrades_ignorereads(itName, tpName, igmName, autoscalerName, diskName, policyName, + itNameRegion, tpNameRegion, igmNameRegion, autoscalerNameRegion, endpointContext, + policyContext, attachmentContext), + }, + { + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Config: testProvider_versionfive_upgrades_ignorereads(itName, tpName, igmName, autoscalerName, diskName, policyName, + itNameRegion, tpNameRegion, igmNameRegion, autoscalerNameRegion, endpointContext, + policyContext, attachmentContext), + PlanOnly: true, + }, + }, + }) +} + +func testProvider_versionfive_upgrades(project, org, billing, name1, name2, name3, name4 string) string { + return fmt.Sprintf(` +resource "google_project" "host" { + project_id = "%s" + name = "%s" + org_id = "%s" + billing_account = "%s" +} + +resource "google_project_service" "dfapi" { + project = google_project.host.project_id + service = "datafusion.googleapis.com" + + disable_dependent_services = false +} + +resource "google_data_fusion_instance" "unset" { + name = "%s" + type = "BASIC" + options = { + prober_test_run = "true" + } +} + +resource "google_data_fusion_instance" "set" { + name = "%s" + region = "us-west1" + type = "BASIC" + options = { + prober_test_run = "true" + } +} + +resource "google_data_fusion_instance" "reference" { + project = google_project.host.project_id + name = "%s" + type = "DEVELOPER" + options = { + prober_test_run = "true" + } + zone = "us-west1-a" + depends_on = [ + google_project_service.dfapi + ] +} + +resource "google_redis_instance" "overridewithnonstandardlogic" { + name = "%s" + memory_size_gb = 1 + location_id = "us-south1-a" +} + + +`, project, project, org, billing, name1, name2, name3, name4) +} + +func testProvider_versionfive_upgrades_ignorereads(itName, tpName, igmName, autoscalerName, diskName, policyName, itNameRegion, tpNameRegion, igmNameRegion, autoscalerNameRegion string, endpointContext, policyContext, attachmentContext map[string]interface{}) string { + return testAccComputeAutoscaler_basic(itName, tpName, igmName, autoscalerName) + + testAccComputeDiskResourcePolicyAttachment_basic(diskName, policyName) + + testAccComputeNetworkEndpointGroup_networkEndpointGroup(endpointContext) + + testAccComputeRegionAutoscaler_basic(itNameRegion, tpNameRegion, igmNameRegion, autoscalerNameRegion) + + testAccComputeResourcePolicy_resourcePolicyBasicExample(policyContext) + + testAccComputeServiceAttachment_serviceAttachmentBasicExample(attachmentContext) +} + +// need to make copies of all the respective resource functions within here as *_test.go files can not be imported +// checkdestroys +func testAccCheckComputeResourcePolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_resource_policy" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/resourcePolicies/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("ComputeResourcePolicy still exists at %s", url) + } + } + + return nil + } +} + +func testAccCheckComputeRegionAutoscalerDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_region_autoscaler" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/autoscalers/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("ComputeRegionAutoscaler still exists at %s", url) + } + } + + return nil + } +} + +func testAccCheckComputeNetworkEndpointGroupDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_network_endpoint_group" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/networkEndpointGroups/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("ComputeNetworkEndpointGroup still exists at %s", url) + } + } + + return nil + } +} + +func testAccCheckComputeAutoscalerDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_autoscaler" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/autoscalers/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("ComputeAutoscaler still exists at %s", url) + } + } + + return nil + } +} + +// tests +func testAccComputeAutoscaler_scaffolding(itName, tpName, igmName string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image1" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance_template" "foobar1" { + name = "%s" + machine_type = "e2-medium" + can_ip_forward = false + tags = ["foo", "bar"] + + disk { + source_image = data.google_compute_image.my_image1.self_link + auto_delete = true + boot = true + } + + network_interface { + network = "default" + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} + +resource "google_compute_target_pool" "foobar1" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + session_affinity = "CLIENT_IP_PROTO" + region = "us-west1" +} + +resource "google_compute_instance_group_manager" "foobar1" { + description = "Terraform test instance group manager" + name = "%s" + version { + instance_template = google_compute_instance_template.foobar1.self_link + name = "primary" + } + target_pools = [google_compute_target_pool.foobar1.self_link] + base_instance_name = "foobar1" + zone = "us-west1-a" +} +`, itName, tpName, igmName) + +} + +func testAccComputeAutoscaler_basic(itName, tpName, igmName, autoscalerName string) string { + return testAccComputeAutoscaler_scaffolding(itName, tpName, igmName) + fmt.Sprintf(` +resource "google_compute_autoscaler" "foobar1" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + zone = "us-west1-a" + target = google_compute_instance_group_manager.foobar1.self_link + autoscaling_policy { + max_replicas = 5 + min_replicas = 1 + cooldown_period = 60 + cpu_utilization { + target = 0.5 + } + } +} +`, autoscalerName) +} + +func testAccComputeDiskResourcePolicyAttachment_basic(diskName, policyName string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image2" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_disk" "foobar2" { + name = "%s" + image = data.google_compute_image.my_image2.self_link + size = 1000 + type = "pd-extreme" + zone = "us-west1-c" + labels = { + my-label = "my-label-value" + } + provisioned_iops = 90000 +} + +resource "google_compute_resource_policy" "foobar2" { + name = "%s" + region = "us-west1" + snapshot_schedule_policy { + schedule { + daily_schedule { + days_in_cycle = 1 + start_time = "04:00" + } + } + } +} + +resource "google_compute_disk_resource_policy_attachment" "foobar2" { + name = google_compute_resource_policy.foobar2.name + disk = google_compute_disk.foobar2.name + zone = "us-west1-c" +} +`, diskName, policyName) +} + +func testAccComputeNetworkEndpointGroup_networkEndpointGroup(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network_endpoint_group" "neg3" { + name = "tf-test-my-lb-neg%{random_suffix}" + network = google_compute_network.default3.id + default_port = "90" + zone = "us-west1-a" +} + +resource "google_compute_network" "default3" { + name = "tf-test-neg-network%{random_suffix}" + auto_create_subnetworks = true +} +`, context) +} + +func testAccComputeRegionAutoscaler_scaffolding(itName, tpName, igmName string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image4" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance_template" "foobar4" { + name = "%s" + machine_type = "e2-medium" + can_ip_forward = false + tags = ["foo", "bar"] + + disk { + source_image = data.google_compute_image.my_image4.self_link + auto_delete = true + boot = true + } + + network_interface { + network = "default" + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} + +resource "google_compute_target_pool" "foobar4" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + session_affinity = "CLIENT_IP_PROTO" + region = "us-west1" +} + +resource "google_compute_region_instance_group_manager" "foobar4" { + description = "Terraform test instance group manager" + name = "%s" + version { + instance_template = google_compute_instance_template.foobar4.self_link + name = "primary" + } + target_pools = [google_compute_target_pool.foobar4.self_link] + base_instance_name = "tf-test-foobar4" + region = "us-west1" +} + +`, itName, tpName, igmName) +} + +func testAccComputeRegionAutoscaler_basic(itName, tpName, igmName, autoscalerName string) string { + return testAccComputeRegionAutoscaler_scaffolding(itName, tpName, igmName) + fmt.Sprintf(` +resource "google_compute_region_autoscaler" "foobar4" { + description = "Resource created for Terraform acceptance testing" + name = "%s" + region = "us-west1" + target = google_compute_region_instance_group_manager.foobar4.self_link + autoscaling_policy { + max_replicas = 5 + min_replicas = 0 + cooldown_period = 60 + cpu_utilization { + target = 0.5 + } + } +} +`, autoscalerName) +} + +func testAccComputeResourcePolicy_resourcePolicyBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_resource_policy" "foo5" { + name = "tf-test-gce-policy%{random_suffix}" + region = "us-west1" + snapshot_schedule_policy { + schedule { + daily_schedule { + days_in_cycle = 1 + start_time = "04:00" + } + } + } +} +`, context) +} + +func testAccComputeServiceAttachment_serviceAttachmentBasicExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_service_attachment" "psc_ilb_service_attachment6" { + name = "tf-test-my-psc-ilb%{random_suffix}" + region = "us-west2" + description = "A service attachment configured with Terraform" + + enable_proxy_protocol = true + connection_preference = "ACCEPT_AUTOMATIC" + nat_subnets = [google_compute_subnetwork.psc_ilb_nat6.id] + target_service = google_compute_forwarding_rule.psc_ilb_target_service6.id + reconcile_connections = true +} + +resource "google_compute_address" "psc_ilb_consumer_address6" { + name = "tf-test-psc-ilb-consumer-address%{random_suffix}" + region = "us-west2" + + subnetwork = "default" + address_type = "INTERNAL" +} + +resource "google_compute_forwarding_rule" "psc_ilb_consumer6" { + name = "tf-test-psc-ilb-consumer-forwarding-rule%{random_suffix}" + region = "us-west2" + + target = google_compute_service_attachment.psc_ilb_service_attachment6.id + load_balancing_scheme = "" # need to override EXTERNAL default when target is a service attachment + network = "default" + ip_address = google_compute_address.psc_ilb_consumer_address6.id +} + +resource "google_compute_forwarding_rule" "psc_ilb_target_service6" { + name = "tf-test-producer-forwarding-rule%{random_suffix}" + region = "us-west2" + + load_balancing_scheme = "INTERNAL" + backend_service = google_compute_region_backend_service.producer_service_backend6.id + all_ports = true + network = google_compute_network.psc_ilb_network6.name + subnetwork = google_compute_subnetwork.psc_ilb_producer_subnetwork6.name +} + +resource "google_compute_region_backend_service" "producer_service_backend6" { + name = "tf-test-producer-service%{random_suffix}" + region = "us-west2" + + health_checks = [google_compute_health_check.producer_service_health_check6.id] +} + +resource "google_compute_health_check" "producer_service_health_check6" { + name = "tf-test-producer-service-health-check%{random_suffix}" + + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } +} + +resource "google_compute_network" "psc_ilb_network6" { + name = "tf-test-psc-ilb-network%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "psc_ilb_producer_subnetwork6" { + name = "tf-test-psc-ilb-producer-subnetwork%{random_suffix}" + region = "us-west2" + + network = google_compute_network.psc_ilb_network6.id + ip_cidr_range = "10.0.0.0/16" +} + +resource "google_compute_subnetwork" "psc_ilb_nat6" { + name = "tf-test-psc-ilb-nat%{random_suffix}" + region = "us-west2" + + network = google_compute_network.psc_ilb_network6.id + purpose = "PRIVATE_SERVICE_CONNECT" + ip_cidr_range = "10.1.0.0/16" +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/cloudfunctions_function.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloudfunctions_function.html.markdown index e3ca05447d0c..1b4e2f7dd5b2 100644 --- a/mmv1/third_party/terraform/website/docs/d/cloudfunctions_function.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/cloudfunctions_function.html.markdown @@ -49,7 +49,7 @@ exported: * `event_trigger` - A source that fires events in response to a condition in another service. Structure is [documented below](#nested_event_trigger). * `https_trigger_url` - If function is triggered by HTTP, trigger URL is set here. * `ingress_settings` - Controls what traffic can reach the function. -* `labels` - A map of labels applied to this function. +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `service_account_email` - The service account email to be assumed by the cloud function. * `vpc_connector` - The VPC Network Connector that this cloud function can connect to. * `vpc_connector_egress_settings` - The egress settings for the connector, controlling what traffic is diverted through it. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_disk.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_disk.html.markdown index 65596b090bfa..33ad9dc772af 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_disk.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_disk.html.markdown @@ -82,7 +82,7 @@ In addition to the arguments listed above, the following computed attributes are * `description` - The optional description of this resource. -* `labels` - A map of labels applied to this disk. +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `size` - Size of the persistent disk, specified in GB. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_image.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_image.html.markdown index e9cdc9616ad6..883e99fc0bfd 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_image.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_image.html.markdown @@ -71,7 +71,7 @@ exported: * `source_disk_id` - The ID value of the disk used to create this image. * `creation_timestamp` - The creation timestamp in RFC3339 text format. * `description` - An optional description of this image. -* `labels` - A map of labels applied to this image. +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `label_fingerprint` - A fingerprint for the labels being applied to this image. * `licenses` - A list of applicable license URI. * `status` - The status of the image. Possible values are **FAILED**, **PENDING**, or **READY**. 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 d478a3eca5ae..1d3e8dc06205 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 @@ -57,7 +57,7 @@ The following arguments are supported: * `guest_accelerator` - List of the type and count of accelerator cards attached to the instance. Structure is [documented below](#nested_guest_accelerator). -* `labels` - A set of key/value label pairs assigned to the instance. +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `metadata` - Metadata key/value pairs made available within the instance. diff --git a/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown index e771c3be87c5..3142f0af8932 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_instance_template.html.markdown @@ -78,8 +78,7 @@ The following arguments are supported: * `instance_description` - A brief description to use for instances created from this template. -* `labels` - A set of key/value label pairs to assign to instances - created from this template, +* `labels` - All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `metadata` - Metadata key/value pairs to make available from within instances created from this template. diff --git a/mmv1/third_party/terraform/website/docs/d/game_services_game_server_deployment_rollout.html.markdown b/mmv1/third_party/terraform/website/docs/d/game_services_game_server_deployment_rollout.html.markdown deleted file mode 100644 index 263c218a36da..000000000000 --- a/mmv1/third_party/terraform/website/docs/d/game_services_game_server_deployment_rollout.html.markdown +++ /dev/null @@ -1,68 +0,0 @@ ---- -subcategory: "Game Servers" -description: |- - Get the rollout state. ---- - -# google\_game\_services\_game\_server\_deployment\_rollout - -Use this data source to get the rollout state. - -https://cloud.google.com/game-servers/docs/reference/rest/v1beta/GameServerDeploymentRollout - -## Example Usage - - -```hcl -data "google_game_services_game_server_deployment_rollout" "qa" { - deployment_id = "tf-test-deployment-s8sn12jt2c" -} -``` - -## Argument Reference - -The following arguments are supported: - - -* `deployment_id` - (Required) - The deployment to get the rollout state from. Only 1 rollout must be associated with each deployment. - - -## Attributes Reference - -In addition to the arguments listed above, the following attributes are exported: - -* `default_game_server_config` - - This field points to the game server config that is - applied by default to all realms and clusters. For example, - `projects/my-project/locations/global/gameServerDeployments/my-game/configs/my-config`. - - -* `game_server_config_overrides` - - The game_server_config_overrides contains the per game server config - overrides. The overrides are processed in the order they are listed. As - soon as a match is found for a cluster, the rest of the list is not - processed. Structure is [documented below](#nested_game_server_config_overrides). - -* `project` - The ID of the project in which the resource belongs. - If it is not provided, the provider project is used. - - -The `game_server_config_overrides` block contains: - -* `realms_selector` - - Selection by realms. Structure is [documented below](#nested_realms_selector). - -* `config_version` - - Version of the configuration. - -The `realms_selector` block contains: - -* `realms` - - List of realms to match against. - -* `id` - an identifier for the resource with format `projects/{{project}}/locations/global/gameServerDeployments/{{deployment_id}}/rollout` - -* `name` - - The resource id of the game server deployment - eg: `projects/my-project/locations/global/gameServerDeployments/my-deployment/rollout`. diff --git a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown index 2fb0cd7fb3a7..929a8e8f2c70 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown @@ -114,6 +114,15 @@ The following arguments are supported: * `labels` - (Optional) A mapping of labels to assign to the resource. + **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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `schema` - (Optional) A JSON schema for the table. ~>**NOTE:** Because this field expects a JSON string, any changes to the diff --git a/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown index a6f1d14cb34f..b01760722087 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigtable_instance.html.markdown @@ -102,6 +102,14 @@ in Terraform state, a `terraform destroy` or `terraform apply` that would delete * `labels` - (Optional) A set of key/value label pairs to assign to the resource. Label keys must follow the requirements at https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements. + **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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. ----- diff --git a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown index 40d8a29bd42b..c73d6561aab6 100644 --- a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown @@ -134,6 +134,15 @@ Eg. `"nodejs16"`, `"python39"`, `"dotnet3"`, `"go116"`, `"java11"`, `"ruby30"`, * `labels` - (Optional) A set of key/value label pairs to assign to the function. Label keys must follow the requirements at https://cloud.google.com/resource-manager/docs/creating-managing-labels#requirements. +**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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `service_account_email` - (Optional) If provided, the self-provided service account to run the function with. * `environment_variables` - (Optional) A set of key/value environment variable pairs to assign to the function. diff --git a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown index 438b688d9f7c..94c3fb60920d 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown @@ -262,6 +262,15 @@ The following arguments are supported: No more than 64 labels can be associated with a given environment. Both keys and values must be <= 128 bytes in size. + **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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `region` - (Optional) The location or Compute Engine region for the environment. 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 00e16e341146..7ad77392768c 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 @@ -117,6 +117,14 @@ The following arguments are supported: For more details about this behavior, see [this section](https://www.terraform.io/docs/configuration/attr-as-blocks.html#defining-a-fixed-object-collection-value). * `labels` - (Optional) A map of key/value label pairs to assign to the instance. + **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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `metadata` - (Optional) Metadata key/value pairs to make available from within the instance. Ssh keys attached in the Cloud Console will be removed. 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 c04c64137d4d..a1c450d39ccf 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 @@ -308,6 +308,15 @@ The following arguments are supported: * `labels` - (Optional) A set of key/value label pairs to assign to instances created from this template. + **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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `metadata` - (Optional) Metadata key/value pairs to make available from within instances created from this template. 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 4e1c3a29838f..5364b3197115 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 @@ -320,6 +320,15 @@ The following arguments are supported: * `labels` - (Optional) A set of key/value label pairs to assign to instances created from this template. + **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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. + * `metadata` - (Optional) Metadata key/value pairs to make available from within instances created from this template. diff --git a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown index cc08f95c2404..2ad540829e02 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown @@ -16,6 +16,10 @@ Manages a Google Kubernetes Engine (GKE) cluster. For more information see [the official documentation](https://cloud.google.com/container-engine/docs/clusters) and [the API reference](https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1beta1/projects.locations.clusters). +-> **Note**: On version 5.0.0+ of the provider, you must explicitly set `deletion_protection=false` +(and run `terraform apply` to write the field to state) in order to destroy a cluster. +It is recommended to not set this field (or set it to true) until you're ready to destroy. + ~> **Warning:** All arguments and attributes, including basic auth username and passwords as well as certificate outputs will be stored in the raw state as plaintext. [Read more about sensitive data in state](https://www.terraform.io/language/state/sensitive-data). @@ -118,6 +122,10 @@ locations. In contrast, in a regional cluster, cluster master nodes are present in multiple zones in the region. For that reason, regional clusters should be preferred. +* `deletion_protection` - (Optional) Whether or not to allow Terraform to destroy +the cluster. Unless this field is set to false in Terraform state, a +`terraform destroy` or `terraform apply` that would delete the cluster will fail. + * `addons_config` - (Optional) The configuration for addons supported by GKE. Structure is [documented below](#nested_addons_config). @@ -156,10 +164,6 @@ per node in this cluster. This doesn't work on "routes-based" clusters, clusters that don't have IP Aliasing enabled. See the [official documentation](https://cloud.google.com/kubernetes-engine/docs/how-to/flexible-pod-cidr) for more information. -* `enable_binary_authorization` - (DEPRECATED) Enable Binary Authorization for this cluster. - If enabled, all container images will be validated by Google Binary Authorization. - Deprecated in favor of `binary_authorization`. - * `enable_kubernetes_alpha` - (Optional) Whether to enable Kubernetes Alpha features for this cluster. Note that when this option is enabled, the cluster cannot be upgraded and will be automatically deleted after 30 days. @@ -460,8 +464,7 @@ addons_config { * `enabled` - (DEPRECATED) Enable Binary Authorization for this cluster. Deprecated in favor of `evaluation_mode`. * `evaluation_mode` - (Optional) Mode of operation for Binary Authorization policy evaluation. Valid values are `DISABLED` - and `PROJECT_SINGLETON_POLICY_ENFORCE`. `PROJECT_SINGLETON_POLICY_ENFORCE` is functionally equivalent to the - deprecated `enable_binary_authorization` parameter being set to `true`. + and `PROJECT_SINGLETON_POLICY_ENFORCE`. The `service_external_ips_config` block supports: @@ -895,14 +898,13 @@ gvnic { * `tags` - (Optional) The list of instance tags applied to all nodes. Tags are used to identify valid sources or targets for network firewalls. -* `taint` - (Optional) A list of [Kubernetes taints](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) -to apply to nodes. GKE's API can only set this field on cluster creation. -However, GKE will add taints to your nodes if you enable certain features such -as GPUs. If this field is set, any diffs on this field will cause Terraform to -recreate the underlying resource. Taint values can be updated safely in -Kubernetes (eg. through `kubectl`), and it's recommended that you do not use -this field to manage taints. If you do, `lifecycle.ignore_changes` is -recommended. Structure is [documented below](#nested_taint). +* `taint` - (Optional) A list of +[Kubernetes taints](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) +to apply to nodes. This field will only report drift on taint keys that are +already managed with Terraform, use `effective_taints` to view the list of +GKE-managed taints on the node pool from all sources. Importing this resource +will not record any taints as being Terraform-managed, and will cause drift with +any configured taints. Structure is [documented below](#nested_taint). * `workload_metadata_config` - (Optional) Metadata configuration to expose to workloads on the node pool. Structure is [documented below](#nested_workload_metadata_config). @@ -1317,6 +1319,8 @@ exported: * `cluster_autoscaling.0.auto_provisioning_defaults.0.management.0.upgrade_options` - Specifies the [Auto Upgrade knobs](https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1beta1/NodeManagement#AutoUpgradeOptions) for the node pool. +* `node_config.0.effective_taints` - List of kubernetes taints applied to each node. Structure is [documented above](#nested_taint). + ## Timeouts This resource provides the following diff --git a/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown index 523d2684a41f..bbf814662a88 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown @@ -201,9 +201,9 @@ cluster. The `management` block supports: -* `auto_repair` - (Optional) Whether the nodes will be automatically repaired. +* `auto_repair` - (Optional) Whether the nodes will be automatically repaired. Enabled by default. -* `auto_upgrade` - (Optional) Whether the nodes will be automatically upgraded. +* `auto_upgrade` - (Optional) Whether the nodes will be automatically upgraded. Enabled by default. The `network_config` block supports: diff --git a/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown index 4064c913467c..d592b3fdb39c 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown @@ -98,9 +98,13 @@ such as `serviceAccount`, `workerMachineType`, etc can be specified here. * `labels` - (Optional) User labels to be specified for the job. Keys and values should follow the restrictions specified in the [labeling restrictions](https://cloud.google.com/compute/docs/labeling-resources#restrictions) page. -**NOTE**: Google-provided Dataflow templates often provide default labels -that begin with `goog-dataflow-provided`. Unless explicitly set in config, these -labels will be ignored to prevent diffs on re-apply. +**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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `on_delete` - (Optional) One of "drain" or "cancel". Specifies behavior of deletion during `terraform destroy`. See above note. diff --git a/mmv1/third_party/terraform/website/docs/r/dataflow_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataflow_job.html.markdown index 6000b964995a..a3acbcfcaa75 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataflow_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataflow_job.html.markdown @@ -102,8 +102,11 @@ The following arguments are supported: * `parameters` - (Optional) Key/Value pairs to be passed to the Dataflow job (as used in the template). * `labels` - (Optional) User labels to be specified for the job. Keys and values should follow the restrictions specified in the [labeling restrictions](https://cloud.google.com/compute/docs/labeling-resources#restrictions) page. - **NOTE**: Google-provided Dataflow templates often provide default labels that begin with `goog-dataflow-provided`. - Unless explicitly set in config, these labels will be ignored to prevent diffs on re-apply. + **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. +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `transform_name_mapping` - (Optional) Only applicable when updating a pipeline. Map of transform name prefixes of the job to be replaced with the corresponding name prefixes of the new job. This field is not used outside of update. * `max_workers` - (Optional) The number of workers permitted to work on the job. More workers may improve processing speed at additional cost. * `on_delete` - (Optional) One of "drain" or "cancel". Specifies behavior of deletion during `terraform destroy`. See above note. diff --git a/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown index 1aa6310d0b12..e4efda5aa41b 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown @@ -129,7 +129,14 @@ resource "google_dataproc_cluster" "accelerated_cluster" { * `region` - (Optional) The region in which the cluster and associated nodes will be created in. Defaults to `global`. -* `labels` - (Optional, Computed) The list of labels (key/value pairs) to be applied to +* `labels` - (Optional) The list of labels (key/value pairs) configured on the resource through Terraform and to be applied to + instances in the cluster. + **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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - (Computed) The list of labels (key/value pairs) to be applied to instances in the cluster. GCP generates some itself including `goog-dataproc-cluster-name` which is the name of the cluster. diff --git a/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown index 3c8b99fee706..84094a189b4a 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataproc_job.html.markdown @@ -102,6 +102,14 @@ output "pyspark_status" { job is first cancelled before issuing the delete. * `labels` - (Optional) The list of labels (key/value pairs) to add to the job. + **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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `scheduling.max_failures_per_hour` - (Required) Maximum number of times per hour a driver may be restarted as a result of driver exiting with non-zero code before job is reported failed. 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 36f5eb06919c..1f3a4dff8368 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 @@ -82,6 +82,14 @@ The following arguments are supported: without deleting the Project via the Google API. * `labels` - (Optional) 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. + +* `terraform_labels` - + The combination of labels configured directly on the resource and default labels configured on the provider. + +* `effective_labels` - + All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services. * `auto_create_network` - (Optional) Controls whether the 'default' network exists on the project. Defaults to `true`, where it is created. If set to `false`, the default network will still be created by GCP but diff --git a/mmv1/third_party/terraform/website/docs/r/monitoring_dashboard.html.markdown b/mmv1/third_party/terraform/website/docs/r/monitoring_dashboard.html.markdown index b3d0e0dd63b6..97c32f85b993 100644 --- a/mmv1/third_party/terraform/website/docs/r/monitoring_dashboard.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/monitoring_dashboard.html.markdown @@ -114,6 +114,12 @@ The following arguments are supported: The JSON representation of a dashboard, following the format at https://cloud.google.com/monitoring/api/ref_v3/rest/v1/projects.dashboards. The representation of an existing dashboard can be found by using the [API Explorer](https://cloud.google.com/monitoring/api/ref_v3/rest/v1/projects.dashboards/get) + ~> **Warning:** Because this is represented as a JSON string, Terraform doesn't have underlying information to know + which fields in the string have defaults. To prevent permanent diffs from default values, Terraform will attempt to + suppress diffs where the value is returned in the JSON string but doesn't exist in the configuration. Consequently, + legitmate remove-only diffs will also be suppressed. For Terraform to detect the diff, key removals must also be + accompanied by a non-removal change (trivial or not). + - - - diff --git a/mmv1/third_party/tgc/container.go b/mmv1/third_party/tgc/container.go index 86085212e70f..806b64e228b4 100644 --- a/mmv1/third_party/tgc/container.go +++ b/mmv1/third_party/tgc/container.go @@ -47,10 +47,6 @@ func expandContainerClusterEnableLegacyAbac(v interface{}, d tpgresource.Terrafo return expandContainerEnabledObject(v, d, config) } -func expandContainerClusterEnableBinaryAuthorization(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { - return expandContainerEnabledObject(v, d, config) -} - func expandContainerMaxPodsConstraint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { if val := reflect.ValueOf(v); !val.IsValid() || tpgresource.IsEmptyValue(val) { return nil, nil @@ -126,12 +122,6 @@ func GetContainerClusterCaiObject(d tpgresource.TerraformResourceData, config *t func GetContainerClusterApiObject(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]interface{}, error) { obj := make(map[string]interface{}) - binaryAuthorizationProp, err := expandContainerClusterEnableBinaryAuthorization(d.Get("enable_binary_authorization"), d, config) - if err != nil { - return nil, err - } else if v, ok := d.GetOkExists("enable_binary_authorization"); !tpgresource.IsEmptyValue(reflect.ValueOf(binaryAuthorizationProp)) && (ok || !reflect.DeepEqual(v, binaryAuthorizationProp)) { - obj["binaryAuthorization"] = binaryAuthorizationProp - } enableKubernetesAlphaProp, err := expandContainerClusterEnableKubernetesAlpha(d.Get("enable_kubernetes_alpha"), d, config) if err != nil { return nil, err diff --git a/mmv1/third_party/tgc/sql_database_instance.go b/mmv1/third_party/tgc/sql_database_instance.go index 9eba9d623725..add0a43f459c 100644 --- a/mmv1/third_party/tgc/sql_database_instance.go +++ b/mmv1/third_party/tgc/sql_database_instance.go @@ -110,7 +110,7 @@ func expandSqlDatabaseInstanceSettings(configured []interface{}, secondGen bool) PricingPlan: _settings["pricing_plan"].(string), UserLabels: tpgresource.ConvertStringMap(_settings["user_labels"].(map[string]interface{})), BackupConfiguration: expandBackupConfiguration(_settings["backup_configuration"].([]interface{})), - DatabaseFlags: expandDatabaseFlags(_settings["database_flags"].([]interface{})), + DatabaseFlags: expandDatabaseFlags(_settings["database_flags"].(*schema.Set).List()), IpConfiguration: expandIpConfiguration(_settings["ip_configuration"].([]interface{})), LocationPreference: expandLocationPreference(_settings["location_preference"].([]interface{})), MaintenanceWindow: expandMaintenanceWindow(_settings["maintenance_window"].([]interface{})), diff --git a/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.json b/mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.json rename to mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.json diff --git a/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tf b/mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.tf diff --git a/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_access_context_manager_service_perimeter.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.json index c55d9a2c4ee6..a4a2b676db21 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.json @@ -13,12 +13,9 @@ "datasetReference": { "datasetId": "test-dataset" }, - "labels": { - "env": "dev" - }, "location": "EU", "defaultTableExpirationMs": 3.6e+06 } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tfplan.json similarity index 88% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tfplan.json index 9249c8265cf9..75f53ab54889 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset.tfplan.json @@ -18,10 +18,16 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "timeouts": null } @@ -48,10 +54,16 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "timeouts": null }, @@ -59,9 +71,11 @@ "access": true, "creation_time": true, "default_encryption_configuration": [], + "effective_labels": {}, "etag": true, "id": true, "labels": {}, + "terraform_labels": {}, "last_modified_time": true, "project": true, "self_link": true diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.json similarity index 94% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.json index 770149249ec3..475d09d6eed7 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.json @@ -13,9 +13,6 @@ "datasetId": "test-dataset" }, "defaultTableExpirationMs": 3600000, - "labels": { - "env": "dev" - }, "location": "EU", "friendlyName": "" } @@ -32,4 +29,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tfplan.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tfplan.json index d3a1e114db80..057733326a31 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_binding.tfplan.json @@ -17,10 +17,16 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -57,10 +63,16 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -69,9 +81,11 @@ "access": true, "creation_time": true, "default_encryption_configuration": [], + "effective_labels": {}, "etag": true, "id": true, "labels": {}, + "terraform_labels": {}, "last_modified_time": true, "self_link": true } diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.json similarity index 94% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.json index 7aed9ac6ce97..c352a6c27d7e 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.json @@ -13,9 +13,6 @@ "datasetId": "test-dataset" }, "defaultTableExpirationMs": 3600000, - "labels": { - "env": "dev" - }, "location": "EU", "friendlyName": "" } @@ -31,4 +28,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tfplan.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tfplan.json index 5848f267fdd9..45223f402c7c 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_member.tfplan.json @@ -17,10 +17,16 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -57,10 +63,16 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -69,9 +81,11 @@ "access": true, "creation_time": true, "default_encryption_configuration": [], + "effective_labels": {}, "etag": true, "id": true, "labels": {}, + "terraform_labels": {}, "last_modified_time": true, "self_link": true } diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.json similarity index 94% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.json index 5908f8d7600c..610a1d876072 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.json @@ -13,9 +13,6 @@ "datasetId": "test-dataset" }, "defaultTableExpirationMs": 3600000, - "labels": { - "env": "dev" - }, "location": "EU", "friendlyName": "" } @@ -32,4 +29,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tfplan.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tfplan.json index 6a19eeda793f..7885b3b94ef0 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy.tfplan.json @@ -17,10 +17,16 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -55,10 +61,16 @@ "default_table_expiration_ms": 3600000, "delete_contents_on_destroy": false, "description": null, + "effective_labels": { + "env": "dev" + }, "friendly_name": null, "labels": { "env": "dev" }, + "terraform_labels": { + "env": "dev" + }, "location": "EU", "project": "{{.Provider.project}}", "timeouts": null @@ -67,9 +79,11 @@ "access": true, "creation_time": true, "default_encryption_configuration": [], + "effective_labels": {}, "etag": true, "id": true, "labels": {}, + "terraform_labels": {}, "last_modified_time": true, "self_link": true } diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.json diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tf b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.tf diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.json b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.json similarity index 94% rename from mmv1/third_party/tgc/tests/data/example_cloud_run_service.json rename to mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.json index 70c5a7a0e44f..1816a9eedf8a 100644 --- a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.json @@ -12,9 +12,6 @@ "apiVersion": "serving.knative.dev/v1", "kind": "Service", "metadata": { - "annotations": { - "generated-by": "magic-modules" - }, "name": "cloudrun-to-get-cai", "namespace": "{{.Provider.project}}" }, @@ -48,4 +45,4 @@ } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tf b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_cloud_run_service.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tf diff --git a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tfplan.json similarity index 96% rename from mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tfplan.json index 830211d59cad..1adfddbe14c4 100644 --- a/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_cloud_run_service.tfplan.json @@ -19,6 +19,9 @@ "annotations": { "generated-by": "magic-modules" }, + "effective_annotations": { + "generated-by": "magic-modules" + }, "namespace": "{{.Provider.project}}" } ], @@ -86,6 +89,9 @@ "annotations": { "generated-by": "magic-modules" }, + "effective_annotations": { + "generated-by": "magic-modules" + }, "namespace": "{{.Provider.project}}" } ], @@ -134,6 +140,7 @@ "metadata": [ { "annotations": {}, + "effective_annotations": {}, "generation": true, "labels": true, "resource_version": true, diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_compute_disk.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.json index 61a32615a0ac..7e41c7aee5fb 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_disk.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.json @@ -9,9 +9,6 @@ "discovery_name": "Disk", "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { - "labels": { - "environment": "dev" - }, "name": "test-disk", "physicalBlockSizeBytes": 4096, "sourceImage": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", @@ -20,4 +17,4 @@ } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk.tf b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_disk.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tf diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tfplan.json similarity index 90% rename from mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tfplan.json index ebc95b4dca87..e80e5b6ee646 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk.tfplan.json @@ -15,6 +15,9 @@ "description": null, "disk_encryption_key": [], "disk_encryption_key_raw": null, + "effective_labels": { + "environment": "dev" + }, "image": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", "labels": { "environment": "dev" @@ -24,6 +27,9 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": { + "environment": "dev" + }, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -48,6 +54,9 @@ "description": null, "disk_encryption_key": [], "disk_encryption_key_raw": null, + "effective_labels": { + "environment": "dev" + }, "image": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", "labels": { "environment": "dev" @@ -57,6 +66,9 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": { + "environment": "dev" + }, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -65,6 +77,7 @@ "creation_timestamp": true, "disk_encryption_key": [], "disk_encryption_key_sha256": true, + "effective_labels": {}, "id": true, "label_fingerprint": true, "labels": {}, @@ -77,6 +90,7 @@ "source_image_id": true, "source_snapshot_encryption_key": [], "source_snapshot_id": true, + "terraform_labels": {}, "users": true } } diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.json index ce1e0ebe8700..8df2a102df02 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.json @@ -9,9 +9,6 @@ "discovery_name": "Disk", "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { - "labels": { - "environment": "dev" - }, "name": "test-disk", "physicalBlockSizeBytes": 4096, "type": "projects/{{.Provider.project}}/zones/us-central1-a/diskTypes/pd-ssd", @@ -19,4 +16,4 @@ } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tf b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tf diff --git a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tfplan.json similarity index 89% rename from mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tfplan.json index e44bdfa8c85c..bd8ebb490d6f 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_disk_empty_image.tfplan.json @@ -15,6 +15,9 @@ "description": null, "disk_encryption_key": [], "disk_encryption_key_raw": null, + "effective_labels": { + "environment": "dev" + }, "image": "", "labels": { "environment": "dev" @@ -24,6 +27,9 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": { + "environment": "dev" + }, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -48,6 +54,9 @@ "description": null, "disk_encryption_key": [], "disk_encryption_key_raw": null, + "effective_labels": { + "environment": "dev" + }, "image": "", "labels": { "environment": "dev" @@ -57,6 +66,9 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": { + "environment": "dev" + }, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -65,6 +77,7 @@ "creation_timestamp": true, "disk_encryption_key": [], "disk_encryption_key_sha256": true, + "effective_labels": {}, "id": true, "label_fingerprint": true, "labels": {}, @@ -77,6 +90,7 @@ "source_image_id": true, "source_snapshot_encryption_key": [], "source_snapshot_id": true, + "terraform_labels": {}, "users": true } } diff --git a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.json similarity index 95% rename from mmv1/third_party/tgc/tests/data/example_compute_snapshot.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.json index dc1590f5f74c..2b42e398093b 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.json @@ -9,9 +9,6 @@ "discovery_name": "Snapshot", "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { - "labels": { - "test-name": "test-value" - }, "name": "test-instance", "sourceDisk": "projects/{{.Provider.project}}/zones/us-central1-a/disks/debian-disk", "storageLocations": [ @@ -39,4 +36,4 @@ } } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tf b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_compute_snapshot.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tf diff --git a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tfplan.json similarity index 90% rename from mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tfplan.json index 18c079b12317..4f1e403b2434 100644 --- a/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_compute_snapshot.tfplan.json @@ -14,6 +14,7 @@ "values": { "description": null, "disk_encryption_key": [], + "effective_labels": null, "image": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", "labels": null, "name": "debian-disk", @@ -22,6 +23,7 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": null, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -42,6 +44,9 @@ "schema_version": 0, "values": { "description": null, + "effective_labels": { + "test-name": "test-value" + }, "labels": { "test-name": "test-value" }, @@ -52,17 +57,22 @@ "storage_locations": [ "us-central1" ], + "terraform_labels": { + "test-name": "test-value" + }, "timeouts": null, "zone": "us-central1-a" }, "sensitive_values": { + "effective_labels": {}, "labels": {}, "licenses": [], "snapshot_encryption_key": [], "source_disk_encryption_key": [], "storage_locations": [ false - ] + ], + "terraform_labels": {} } } ] @@ -83,6 +93,7 @@ "after": { "description": null, "disk_encryption_key": [], + "effective_labels": null, "image": "projects/debian-cloud/global/images/debian-8-jessie-v20170523", "labels": null, "name": "debian-disk", @@ -91,6 +102,7 @@ "snapshot": null, "source_image_encryption_key": [], "source_snapshot_encryption_key": [], + "terraform_labels": null, "timeouts": null, "type": "pd-ssd", "zone": "us-central1-a" @@ -133,6 +145,9 @@ "before": null, "after": { "description": null, + "effective_labels": { + "test-name": "test-value" + }, "labels": { "test-name": "test-value" }, @@ -143,12 +158,16 @@ "storage_locations": [ "us-central1" ], + "terraform_labels": { + "test-name": "test-value" + }, "timeouts": null, "zone": "us-central1-a" }, "after_unknown": { "creation_timestamp": true, "disk_size_gb": true, + "effective_labels": {}, "id": true, "label_fingerprint": true, "labels": {}, @@ -161,17 +180,20 @@ "storage_bytes": true, "storage_locations": [ false - ] + ], + "terraform_labels": {} }, "before_sensitive": false, "after_sensitive": { + "effective_labels": {}, "labels": {}, "licenses": [], "snapshot_encryption_key": [], "source_disk_encryption_key": [], "storage_locations": [ false - ] + ], + "terraform_labels": {} } } } diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.json index f883358d426c..975dba182166 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.json @@ -14,9 +14,6 @@ "expirationPolicy": { "ttl": "300000.5s" }, - "labels": { - "test-label2": "test-value2" - }, "messageRetentionDuration": "1200s", "retainAckedMessages": true, "retryPolicy": { @@ -39,9 +36,6 @@ "ackDeadlineSeconds": 20, "deadLetterPolicy": null, "expirationPolicy": null, - "labels": { - "test-label1": "test-value1" - }, "messageRetentionDuration": "604800s", "pushConfig": { "pushEndpoint": "https://example.com/push" diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tfplan.json similarity index 89% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tfplan.json index 28b2fa772da3..16cacd39e9bb 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription.tfplan.json @@ -14,6 +14,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label2": "test-value2" + }, "enable_message_ordering": false, "expiration_policy": [ { @@ -33,6 +36,9 @@ "minimum_backoff": "10s" } ], + "terraform_labels": { + "test-label2": "test-value2" + }, "timeouts": null, "topic": "example-pubsub-topic" } @@ -47,6 +53,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -63,6 +72,9 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" } @@ -85,6 +97,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label2": "test-value2" + }, "enable_message_ordering": false, "expiration_policy": [ { @@ -104,11 +119,15 @@ "minimum_backoff": "10s" } ], + "terraform_labels": { + "test-label2": "test-value2" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": [ {} ], @@ -121,7 +140,8 @@ { "maximum_backoff": true } - ] + ], + "terraform_labels": {} } } }, @@ -139,6 +159,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -155,11 +178,15 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label2": "test-value2" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": true, "id": true, "labels": {}, @@ -170,7 +197,8 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} } } } diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.json index de0fda73b41b..8780c890de23 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.json @@ -12,9 +12,6 @@ "ackDeadlineSeconds": 20, "deadLetterPolicy": null, "expirationPolicy": null, - "labels": { - "test-label1": "test-value1" - }, "messageRetentionDuration": "604800s", "pushConfig": { "pushEndpoint": "https://example.com/push" @@ -33,4 +30,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tfplan.json similarity index 92% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tfplan.json index 0a730e6b809e..2de05102765e 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_binding.tfplan.json @@ -14,6 +14,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -30,6 +33,9 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, @@ -85,6 +91,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -101,11 +110,15 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": true, "id": true, "labels": {}, @@ -115,11 +128,13 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} }, "before_sensitive": false, "after_sensitive": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": [], "labels": {}, "push_config": [ @@ -127,7 +142,8 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} } } }, diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.json index de0fda73b41b..8780c890de23 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.json @@ -12,9 +12,6 @@ "ackDeadlineSeconds": 20, "deadLetterPolicy": null, "expirationPolicy": null, - "labels": { - "test-label1": "test-value1" - }, "messageRetentionDuration": "604800s", "pushConfig": { "pushEndpoint": "https://example.com/push" @@ -33,4 +30,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tfplan.json similarity index 91% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tfplan.json index 691e23ba6c4c..292f2c542161 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_member.tfplan.json @@ -14,6 +14,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -30,6 +33,9 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, @@ -80,6 +86,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -96,11 +105,15 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": true, "id": true, "labels": {}, @@ -110,11 +123,13 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} }, "before_sensitive": false, "after_sensitive": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": [], "labels": {}, "push_config": [ @@ -122,7 +137,8 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} } } }, diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.json similarity index 93% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.json index de0fda73b41b..8780c890de23 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.json @@ -12,9 +12,6 @@ "ackDeadlineSeconds": 20, "deadLetterPolicy": null, "expirationPolicy": null, - "labels": { - "test-label1": "test-value1" - }, "messageRetentionDuration": "604800s", "pushConfig": { "pushEndpoint": "https://example.com/push" @@ -33,4 +30,4 @@ ] } } -] +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tfplan.json similarity index 91% rename from mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tfplan.json index 281258b9501e..94478b15fee2 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_subscription_iam_policy.tfplan.json @@ -14,6 +14,9 @@ "values": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -30,6 +33,9 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, @@ -76,6 +82,9 @@ "after": { "ack_deadline_seconds": 20, "dead_letter_policy": [], + "effective_labels": { + "test-label1": "test-value1" + }, "enable_message_ordering": null, "filter": null, "labels": { @@ -92,11 +101,15 @@ ], "retain_acked_messages": null, "retry_policy": [], + "terraform_labels": { + "test-label1": "test-value1" + }, "timeouts": null, "topic": "example-pubsub-topic" }, "after_unknown": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": true, "id": true, "labels": {}, @@ -106,11 +119,13 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} }, "before_sensitive": false, "after_sensitive": { "dead_letter_policy": [], + "effective_labels": {}, "expiration_policy": [], "labels": {}, "push_config": [ @@ -118,7 +133,8 @@ "oidc_token": [] } ], - "retry_policy": [] + "retry_policy": [], + "terraform_labels": {} } } }, diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.json similarity index 90% rename from mmv1/third_party/tgc/tests/data/example_pubsub_topic.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.json index 03f0436f9d32..d51df4736115 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.json @@ -10,9 +10,6 @@ "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { "kmsKeyName": "projects/{{.Provider.project}}/locations/australia-southeast1/keyRings/default_kms_keyring_name/cryptoKeys/default_kms_key_name", - "labels": { - "test-key": "test-value" - }, "messageStoragePolicy": { "allowedPersistenceRegions": [ "australia-southeast1" diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tf b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_pubsub_topic.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tf diff --git a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tfplan.json similarity index 89% rename from mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tfplan.json index ec75e9e92203..740f394fc1b9 100644 --- a/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/example_pubsub_topic.tfplan.json @@ -12,6 +12,9 @@ "provider_name": "registry.terraform.io/hashicorp/google", "schema_version": 0, "values": { + "effective_labels": { + "test-key": "test-value" + }, "kms_key_name": "projects/{{.Provider.project}}/locations/australia-southeast1/keyRings/default_kms_keyring_name/cryptoKeys/default_kms_key_name", "labels": { "test-key": "test-value" @@ -25,6 +28,9 @@ ], "name": "test", "project": "{{.Provider.project}}", + "terraform_labels": { + "test-key": "test-value" + }, "timeouts": null } } @@ -44,6 +50,9 @@ ], "before": null, "after": { + "effective_labels": { + "test-key": "test-value" + }, "kms_key_name": "projects/{{.Provider.project}}/locations/australia-southeast1/keyRings/default_kms_keyring_name/cryptoKeys/default_kms_key_name", "labels": { "test-key": "test-value" @@ -57,9 +66,13 @@ ], "name": "test", "project": "{{.Provider.project}}", + "terraform_labels": { + "test-key": "test-value" + }, "timeouts": null }, "after_unknown": { + "effective_labels": {}, "id": true, "labels": {}, "message_storage_policy": [ @@ -68,7 +81,8 @@ false ] } - ] + ], + "terraform_labels": {} } } } diff --git a/mmv1/third_party/tgc/tests/data/example_sql_database_instance.json b/mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_sql_database_instance.json rename to mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.json diff --git a/mmv1/third_party/tgc/tests/data/example_sql_database_instance.tf b/mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_sql_database_instance.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.tf diff --git a/mmv1/third_party/tgc/tests/data/example_sql_database_instance.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/example_sql_database_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_sql_database_instance.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.json b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.json new file mode 100644 index 000000000000..44bdf373c50d --- /dev/null +++ b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.json @@ -0,0 +1,21 @@ +[ + { + "name": "//spanner.googleapis.com/projects/{{.Provider.project}}/instances/spanner-instance", + "asset_type": "spanner.googleapis.com/Instance", + "ancestry_path": "{{.Ancestry}}/project/{{.Provider.project}}", + "resource": { + "version": "v1", + "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/spanner/v1/rest", + "discovery_name": "Instance", + "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", + "data": { + "instance": { + "config": "projects/{{.Provider.project}}/instanceConfigs/regional-us-central1", + "displayName": "spanner-instance", + "nodeCount": 1 + }, + "instanceId": "spanner-instance" + } + } + } +] \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/full_spanner_instance.tf b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_spanner_instance.tf rename to mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tf diff --git a/mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tfplan.json similarity index 79% rename from mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tfplan.json index ead499d7a4eb..ba82885d114d 100644 --- a/mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json +++ b/mmv1/third_party/tgc/tests/data-ignored/full_spanner_instance.tfplan.json @@ -14,6 +14,11 @@ "values": { "config": "regional-us-central1", "display_name": "spanner-instance", + "effective_labels": { + "label1": "value1", + "label2": "value2", + "label3": "value3" + }, "force_destroy": false, "labels": { "label1": "value1", @@ -22,6 +27,11 @@ }, "name": "spanner-instance", "num_nodes": 1, + "terraform_labels": { + "label1": "value1", + "label2": "value2", + "label3": "value3" + }, "timeouts": null } } @@ -43,6 +53,11 @@ "after": { "config": "regional-us-central1", "display_name": "spanner-instance", + "effective_labels": { + "label1": "value1", + "label2": "value2", + "label3": "value3" + }, "force_destroy": false, "labels": { "label1": "value1", @@ -51,13 +66,20 @@ }, "name": "spanner-instance", "num_nodes": 1, + "terraform_labels": { + "label1": "value1", + "label2": "value2", + "label3": "value3" + }, "timeouts": null }, "after_unknown": { + "effective_labels": {}, "id": true, "labels": {}, "project": true, - "state": true + "state": true, + "terraform_labels": {} } } } diff --git a/mmv1/third_party/tgc/tests/data/full_sql_database_instance.json b/mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_sql_database_instance.json rename to mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.json diff --git a/mmv1/third_party/tgc/tests/data/full_sql_database_instance.tf b/mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.tf similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_sql_database_instance.tf rename to mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.tf diff --git a/mmv1/third_party/tgc/tests/data/full_sql_database_instance.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.tfplan.json similarity index 100% rename from mmv1/third_party/tgc/tests/data/full_sql_database_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/full_sql_database_instance.tfplan.json diff --git a/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json b/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json index 998e197fae0d..1f54b16a9b4e 100644 --- a/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json @@ -13,7 +13,6 @@ "schema_version": 1, "values": { "description": null, - "enable_binary_authorization": false, "enable_intranode_visibility": null, "enable_kubernetes_alpha": false, "enable_legacy_abac": false, @@ -98,7 +97,6 @@ "before": null, "after": { "description": null, - "enable_binary_authorization": false, "enable_intranode_visibility": null, "enable_kubernetes_alpha": false, "enable_legacy_abac": false, @@ -344,4 +342,4 @@ ] } } -} +} \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/full_container_cluster.tf b/mmv1/third_party/tgc/tests/data/full_container_cluster.tf index fe7966114c5e..b43baca7f928 100644 --- a/mmv1/third_party/tgc/tests/data/full_container_cluster.tf +++ b/mmv1/third_party/tgc/tests/data/full_container_cluster.tf @@ -36,7 +36,6 @@ resource "google_container_cluster" "full_list_default_1" { # authenticator_groups_config # cluster_autoscaling # database_encryption - # enable_binary_authorization # enable_intranode_visibility # enable_shielded_nodes # enable_tpu diff --git a/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json b/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json index a9370d3d5cc1..f7074cc4d604 100644 --- a/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json +++ b/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json @@ -34,7 +34,6 @@ "default_max_pods_per_node": 42, "description": "test-description", "enable_autopilot": null, - "enable_binary_authorization": false, "enable_kubernetes_alpha": true, "enable_legacy_abac": true, "enable_shielded_nodes": true, @@ -277,7 +276,6 @@ "default_max_pods_per_node": 42, "description": "test-description", "enable_autopilot": null, - "enable_binary_authorization": false, "enable_kubernetes_alpha": true, "enable_legacy_abac": true, "enable_shielded_nodes": true, @@ -815,4 +813,4 @@ ] } } -} +} \ No newline at end of file diff --git a/mmv1/third_party/tgc/tests/data/full_spanner_instance.json b/mmv1/third_party/tgc/tests/data/full_spanner_instance.json deleted file mode 100644 index af1e69cebd46..000000000000 --- a/mmv1/third_party/tgc/tests/data/full_spanner_instance.json +++ /dev/null @@ -1,26 +0,0 @@ -[ -{ - "name": "//spanner.googleapis.com/projects/{{.Provider.project}}/instances/spanner-instance", - "asset_type": "spanner.googleapis.com/Instance", - "ancestry_path": "{{.Ancestry}}/project/{{.Provider.project}}", - "resource": { - "version": "v1", - "discovery_document_uri": "https://www.googleapis.com/discovery/v1/apis/spanner/v1/rest", - "discovery_name": "Instance", - "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", - "data": { - "instance": { - "config": "projects/{{.Provider.project}}/instanceConfigs/regional-us-central1", - "displayName": "spanner-instance", - "labels": { - "label1": "value1", - "label2": "value2", - "label3": "value3" - }, - "nodeCount": 1 - }, - "instanceId": "spanner-instance" - } - } -} -] diff --git a/tpgtools/go.mod b/tpgtools/go.mod index edb1c068553e..07832d3e80b4 100644 --- a/tpgtools/go.mod +++ b/tpgtools/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( bitbucket.org/creachadair/stringset v0.0.11 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0 github.com/golang/glog v1.1.2 github.com/hashicorp/errwrap v1.0.0 github.com/hashicorp/hcl v1.0.0 diff --git a/tpgtools/go.sum b/tpgtools/go.sum index e0e118ffa9fc..981174d17fd5 100644 --- a/tpgtools/go.sum +++ b/tpgtools/go.sum @@ -45,6 +45,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 h1:YhWTPhOf6gVpA9mSfnLOuL8Y6j8W5pzmHE7flXjTke4= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0 h1:KswxXF4E5iWv2ggktqv265zOvwmXA3mgma3UQfYA4tU= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.52.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= diff --git a/tpgtools/handwritten/tpgtools_utils.go b/tpgtools/handwritten/tpgtools_utils.go index 68fa33e1d0e7..2e60238e3daa 100644 --- a/tpgtools/handwritten/tpgtools_utils.go +++ b/tpgtools/handwritten/tpgtools_utils.go @@ -1,6 +1,7 @@ package tpgdclresource import ( + "context" "fmt" "log" @@ -24,3 +25,24 @@ func HandleNotFoundDCLError(err error, d *schema.ResourceData, resourceName stri return errwrap.Wrapf( fmt.Sprintf("Error when reading or editing %s: {{err}}", resourceName), err) } + +func ResourceContainerAwsNodePoolCustomizeDiffFunc(_ context.Context, diff *schema.ResourceDiff, meta interface{}) error { + count := diff.Get("update_settings.#").(int) + if count < 1 { + return nil + } + + oMaxSurge, nMaxSurge := diff.GetChange("update_settings.0.surge_settings.0.max_surge") + oMaxUnavailable, nMaxUnavailable := diff.GetChange("update_settings.0.surge_settings.0.max_unavailable") + + // Server default of maxSurge = 1 and maxUnavailable = 0 is not returned + // Clear the diff if trying to resolve these specific values + if oMaxSurge == 0 && nMaxSurge == 1 && oMaxUnavailable == 0 && nMaxUnavailable == 0 { + err := diff.Clear("update_settings") + if err != nil { + return err + } + } + + return nil +} diff --git a/tpgtools/overrides/apikeys/beta/key.yaml b/tpgtools/overrides/apikeys/beta/key.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/apikeys/beta/key.yaml +++ b/tpgtools/overrides/apikeys/beta/key.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/apikeys/key.yaml b/tpgtools/overrides/apikeys/key.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/apikeys/key.yaml +++ b/tpgtools/overrides/apikeys/key.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/bigqueryreservation/assignment.yaml b/tpgtools/overrides/bigqueryreservation/assignment.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/bigqueryreservation/assignment.yaml +++ b/tpgtools/overrides/bigqueryreservation/assignment.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/bigqueryreservation/beta/assignment.yaml b/tpgtools/overrides/bigqueryreservation/beta/assignment.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/bigqueryreservation/beta/assignment.yaml +++ b/tpgtools/overrides/bigqueryreservation/beta/assignment.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuild/beta/worker_pool.yaml b/tpgtools/overrides/cloudbuild/beta/worker_pool.yaml index 4deb00daaee1..8c8073b08ca5 100644 --- a/tpgtools/overrides/cloudbuild/beta/worker_pool.yaml +++ b/tpgtools/overrides/cloudbuild/beta/worker_pool.yaml @@ -4,3 +4,7 @@ diffsuppressfunc: tpgresource.CompareResourceNames - type: EXCLUDE field: etag +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuild/worker_pool.yaml b/tpgtools/overrides/cloudbuild/worker_pool.yaml index 4deb00daaee1..8c8073b08ca5 100644 --- a/tpgtools/overrides/cloudbuild/worker_pool.yaml +++ b/tpgtools/overrides/cloudbuild/worker_pool.yaml @@ -4,3 +4,7 @@ diffsuppressfunc: tpgresource.CompareResourceNames - type: EXCLUDE field: etag +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuildv2/beta/connection.yaml b/tpgtools/overrides/cloudbuildv2/beta/connection.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/cloudbuildv2/beta/connection.yaml +++ b/tpgtools/overrides/cloudbuildv2/beta/connection.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuildv2/beta/repository.yaml b/tpgtools/overrides/cloudbuildv2/beta/repository.yaml index 01ea7c579c97..8de5a79b7fc7 100644 --- a/tpgtools/overrides/cloudbuildv2/beta/repository.yaml +++ b/tpgtools/overrides/cloudbuildv2/beta/repository.yaml @@ -16,3 +16,7 @@ required: false optional: true computed: true +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuildv2/connection.yaml b/tpgtools/overrides/cloudbuildv2/connection.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/cloudbuildv2/connection.yaml +++ b/tpgtools/overrides/cloudbuildv2/connection.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/cloudbuildv2/repository.yaml b/tpgtools/overrides/cloudbuildv2/repository.yaml index 01ea7c579c97..8de5a79b7fc7 100644 --- a/tpgtools/overrides/cloudbuildv2/repository.yaml +++ b/tpgtools/overrides/cloudbuildv2/repository.yaml @@ -16,3 +16,7 @@ required: false optional: true computed: true +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/clouddeploy/beta/delivery_pipeline.yaml b/tpgtools/overrides/clouddeploy/beta/delivery_pipeline.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/clouddeploy/beta/delivery_pipeline.yaml +++ b/tpgtools/overrides/clouddeploy/beta/delivery_pipeline.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/clouddeploy/beta/target.yaml b/tpgtools/overrides/clouddeploy/beta/target.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/clouddeploy/beta/target.yaml +++ b/tpgtools/overrides/clouddeploy/beta/target.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/clouddeploy/delivery_pipeline.yaml b/tpgtools/overrides/clouddeploy/delivery_pipeline.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/clouddeploy/delivery_pipeline.yaml +++ b/tpgtools/overrides/clouddeploy/delivery_pipeline.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/clouddeploy/target.yaml b/tpgtools/overrides/clouddeploy/target.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/clouddeploy/target.yaml +++ b/tpgtools/overrides/clouddeploy/target.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/beta/firewall_policy.yaml b/tpgtools/overrides/compute/beta/firewall_policy.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/beta/firewall_policy.yaml +++ b/tpgtools/overrides/compute/beta/firewall_policy.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/beta/firewall_policy_association.yaml b/tpgtools/overrides/compute/beta/firewall_policy_association.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/beta/firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/beta/firewall_policy_association.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/beta/firewall_policy_rule.yaml b/tpgtools/overrides/compute/beta/firewall_policy_rule.yaml index e743d253be12..dc91e4f5a9d5 100644 --- a/tpgtools/overrides/compute/beta/firewall_policy_rule.yaml +++ b/tpgtools/overrides/compute/beta/firewall_policy_rule.yaml @@ -2,3 +2,7 @@ field: target_resources details: diffsuppressfunc: tpgresource.CompareSelfLinkOrResourceName +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/beta/network_firewall_policy.yaml b/tpgtools/overrides/compute/beta/network_firewall_policy.yaml index ac4ed8505f0c..ea763ef1b90d 100644 --- a/tpgtools/overrides/compute/beta/network_firewall_policy.yaml +++ b/tpgtools/overrides/compute/beta/network_firewall_policy.yaml @@ -15,3 +15,8 @@ details: id: projects/{{project}}/regions/{{region}}/firewallPolicies/{{name}} location: region +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/beta/network_firewall_policy_association.yaml b/tpgtools/overrides/compute/beta/network_firewall_policy_association.yaml index 8919dd2c7cf8..3260bc51a574 100644 --- a/tpgtools/overrides/compute/beta/network_firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/beta/network_firewall_policy_association.yaml @@ -31,3 +31,8 @@ - "projects/{{project}}/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}" - "{{project}}/{{firewall_policy}}/{{name}}" location: global +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/beta/network_firewall_policy_rule.yaml b/tpgtools/overrides/compute/beta/network_firewall_policy_rule.yaml index 6c0153011095..4ad5ccbeee34 100644 --- a/tpgtools/overrides/compute/beta/network_firewall_policy_rule.yaml +++ b/tpgtools/overrides/compute/beta/network_firewall_policy_rule.yaml @@ -17,3 +17,8 @@ details: id: projects/{{project}}/regions/{{region}}/firewallPolicies/{{firewall_policy}}/{{priority}} location: region +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/firewall_policy.yaml b/tpgtools/overrides/compute/firewall_policy.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/firewall_policy.yaml +++ b/tpgtools/overrides/compute/firewall_policy.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/firewall_policy_association.yaml b/tpgtools/overrides/compute/firewall_policy_association.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/compute/firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/firewall_policy_association.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/firewall_policy_rule.yaml b/tpgtools/overrides/compute/firewall_policy_rule.yaml index e743d253be12..dc91e4f5a9d5 100644 --- a/tpgtools/overrides/compute/firewall_policy_rule.yaml +++ b/tpgtools/overrides/compute/firewall_policy_rule.yaml @@ -2,3 +2,7 @@ field: target_resources details: diffsuppressfunc: tpgresource.CompareSelfLinkOrResourceName +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/compute/network_firewall_policy.yaml b/tpgtools/overrides/compute/network_firewall_policy.yaml index ac4ed8505f0c..ea763ef1b90d 100644 --- a/tpgtools/overrides/compute/network_firewall_policy.yaml +++ b/tpgtools/overrides/compute/network_firewall_policy.yaml @@ -15,3 +15,8 @@ details: id: projects/{{project}}/regions/{{region}}/firewallPolicies/{{name}} location: region +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/network_firewall_policy_association.yaml b/tpgtools/overrides/compute/network_firewall_policy_association.yaml index 8919dd2c7cf8..3260bc51a574 100644 --- a/tpgtools/overrides/compute/network_firewall_policy_association.yaml +++ b/tpgtools/overrides/compute/network_firewall_policy_association.yaml @@ -31,3 +31,8 @@ - "projects/{{project}}/global/firewallPolicies/{{firewall_policy}}/associations/{{name}}" - "{{project}}/{{firewall_policy}}/{{name}}" location: global +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/compute/network_firewall_policy_rule.yaml b/tpgtools/overrides/compute/network_firewall_policy_rule.yaml index 6c0153011095..4ad5ccbeee34 100644 --- a/tpgtools/overrides/compute/network_firewall_policy_rule.yaml +++ b/tpgtools/overrides/compute/network_firewall_policy_rule.yaml @@ -17,3 +17,8 @@ details: id: projects/{{project}}/regions/{{region}}/firewallPolicies/{{firewall_policy}}/{{priority}} location: region +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgresource.DefaultProviderRegion diff --git a/tpgtools/overrides/containeraws/beta/cluster.yaml b/tpgtools/overrides/containeraws/beta/cluster.yaml index 94133162675a..534584d856d3 100644 --- a/tpgtools/overrides/containeraws/beta/cluster.yaml +++ b/tpgtools/overrides/containeraws/beta/cluster.yaml @@ -3,6 +3,10 @@ - type: NO_SWEEPER - type: EXCLUDE field: monitoring_config +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: control_plane.root_volume.volume_type details: diff --git a/tpgtools/overrides/containeraws/beta/node_pool.yaml b/tpgtools/overrides/containeraws/beta/node_pool.yaml index e3742c97ecf1..9a25ea0089a2 100644 --- a/tpgtools/overrides/containeraws/beta/node_pool.yaml +++ b/tpgtools/overrides/containeraws/beta/node_pool.yaml @@ -1,3 +1,8 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject + - tpgdclresource.ResourceContainerAwsNodePoolCustomizeDiffFunc - type: DIFF_SUPPRESS_FUNC field: config.root_volume.volume_type details: diff --git a/tpgtools/overrides/containeraws/cluster.yaml b/tpgtools/overrides/containeraws/cluster.yaml index 5a8e72bbad15..5db8bc4d3ede 100644 --- a/tpgtools/overrides/containeraws/cluster.yaml +++ b/tpgtools/overrides/containeraws/cluster.yaml @@ -1,6 +1,10 @@ # GKE MultiCloud uses a different set of locations than GCE, and our default # sweeper logic assumes that resources are in us-central1. - type: NO_SWEEPER +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: control_plane.root_volume.volume_type details: diff --git a/tpgtools/overrides/containeraws/node_pool.yaml b/tpgtools/overrides/containeraws/node_pool.yaml index bb9479ee716e..f94cbca06d97 100644 --- a/tpgtools/overrides/containeraws/node_pool.yaml +++ b/tpgtools/overrides/containeraws/node_pool.yaml @@ -1,3 +1,7 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: config.root_volume.volume_type details: diff --git a/tpgtools/overrides/containeraws/samples/cluster/beta_basic_enum_update.tf.tmpl b/tpgtools/overrides/containeraws/samples/cluster/beta_basic_enum_update.tf.tmpl index e77928ece260..73b33d002742 100644 --- a/tpgtools/overrides/containeraws/samples/cluster/beta_basic_enum_update.tf.tmpl +++ b/tpgtools/overrides/containeraws/samples/cluster/beta_basic_enum_update.tf.tmpl @@ -14,6 +14,10 @@ resource "google_container_aws_cluster" "primary" { aws_region = "{{aws_region}}" + binary_authorization { + evaluation_mode = "PROJECT_SINGLETON_POLICY_ENFORCE" + } + control_plane { aws_services_authentication { role_arn = "arn:aws:iam::{{aws_account_id}}:role/{{byo_multicloud_prefix}}-1p-dev-oneplatform" diff --git a/tpgtools/overrides/containeraws/samples/nodepool/beta_basic.tf.tmpl b/tpgtools/overrides/containeraws/samples/nodepool/beta_basic.tf.tmpl index cc4db2389621..48e57734a938 100644 --- a/tpgtools/overrides/containeraws/samples/nodepool/beta_basic.tf.tmpl +++ b/tpgtools/overrides/containeraws/samples/nodepool/beta_basic.tf.tmpl @@ -159,6 +159,13 @@ resource "google_container_aws_node_pool" "primary" { label-one = "value-one" } + update_settings { + surge_settings { + max_surge = 1 + max_unavailable = 0 + } + } + project = "{{project}}" } diff --git a/tpgtools/overrides/containeraws/samples/nodepool/beta_basic_update.tf.tmpl b/tpgtools/overrides/containeraws/samples/nodepool/beta_basic_update.tf.tmpl index 42d8c055dbef..1afdb2e909b1 100644 --- a/tpgtools/overrides/containeraws/samples/nodepool/beta_basic_update.tf.tmpl +++ b/tpgtools/overrides/containeraws/samples/nodepool/beta_basic_update.tf.tmpl @@ -158,6 +158,13 @@ resource "google_container_aws_node_pool" "primary" { label-two = "value-two" } + update_settings { + surge_settings { + max_surge = 1 + max_unavailable = 0 + } + } + project = "{{project}}" } diff --git a/tpgtools/overrides/containerazure/azure_client.yaml b/tpgtools/overrides/containerazure/azure_client.yaml index 6c130fe26fab..a3c82651a742 100644 --- a/tpgtools/overrides/containerazure/azure_client.yaml +++ b/tpgtools/overrides/containerazure/azure_client.yaml @@ -1,3 +1,7 @@ # GKE MultiCloud uses a different set of locations than GCE, and our default # sweeper logic assumes that resources are in us-central1. - type: NO_SWEEPER +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/containerazure/beta/azure_client.yaml b/tpgtools/overrides/containerazure/beta/azure_client.yaml index 6c130fe26fab..a3c82651a742 100644 --- a/tpgtools/overrides/containerazure/beta/azure_client.yaml +++ b/tpgtools/overrides/containerazure/beta/azure_client.yaml @@ -1,3 +1,7 @@ # GKE MultiCloud uses a different set of locations than GCE, and our default # sweeper logic assumes that resources are in us-central1. - type: NO_SWEEPER +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/containerazure/beta/cluster.yaml b/tpgtools/overrides/containerazure/beta/cluster.yaml index f4e3a091bafc..c3ce9bb16b32 100644 --- a/tpgtools/overrides/containerazure/beta/cluster.yaml +++ b/tpgtools/overrides/containerazure/beta/cluster.yaml @@ -3,6 +3,10 @@ - type: NO_SWEEPER - type: EXCLUDE field: monitoring_config +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject - type: DIFF_SUPPRESS_FUNC field: logging_config.component_config.enable_components details: diff --git a/tpgtools/overrides/containerazure/beta/node_pool.yaml b/tpgtools/overrides/containerazure/beta/node_pool.yaml index 62a7815cb0d4..7455aaf975dc 100644 --- a/tpgtools/overrides/containerazure/beta/node_pool.yaml +++ b/tpgtools/overrides/containerazure/beta/node_pool.yaml @@ -12,3 +12,7 @@ details: optional: true computed: true +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/containerazure/cluster.yaml b/tpgtools/overrides/containerazure/cluster.yaml index 6c130fe26fab..a3c82651a742 100644 --- a/tpgtools/overrides/containerazure/cluster.yaml +++ b/tpgtools/overrides/containerazure/cluster.yaml @@ -1,3 +1,7 @@ # GKE MultiCloud uses a different set of locations than GCE, and our default # sweeper logic assumes that resources are in us-central1. - type: NO_SWEEPER +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/containerazure/node_pool.yaml b/tpgtools/overrides/containerazure/node_pool.yaml index 62a7815cb0d4..7455aaf975dc 100644 --- a/tpgtools/overrides/containerazure/node_pool.yaml +++ b/tpgtools/overrides/containerazure/node_pool.yaml @@ -12,3 +12,7 @@ details: optional: true computed: true +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/asset.yaml b/tpgtools/overrides/dataplex/asset.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/asset.yaml +++ b/tpgtools/overrides/dataplex/asset.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/beta/asset.yaml b/tpgtools/overrides/dataplex/beta/asset.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/beta/asset.yaml +++ b/tpgtools/overrides/dataplex/beta/asset.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/beta/lake.yaml b/tpgtools/overrides/dataplex/beta/lake.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/beta/lake.yaml +++ b/tpgtools/overrides/dataplex/beta/lake.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/beta/zone.yaml b/tpgtools/overrides/dataplex/beta/zone.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/beta/zone.yaml +++ b/tpgtools/overrides/dataplex/beta/zone.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/lake.yaml b/tpgtools/overrides/dataplex/lake.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/lake.yaml +++ b/tpgtools/overrides/dataplex/lake.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataplex/samples/asset/basic_asset.tf.tmpl b/tpgtools/overrides/dataplex/samples/asset/basic_asset.tf.tmpl index 07c9141bb937..d3f18d1990dd 100644 --- a/tpgtools/overrides/dataplex/samples/asset/basic_asset.tf.tmpl +++ b/tpgtools/overrides/dataplex/samples/asset/basic_asset.tf.tmpl @@ -52,6 +52,12 @@ resource "google_dataplex_asset" "primary" { name = "projects/{{project}}/buckets/{{bucket}}" type = "STORAGE_BUCKET" } + + labels = { + env = "foo" + my-asset = "exists" + } + project = "{{project}}" depends_on = [ diff --git a/tpgtools/overrides/dataplex/zone.yaml b/tpgtools/overrides/dataplex/zone.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/dataplex/zone.yaml +++ b/tpgtools/overrides/dataplex/zone.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataproc/beta/workflow_template.yaml b/tpgtools/overrides/dataproc/beta/workflow_template.yaml index a0cea3403c87..da6b1fa0e6ad 100644 --- a/tpgtools/overrides/dataproc/beta/workflow_template.yaml +++ b/tpgtools/overrides/dataproc/beta/workflow_template.yaml @@ -9,3 +9,7 @@ details: message: >- version is not useful as a configurable field, and will be removed in the future. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/dataproc/workflow_template.yaml b/tpgtools/overrides/dataproc/workflow_template.yaml index a0cea3403c87..da6b1fa0e6ad 100644 --- a/tpgtools/overrides/dataproc/workflow_template.yaml +++ b/tpgtools/overrides/dataproc/workflow_template.yaml @@ -9,3 +9,7 @@ details: message: >- version is not useful as a configurable field, and will be removed in the future. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/beta/channel.yaml b/tpgtools/overrides/eventarc/beta/channel.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/eventarc/beta/channel.yaml +++ b/tpgtools/overrides/eventarc/beta/channel.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/beta/google_channel_config.yaml b/tpgtools/overrides/eventarc/beta/google_channel_config.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/eventarc/beta/google_channel_config.yaml +++ b/tpgtools/overrides/eventarc/beta/google_channel_config.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/beta/trigger.yaml b/tpgtools/overrides/eventarc/beta/trigger.yaml index 2b02fd09b9ce..9014b1241575 100644 --- a/tpgtools/overrides/eventarc/beta/trigger.yaml +++ b/tpgtools/overrides/eventarc/beta/trigger.yaml @@ -11,4 +11,7 @@ # 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. - +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/channel.yaml b/tpgtools/overrides/eventarc/channel.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/eventarc/channel.yaml +++ b/tpgtools/overrides/eventarc/channel.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/google_channel_config.yaml b/tpgtools/overrides/eventarc/google_channel_config.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/eventarc/google_channel_config.yaml +++ b/tpgtools/overrides/eventarc/google_channel_config.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/eventarc/trigger.yaml b/tpgtools/overrides/eventarc/trigger.yaml index 13ed711e62fe..9014b1241575 100644 --- a/tpgtools/overrides/eventarc/trigger.yaml +++ b/tpgtools/overrides/eventarc/trigger.yaml @@ -11,3 +11,7 @@ # 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. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/beta/release.yaml b/tpgtools/overrides/firebaserules/beta/release.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/firebaserules/beta/release.yaml +++ b/tpgtools/overrides/firebaserules/beta/release.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/beta/ruleset.yaml b/tpgtools/overrides/firebaserules/beta/ruleset.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/firebaserules/beta/ruleset.yaml +++ b/tpgtools/overrides/firebaserules/beta/ruleset.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/release.yaml b/tpgtools/overrides/firebaserules/release.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/firebaserules/release.yaml +++ b/tpgtools/overrides/firebaserules/release.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/ruleset.yaml b/tpgtools/overrides/firebaserules/ruleset.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/firebaserules/ruleset.yaml +++ b/tpgtools/overrides/firebaserules/ruleset.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml b/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml index 4ae842c1d411..814b4c37d22a 100644 --- a/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml +++ b/tpgtools/overrides/firebaserules/samples/release/firestore_release.yaml @@ -18,8 +18,6 @@ versions: - ga - beta resource: ./firestore_release.tf.tmpl -updates: -- resource: ./firestore_release_update.tf.tmpl variables: - name: project type: project \ No newline at end of file diff --git a/tpgtools/overrides/firebaserules/samples/release/firestore_release_update.tf.tmpl b/tpgtools/overrides/firebaserules/samples/release/firestore_release_update.tf.tmpl deleted file mode 100644 index d279c25e2a58..000000000000 --- a/tpgtools/overrides/firebaserules/samples/release/firestore_release_update.tf.tmpl +++ /dev/null @@ -1,22 +0,0 @@ -resource "google_firebaserules_release" "primary" { - name = "cloud.firestore" - ruleset_name = "projects/{{project}}/rulesets/${google_firebaserules_ruleset.firestore.name}" - project = "{{project}}" - - lifecycle { - replace_triggered_by = [ - google_firebaserules_ruleset.firestore - ] - } -} - -resource "google_firebaserules_ruleset" "firestore" { - source { - files { - content = "service cloud.firestore {match /databases/{database}/documents { match /{document=**} { allow read, write: if request.auth != null; } } }" - name = "firestore.rules" - } - } - - project = "{{project}}" -} diff --git a/tpgtools/overrides/gkehub/beta/feature_membership.yaml b/tpgtools/overrides/gkehub/beta/feature_membership.yaml index 2e8b8f32503c..3eac7364e119 100644 --- a/tpgtools/overrides/gkehub/beta/feature_membership.yaml +++ b/tpgtools/overrides/gkehub/beta/feature_membership.yaml @@ -24,4 +24,8 @@ field: mesh.control_plane details: message: >- - Deprecated in favor of the `management` field \ No newline at end of file + Deprecated in favor of the `management` field +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/networkconnectivity/beta/hub.yaml b/tpgtools/overrides/networkconnectivity/beta/hub.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/networkconnectivity/beta/hub.yaml +++ b/tpgtools/overrides/networkconnectivity/beta/hub.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/networkconnectivity/beta/spoke.yaml b/tpgtools/overrides/networkconnectivity/beta/spoke.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/networkconnectivity/beta/spoke.yaml +++ b/tpgtools/overrides/networkconnectivity/beta/spoke.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/networkconnectivity/hub.yaml b/tpgtools/overrides/networkconnectivity/hub.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/networkconnectivity/hub.yaml +++ b/tpgtools/overrides/networkconnectivity/hub.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/networkconnectivity/spoke.yaml b/tpgtools/overrides/networkconnectivity/spoke.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/networkconnectivity/spoke.yaml +++ b/tpgtools/overrides/networkconnectivity/spoke.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/privateca/beta/certificate_template.yaml b/tpgtools/overrides/privateca/beta/certificate_template.yaml index 13ed711e62fe..9014b1241575 100644 --- a/tpgtools/overrides/privateca/beta/certificate_template.yaml +++ b/tpgtools/overrides/privateca/beta/certificate_template.yaml @@ -11,3 +11,7 @@ # 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. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/privateca/certificate_template.yaml b/tpgtools/overrides/privateca/certificate_template.yaml index 13ed711e62fe..9014b1241575 100644 --- a/tpgtools/overrides/privateca/certificate_template.yaml +++ b/tpgtools/overrides/privateca/certificate_template.yaml @@ -11,3 +11,7 @@ # 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. +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/recaptchaenterprise/beta/key.yaml b/tpgtools/overrides/recaptchaenterprise/beta/key.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/recaptchaenterprise/beta/key.yaml +++ b/tpgtools/overrides/recaptchaenterprise/beta/key.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/overrides/recaptchaenterprise/key.yaml b/tpgtools/overrides/recaptchaenterprise/key.yaml index e69de29bb2d1..af851d79a0c9 100644 --- a/tpgtools/overrides/recaptchaenterprise/key.yaml +++ b/tpgtools/overrides/recaptchaenterprise/key.yaml @@ -0,0 +1,4 @@ +- type: CUSTOMIZE_DIFF + details: + functions: + - tpgresource.DefaultProviderProject diff --git a/tpgtools/property.go b/tpgtools/property.go index 0ee26f2af299..f95c8ddbb089 100644 --- a/tpgtools/property.go +++ b/tpgtools/property.go @@ -311,6 +311,10 @@ func (p Property) DefaultStateSetter() string { case SchemaTypeFloat: fallthrough case SchemaTypeMap: + if p.IsResourceLabels() || p.IsResourceAnnotations() { + return fmt.Sprintf("d.Set(%q, flatten%s%s(res.%s, d))", p.Name(), p.resource.PathType(), p.PackagePath(), p.PackageName) + } + return fmt.Sprintf("d.Set(%q, res.%s)", p.Name(), p.PackageName) case SchemaTypeList, SchemaTypeSet: if p.typ.Items != nil && ((p.typ.Items.Type == "string" && len(p.typ.Items.Enum) == 0) || p.typ.Items.Type == "integer") { @@ -440,6 +444,18 @@ func (p Property) Objects() (props []Property) { return props } +func (p Property) IsResourceLabels() bool { + return p.Name() == "labels" && p.parent == nil +} + +func (p Property) IsResourceAnnotations() bool { + return p.Name() == "annotations" && p.parent == nil +} + +func (p Property) ShouldShowUpInSamples() bool { + return (p.Settable && p.Name() != "effective_labels" && p.Name() != "effective_annotations") || p.IsResourceLabels() || p.IsResourceAnnotations() +} + // collapsedProperties returns the input list of properties with nested objects collapsed if needed. func collapsedProperties(props []Property) (collapsed []Property) { for _, v := range props { @@ -878,6 +894,23 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher resource.ReusedTypes = resource.RegisterReusedType(p) } + // Add the "effective_labels" property when the current property is top level "labels" or + // add the "effective_annotations" property when the current property is top level "annotations" + + if p.IsResourceLabels() || p.IsResourceAnnotations() { + note := "**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." + p.Description = fmt.Sprintf("%s\n\n%s", p.Description, note) + p.Settable = false + p.StateGetter = nil + + props = append(props, build_effective_labels_field(p, resource, parent)) + + if p.IsResourceLabels() { + props = append(props, build_terraform_labels_field(p, resource, parent)) + } + } + props = append(props, p) } @@ -901,3 +934,44 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher return props, nil } + +func build_effective_labels_field(p Property, resource *Resource, parent *Property) Property { + title := fmt.Sprintf("effective_%s", p.title) + description := fmt.Sprintf("All of %s (key/value pairs) present on the resource in GCP, including the %s configured through Terraform, other clients and services.", p.title, p.title) + stateSetter := fmt.Sprintf("d.Set(%q, res.%s)", title, p.PackageName) + + effectiveLabels := Property{ + title: title, + Type: p.Type, + Description: description, + resource: resource, + parent: parent, + Optional: false, + Computed: true, + ForceNew: p.ForceNew, // Add ForceNew property if labels field has it + PackageName: p.PackageName, + Settable: true, + StateSetter: &stateSetter, + } + + stateGetter := effectiveLabels.DefaultStateGetter() + effectiveLabels.StateGetter = &stateGetter + return effectiveLabels +} + +func build_terraform_labels_field(p Property, resource *Resource, parent *Property) Property { + title := fmt.Sprintf("terraform_%s", p.title) + description := fmt.Sprintf("The combination of %s configured directly on the resource and default %s configured on the provider.", p.title, p.title) + stateSetter := fmt.Sprintf("d.Set(%q, flatten%sTerraform%s(res.%s, d))", title, p.resource.PathType(), p.PackagePath(), p.PackageName) + + return Property{ + title: title, + Type: p.Type, + Description: description, + resource: resource, + parent: parent, + Computed: true, + PackageName: p.PackageName, + StateSetter: &stateSetter, + } +} diff --git a/tpgtools/resource.go b/tpgtools/resource.go index b65c2061f9f9..26c94420ef45 100644 --- a/tpgtools/resource.go +++ b/tpgtools/resource.go @@ -381,6 +381,26 @@ func (r Resource) IDFunction() string { return "tpgresource.ReplaceVarsForId" } +// Check if the resource has the lables field for the resource +func (r Resource) HasLabels() bool { + for _, p := range r.Properties { + if p.IsResourceLabels() { + return true + } + } + return false +} + +// Check if the resource has the annotations field for the resource +func (r Resource) HasAnnotations() bool { + for _, p := range r.Properties { + if p.IsResourceAnnotations() { + return true + } + } + return false +} + // ResourceInput is a Resource along with additional generation metadata. type ResourceInput struct { Resource @@ -566,6 +586,14 @@ func createResource(schema *openapi.Schema, info *openapi.Info, typeFetcher *Typ res.CustomizeDiff = cdiff.Functions } + if res.HasLabels() { + res.CustomizeDiff = append(res.CustomizeDiff, "tpgresource.SetLabelsDiff") + } + + if res.HasAnnotations() { + res.CustomizeDiff = append(res.CustomizeDiff, "tpgresource.SetAnnotationsDiff") + } + // ListFields if parameters, ok := typeFetcher.doc.Paths["list"]; ok { for _, param := range parameters.Parameters { @@ -810,6 +838,18 @@ func (r *Resource) loadHandWrittenSamples() []Sample { sample.Name = &sampleName } sample.TestSlug = RenderedString(snakeToTitleCase(miscellaneousNameSnakeCase(sampleName)).titlecase() + "HandWritten") + + // The "labels" and "annotations" fields in the state are decided by the configuration. + // During importing, as the configuration is unavailableafter, the "labels" and "annotations" fields in the state will be empty. + // So add the "labels" and the "annotations" fields to the ImportStateVerifyIgnore list. + if r.HasLabels() { + sample.IgnoreRead = append(sample.IgnoreRead, "labels", "terraform_labels") + } + + if r.HasAnnotations() { + sample.IgnoreRead = append(sample.IgnoreRead, "annotations") + } + samples = append(samples, sample) } @@ -896,6 +936,18 @@ func (r *Resource) loadDCLSamples() []Sample { } sample.DependencyList = dependencies sample.TestSlug = RenderedString(sampleNameToTitleCase(*sample.Name).titlecase()) + + // The "labels" and "annotations" fields in the state are decided by the configuration. + // During importing, as the configuration is unavailable, the "labels" and "annotations" fields in the state will be empty. + // So add the "labels" and the "annotations" fields to the ImportStateVerifyIgnore list. + if r.HasLabels() { + sample.IgnoreRead = append(sample.IgnoreRead, "labels", "terraform_labels") + } + + if r.HasAnnotations() { + sample.IgnoreRead = append(sample.IgnoreRead, "annotations") + } + samples = append(samples, sample) } diff --git a/tpgtools/templates/resource.go.tmpl b/tpgtools/templates/resource.go.tmpl index 532dd4c4c75b..db1eeb4d6aea 100644 --- a/tpgtools/templates/resource.go.tmpl +++ b/tpgtools/templates/resource.go.tmpl @@ -714,6 +714,55 @@ func flatten{{$.PathType}}{{$v.PackagePath}}(obj *{{$.Package}}.{{$v.ObjectType} } {{ end -}} +{{ if $.HasLabels }} +func flatten{{$.PathType}}Labels(v map[string]string, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + + transformed := make(map[string]interface{}) + if l, ok := d.Get("labels").(map[string]interface{}); ok { + for k, _ := range l { + transformed[k] = v[k] + } + } + + return transformed +} + +func flatten{{$.PathType}}TerraformLabels(v map[string]string, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + + transformed := make(map[string]interface{}) + if l, ok := d.Get("terraform_labels").(map[string]interface{}); ok { + for k, _ := range l { + transformed[k] = v[k] + } + } + + return transformed +} +{{ end }} + +{{ if $.HasAnnotations }} +func flatten{{$.PathType}}Annotations(v map[string]string, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + + transformed := make(map[string]interface{}) + if l, ok := d.Get("annotations").(map[string]interface{}); ok { + for k, _ := range l { + transformed[k] = v[k] + } + } + + return transformed +} +{{ end }} + {{ range $v := .EnumArrays -}} func flatten{{$.PathType}}{{$v.PackagePath}}Array(obj []{{$.Package}}.{{$v.ObjectType}}Enum) interface{} { if obj == nil { diff --git a/tpgtools/templates/serialization.go.tmpl b/tpgtools/templates/serialization.go.tmpl index 7936e1a0119c..faba0a38cdfc 100644 --- a/tpgtools/templates/serialization.go.tmpl +++ b/tpgtools/templates/serialization.go.tmpl @@ -126,7 +126,7 @@ func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSn func {{ $res.TitleCaseFullName }}{{$version.SerializationSuffix}}AsHCL(r {{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLStructName}}, hasGAEquivalent bool) (string, error) { outputConfig := "resource \"{{$res.TerraformName}}\" \"output\" {\n" {{- range $field := $res.Properties}} - {{- if $field.Settable }} + {{- if $field.ShouldShowUpInSamples }} {{- if eq $field.Type.String "TypeString" "TypeInt" "TypeBool" "TypeFloat" }} {{- if $field.Type.IsDateTime }} if !r.{{$field.PackageName}}.IsZero() {