From b6759652848869b2b6c7f02319986486621ea056 Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Fri, 30 Sep 2022 13:20:24 +0100 Subject: [PATCH 01/17] bigqueryreservation: move beta to v1 + add fields (#6567) * move to v1 + fields * default value --- mmv1/products/bigqueryreservation/api.yaml | 14 ++++++++++++-- .../examples/bigquery_reservation_basic.tf.erb | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/mmv1/products/bigqueryreservation/api.yaml b/mmv1/products/bigqueryreservation/api.yaml index d6d682d4501f..491dc34dfc9e 100644 --- a/mmv1/products/bigqueryreservation/api.yaml +++ b/mmv1/products/bigqueryreservation/api.yaml @@ -17,7 +17,7 @@ display_name: BigQuery Reservation versions: - !ruby/object:Api::Product::Version name: beta - base_url: https://bigqueryreservation.googleapis.com/v1beta1/ + base_url: https://bigqueryreservation.googleapis.com/v1/ - !ruby/object:Api::Product::Version name: ga base_url: https://bigqueryreservation.googleapis.com/v1/ @@ -39,7 +39,7 @@ objects: references: !ruby/object:Api::Resource::ReferenceLinks guides: "Introduction to Reservations": "https://cloud.google.com/bigquery/docs/reservations-intro" - api: "https://cloud.google.com/bigquery/docs/reference/reservations/rest/v1beta1/projects.locations.reservations/create" + api: "https://cloud.google.com/bigquery/docs/reference/reservations/rest/v1/projects.locations.reservations/create" parameters: - !ruby/object:Api::Type::String name: 'location' @@ -70,3 +70,13 @@ objects: If false, any query using this reservation will use idle slots from other reservations within the same admin project. If true, a query using this reservation will execute with the slot capacity specified above at most. + - !ruby/object:Api::Type::Integer + name: 'concurrency' + default_value: 0 + description: | + Maximum number of queries that are allowed to run concurrently in this reservation. This is a soft limit due to asynchronous nature of the system and various optimizations for small queries. Default value is 0 which means that concurrency will be automatically set based on the reservation size. + - !ruby/object:Api::Type::Boolean + name: 'multiRegionAuxiliary' + description: | + Applicable only for reservations located within one of the BigQuery multi-regions (US or EU). + If set to true, this reservation is placed in the organization's secondary region which is designated for disaster recovery purposes. If false, this reservation is placed in the organization's default region. \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/bigquery_reservation_basic.tf.erb b/mmv1/templates/terraform/examples/bigquery_reservation_basic.tf.erb index 5d0fc062f0ee..6fc9a5df9d00 100644 --- a/mmv1/templates/terraform/examples/bigquery_reservation_basic.tf.erb +++ b/mmv1/templates/terraform/examples/bigquery_reservation_basic.tf.erb @@ -3,6 +3,7 @@ resource "google_bigquery_reservation" "<%= ctx[:primary_resource_id] %>" { location = "asia-northeast1" // Set to 0 for testing purposes // In reality this would be larger than zero - slot_capacity = 0 + slot_capacity = 0 ignore_idle_slots = false + concurrency = 0 } From 95f51ff13b77c0d14f3ef5ef19d06d8e8359b9ee Mon Sep 17 00:00:00 2001 From: Jay Sanghani <111726632+sanghaniJ@users.noreply.github.com> Date: Fri, 30 Sep 2022 16:04:38 +0000 Subject: [PATCH 02/17] Labels added to Disk in Compute Instance (#6620) --- .../terraform/website/docs/r/compute_instance.html.markdown | 6 ++++++ 1 file changed, 6 insertions(+) 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 a07a31f2040b..94febb6ad203 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 @@ -30,6 +30,9 @@ resource "google_compute_instance" "default" { boot_disk { initialize_params { image = "debian-cloud/debian-11" + labels = { + my_label = "value" + } } } @@ -231,6 +234,9 @@ is desired, you will need to modify your state file manually using For instance, the image `centos-6-v20180104` includes its family name `centos-6`. These images can be referred by family name here. +* `labels` - (Optional) A set of key/value label pairs assigned to the disk. This + field is only applicable for persistent disks. + The `scratch_disk` block supports: * `interface` - (Required) The disk interface to use for attaching this disk; either SCSI or NVME. From e6985aea75c311e6592c180e910a32e60a759af9 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Fri, 30 Sep 2022 15:21:53 -0400 Subject: [PATCH 03/17] Add org_policy_custom_constraint resource (#6608) * Add org_policy_custom_constraint resource * Update resource config to reflect beta version * Update handwritten test to reflect beta version * Update example to use beta version of the provider * Remove unnecessary TestCheckResourceAttr calls * Update name attribute to be specified as a shortname * Add full example * Tweak config and documentation per final PR comments --- mmv1/products/orgpolicy/api.yaml | 98 +++++++++++++++++++ mmv1/products/orgpolicy/terraform.yaml | 44 +++++++++ .../org_policy_custom_constraint_basic.tf.erb | 11 +++ .../org_policy_custom_constraint_full.tf.erb | 26 +++++ .../org_policy_custom_constraint.go.erb | 7 ++ ...e_org_policy_custom_constraint_test.go.erb | 78 +++++++++++++++ .../orgpolicy/beta/tpgtools_product.yaml | 5 + 7 files changed, 269 insertions(+) create mode 100644 mmv1/products/orgpolicy/api.yaml create mode 100644 mmv1/products/orgpolicy/terraform.yaml create mode 100644 mmv1/templates/terraform/examples/org_policy_custom_constraint_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/org_policy_custom_constraint_full.tf.erb create mode 100644 mmv1/templates/terraform/update_encoder/org_policy_custom_constraint.go.erb create mode 100644 mmv1/third_party/terraform/tests/resource_org_policy_custom_constraint_test.go.erb create mode 100644 tpgtools/overrides/orgpolicy/beta/tpgtools_product.yaml diff --git a/mmv1/products/orgpolicy/api.yaml b/mmv1/products/orgpolicy/api.yaml new file mode 100644 index 000000000000..5ab7d84390e1 --- /dev/null +++ b/mmv1/products/orgpolicy/api.yaml @@ -0,0 +1,98 @@ +# Copyright 2022 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: OrgPolicy +display_name: Organization Policy +versions: + - !ruby/object:Api::Product::Version + name: beta + base_url: https://orgpolicy.googleapis.com/v2/ +scopes: + - https://www.googleapis.com/auth/cloud-platform +apis_required: + - !ruby/object:Api::Product::ApiReference + name: Organization Policy API + url: https://console.cloud.google.com/apis/api/orgpolicy.googleapis.com/overview +objects: + - !ruby/object:Api::Resource + name: 'CustomConstraint' + self_link: '{{parent}}/customConstraints/{{name}}' + base_url: '{{parent}}/customConstraints' + update_verb: :PATCH + min_version: beta + references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': + 'https://cloud.google.com/resource-manager/docs/organization-policy/creating-managing-custom-constraints' + 'Supported Services': + 'https://cloud.google.com/resource-manager/docs/organization-policy/custom-constraint-supported-services' + api: 'https://cloud.google.com/resource-manager/docs/reference/orgpolicy/rest/v2/organizations.constraints' + description: | + Custom constraints are created by administrators to provide more granular and customizable control over the specific fields that are restricted by your organization policies. + parameters: + - !ruby/object:Api::Type::String + name: parent + description: | + The parent of the resource, an organization. Format should be `organizations/{organization_id}`. + input: true + url_param_only: true + required: true + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + input: true + description: | + Immutable. The name of the custom constraint. This is unique within the organization. + - !ruby/object:Api::Type::String + name: 'displayName' + description: | + A human-friendly name for the constraint. + - !ruby/object:Api::Type::String + name: 'description' + description: | + A human-friendly description of the constraint to display as an error message when the policy is violated. + - !ruby/object:Api::Type::String + name: 'condition' + required: true + description: | + A CEL condition that refers to a supported service resource, for example `resource.management.autoUpgrade == false`. For details about CEL usage, see [Common Expression Language](https://cloud.google.com/resource-manager/docs/organization-policy/creating-managing-custom-constraints#common_expression_language). + - !ruby/object:Api::Type::Enum + name: 'actionType' + required: true + description: | + The action to take if the condition is met. + values: + - :ALLOW + - :DENY + - !ruby/object:Api::Type::Array + name: 'methodTypes' + min_size: 1 + required: true + description: | + A list of RESTful methods for which to enforce the constraint. Can be `CREATE`, `UPDATE`, or both. Not all Google Cloud services support both methods. To see supported methods for each service, find the service in [Supported services](https://cloud.google.com/resource-manager/docs/organization-policy/custom-constraint-supported-services). + item_type: Api::Type::String + - !ruby/object:Api::Type::Array + name: 'resourceTypes' + input: true + min_size: 1 + required: true + description: | + Immutable. The fully qualified name of the Google Cloud REST resource containing the object and field you want to restrict. For example, `container.googleapis.com/NodePool`. + item_type: Api::Type::String + - !ruby/object:Api::Type::String + name: 'updateTime' + output: true + description: | + Output only. The timestamp representing when the constraint was last updated. diff --git a/mmv1/products/orgpolicy/terraform.yaml b/mmv1/products/orgpolicy/terraform.yaml new file mode 100644 index 000000000000..ee11bb99e7e9 --- /dev/null +++ b/mmv1/products/orgpolicy/terraform.yaml @@ -0,0 +1,44 @@ +# Copyright 2022 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:Provider::Terraform::Config +overrides: !ruby/object:Overrides::ResourceOverrides + CustomConstraint: !ruby/object:Overrides::Terraform::ResourceOverride + id_format: '{{parent}}/customConstraints/{{name}}' + import_format: ["{{%parent}}/customConstraints/{{name}}"] + custom_code: !ruby/object:Provider::Terraform::CustomCode + update_encoder: 'templates/terraform/update_encoder/org_policy_custom_constraint.go.erb' + examples: + - !ruby/object:Provider::Terraform::Examples + min_version: beta + name: "org_policy_custom_constraint_basic" + primary_resource_id: "constraint" + test_env_vars: + org_id: :ORG_ID + - !ruby/object:Provider::Terraform::Examples + min_version: beta + name: "org_policy_custom_constraint_full" + primary_resource_id: "constraint" + test_env_vars: + org_id: :ORG_TARGET + properties: + name: !ruby/object:Overrides::Terraform::PropertyOverride + custom_expand: 'templates/terraform/custom_expand/shortname_to_url.go.erb' + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + +# This is for copying files over +files: !ruby/object:Provider::Config::Files + # These files have templating (ERB) code that will be run. + # This is usually to add licensing info, autogeneration notices, etc. + compile: +<%= lines(indent(compile('provider/terraform/product~compile.yaml'), 4)) -%> diff --git a/mmv1/templates/terraform/examples/org_policy_custom_constraint_basic.tf.erb b/mmv1/templates/terraform/examples/org_policy_custom_constraint_basic.tf.erb new file mode 100644 index 000000000000..552ea7ea749f --- /dev/null +++ b/mmv1/templates/terraform/examples/org_policy_custom_constraint_basic.tf.erb @@ -0,0 +1,11 @@ +resource "google_org_policy_custom_constraint" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + + name = "custom.disableGkeAutoUpgrade" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + + action_type = "ALLOW" + condition = "resource.management.autoUpgrade == false" + method_types = ["CREATE", "UPDATE"] + resource_types = ["container.googleapis.com/NodePool"] +} diff --git a/mmv1/templates/terraform/examples/org_policy_custom_constraint_full.tf.erb b/mmv1/templates/terraform/examples/org_policy_custom_constraint_full.tf.erb new file mode 100644 index 000000000000..9f5a73289c8a --- /dev/null +++ b/mmv1/templates/terraform/examples/org_policy_custom_constraint_full.tf.erb @@ -0,0 +1,26 @@ +resource "google_org_policy_custom_constraint" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + + name = "custom.disableGkeAutoUpgrade" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + display_name = "Disable GKE auto upgrade" + description = "Only allow GKE NodePool resource to be created or updated if AutoUpgrade is not enabled where this custom constraint is enforced." + + action_type = "ALLOW" + condition = "resource.management.autoUpgrade == false" + method_types = ["CREATE", "UPDATE"] + resource_types = ["container.googleapis.com/NodePool"] +} + +resource "google_org_policy_policy" "bool" { + provider = google-beta + + name = "organizations/<%= ctx[:test_env_vars]['org_id'] %>/policies/${google_org_policy_custom_constraint.constraint.name}" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + + spec { + rules { + enforce = "TRUE" + } + } +} diff --git a/mmv1/templates/terraform/update_encoder/org_policy_custom_constraint.go.erb b/mmv1/templates/terraform/update_encoder/org_policy_custom_constraint.go.erb new file mode 100644 index 000000000000..56e89bdf09fc --- /dev/null +++ b/mmv1/templates/terraform/update_encoder/org_policy_custom_constraint.go.erb @@ -0,0 +1,7 @@ +// need to send resource_types in all PATCH requests +resourceTypesProp := d.Get("resource_types") +if v, ok := d.GetOkExists("resource_types"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, resourceTypesProp)) { + obj["resourceTypes"] = resourceTypesProp +} + +return obj, nil diff --git a/mmv1/third_party/terraform/tests/resource_org_policy_custom_constraint_test.go.erb b/mmv1/third_party/terraform/tests/resource_org_policy_custom_constraint_test.go.erb new file mode 100644 index 000000000000..50aca43ad202 --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_org_policy_custom_constraint_test.go.erb @@ -0,0 +1,78 @@ +<% autogen_exception -%> +package google +<% unless version == 'ga' -%> + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccOrgPolicyCustomConstraint_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": getTestOrgFromEnv(t), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckOrgPolicyCustomConstraintDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccOrgPolicyCustomConstraint_v1(context), + }, + { + ResourceName: "google_org_policy_custom_constraint.constraint", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + { + Config: testAccOrgPolicyCustomConstraint_v2(context), + }, + { + ResourceName: "google_org_policy_custom_constraint.constraint", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent"}, + }, + }, + }) +} + +func testAccOrgPolicyCustomConstraint_v1(context map[string]interface{}) string { + return Nprintf(` +resource "google_org_policy_custom_constraint" "constraint" { + name = "custom.tfTest%{random_suffix}" + parent = "organizations/%{org_id}" + display_name = "Disable GKE auto upgrade" + description = "Only allow GKE NodePool resource to be created or updated if AutoUpgrade is not enabled where this custom constraint is enforced." + + action_type = "ALLOW" + condition = "resource.management.autoUpgrade == false" + method_types = ["CREATE", "UPDATE"] + resource_types = ["container.googleapis.com/NodePool"] +} +`, context) +} + +func testAccOrgPolicyCustomConstraint_v2(context map[string]interface{}) string { + return Nprintf(` +resource "google_org_policy_custom_constraint" "constraint" { + name = "custom.tfTest%{random_suffix}" + parent = "organizations/%{org_id}" + display_name = "Updated" + description = "Updated" + + action_type = "DENY" + condition = "resource.management.autoUpgrade == true" + method_types = ["CREATE"] + resource_types = ["container.googleapis.com/NodePool"] +} +`, context) +} + +<% end -%> diff --git a/tpgtools/overrides/orgpolicy/beta/tpgtools_product.yaml b/tpgtools/overrides/orgpolicy/beta/tpgtools_product.yaml new file mode 100644 index 000000000000..21c439217d43 --- /dev/null +++ b/tpgtools/overrides/orgpolicy/beta/tpgtools_product.yaml @@ -0,0 +1,5 @@ +## product level overrides + +- type: PRODUCT_BASE_PATH + details: + skip: true From 520e78b5db2970a5b0bbbbd86427043842ad442b Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 30 Sep 2022 14:08:47 -0700 Subject: [PATCH 04/17] Added support for google_datastream_connection_profile.bigquery_profile field (#6616) * Added support for google_datastream_connection_profile.bigquery_profile field Related to https://github.com/hashicorp/terraform-provider-google/issues/10810 This required making some changes to compilation & templates to truly support completely empty "nested objects". I removed .nested_properties? in favor of more explicitly checking whether the nested properties are not specified or are present but empty. * Fixed ruby errors * Added bigquery test * Made logic for 'Structure is documented below' match the logic for generating the related docs block --- mmv1/api/resource.rb | 4 ++-- mmv1/api/type.rb | 6 +----- mmv1/overrides/runner.rb | 3 ++- mmv1/products/datastream/api.yaml | 17 +++++++++++++++++ mmv1/products/datastream/terraform.yaml | 5 +++++ mmv1/provider/ansible/documentation.rb | 4 ++-- mmv1/provider/ansible/module.rb | 2 +- mmv1/provider/ansible/request.rb | 2 +- mmv1/templates/inspec/nested_object.erb | 4 ++-- ...atastream_connection_profile_bigquery.tf.erb | 7 +++++++ .../terraform/expand_property_method.erb | 11 +++++++---- .../terraform/flatten_property_method.erb | 6 ++++-- .../terraform/nested_property_documentation.erb | 2 +- .../terraform/property_documentation.erb | 2 +- mmv1/templates/terraform/schema_subresource.erb | 2 ++ 15 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 mmv1/templates/terraform/examples/datastream_connection_profile_bigquery.tf.erb diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 2fbc09182855..2d63b7846cea 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -216,7 +216,7 @@ def required_properties def all_nested_properties(props) nested = props props.each do |prop| - if !prop.flatten_object && prop.nested_properties? + if !prop.flatten_object && !prop.nested_properties.nil? nested += all_nested_properties(prop.nested_properties) end end @@ -449,7 +449,7 @@ def resourcerefs_for_properties(props, original_obj) rrefs.concat(resourcerefs_for_properties(p.resource_ref .required_properties, original_obj)) - elsif p.nested_properties? + elsif !p.nested_properties.nil? rrefs.concat(resourcerefs_for_properties(p.nested_properties, original_obj)) elsif p.is_a? Api::Type::Array if p.item_type.is_a? Api::Type::ResourceRef diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index f49bb36994de..b1f721e4b784 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -319,11 +319,7 @@ def class # Returns nested properties for this property. def nested_properties - [] - end - - def nested_properties? - !nested_properties.empty? + nil end def removed? diff --git a/mmv1/overrides/runner.rb b/mmv1/overrides/runner.rb index 3591e21a69da..141823006bea 100644 --- a/mmv1/overrides/runner.rb +++ b/mmv1/overrides/runner.rb @@ -56,6 +56,7 @@ def build(api, overrides, res_override_class = Overrides::ResourceOverride, validator = Overrides::Validator.new(api, overrides) validator.run + build_product(api, overrides, resource: res_override_class, property: prop_override_class) end @@ -131,7 +132,7 @@ def build_property(old_property, property_overrides, override_classes, prefix = new_prop = build_primitive_property(old_property, property_overrides["#{prefix}#{old_property.name}"], override_classes) - if old_property.nested_properties? + unless old_property.nested_properties.nil? new_props = old_property.nested_properties.map do |p| build_property(p, property_overrides, override_classes, "#{prefix}#{old_property.name}.") diff --git a/mmv1/products/datastream/api.yaml b/mmv1/products/datastream/api.yaml index 2cbfac20c736..fd4e1e7021b6 100644 --- a/mmv1/products/datastream/api.yaml +++ b/mmv1/products/datastream/api.yaml @@ -87,6 +87,7 @@ objects: - oracle_profile - gcs_profile - mysql_profile + - bigquery_profile - postgresql_profile description: | Oracle database profile. @@ -125,6 +126,7 @@ objects: - oracle_profile - gcs_profile - mysql_profile + - bigquery_profile - postgresql_profile description: | Cloud Storage bucket profile. @@ -144,6 +146,7 @@ objects: - oracle_profile - gcs_profile - mysql_profile + - bigquery_profile - postgresql_profile description: | MySQL database profile. @@ -210,12 +213,26 @@ objects: output: true description: | Indicates whether the clientKey field is set. + - !ruby/object:Api::Type::NestedObject + name: 'bigqueryProfile' + send_empty_value: true + allow_empty_object: true + exactly_one_of: + - oracle_profile + - gcs_profile + - mysql_profile + - bigquery_profile + - postgresql_profile + description: | + BigQuery warehouse profile. + properties: [] - !ruby/object:Api::Type::NestedObject name: 'postgresqlProfile' exactly_one_of: - oracle_profile - gcs_profile - mysql_profile + - bigquery_profile - postgresql_profile description: | PostgreSQL database profile. diff --git a/mmv1/products/datastream/terraform.yaml b/mmv1/products/datastream/terraform.yaml index a7330c746d6b..b4e5a72b32d4 100644 --- a/mmv1/products/datastream/terraform.yaml +++ b/mmv1/products/datastream/terraform.yaml @@ -55,6 +55,11 @@ overrides: !ruby/object:Overrides::ResourceOverrides primary_resource_id: "default" vars: connection_profile_id: "my-profile" + - !ruby/object:Provider::Terraform::Examples + name: "datastream_connection_profile_bigquery" + primary_resource_id: "default" + vars: + connection_profile_id: "my-profile" - !ruby/object:Provider::Terraform::Examples name: "datastream_connection_profile_full" primary_resource_id: "default" diff --git a/mmv1/provider/ansible/documentation.rb b/mmv1/provider/ansible/documentation.rb index bc99100bdffa..b1e625bdbf60 100644 --- a/mmv1/provider/ansible/documentation.rb +++ b/mmv1/provider/ansible/documentation.rb @@ -49,7 +49,7 @@ def documentation_for_property(prop) 'type' => python_type(prop), 'aliases' => prop.aliases, 'suboptions' => ( - if prop.nested_properties? + if !prop.nested_properties.nil? && !prop.nested_properties.empty? prop.nested_properties.reject(&:output).map { |p| documentation_for_property(p) } .reduce({}, :merge) end @@ -76,7 +76,7 @@ def returns_for_property(prop) 'returned' => 'success', 'type' => type, 'contains' => ( - if prop.nested_properties? + if !prop.nested_properties.nil? && !prop.nested_properties.empty? prop.nested_properties.map { |p| returns_for_property(p) } .reduce({}, :merge) end diff --git a/mmv1/provider/ansible/module.rb b/mmv1/provider/ansible/module.rb index 2874d57a4788..4c58e92a3ff9 100644 --- a/mmv1/provider/ansible/module.rb +++ b/mmv1/provider/ansible/module.rb @@ -36,7 +36,7 @@ def python_dict_for_property(prop) 'elements' => (python_type(prop.item_type) \ if prop.is_a?(Api::Type::Array) && python_type(prop.item_type)), 'aliases' => prop.aliases, - 'options' => (if prop.nested_properties? + 'options' => (if !prop.nested_properties.nil? && !prop.nested_properties.empty? prop.nested_properties.reject(&:output) .map { |x| python_dict_for_property(x) } .reduce({}, :merge) diff --git a/mmv1/provider/ansible/request.rb b/mmv1/provider/ansible/request.rb index 68b99fe99bc8..54c922fe3ef6 100644 --- a/mmv1/provider/ansible/request.rb +++ b/mmv1/provider/ansible/request.rb @@ -39,7 +39,7 @@ def response_properties(properties, hash_name = 'response', module_name = 'modul # This returns a list of properties that require classes being built out. def properties_with_classes(properties) properties.map do |p| - [p] + properties_with_classes(p.nested_properties) if p.nested_properties? + [p] + properties_with_classes(p.nested_properties) unless p.nested_properties.nil? end.compact.flatten end diff --git a/mmv1/templates/inspec/nested_object.erb b/mmv1/templates/inspec/nested_object.erb index 05a4382b2e05..7168cde7d120 100644 --- a/mmv1/templates/inspec/nested_object.erb +++ b/mmv1/templates/inspec/nested_object.erb @@ -33,13 +33,13 @@ module GoogleInSpec module <%= product_ns %> module Property class <%= class_name -%> -<% if property.nested_properties? -%> +<% if !property.nested_properties.nil? -%> <% property.nested_properties.each do |prop| -%> attr_reader :<%= prop.out_name %> <% end # property.nested_properties.each -%> -<% end # if property.nested_properties? -%> +<% end # !property.nested_properties.nil? -%> def initialize(args = nil, parent_identifier = nil) return if args.nil? @parent_identifier = parent_identifier diff --git a/mmv1/templates/terraform/examples/datastream_connection_profile_bigquery.tf.erb b/mmv1/templates/terraform/examples/datastream_connection_profile_bigquery.tf.erb new file mode 100644 index 000000000000..8f83cee66350 --- /dev/null +++ b/mmv1/templates/terraform/examples/datastream_connection_profile_bigquery.tf.erb @@ -0,0 +1,7 @@ +resource "google_datastream_connection_profile" "<%= ctx[:primary_resource_id] %>" { + display_name = "Connection profile" + location = "us-central1" + connection_profile_id = "<%= ctx[:vars]['connection_profile_id'] %>" + + bigquery_profile {} +} \ No newline at end of file diff --git a/mmv1/templates/terraform/expand_property_method.erb b/mmv1/templates/terraform/expand_property_method.erb index 0c7301f9ebad..e32ce109412c 100644 --- a/mmv1/templates/terraform/expand_property_method.erb +++ b/mmv1/templates/terraform/expand_property_method.erb @@ -98,7 +98,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d T <% if property.is_set -%> v = v.(*schema.Set).List() <% end -%> -<% if property.nested_properties? -%> +<% if !property.nested_properties.nil? -%> l := v.([]interface{}) <% if property.is_a?(Api::Type::Array) -%> req := make([]interface{}, 0, len(l)) @@ -106,6 +106,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d T if raw == nil { continue } + original := raw.(map[string]interface{}) <% else -%> <% if property.allow_empty_object -%> if len(l) == 0 { @@ -116,14 +117,16 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d T transformed := make(map[string]interface{}) return transformed, nil } -<% else -%> +<% else -%> if len(l) == 0 || l[0] == nil { return nil, nil } <% end -%> +<% if !property.nested_properties.empty? -%> raw := l[0] + original := raw.(map[string]interface{}) +<% end -%> <% end -%> - original := raw.(map[string]interface{}) transformed := make(map[string]interface{}) <% property.nested_properties.each do |prop| -%> @@ -183,7 +186,7 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d T } <% end # tf_types.include?(property.class) -%> -<% if property.nested_properties? -%> +<% if !property.nested_properties.nil? -%> <% property.nested_properties.each do |prop| -%> <%# 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. %> diff --git a/mmv1/templates/terraform/flatten_property_method.erb b/mmv1/templates/terraform/flatten_property_method.erb index f2c15085c141..0c07a553fcaf 100644 --- a/mmv1/templates/terraform/flatten_property_method.erb +++ b/mmv1/templates/terraform/flatten_property_method.erb @@ -24,11 +24,13 @@ func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d if v == nil { return nil } + <% if !property.allow_empty_object -%> original := v.(map[string]interface{}) - <% unless property.allow_empty_object -%> if len(original) == 0 { return nil } + <% elsif !property.properties.empty? -%> + original := v.(map[string]interface{}) <% end -%> transformed := make(map[string]interface{}) <% property.properties.each do |prop| -%> @@ -131,7 +133,7 @@ func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d return v <% end # property.is_a?(Api::Type::NestedObject) -%> } -<% if property.nested_properties? -%> +<% if !property.nested_properties.nil? -%> <% property.nested_properties.each do |prop| -%> <%= lines(build_flatten_method(prefix + titlelize_property(property), prop, object, pwd), 1) -%> <% end -%> diff --git a/mmv1/templates/terraform/nested_property_documentation.erb b/mmv1/templates/terraform/nested_property_documentation.erb index 6115a4cf5a3a..2c993fcc2aeb 100644 --- a/mmv1/templates/terraform/nested_property_documentation.erb +++ b/mmv1/templates/terraform/nested_property_documentation.erb @@ -4,7 +4,7 @@ <%= lines(build_nested_property_documentation(prop, pwd)) -%> <% end -%> <% - elsif property.nested_properties? + elsif !property.nested_properties.nil? && !property.nested_properties.empty? -%> The `<%= property.name.underscore -%>` block <%= if property.output then "contains" else "supports" end -%>: <%- if property.is_a?(Api::Type::Map) %> diff --git a/mmv1/templates/terraform/property_documentation.erb b/mmv1/templates/terraform/property_documentation.erb index 55d5deb83c04..8857958bf75a 100644 --- a/mmv1/templates/terraform/property_documentation.erb +++ b/mmv1/templates/terraform/property_documentation.erb @@ -32,6 +32,6 @@ <% if property.sensitive -%> **Note**: This property is sensitive and will not be displayed in the plan. <% end -%> -<% if property.is_a?(Api::Type::NestedObject) || property.is_a?(Api::Type::Map) || (property.is_a?(Api::Type::Array) && property.item_type.is_a?(Api::Type::NestedObject)) -%> +<% if !property.flatten_object && !property.nested_properties.nil? && !property.nested_properties.empty? -%> Structure is [documented below](#nested_<%= property.name.underscore -%>). <% end -%> diff --git a/mmv1/templates/terraform/schema_subresource.erb b/mmv1/templates/terraform/schema_subresource.erb index a62023a5d884..33e849bc6766 100644 --- a/mmv1/templates/terraform/schema_subresource.erb +++ b/mmv1/templates/terraform/schema_subresource.erb @@ -26,6 +26,8 @@ func <%= namespace_property_from_object(property, object) -%>Schema() *schema.Re } <% end %> +<% if !property.nested_properties.nil? -%> <% property.nested_properties.each do |prop| -%> <%= lines(build_subresource_schema(prop, object, pwd), 1) -%> <% end -%> +<% end -%> From 13f6fa6577c7a72f42ee1a934e6c7ece67e48018 Mon Sep 17 00:00:00 2001 From: Patrick Rauchfuss Date: Fri, 30 Sep 2022 23:35:21 +0200 Subject: [PATCH 05/17] suppress dataplex labels (#6518) --- .../resources/resource_storage_bucket.go.erb | 18 +++++ .../tests/resource_storage_bucket_test.go.erb | 79 +++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/mmv1/third_party/terraform/resources/resource_storage_bucket.go.erb b/mmv1/third_party/terraform/resources/resource_storage_bucket.go.erb index 116e8c49e2ff..5fc49a4fadd3 100644 --- a/mmv1/third_party/terraform/resources/resource_storage_bucket.go.erb +++ b/mmv1/third_party/terraform/resources/resource_storage_bucket.go.erb @@ -82,6 +82,8 @@ func resourceStorageBucket() *schema.Resource { "labels": { Type: schema.TypeMap, Optional: 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.`, }, @@ -377,6 +379,22 @@ func resourceStorageBucket() *schema.Resource { } } +const resourceDataplexGoogleProvidedLabelPrefix = "labels.goog-dataplex" + +func resourceDataplexLabelDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + if strings.HasPrefix(k, resourceDataplexGoogleProvidedLabelPrefix) && new == "" { + return true + } + + // Let diff be determined by labels (above) + if strings.HasPrefix(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + // Is the old bucket retention policy locked? func isPolicyLocked(_ context.Context, old, new, _ interface{}) bool { if old == nil || new == nil { diff --git a/mmv1/third_party/terraform/tests/resource_storage_bucket_test.go.erb b/mmv1/third_party/terraform/tests/resource_storage_bucket_test.go.erb index 89443c93e899..6cf46ee00037 100644 --- a/mmv1/third_party/terraform/tests/resource_storage_bucket_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_storage_bucket_test.go.erb @@ -1047,6 +1047,85 @@ func TestAccStorageBucket_retentionPolicyLocked(t *testing.T) { }) } +func TestLabelDiffSuppress(t *testing.T) { + cases := map[string]struct { + K, Old, New string + ExpectDiffSuppress bool + }{ + "missing goog-dataplex-asset-id": { + K: "labels.goog-dataplex-asset-id", + Old: "test-bucket", + New: "", + ExpectDiffSuppress: true, + }, + "explicit goog-dataplex-asset-id": { + K: "labels.goog-dataplex-asset-id", + Old: "test-bucket", + New: "test-bucket-1", + ExpectDiffSuppress: false, + }, + "missing goog-dataplex-lake-id": { + K: "labels.goog-dataplex-lake-id", + Old: "test-lake", + New: "", + ExpectDiffSuppress: true, + }, + "explicit goog-dataplex-lake-id": { + K: "labels.goog-dataplex-lake-id", + Old: "test-lake", + New: "test-lake-1", + ExpectDiffSuppress: false, + }, + "missing goog-dataplex-project-id": { + K: "labels.goog-dataplex-project-id", + Old: "test-project-12345", + New: "", + ExpectDiffSuppress: true, + }, + "explicit goog-dataplex-project-id": { + K: "labels.goog-dataplex-project-id", + Old: "test-project-12345", + New: "test-project-12345-1", + ExpectDiffSuppress: false, + }, + "missing goog-dataplex-zone-id": { + K: "labels.goog-dataplex-zone-id", + Old: "test-zone1", + New: "", + ExpectDiffSuppress: true, + }, + "explicit goog-dataplex-zone-id": { + K: "labels.goog-dataplex-zone-id", + Old: "test-zone1", + New: "test-zone1-1", + ExpectDiffSuppress: false, + }, + "labels.%": { + K: "labels.%", + Old: "5", + New: "1", + ExpectDiffSuppress: true, + }, + "deleted custom key": { + K: "labels.my-label", + Old: "my-value", + New: "", + ExpectDiffSuppress: false, + }, + "added custom key": { + K: "labels.my-label", + Old: "", + New: "my-value", + ExpectDiffSuppress: false, + }, + } + for tn, tc := range cases { + if resourceDataplexLabelDiffSuppress(tc.K, tc.Old, tc.New, nil) != tc.ExpectDiffSuppress { + t.Errorf("bad: %s, %q: %q => %q expect DiffSuppress to return %t", tn, tc.K, tc.Old, tc.New, tc.ExpectDiffSuppress) + } + } +} + func testAccCheckStorageBucketExists(t *testing.T, n string, bucketName string, bucket *storage.Bucket) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] From 81e8258e9daf0d973d352a660a07ebbf568aa195 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Mon, 3 Oct 2022 14:17:42 -0500 Subject: [PATCH 06/17] add nil check to storagetransfer_job transfer schedule (#6634) --- .../terraform/resources/resource_storage_transfer_job.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/resources/resource_storage_transfer_job.go b/mmv1/third_party/terraform/resources/resource_storage_transfer_job.go index 4dd7116d7847..8ce77ec4fa3c 100644 --- a/mmv1/third_party/terraform/resources/resource_storage_transfer_job.go +++ b/mmv1/third_party/terraform/resources/resource_storage_transfer_job.go @@ -839,7 +839,7 @@ func expandTransferSchedules(transferSchedules []interface{}) *storagetransfer.S } func flattenTransferSchedule(transferSchedule *storagetransfer.Schedule) []map[string]interface{} { - if reflect.DeepEqual(transferSchedule, &storagetransfer.Schedule{}) { + if transferSchedule == nil || reflect.DeepEqual(transferSchedule, &storagetransfer.Schedule{}) { return nil } From 3b8ba06c8782d59447328548dab5417d7213bff0 Mon Sep 17 00:00:00 2001 From: Kevin Si Date: Mon, 3 Oct 2022 16:52:58 -0400 Subject: [PATCH 07/17] Bigtable: Update retryable logic (#6612) --- .../terraform/utils/error_retry_predicates.go | 25 +++++++++++--- .../utils/error_retry_predicates_test.go | 33 ++++++++++++++----- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/mmv1/third_party/terraform/utils/error_retry_predicates.go b/mmv1/third_party/terraform/utils/error_retry_predicates.go index abb26b2816c7..b65b312a0cae 100644 --- a/mmv1/third_party/terraform/utils/error_retry_predicates.go +++ b/mmv1/third_party/terraform/utils/error_retry_predicates.go @@ -8,9 +8,12 @@ import ( "net/url" "regexp" "strings" + "time" "google.golang.org/api/googleapi" sqladmin "google.golang.org/api/sqladmin/v1beta4" + "google.golang.org/genproto/googleapis/rpc/errdetails" + "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -408,13 +411,27 @@ func iamServiceAccountNotFound(err error) (bool, string) { return false, "" } -// Big Table uses gRPC and thus does not return errors of type *googleapi.Error. +// Bigtable uses gRPC and thus does not return errors of type *googleapi.Error. // Instead the errors returned are *status.Error. See the types of codes returned // here (https://pkg.go.dev/google.golang.org/grpc/codes#Code). func isBigTableRetryableError(err error) (bool, string) { - statusCode := status.Code(err) - if statusCode.String() == "FailedPrecondition" { - return true, "Waiting for table to be in a valid state" + // The error is retryable if the error code is not OK and has a retry delay. + // The retry delay is currently not used. + if errorStatus, ok := status.FromError(err); ok && errorStatus.Code() != codes.OK { + var retryDelayDuration time.Duration + for _, detail := range errorStatus.Details() { + retryInfo, ok := detail.(*errdetails.RetryInfo) + if !ok { + continue + } + retryDelay := retryInfo.GetRetryDelay() + retryDelayDuration = time.Duration(retryDelay.Seconds)*time.Second + time.Duration(retryDelay.Nanos)*time.Nanosecond + break + } + if retryDelayDuration != 0 { + // TODO: Consider sleep for `retryDelayDuration` before retrying. + return true, "Bigtable operation failed with a retryable error, will retry" + } } return false, "" diff --git a/mmv1/third_party/terraform/utils/error_retry_predicates_test.go b/mmv1/third_party/terraform/utils/error_retry_predicates_test.go index f34a04456596..464ec52927cc 100644 --- a/mmv1/third_party/terraform/utils/error_retry_predicates_test.go +++ b/mmv1/third_party/terraform/utils/error_retry_predicates_test.go @@ -5,8 +5,10 @@ import ( "testing" "google.golang.org/api/googleapi" + "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/durationpb" ) func TestIsAppEngineRetryableError_operationInProgress(t *testing.T) { @@ -114,19 +116,34 @@ func TestIs403QuotaExceededPerMinuteError_perDayQuotaExceededNotRetryable(t *tes } } -func TestGRPCRetryable(t *testing.T) { - code := codes.FailedPrecondition - err := status.Error(code, "is retryable") - isRetryable, _ := isBigTableRetryableError(err) +// An error with retry info is retryable. +func TestBigtableError_retryable(t *testing.T) { + retryInfo := &errdetails.RetryInfo{ + RetryDelay: &durationpb.Duration{Seconds: 10, Nanos: 10}, + } + status, _ := status.New(codes.FailedPrecondition, "is retryable").WithDetails(retryInfo) + isRetryable, _ := isBigTableRetryableError(status.Err()) if !isRetryable { t.Errorf("Error not detected as retryable") } } -func TestGRPCNotRetryable(t *testing.T) { - code := codes.InvalidArgument - err := status.Error(code, "is noto retryable") - isRetryable, _ := isBigTableRetryableError(err) +// An error without retry info is not retryable. +func TestBigtableError_withoutRetryInfoNotRetryable(t *testing.T) { + status := status.New(codes.FailedPrecondition, "is not retryable") + isRetryable, _ := isBigTableRetryableError(status.Err()) + if isRetryable { + t.Errorf("Error incorrectly detected as retryable") + } +} + +// An OK status with retry info is not retryable. +func TestBigtableError_okIsNotRetryable(t *testing.T) { + retryInfo := &errdetails.RetryInfo{ + RetryDelay: &durationpb.Duration{Seconds: 10, Nanos: 10}, + } + status, _ := status.New(codes.OK, "is not retryable").WithDetails(retryInfo) + isRetryable, _ := isBigTableRetryableError(status.Err()) if isRetryable { t.Errorf("Error incorrectly detected as retryable") } From 1750a0751ae82d73ea1c63d32d7a163c25efb227 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Mon, 3 Oct 2022 14:00:16 -0700 Subject: [PATCH 08/17] Add the vertex endpoint resource. (#6583) * Add the vertex endpoint resource. * Add a KMS key to the test. * Add an iam member for encypter decrypter role on kms key. * Use a bootstrapped test network. * Make bootstrapped network a data source. * Use long form for self link. * Add property overrides. * Make accelerator_type a string. --- mmv1/products/vertexai/api.yaml | 210 ++++++++++++++++++ mmv1/products/vertexai/terraform.yaml | 19 ++ .../vertex_ai_endpoint_network.tf.erb | 41 ++++ 3 files changed, 270 insertions(+) create mode 100644 mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb diff --git a/mmv1/products/vertexai/api.yaml b/mmv1/products/vertexai/api.yaml index e62e71a89701..fae09d3f9dcb 100644 --- a/mmv1/products/vertexai/api.yaml +++ b/mmv1/products/vertexai/api.yaml @@ -96,6 +96,7 @@ objects: description: | Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key. The key needs to be in the same region as where the resource is created. + required: true input: true - !ruby/object:Api::Type::String name: 'metadataSchemaUri' @@ -103,6 +104,214 @@ objects: input: true description: | Points to a YAML file stored on Google Cloud Storage describing additional information about the Dataset. The schema is defined as an OpenAPI 3.0.2 Schema Object. The schema files that can be used here are found in gs://google-cloud-aiplatform/schema/dataset/metadata/. + +# Vertex AI Endpoints + - !ruby/object:Api::Resource + name: Endpoint + base_url: projects/{{project}}/locations/{{location}}/endpoints + create_url: projects/{{project}}/locations/{{location}}/endpoints + self_link: 'projects/{{project}}/locations/{{location}}/endpoints/{{name}}' + update_verb: :PATCH + update_mask: true + references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': + 'https://cloud.google.com/vertex-ai/docs' + api: 'https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/projects.locations.endpoints' + 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' + message: 'message' + description: "Models are deployed into it, and afterwards Endpoint is called to obtain predictions and explanations." + parameters: + - !ruby/object:Api::Type::String + name: location + description: The location for the resource + url_param_only: true + input: true + properties: + - !ruby/object:Api::Type::String + name: name + description: Output only. The resource name of the Endpoint. + output: true + - !ruby/object:Api::Type::String + name: displayName + description: Required. The display name of the Endpoint. The name can be up to 128 characters long and can consist of any UTF-8 characters. + required: true + - !ruby/object:Api::Type::String + name: description + description: The description of the Endpoint. + - !ruby/object:Api::Type::Array + name: deployedModels + description: Output only. The models deployed in this Endpoint. To add or remove DeployedModels use EndpointService.DeployModel and EndpointService.UndeployModel respectively. + output: true + item_type: !ruby/object:Api::Type::NestedObject + name: deployedModels + description: Output only. The models deployed in this Endpoint. To add or remove DeployedModels use EndpointService.DeployModel and EndpointService.UndeployModel respectively. + properties: + - !ruby/object:Api::Type::NestedObject + name: dedicatedResources + description: A description of resources that are dedicated to the DeployedModel, and that need a higher degree of manual configuration. + output: true + properties: + - !ruby/object:Api::Type::NestedObject + name: machineSpec + description: The specification of a single machine used by the prediction. + output: true + properties: + - !ruby/object:Api::Type::String + name: machineType + description: 'The type of the machine. See the [list of machine types supported for prediction](https://cloud.google.com/vertex-ai/docs/predictions/configure-compute#machine-types) See the [list of machine types supported for custom training](https://cloud.google.com/vertex-ai/docs/training/configure-compute#machine-types). For DeployedModel this field is optional, and the default value is `n1-standard-2`. For BatchPredictionJob or as part of WorkerPoolSpec this field is required. TODO(rsurowka): Try to better unify the required vs optional.' + output: true + - !ruby/object:Api::Type::String + name: acceleratorType + description: The type of accelerator(s) that may be attached to the machine as per accelerator_count. See possible values [here](https://cloud.google.com/vertex-ai/docs/reference/rest/v1/MachineSpec#AcceleratorType). + output: true + - !ruby/object:Api::Type::Integer + name: acceleratorCount + description: The number of accelerators to attach to the machine. + output: true + - !ruby/object:Api::Type::Integer + name: minReplicaCount + description: The minimum number of machine replicas this DeployedModel will be always deployed on. This value must be greater than or equal to 1. If traffic against the DeployedModel increases, it may dynamically be deployed onto more replicas, and as traffic decreases, some of these extra replicas may be freed. + output: true + - !ruby/object:Api::Type::Integer + name: maxReplicaCount + description: The maximum number of replicas this DeployedModel may be deployed on when the traffic against it increases. If the requested value is too large, the deployment will error, but if deployment succeeds then the ability to scale the model to that many replicas is guaranteed (barring service outages). If traffic against the DeployedModel increases beyond what its replicas at maximum may handle, a portion of the traffic will be dropped. If this value is not provided, will use min_replica_count as the default value. The value of this field impacts the charge against Vertex CPU and GPU quotas. Specifically, you will be charged for max_replica_count * number of cores in the selected machine type) and (max_replica_count * number of GPUs per replica in the selected machine type). + output: true + - !ruby/object:Api::Type::Array + name: autoscalingMetricSpecs + description: The metric specifications that overrides a resource utilization metric (CPU utilization, accelerator's duty cycle, and so on) target value (default to 60 if not set). At most one entry is allowed per metric. If machine_spec.accelerator_count is above 0, the autoscaling will be based on both CPU utilization and accelerator's duty cycle metrics and scale up when either metrics exceeds its target value while scale down if both metrics are under their target value. The default target value is 60 for both metrics. If machine_spec.accelerator_count is 0, the autoscaling will be based on CPU utilization metric only with default target value 60 if not explicitly set. For example, in the case of Online Prediction, if you want to override target CPU utilization to 80, you should set autoscaling_metric_specs.metric_name to `aiplatform.googleapis.com/prediction/online/cpu/utilization` and autoscaling_metric_specs.target to `80`. + output: true + item_type: !ruby/object:Api::Type::NestedObject + name: autoscalingMetricSpecs + description: The metric specifications that overrides a resource utilization metric (CPU utilization, accelerator's duty cycle, and so on) target value (default to 60 if not set). At most one entry is allowed per metric. If machine_spec.accelerator_count is above 0, the autoscaling will be based on both CPU utilization and accelerator's duty cycle metrics and scale up when either metrics exceeds its target value while scale down if both metrics are under their target value. The default target value is 60 for both metrics. If machine_spec.accelerator_count is 0, the autoscaling will be based on CPU utilization metric only with default target value 60 if not explicitly set. For example, in the case of Online Prediction, if you want to override target CPU utilization to 80, you should set autoscaling_metric_specs.metric_name to `aiplatform.googleapis.com/prediction/online/cpu/utilization` and autoscaling_metric_specs.target to `80`. + properties: + - !ruby/object:Api::Type::String + name: metricName + description: 'The resource metric name. Supported metrics: * For Online Prediction: * `aiplatform.googleapis.com/prediction/online/accelerator/duty_cycle` * `aiplatform.googleapis.com/prediction/online/cpu/utilization`' + output: true + - !ruby/object:Api::Type::Integer + name: target + description: The target resource utilization in percentage (1% - 100%) for the given metric; once the real usage deviates from the target by a certain percentage, the machine replicas change. The default value is 60 (representing 60%) if not provided. + output: true + - !ruby/object:Api::Type::NestedObject + name: automaticResources + description: A description of resources that to large degree are decided by Vertex AI, and require only a modest additional configuration. + output: true + properties: + - !ruby/object:Api::Type::Integer + name: minReplicaCount + description: The minimum number of replicas this DeployedModel will be always deployed on. If traffic against it increases, it may dynamically be deployed onto more replicas up to max_replica_count, and as traffic decreases, some of these extra replicas may be freed. If the requested value is too large, the deployment will error. + output: true + - !ruby/object:Api::Type::Integer + name: maxReplicaCount + description: The maximum number of replicas this DeployedModel may be deployed on when the traffic against it increases. If the requested value is too large, the deployment will error, but if deployment succeeds then the ability to scale the model to that many replicas is guaranteed (barring service outages). If traffic against the DeployedModel increases beyond what its replicas at maximum may handle, a portion of the traffic will be dropped. If this value is not provided, a no upper bound for scaling under heavy traffic will be assume, though Vertex AI may be unable to scale beyond certain replica number. + output: true + - !ruby/object:Api::Type::String + name: id + description: The ID of the DeployedModel. If not provided upon deployment, Vertex AI will generate a value for this ID. This value should be 1-10 characters, and valid characters are /[0-9]/. + output: true + - !ruby/object:Api::Type::String + name: model + description: The name of the Model that this is the deployment of. Note that the Model may be in a different location than the DeployedModel's Endpoint. + output: true + - !ruby/object:Api::Type::String + name: modelVersionId + description: Output only. The version ID of the model that is deployed. + output: true + - !ruby/object:Api::Type::String + name: displayName + description: The display name of the DeployedModel. If not provided upon creation, the Model's display_name is used. + output: true + - !ruby/object:Api::Type::String + name: createTime + description: Output only. Timestamp when the DeployedModel was created. + output: true + - !ruby/object:Api::Type::String + name: serviceAccount + description: The service account that the DeployedModel's container runs as. Specify the email address of the service account. If this service account is not specified, the container runs as a service account that doesn't have access to the resource project. Users deploying the Model must have the `iam.serviceAccounts.actAs` permission on this service account. + output: true + - !ruby/object:Api::Type::Boolean + name: enableAccessLogging + description: These logs are like standard server access logs, containing information like timestamp and latency for each prediction request. Note that Stackdriver logs may incur a cost, especially if your project receives prediction requests at a high queries per second rate (QPS). Estimate your costs before enabling this option. + output: true + - !ruby/object:Api::Type::NestedObject + name: privateEndpoints + description: Output only. Provide paths for users to send predict/explain/health requests directly to the deployed model services running on Cloud via private services access. This field is populated if network is configured. + output: true + properties: + - !ruby/object:Api::Type::String + name: predictHttpUri + description: Output only. Http(s) path to send prediction requests. + output: true + - !ruby/object:Api::Type::String + name: explainHttpUri + description: Output only. Http(s) path to send explain requests. + output: true + - !ruby/object:Api::Type::String + name: healthHttpUri + description: Output only. Http(s) path to send health check requests. + output: true + - !ruby/object:Api::Type::String + name: serviceAttachment + description: Output only. The name of the service attachment resource. Populated if private service connect is enabled. + output: true + - !ruby/object:Api::Type::String + name: sharedResources + description: 'The resource name of the shared DeploymentResourcePool to deploy on. Format: projects/{project}/locations/{location}/deploymentResourcePools/{deployment_resource_pool}' + output: true + - !ruby/object:Api::Type::Boolean + name: enableContainerLogging + description: If true, the container of the DeployedModel instances will send `stderr` and `stdout` streams to Stackdriver Logging. Only supported for custom-trained Models and AutoML Tabular Models. + output: true + - !ruby/object:Api::Type::String + name: etag + description: Used to perform consistent read-modify-write updates. If not set, a blind "overwrite" update happens. + output: true + - !ruby/object:Api::Type::KeyValuePairs + 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), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. + - !ruby/object:Api::Type::String + name: createTime + description: Output only. Timestamp when this Endpoint was created. + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: Output only. Timestamp when this Endpoint was last updated. + output: true + - !ruby/object:Api::Type::NestedObject + name: encryptionSpec + description: Customer-managed encryption key spec for an Endpoint. If set, this Endpoint and all sub-resources of this Endpoint will be secured by this key. + input: true + properties: + - !ruby/object:Api::Type::String + name: kmsKeyName + description: 'Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created.' + required: true + input: true + - !ruby/object:Api::Type::String + name: network + description: 'The full name of the Google Compute Engine [network](https://cloud.google.com//compute/docs/networks-and-firewalls#networks) to which the Endpoint should be peered. Private services access must already be configured for the network. If left unspecified, the Endpoint is not peered with any network. Only one of the fields, network or enable_private_service_connect, can be set. [Format](https://cloud.google.com/compute/docs/reference/rest/v1/networks/insert): `projects/{project}/global/networks/{network}`. Where `{project}` is a project number, as in `12345`, and `{network}` is network name.' + input: true + - !ruby/object:Api::Type::String + name: modelDeploymentMonitoringJob + description: 'Output only. Resource name of the Model Monitoring job associated with this Endpoint if monitoring is enabled by CreateModelDeploymentMonitoringJob. Format: `projects/{project}/locations/{location}/modelDeploymentMonitoringJobs/{model_deployment_monitoring_job}`' + output: true + # Vertex AI Featurestores - !ruby/object:Api::Resource name: Featurestore @@ -422,6 +631,7 @@ objects: description: | Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key. The key needs to be in the same region as where the resource is created. + required: true input: true - !ruby/object:Api::Type::NestedObject name: 'state' diff --git a/mmv1/products/vertexai/terraform.yaml b/mmv1/products/vertexai/terraform.yaml index a8edc29f1d2e..a4d1e8e08a68 100644 --- a/mmv1/products/vertexai/terraform.yaml +++ b/mmv1/products/vertexai/terraform.yaml @@ -30,6 +30,25 @@ overrides: !ruby/object:Overrides::ResourceOverrides default_from_api: true region: !ruby/object:Overrides::Terraform::PropertyOverride default_from_api: true + Endpoint: !ruby/object:Overrides::Terraform::ResourceOverride + examples: + - !ruby/object:Provider::Terraform::Examples + name: "vertex_ai_endpoint_network" + primary_resource_id: "endpoint" + vars: + name: "vertex_ai_endpoint" + project: "vertex-ai" + address_name: "address-name" + kms_key_name: "kms-name" + network_name: "network-name" + test_vars_overrides: + kms_key_name: 'BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' + network_name: 'BootstrapSharedTestNetwork(t, "vertex")' + properties: + etag: !ruby/object:Overrides::Terraform::PropertyOverride + ignore_read: true + name: !ruby/object:Overrides::Terraform::PropertyOverride + custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb Featurestore: !ruby/object:Overrides::Terraform::ResourceOverride autogen_async: false skip_sweeper: true diff --git a/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb new file mode 100644 index 000000000000..4de7864561db --- /dev/null +++ b/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb @@ -0,0 +1,41 @@ +resource "google_vertex_ai_endpoint" "<%= ctx[:primary_resource_id] %>" { + display_name = "sample-endpoint" + description = "A sample vertex endpoint" + location = "us-central1" + labels = { + label-one = "value-one" + } + network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" + encryption_spec { + kms_key_name = "<%= ctx[:vars]['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 = "<%= ctx[:vars]['address_name'] %>" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 24 + network = data.google_compute_network.vertex_network.id +} + +data "google_compute_network" "vertex_network" { + name = "<%= ctx[:vars]['network_name'] %>" +} + +resource "google_kms_crypto_key_iam_member" "crypto_key" { + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-aiplatform.iam.gserviceaccount.com" +} + +data "google_project" "project" {} From 44a4b66e1bed9ce368352c28cf51012f1b6dc78e Mon Sep 17 00:00:00 2001 From: AarshDhokai <111489014+AarshDhokai@users.noreply.github.com> Date: Tue, 4 Oct 2022 05:04:06 +0530 Subject: [PATCH 09/17] Fix dataflow flextemplate job labels (#6559) --- .../resource_dataflow_flex_template_job.go.erb | 15 +++++++++++++-- ...esource_dataflow_flex_template_job_test.go.erb | 7 +++++++ .../r/dataflow_flex_template_job.html.markdown | 3 +-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_dataflow_flex_template_job.go.erb b/mmv1/third_party/terraform/resources/resource_dataflow_flex_template_job.go.erb index 0a3f79324966..e09f44e26b17 100644 --- a/mmv1/third_party/terraform/resources/resource_dataflow_flex_template_job.go.erb +++ b/mmv1/third_party/terraform/resources/resource_dataflow_flex_template_job.go.erb @@ -59,8 +59,6 @@ func resourceDataflowFlexTemplateJob() *schema.Resource { Type: schema.TypeMap, Optional: true, DiffSuppressFunc: resourceDataflowJobLabelDiffSuppress, - // TODO add support for labels when the API supports it - Deprecated: "Deprecated until the API supports this field", }, "parameters": { @@ -119,6 +117,9 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac ContainerSpecGcsPath: d.Get("container_spec_gcs_path").(string), JobName: d.Get("name").(string), Parameters: expandStringMap(d, "parameters"), + Environment: &dataflow.FlexTemplateRuntimeEnvironment{ + AdditionalUserLabels: expandStringMap(d, "labels"), + }, }, } @@ -128,6 +129,13 @@ func resourceDataflowFlexTemplateJobCreate(d *schema.ResourceData, meta interfac } job := response.Job + + //adding wait time for setting all the parameters into state file + err = waitForDataflowJobState(d, config, job.Id, userAgent, d.Timeout(schema.TimeoutUpdate), "JOB_STATE_RUNNING") + if err != nil { + return fmt.Errorf("Error waiting for job with job ID %q to be running: %s", job.Id, err) + } + d.SetId(job.Id) if err := d.Set("job_id", job.Id); err != nil { return fmt.Errorf("Error setting job_id: %s", err) @@ -255,6 +263,9 @@ func resourceDataflowFlexTemplateJobUpdate(d *schema.ResourceData, meta interfac ContainerSpecGcsPath: d.Get("container_spec_gcs_path").(string), JobName: d.Get("name").(string), Parameters: expandStringMap(d, "parameters"), + Environment: &dataflow.FlexTemplateRuntimeEnvironment{ + AdditionalUserLabels: expandStringMap(d, "labels"), + }, Update: true, }, } diff --git a/mmv1/third_party/terraform/tests/resource_dataflow_flex_template_job_test.go.erb b/mmv1/third_party/terraform/tests/resource_dataflow_flex_template_job_test.go.erb index 3212225a1e56..39f26b539b28 100644 --- a/mmv1/third_party/terraform/tests/resource_dataflow_flex_template_job_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_dataflow_flex_template_job_test.go.erb @@ -104,6 +104,7 @@ func TestAccDataflowFlexTemplateJob_streamUpdateFail(t *testing.T) { }) } + func TestAccDataflowFlexTemplateJob_withServiceAccount(t *testing.T) { // Dataflow responses include serialized java classes and bash commands // This makes body comparison infeasible @@ -210,6 +211,9 @@ resource "google_dataflow_flex_template_job" "job" { qps = "1" %s } + labels = { + "my_labels" = "value" + } } `, job, topicField) } @@ -243,6 +247,9 @@ resource "google_dataflow_flex_template_job" "job" { serviceAccount = google_service_account.dataflow-sa.email zone = "%s" } + labels = { + "my_labels" = "value" + } } `, accountId, job, zone) } 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 49c1db9ea76a..69bde966b1df 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 @@ -95,8 +95,7 @@ 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**: This field is marked as deprecated in Terraform as the API does not currently -support adding labels. +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. From 5e28298939cae68589002f969d6c34f0cdc4154f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Taneli=20Lepp=C3=A4?= Date: Tue, 4 Oct 2022 18:24:43 +0200 Subject: [PATCH 10/17] Added support for regional target TCP proxy and removed some unused fields from target regional HTTP/HTTPS proxy. (#6622) --- mmv1/products/compute/api.yaml | 93 +++++++++- mmv1/products/compute/terraform.yaml | 21 +++ .../region_target_tcp_proxy_basic.tf.erb | 31 ++++ ...ompute_region_target_tcp_proxy_test.go.erb | 164 ++++++++++++++++++ 4 files changed, 305 insertions(+), 4 deletions(-) create mode 100644 mmv1/templates/terraform/examples/region_target_tcp_proxy_basic.tf.erb create mode 100644 mmv1/third_party/terraform/tests/resource_compute_region_target_tcp_proxy_test.go.erb diff --git a/mmv1/products/compute/api.yaml b/mmv1/products/compute/api.yaml index 4bbbb7881835..b5efb4ee8c61 100644 --- a/mmv1/products/compute/api.yaml +++ b/mmv1/products/compute/api.yaml @@ -15450,9 +15450,7 @@ objects: this target proxy has a loadBalancingScheme set to INTERNAL_SELF_MANAGED. - !ruby/object:Api::Resource name: 'RegionTargetHttpProxy' - kind: 'compute#targetHttpProxy' base_url: projects/{{project}}/regions/{{region}}/targetHttpProxies - collection_url_key: 'items' has_self_link: true input: true description: | @@ -15525,9 +15523,7 @@ objects: update_url: 'projects/{{project}}/regions/{{region}}/targetHttpProxies/{{name}}/setUrlMap' - !ruby/object:Api::Resource name: 'RegionTargetHttpsProxy' - kind: 'compute#targetHttpsProxy' base_url: projects/{{project}}/regions/{{region}}/targetHttpsProxies - collection_url_key: 'items' has_self_link: true input: true description: | @@ -15647,6 +15643,95 @@ objects: required: true update_verb: :POST update_url: 'projects/{{project}}/regions/{{region}}/targetHttpsProxies/{{name}}/setUrlMap' + - !ruby/object:Api::Resource + name: 'RegionTargetTcpProxy' + base_url: projects/{{project}}/regions/{{region}}/targetTcpProxies + has_self_link: true + input: true + description: | + Represents a RegionTargetTcpProxy resource, which is used by one or more + forwarding rules to route incoming TCP requests to a regional TCP proxy load + balancer. + references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': + 'https://cloud.google.com/load-balancing/docs/tcp/internal-proxy' + api: 'https://cloud.google.com/compute/docs/reference/rest/beta/targetTcpProxies' + min_version: beta + async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + kind: 'compute#operation' + path: 'name' + base_url: 'projects/{{project}}/regions/{{region}}/operations/{{op_id}}' + wait_ms: 1000 + result: !ruby/object:Api::OpAsync::Result + path: 'targetLink' + status: !ruby/object:Api::OpAsync::Status + path: 'status' + complete: 'DONE' + allowed: + - 'PENDING' + - 'RUNNING' + - 'DONE' + error: !ruby/object:Api::OpAsync::Error + path: 'error/errors' + message: 'message' + parameters: + - !ruby/object:Api::Type::ResourceRef + name: 'region' + resource: 'Region' + imports: 'name' + required: true + input: true + description: | + The region where the regional proxy resides. + properties: + - !ruby/object:Api::Type::Time + name: 'creationTimestamp' + description: 'Creation timestamp in RFC3339 text format.' + output: true + - !ruby/object:Api::Type::String + name: 'description' + description: 'An optional description of this resource.' + input: true + - !ruby/object:Api::Type::Integer + name: 'proxyId' + api_name: 'id' + description: 'The unique identifier for the resource.' + output: true + - !ruby/object:Api::Type::String + name: 'name' + description: | + Name of the resource. Provided by the client when the resource is + created. The name must be 1-63 characters long, and comply with + RFC1035. Specifically, the name must be 1-63 characters long and match + the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the + first character must be a lowercase letter, and all following + characters must be a dash, lowercase letter, or digit, except the last + character, which cannot be a dash. + input: true + required: true + - !ruby/object:Api::Type::Enum + name: 'proxyHeader' + description: | + Specifies the type of proxy header to append before sending data to + the backend. + values: + - :NONE + - :PROXY_V1 + default_value: :NONE + - !ruby/object:Api::Type::ResourceRef + name: 'service' + resource: 'RegionBackendService' + imports: 'selfLink' + description: | + A reference to the BackendService resource. + required: true + - !ruby/object:Api::Type::Boolean + name: 'proxyBind' + description: | + This field only applies when the forwarding rule that references + this target proxy has a loadBalancingScheme set to INTERNAL_SELF_MANAGED. - !ruby/object:Api::Resource name: 'TargetInstance' kind: 'compute#targetInstance' diff --git a/mmv1/products/compute/terraform.yaml b/mmv1/products/compute/terraform.yaml index 87c63342a578..65afadbc42f6 100644 --- a/mmv1/products/compute/terraform.yaml +++ b/mmv1/products/compute/terraform.yaml @@ -3221,6 +3221,27 @@ overrides: !ruby/object:Overrides::ResourceOverrides default_value: :NONE proxyBind: !ruby/object:Overrides::Terraform::PropertyOverride default_from_api: true + RegionTargetTcpProxy: !ruby/object:Overrides::Terraform::ResourceOverride + examples: + - !ruby/object:Provider::Terraform::Examples + name: "region_target_tcp_proxy_basic" + primary_resource_id: "default" + vars: + region_target_tcp_proxy_name: "test-proxy" + region_backend_service_name: "backend-service" + health_check_name: "health-check" + properties: + service: !ruby/object:Overrides::Terraform::PropertyOverride + name: backendService + proxyBind: !ruby/object:Overrides::Terraform::PropertyOverride + default_from_api: true + region: !ruby/object:Overrides::Terraform::PropertyOverride + default_from_api: true + required: false + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + description: | + The Region in which the created target TCP proxy should reside. + If it is not provided, the provider region is used. TargetVpnGateway: !ruby/object:Overrides::Terraform::ResourceOverride name: 'VpnGateway' docs: !ruby/object:Provider::Terraform::Docs diff --git a/mmv1/templates/terraform/examples/region_target_tcp_proxy_basic.tf.erb b/mmv1/templates/terraform/examples/region_target_tcp_proxy_basic.tf.erb new file mode 100644 index 000000000000..f8d48c7b12b7 --- /dev/null +++ b/mmv1/templates/terraform/examples/region_target_tcp_proxy_basic.tf.erb @@ -0,0 +1,31 @@ +# [START cloudloadbalancing_region_target_tcp_proxy_basic] +resource "google_compute_region_target_tcp_proxy" "default" { + provider = google-beta + name = "<%= ctx[:vars]['region_target_tcp_proxy_name'] %>" + region = "europe-west4" + backend_service = google_compute_region_backend_service.default.id +} + +resource "google_compute_region_backend_service" "default" { + provider = google-beta + name = "<%= ctx[:vars]['region_backend_service_name'] %>" + protocol = "TCP" + timeout_sec = 10 + region = "europe-west4" + + health_checks = [google_compute_region_health_check.default.id] + load_balancing_scheme = "INTERNAL_MANAGED" +} + +resource "google_compute_region_health_check" "default" { + provider = google-beta + name = "<%= ctx[:vars]['health_check_name'] %>" + region = "europe-west4" + timeout_sec = 1 + check_interval_sec = 1 + + tcp_health_check { + port = "80" + } +} +# [END cloudloadbalancing_region_target_tcp_proxy_basic] \ No newline at end of file diff --git a/mmv1/third_party/terraform/tests/resource_compute_region_target_tcp_proxy_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_region_target_tcp_proxy_test.go.erb new file mode 100644 index 000000000000..ed41b4ce832d --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_compute_region_target_tcp_proxy_test.go.erb @@ -0,0 +1,164 @@ +<% autogen_exception -%> +package google +<% unless version == 'ga' -%> + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccComputeRegionTargetTcpProxy_update(t *testing.T) { + t.Parallel() + + target := fmt.Sprintf("trtcp-test-%s", randString(t, 10)) + backend := fmt.Sprintf("trtcp-test-%s", randString(t, 10)) + hc := fmt.Sprintf("trtcp-test-%s", randString(t, 10)) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckComputeRegionTargetTcpProxyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionTargetTcpProxy_basic1(target, backend, hc), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionTargetTcpProxyExists( + t, "google_compute_region_target_tcp_proxy.foobar"), + ), + }, + { + ResourceName: "google_compute_region_target_tcp_proxy.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_compute_region_backend_service.foobar", + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_compute_region_health_check.zero", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccComputeRegionTargetTcpProxy_update2(target, backend, hc), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionTargetTcpProxyExists( + t, "google_compute_region_target_tcp_proxy.foobar"), + ), + }, + }, + }) +} + +func testAccCheckComputeRegionTargetTcpProxyExists(t *testing.T, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No ID is set") + } + + config := googleProviderConfig(t) + name := rs.Primary.Attributes["name"] + region := rs.Primary.Attributes["region"] + + found, err := config.NewComputeClient(config.userAgent).RegionTargetTcpProxies.Get( + config.Project, region, name).Do() + if err != nil { + return err + } + + if found.Name != name { + return fmt.Errorf("RegionTargetTcpProxy not found") + } + + return nil + } +} + +func testAccComputeRegionTargetTcpProxy_basic1(target, backend, hc string) string { + return fmt.Sprintf(` +resource "google_compute_region_target_tcp_proxy" "foobar" { + provider = google-beta + description = "Resource created for Terraform acceptance testing" + name = "%s" + backend_service = google_compute_region_backend_service.foobar.self_link + proxy_header = "NONE" + region = "us-central1" +} + +resource "google_compute_region_backend_service" "foobar" { + provider = google-beta + name = "%s" + protocol = "TCP" + health_checks = [google_compute_region_health_check.zero.self_link] + region = "us-central1" + + load_balancing_scheme = "INTERNAL_MANAGED" +} + +resource "google_compute_region_health_check" "zero" { + provider = google-beta + name = "%s" + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "443" + } + region = "us-central1" +} +`, target, backend, hc) +} + +func testAccComputeRegionTargetTcpProxy_update2(target, backend, hc string) string { + return fmt.Sprintf(` +resource "google_compute_region_target_tcp_proxy" "foobar" { + provider = google-beta + description = "Resource created for Terraform acceptance testing" + name = "%s" + backend_service = google_compute_region_backend_service.foobar2.self_link + proxy_header = "PROXY_V1" + region = "us-central1" +} + +resource "google_compute_region_backend_service" "foobar" { + provider = google-beta + name = "%s" + protocol = "TCP" + health_checks = [google_compute_region_health_check.zero.self_link] + region = "us-central1" + + load_balancing_scheme = "INTERNAL_MANAGED" +} + +resource "google_compute_region_backend_service" "foobar2" { + provider = google-beta + name = "%s-2" + protocol = "TCP" + health_checks = [google_compute_region_health_check.zero.self_link] + region = "us-central1" + + load_balancing_scheme = "INTERNAL_MANAGED" +} + +resource "google_compute_region_health_check" "zero" { + provider = google-beta + name = "%s" + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "443" + } + region = "us-central1" +} +`, target, backend, backend, hc) +} +<% end -%> \ No newline at end of file From 1a4adadd24d4d68f1723a944b8a73918b181eb41 Mon Sep 17 00:00:00 2001 From: Kevin Si Date: Tue, 4 Oct 2022 17:34:29 -0400 Subject: [PATCH 11/17] Bigtable: Retry GC policy operations with a longer poll interval (#6627) Co-authored-by: Riley Karson --- .../resources/resource_bigtable_gc_policy.go | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/mmv1/third_party/terraform/resources/resource_bigtable_gc_policy.go b/mmv1/third_party/terraform/resources/resource_bigtable_gc_policy.go index df3151e5667a..b511236301d5 100644 --- a/mmv1/third_party/terraform/resources/resource_bigtable_gc_policy.go +++ b/mmv1/third_party/terraform/resources/resource_bigtable_gc_policy.go @@ -202,10 +202,17 @@ func resourceBigtableGCPolicyUpsert(d *schema.ResourceData, meta interface{}) er tableName := d.Get("table").(string) columnFamily := d.Get("column_family").(string) - err = retryTimeDuration(func() error { + retryFunc := func() (interface{}, error) { reqErr := c.SetGCPolicy(ctx, tableName, columnFamily, gcPolicy) - return reqErr - }, d.Timeout(schema.TimeoutCreate), isBigTableRetryableError) + return "", reqErr + } + // The default create timeout is 20 minutes. + timeout := d.Timeout(schema.TimeoutCreate) + pollInterval := time.Duration(30) * time.Second + // Mutations to gc policies can only happen one-at-a-time and take some amount of time. + // Use a fixed polling rate of 30s based on the RetryInfo returned by the server rather than + // the standard up-to-10s exponential backoff for those operations. + _, err = retryWithPolling(retryFunc, timeout, pollInterval, isBigTableRetryableError) if err != nil { return err } @@ -376,10 +383,14 @@ func resourceBigtableGCPolicyDestroy(d *schema.ResourceData, meta interface{}) e defer c.Close() - err = retryTimeDuration(func() error { + retryFunc := func() (interface{}, error) { reqErr := c.SetGCPolicy(ctx, d.Get("table").(string), d.Get("column_family").(string), bigtable.NoGcPolicy()) - return reqErr - }, d.Timeout(schema.TimeoutDelete), isBigTableRetryableError) + return "", reqErr + } + // The default delete timeout is 20 minutes. + timeout := d.Timeout(schema.TimeoutDelete) + pollInterval := time.Duration(30) * time.Second + _, err = retryWithPolling(retryFunc, timeout, pollInterval, isBigTableRetryableError) if err != nil { return err } From 5b32e33ecde79fa58b9d944d810a9159a2fea363 Mon Sep 17 00:00:00 2001 From: Aaron Liberatore Date: Tue, 4 Oct 2022 14:55:07 -0700 Subject: [PATCH 12/17] Add resource override to tainted on create failures (#6632) --- mmv1/overrides/terraform/resource_override.rb | 8 +++++++- mmv1/templates/terraform/resource.erb | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/mmv1/overrides/terraform/resource_override.rb b/mmv1/overrides/terraform/resource_override.rb index 53da22a6ce4e..5fbb429ecefb 100644 --- a/mmv1/overrides/terraform/resource_override.rb +++ b/mmv1/overrides/terraform/resource_override.rb @@ -94,7 +94,12 @@ def self.attributes :read_error_transform, # If true, only generate tests and cgc samples - :cgc_only + :cgc_only, + + # If true, resources that failed creation will be marked as tainted. As a consequence + # these resources will be deleted and recreated on the next apply call. This pattern + # is preferred over deleting the resource directly in post_create_failure hooks. + :taint_resource_on_failed_create ] end @@ -130,6 +135,7 @@ def validate check :supports_indirect_user_project_override, type: :boolean, default: false check :read_error_transform, type: String check :cgc_only, type: :boolean, default: false + check :taint_resource_on_failed_create, type: :boolean, default: false end def apply(resource) diff --git a/mmv1/templates/terraform/resource.erb b/mmv1/templates/terraform/resource.erb index 6e607e10d5f8..6743adcdf6a1 100644 --- a/mmv1/templates/terraform/resource.erb +++ b/mmv1/templates/terraform/resource.erb @@ -284,8 +284,10 @@ func resource<%= resource_name -%>Create(d *schema.ResourceData, meta interface{ <% if object.custom_code.post_create_failure -%> resource<%= resource_name -%>PostCreateFailure(d, meta) <% end -%> +<% unless object.taint_resource_on_failed_create -%> // The resource didn't actually create d.SetId("") +<% end -%> return fmt.Errorf("Error waiting to create <%= object.name -%>: %s", err) } @@ -335,8 +337,10 @@ func resource<%= resource_name -%>Create(d *schema.ResourceData, meta interface{ <% if object.custom_code.post_create_failure -%> resource<%= resource_name -%>PostCreateFailure(d, meta) <% end -%> +<% unless object.taint_resource_on_failed_create -%> // The resource didn't actually create d.SetId("") +<% end -%> return fmt.Errorf("Error waiting to create <%= object.name -%>: %s", err) } From 799339c4fd197263d2ec3b11d32f0d271fa50e44 Mon Sep 17 00:00:00 2001 From: AlfatahB <111489009+AlfatahB@users.noreply.github.com> Date: Wed, 5 Oct 2022 16:13:50 +0000 Subject: [PATCH 13/17] Added custom_placement_config field in google_storage_bucket resource (#6619) --- .../resources/resource_storage_bucket.go.erb | 64 +++++++++++++++++++ .../tests/resource_storage_bucket_test.go.erb | 36 +++++++++++ .../docs/r/storage_bucket.html.markdown | 6 ++ 3 files changed, 106 insertions(+) diff --git a/mmv1/third_party/terraform/resources/resource_storage_bucket.go.erb b/mmv1/third_party/terraform/resources/resource_storage_bucket.go.erb index 5fc49a4fadd3..efe0460b9e8a 100644 --- a/mmv1/third_party/terraform/resources/resource_storage_bucket.go.erb +++ b/mmv1/third_party/terraform/resources/resource_storage_bucket.go.erb @@ -366,6 +366,27 @@ func resourceStorageBucket() *schema.Resource { 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.`, + }, <% unless version == "ga" -%> "public_access_prevention": { Type: schema.TypeString, @@ -491,6 +512,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error } } + if v, ok := d.GetOk("custom_placement_config"); ok { + sb.CustomPlacementConfig = expandBucketCustomPlacementConfig(v.([]interface{})) + } + var res *storage.Bucket err = retry(func() error { @@ -903,6 +928,42 @@ func flattenBucketEncryption(enc *storage.BucketEncryption) []map[string]interfa return encryption } +func expandBucketCustomPlacementConfig(configured interface{}) *storage.BucketCustomPlacementConfig { + cfcs := configured.([]interface{}) + if len(cfcs) == 0 || cfcs[0] == nil { + return nil + } + cfc := cfcs[0].(map[string]interface{}) + bucketcfc := &storage.BucketCustomPlacementConfig{ + DataLocations: expandBucketDataLocations(cfc["data_locations"]), + } + return bucketcfc +} + +func flattenBucketCustomPlacementConfig(cfc *storage.BucketCustomPlacementConfig) []map[string]interface{} { + customPlacementConfig := make([]map[string]interface{}, 0, 1) + + if cfc == nil { + return customPlacementConfig + } + + customPlacementConfig = append(customPlacementConfig, map[string]interface{}{ + "data_locations": cfc.DataLocations, + }) + + return customPlacementConfig +} + +func expandBucketDataLocations(configured interface{}) []string { + l := configured.(*schema.Set).List() + + req := make([]string, 0, len(l)) + for _, raw := range l { + req = append(req, raw.(string)) + } + return req +} + func expandBucketLogging(configured interface{}) *storage.BucketLogging { loggings := configured.([]interface{}) if len(loggings) == 0 { @@ -1445,6 +1506,9 @@ func setStorageBucket(d *schema.ResourceData, config *Config, res *storage.Bucke if err := d.Set("retention_policy", flattenBucketRetentionPolicy(res.RetentionPolicy)); err != nil { return fmt.Errorf("Error setting retention_policy: %s", err) } + if err := d.Set("custom_placement_config", flattenBucketCustomPlacementConfig(res.CustomPlacementConfig)); err != nil { + return fmt.Errorf("Error setting custom_placement_config: %s", err) + } if res.IamConfiguration != nil && res.IamConfiguration.UniformBucketLevelAccess != nil { if err := d.Set("uniform_bucket_level_access", res.IamConfiguration.UniformBucketLevelAccess.Enabled); err != nil { diff --git a/mmv1/third_party/terraform/tests/resource_storage_bucket_test.go.erb b/mmv1/third_party/terraform/tests/resource_storage_bucket_test.go.erb index 6cf46ee00037..6be21bc53e82 100644 --- a/mmv1/third_party/terraform/tests/resource_storage_bucket_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_storage_bucket_test.go.erb @@ -104,6 +104,29 @@ func TestAccStorageBucket_lowercaseLocation(t *testing.T) { }) } +func TestAccStorageBucket_dualLocation(t *testing.T) { + t.Parallel() + + bucketName := testBucketName(t) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccStorageBucketDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccStorageBucket_dualLocation(bucketName), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + }, + }) +} + func TestAccStorageBucket_customAttributes(t *testing.T) { t.Parallel() @@ -1312,6 +1335,19 @@ resource "google_storage_bucket" "bucket" { `, bucketName) } +func testAccStorageBucket_dualLocation(bucketName string) string { + return fmt.Sprintf(` +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "ASIA" + force_destroy = true + custom_placement_config { + data_locations = ["ASIA-EAST1", "ASIA-SOUTHEAST1"] + } +} +`, bucketName) +} + func testAccStorageBucket_customAttributes(bucketName string) string { return fmt.Sprintf(` resource "google_storage_bucket" "bucket" { diff --git a/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown b/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown index 154b1312d2ab..46d34633d697 100644 --- a/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/storage_bucket.html.markdown @@ -101,6 +101,8 @@ The following arguments are supported: * `uniform_bucket_level_access` - (Optional, Default: false) Enables [Uniform bucket-level access](https://cloud.google.com/storage/docs/uniform-bucket-level-access) access to a bucket. +* `custom_placement_config` - (Optional) 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. Structure is [documented below](#nested_custom_placement_config). + The `lifecycle_rule` block supports: * `action` - (Required) The Lifecycle Rule's action configuration. A single block of this type is supported. Structure is [documented below](#nested_action). @@ -189,6 +191,10 @@ The following arguments are supported: state of the project. You should take care for race conditions when the same Terraform manages IAM policy on the Cloud KMS crypto key. See the data source page for more details. +The `custom_placement_config` block supports: + +* `data_locations` - (Required) The list of individual regions that comprise a dual-region bucket. See [Cloud Storage bucket locations](https://cloud.google.com/storage/docs/dual-regions#availability) for a list of acceptable regions. **Note**: If any of the data_locations changes, it will [recreate the bucket](https://cloud.google.com/storage/docs/locations#key-concepts). + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are From 37ae11ea97e0b641d55bb0f239a9d1e6091523eb Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Wed, 5 Oct 2022 20:45:13 +0300 Subject: [PATCH 14/17] dataproc metastore - add BQ support (#6631) --- mmv1/products/metastore/api.yaml | 5 +-- mmv1/products/metastore/terraform.yaml | 7 ++++ ...dataproc_metastore_federation_basic.tf.erb | 8 ++--- ...aproc_metastore_federation_bigquery.tf.erb | 35 +++++++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 mmv1/templates/terraform/examples/dataproc_metastore_federation_bigquery.tf.erb diff --git a/mmv1/products/metastore/api.yaml b/mmv1/products/metastore/api.yaml index e30536d015d4..183a37f60d2d 100644 --- a/mmv1/products/metastore/api.yaml +++ b/mmv1/products/metastore/api.yaml @@ -379,7 +379,7 @@ objects: name: 'name' required: true description: | - The relative resource name of the metastore that is being federated. + The relative resource name of the metastore that is being federated. The formats of the relative resource names for the currently supported metastores are listed below: Dataplex: projects/{projectId}/locations/{location}/lakes/{lake_id} BigQuery: projects/{projectId} Dataproc Metastore: projects/{projectId}/locations/{location}/services/{serviceId} - !ruby/object:Api::Type::Enum name: 'metastoreType' required: true @@ -387,4 +387,5 @@ objects: The type of the backend metastore. values: - :METASTORE_TYPE_UNSPECIFIED - - :DATAPROC_METASTORE + - :DATAPROC_METASTORE + - :BIGQUERY diff --git a/mmv1/products/metastore/terraform.yaml b/mmv1/products/metastore/terraform.yaml index a8400fa94417..e0cf0e832270 100644 --- a/mmv1/products/metastore/terraform.yaml +++ b/mmv1/products/metastore/terraform.yaml @@ -81,3 +81,10 @@ overrides: !ruby/object:Overrides::ResourceOverrides primary_resource_name: 'fmt.Sprintf("tf-test-metastore-fed%s", context["random_suffix"])' vars: metastore_federation_name: "fed-1" + - !ruby/object:Provider::Terraform::Examples + name: "dataproc_metastore_federation_bigquery" + primary_resource_id: "default" + min_version: beta + primary_resource_name: 'fmt.Sprintf("tf-test-metastore-fed-bq%s", context["random_suffix"])' + vars: + metastore_federation_name: "fed-2" diff --git a/mmv1/templates/terraform/examples/dataproc_metastore_federation_basic.tf.erb b/mmv1/templates/terraform/examples/dataproc_metastore_federation_basic.tf.erb index 2e8562cda1d4..20f417ec0f2d 100644 --- a/mmv1/templates/terraform/examples/dataproc_metastore_federation_basic.tf.erb +++ b/mmv1/templates/terraform/examples/dataproc_metastore_federation_basic.tf.erb @@ -5,10 +5,10 @@ resource "google_dataproc_metastore_federation" "<%= ctx[:primary_resource_id] % version = "3.1.2" backend_metastores { - rank = "1" - name = google_dataproc_metastore_service.<%= ctx[:primary_resource_id] %>.id - metastore_type = "DATAPROC_METASTORE" - } + rank = "1" + name = google_dataproc_metastore_service.<%= ctx[:primary_resource_id] %>.id + metastore_type = "DATAPROC_METASTORE" + } } resource "google_dataproc_metastore_service" "<%= ctx[:primary_resource_id] %>" { diff --git a/mmv1/templates/terraform/examples/dataproc_metastore_federation_bigquery.tf.erb b/mmv1/templates/terraform/examples/dataproc_metastore_federation_bigquery.tf.erb new file mode 100644 index 000000000000..495412fc19bb --- /dev/null +++ b/mmv1/templates/terraform/examples/dataproc_metastore_federation_bigquery.tf.erb @@ -0,0 +1,35 @@ +resource "google_dataproc_metastore_federation" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + location = "us-central1" + federation_id = "<%= ctx[:vars]['metastore_federation_name'] %>" + version = "3.1.2" + + backend_metastores { + rank = "2" + name = data.google_project.project.id + metastore_type = "BIGQUERY" + } + + backend_metastores { + rank = "1" + name = google_dataproc_metastore_service.<%= ctx[:primary_resource_id] %>.id + metastore_type = "DATAPROC_METASTORE" + } +} + +resource "google_dataproc_metastore_service" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + service_id = "<%= ctx[:vars]['metastore_federation_name'] %>" + location = "us-central1" + tier = "DEVELOPER" + + + hive_metastore_config { + version = "3.1.2" + endpoint_protocol = "GRPC" + } +} + +data "google_project" "project" { + provider = google-beta +} From 6ba55a35fe3cb35c607ff9d58589186e5b9f7bac Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Wed, 5 Oct 2022 21:26:25 +0300 Subject: [PATCH 15/17] bigquery datamasking (#6425) * data masking * data masking - examples * import * cr comments * cr comments - update test * align with connection resource --- mmv1/products/bigquerydatapolicy/api.yaml | 97 +++++++++++++++++++ .../bigquerydatapolicy/terraform.yaml | 36 +++++++ ...gquery_datapolicy_data_policy_basic.tf.erb | 22 +++++ ...igquery_datapolicy_data_policy_test.go.erb | 74 ++++++++++++++ 4 files changed, 229 insertions(+) create mode 100644 mmv1/products/bigquerydatapolicy/api.yaml create mode 100644 mmv1/products/bigquerydatapolicy/terraform.yaml create mode 100644 mmv1/templates/terraform/examples/bigquery_datapolicy_data_policy_basic.tf.erb create mode 100644 mmv1/third_party/terraform/tests/resource_bigquery_datapolicy_data_policy_test.go.erb diff --git a/mmv1/products/bigquerydatapolicy/api.yaml b/mmv1/products/bigquerydatapolicy/api.yaml new file mode 100644 index 000000000000..0f4634167df9 --- /dev/null +++ b/mmv1/products/bigquerydatapolicy/api.yaml @@ -0,0 +1,97 @@ +# Copyright 2022 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: BigqueryDatapolicy +display_name: BigQuery Data Policy +scopes: + - https://www.googleapis.com/auth/cloud-platform +versions: + - !ruby/object:Api::Product::Version + name: beta + base_url: https://bigquerydatapolicy.googleapis.com/v1beta1/ +apis_required: + - !ruby/object:Api::Product::ApiReference + name: BigQuery Data Policy API + url: https://console.cloud.google.com/apis/library/bigquerydatapolicy.googleapis.com/ +objects: + - !ruby/object:Api::Resource + name: "DataPolicy" + min_version: beta + base_url: projects/{{project}}/locations/{{location}}/dataPolicies + create_url: projects/{{project}}/locations/{{location}}/dataPolicies + self_link: projects/{{project}}/locations/{{location}}/dataPolicies/{{data_policy_id}} + update_verb: :PATCH + update_mask: true + description: A BigQuery Data Policy + references: !ruby/object:Api::Resource::ReferenceLinks + guides: + "Official Documentation": "https://cloud.google.com/bigquery/docs/column-data-masking-intro" + api: "https://cloud.google.com/bigquery/docs/reference/bigquerydatapolicy/rest/v1beta1/projects.locations.dataPolicies/create" + iam_policy: !ruby/object:Api::Resource::IamPolicy + exclude: false + method_name_separator: ":" + fetch_iam_policy_verb: :POST + parent_resource_attribute: "data_policy_id" + import_format: + [ + "projects/{{project}}/locations/{{location}}/dataPolicies/{{data_policy_id}}", + "{{data_policy_id}}" + ] + properties: + - !ruby/object:Api::Type::String + name: name + description: |- + Resource name of this data policy, in the format of projects/{project_number}/locations/{locationId}/dataPolicies/{dataPolicyId}. + output: true + - !ruby/object:Api::Type::String + name: dataPolicyId + description: |- + User-assigned (human readable) ID of the data policy that needs to be unique within a project. Used as {dataPolicyId} in part of the resource name. + required: true + input: true + - !ruby/object:Api::Type::String + name: location + description: | + The name of the location of the data policy. + required: true + input: true + url_param_only: true + - !ruby/object:Api::Type::String + name: policyTag + description: |- + Policy tag resource name, in the format of projects/{project_number}/locations/{locationId}/taxonomies/{taxonomyId}/policyTags/{policyTag_id}. + required: true + - !ruby/object:Api::Type::Enum + name: dataPolicyType + description: | + The enrollment level of the service. + required: true + values: + - :COLUMN_LEVEL_SECURITY_POLICY + - :DATA_MASKING_POLICY + - !ruby/object:Api::Type::NestedObject + name: "dataMaskingPolicy" + description: | + The data masking policy that specifies the data masking rule to use. + properties: + - !ruby/object:Api::Type::Enum + name: "predefinedExpression" + required: true + description: |- + The available masking rules. Learn more here: https://cloud.google.com/bigquery/docs/column-data-masking-intro#masking_options. + values: + - :SHA256 + - :ALWAYS_NULL + - :DEFAULT_MASKING_VALUE diff --git a/mmv1/products/bigquerydatapolicy/terraform.yaml b/mmv1/products/bigquerydatapolicy/terraform.yaml new file mode 100644 index 000000000000..90763c880703 --- /dev/null +++ b/mmv1/products/bigquerydatapolicy/terraform.yaml @@ -0,0 +1,36 @@ +# Copyright 2022 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:Provider::Terraform::Config +overrides: !ruby/object:Overrides::ResourceOverrides + DataPolicy: !ruby/object:Overrides::Terraform::ResourceOverride + id_format: projects/{{project}}/locations/{{location}}/dataPolicies/{{data_policy_id}} + import_format: + [ + "projects/{{project}}/locations/{{location}}/dataPolicies/{{data_policy_id}}", + "{{project}}/{{location}}/{{data_policy_id}}", + "{{location}}/{{data_policy_id}}" + ] + examples: + - !ruby/object:Provider::Terraform::Examples + name: "bigquery_datapolicy_data_policy_basic" + min_version: beta + primary_resource_id: "data_policy" + primary_resource_name: 'fmt.Sprintf("tf_test_data_policy%s", context["random_suffix"])' + vars: + data_policy_id: "data_policy" + taxonomy: "taxonomy" + properties: + policyTag: !ruby/object:Overrides::Terraform::PropertyOverride + diff_suppress_func: "projectNumberDiffSuppress" diff --git a/mmv1/templates/terraform/examples/bigquery_datapolicy_data_policy_basic.tf.erb b/mmv1/templates/terraform/examples/bigquery_datapolicy_data_policy_basic.tf.erb new file mode 100644 index 000000000000..2be6dfea1de0 --- /dev/null +++ b/mmv1/templates/terraform/examples/bigquery_datapolicy_data_policy_basic.tf.erb @@ -0,0 +1,22 @@ +resource "google_bigquery_datapolicy_data_policy" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + location = "us-central1" + data_policy_id = "<%= ctx[:vars]['data_policy_id'] %>" + policy_tag = google_data_catalog_policy_tag.policy_tag.name + data_policy_type = "COLUMN_LEVEL_SECURITY_POLICY" + } + + resource "google_data_catalog_policy_tag" "policy_tag" { + provider = google-beta + taxonomy = google_data_catalog_taxonomy.taxonomy.id + display_name = "Low security" + description = "A policy tag normally associated with low security items" + } + + resource "google_data_catalog_taxonomy" "taxonomy" { + provider = google-beta + region = "us-central1" + display_name = "<%= ctx[:vars]['taxonomy'] %>" + description = "A collection of policy tags" + activated_policy_types = ["FINE_GRAINED_ACCESS_CONTROL"] + } \ No newline at end of file diff --git a/mmv1/third_party/terraform/tests/resource_bigquery_datapolicy_data_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_bigquery_datapolicy_data_policy_test.go.erb new file mode 100644 index 000000000000..529786211466 --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_bigquery_datapolicy_data_policy_test.go.erb @@ -0,0 +1,74 @@ +<% autogen_exception -%> +package google + +<% unless version == 'ga' -%> + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccBigqueryDatapolicyDataPolicy_bigqueryDatapolicyDataPolicyUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProvidersOiCS, + CheckDestroy: testAccCheckBigqueryDatapolicyDataPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigqueryDatapolicyDataPolicy_bigqueryDatapolicyDataPolicyBasicExample(context), + }, + { + ResourceName: "google_bigquery_datapolicy_data_policy.data_policy", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location"}, + }, + { + Config: testAccBigqueryDatapolicyDataPolicy_bigqueryDatapolicyDataPolicyUpdate(context), + }, + }, + }) +} + +func testAccBigqueryDatapolicyDataPolicy_bigqueryDatapolicyDataPolicyUpdate(context map[string]interface{}) string { + return Nprintf(` +resource "google_bigquery_datapolicy_data_policy" "data_policy" { + provider = google-beta + location = "us-central1" + data_policy_id = "tf_test_data_policy%{random_suffix}" + policy_tag = google_data_catalog_policy_tag.policy_tag_updated.name + data_policy_type = "COLUMN_LEVEL_SECURITY_POLICY" + } + + resource "google_data_catalog_policy_tag" "policy_tag" { + provider = google-beta + taxonomy = google_data_catalog_taxonomy.taxonomy.id + display_name = "Low security" + description = "A policy tag normally associated with low security items" + } + + resource "google_data_catalog_policy_tag" "policy_tag_updated" { + provider = google-beta + taxonomy = google_data_catalog_taxonomy.taxonomy.id + display_name = "Low security updated" + description = "A policy tag normally associated with low security items" + } + + resource "google_data_catalog_taxonomy" "taxonomy" { + provider = google-beta + region = "us-central1" + display_name = "taxonomy%{random_suffix}" + description = "A collection of policy tags" + activated_policy_types = ["FINE_GRAINED_ACCESS_CONTROL"] + } +`, context) +} + +<% end %> \ No newline at end of file From cf350d176765b49a9d0f2d0eb198b092ef13c050 Mon Sep 17 00:00:00 2001 From: Edward Sun <42220489+edwardmedia@users.noreply.github.com> Date: Wed, 5 Oct 2022 14:11:02 -0700 Subject: [PATCH 16/17] update import format (#6640) Co-authored-by: Edward Sun --- mmv1/products/secretmanager/terraform.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/secretmanager/terraform.yaml b/mmv1/products/secretmanager/terraform.yaml index a578ddf7ac38..46ef32a4def2 100644 --- a/mmv1/products/secretmanager/terraform.yaml +++ b/mmv1/products/secretmanager/terraform.yaml @@ -40,6 +40,7 @@ overrides: !ruby/object:Overrides::ResourceOverrides vars: secret_id: "secret-version" data: "secret-data" + import_format: ["projects/{{%project}}/secrets/{{%secret_id}}/versions/{{%version}}"] custom_code: !ruby/object:Provider::Terraform::CustomCode custom_import: templates/terraform/custom_import/self_link_as_name.erb post_create: templates/terraform/post_create/secret_version.go.erb From 45c341dd2aa044bf719df8111175143ca67c0390 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Wed, 5 Oct 2022 15:09:22 -0700 Subject: [PATCH 17/17] Revert "Add the vertex endpoint resource. (#6583)" (#6654) This reverts commit 1750a0751ae82d73ea1c63d32d7a163c25efb227. --- mmv1/products/vertexai/api.yaml | 210 ------------------ mmv1/products/vertexai/terraform.yaml | 19 -- .../vertex_ai_endpoint_network.tf.erb | 41 ---- 3 files changed, 270 deletions(-) delete mode 100644 mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb diff --git a/mmv1/products/vertexai/api.yaml b/mmv1/products/vertexai/api.yaml index fae09d3f9dcb..e62e71a89701 100644 --- a/mmv1/products/vertexai/api.yaml +++ b/mmv1/products/vertexai/api.yaml @@ -96,7 +96,6 @@ objects: description: | Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key. The key needs to be in the same region as where the resource is created. - required: true input: true - !ruby/object:Api::Type::String name: 'metadataSchemaUri' @@ -104,214 +103,6 @@ objects: input: true description: | Points to a YAML file stored on Google Cloud Storage describing additional information about the Dataset. The schema is defined as an OpenAPI 3.0.2 Schema Object. The schema files that can be used here are found in gs://google-cloud-aiplatform/schema/dataset/metadata/. - -# Vertex AI Endpoints - - !ruby/object:Api::Resource - name: Endpoint - base_url: projects/{{project}}/locations/{{location}}/endpoints - create_url: projects/{{project}}/locations/{{location}}/endpoints - self_link: 'projects/{{project}}/locations/{{location}}/endpoints/{{name}}' - update_verb: :PATCH - update_mask: true - references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Official Documentation': - 'https://cloud.google.com/vertex-ai/docs' - api: 'https://cloud.google.com/vertex-ai/docs/reference/rest/v1beta1/projects.locations.endpoints' - 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' - message: 'message' - description: "Models are deployed into it, and afterwards Endpoint is called to obtain predictions and explanations." - parameters: - - !ruby/object:Api::Type::String - name: location - description: The location for the resource - url_param_only: true - input: true - properties: - - !ruby/object:Api::Type::String - name: name - description: Output only. The resource name of the Endpoint. - output: true - - !ruby/object:Api::Type::String - name: displayName - description: Required. The display name of the Endpoint. The name can be up to 128 characters long and can consist of any UTF-8 characters. - required: true - - !ruby/object:Api::Type::String - name: description - description: The description of the Endpoint. - - !ruby/object:Api::Type::Array - name: deployedModels - description: Output only. The models deployed in this Endpoint. To add or remove DeployedModels use EndpointService.DeployModel and EndpointService.UndeployModel respectively. - output: true - item_type: !ruby/object:Api::Type::NestedObject - name: deployedModels - description: Output only. The models deployed in this Endpoint. To add or remove DeployedModels use EndpointService.DeployModel and EndpointService.UndeployModel respectively. - properties: - - !ruby/object:Api::Type::NestedObject - name: dedicatedResources - description: A description of resources that are dedicated to the DeployedModel, and that need a higher degree of manual configuration. - output: true - properties: - - !ruby/object:Api::Type::NestedObject - name: machineSpec - description: The specification of a single machine used by the prediction. - output: true - properties: - - !ruby/object:Api::Type::String - name: machineType - description: 'The type of the machine. See the [list of machine types supported for prediction](https://cloud.google.com/vertex-ai/docs/predictions/configure-compute#machine-types) See the [list of machine types supported for custom training](https://cloud.google.com/vertex-ai/docs/training/configure-compute#machine-types). For DeployedModel this field is optional, and the default value is `n1-standard-2`. For BatchPredictionJob or as part of WorkerPoolSpec this field is required. TODO(rsurowka): Try to better unify the required vs optional.' - output: true - - !ruby/object:Api::Type::String - name: acceleratorType - description: The type of accelerator(s) that may be attached to the machine as per accelerator_count. See possible values [here](https://cloud.google.com/vertex-ai/docs/reference/rest/v1/MachineSpec#AcceleratorType). - output: true - - !ruby/object:Api::Type::Integer - name: acceleratorCount - description: The number of accelerators to attach to the machine. - output: true - - !ruby/object:Api::Type::Integer - name: minReplicaCount - description: The minimum number of machine replicas this DeployedModel will be always deployed on. This value must be greater than or equal to 1. If traffic against the DeployedModel increases, it may dynamically be deployed onto more replicas, and as traffic decreases, some of these extra replicas may be freed. - output: true - - !ruby/object:Api::Type::Integer - name: maxReplicaCount - description: The maximum number of replicas this DeployedModel may be deployed on when the traffic against it increases. If the requested value is too large, the deployment will error, but if deployment succeeds then the ability to scale the model to that many replicas is guaranteed (barring service outages). If traffic against the DeployedModel increases beyond what its replicas at maximum may handle, a portion of the traffic will be dropped. If this value is not provided, will use min_replica_count as the default value. The value of this field impacts the charge against Vertex CPU and GPU quotas. Specifically, you will be charged for max_replica_count * number of cores in the selected machine type) and (max_replica_count * number of GPUs per replica in the selected machine type). - output: true - - !ruby/object:Api::Type::Array - name: autoscalingMetricSpecs - description: The metric specifications that overrides a resource utilization metric (CPU utilization, accelerator's duty cycle, and so on) target value (default to 60 if not set). At most one entry is allowed per metric. If machine_spec.accelerator_count is above 0, the autoscaling will be based on both CPU utilization and accelerator's duty cycle metrics and scale up when either metrics exceeds its target value while scale down if both metrics are under their target value. The default target value is 60 for both metrics. If machine_spec.accelerator_count is 0, the autoscaling will be based on CPU utilization metric only with default target value 60 if not explicitly set. For example, in the case of Online Prediction, if you want to override target CPU utilization to 80, you should set autoscaling_metric_specs.metric_name to `aiplatform.googleapis.com/prediction/online/cpu/utilization` and autoscaling_metric_specs.target to `80`. - output: true - item_type: !ruby/object:Api::Type::NestedObject - name: autoscalingMetricSpecs - description: The metric specifications that overrides a resource utilization metric (CPU utilization, accelerator's duty cycle, and so on) target value (default to 60 if not set). At most one entry is allowed per metric. If machine_spec.accelerator_count is above 0, the autoscaling will be based on both CPU utilization and accelerator's duty cycle metrics and scale up when either metrics exceeds its target value while scale down if both metrics are under their target value. The default target value is 60 for both metrics. If machine_spec.accelerator_count is 0, the autoscaling will be based on CPU utilization metric only with default target value 60 if not explicitly set. For example, in the case of Online Prediction, if you want to override target CPU utilization to 80, you should set autoscaling_metric_specs.metric_name to `aiplatform.googleapis.com/prediction/online/cpu/utilization` and autoscaling_metric_specs.target to `80`. - properties: - - !ruby/object:Api::Type::String - name: metricName - description: 'The resource metric name. Supported metrics: * For Online Prediction: * `aiplatform.googleapis.com/prediction/online/accelerator/duty_cycle` * `aiplatform.googleapis.com/prediction/online/cpu/utilization`' - output: true - - !ruby/object:Api::Type::Integer - name: target - description: The target resource utilization in percentage (1% - 100%) for the given metric; once the real usage deviates from the target by a certain percentage, the machine replicas change. The default value is 60 (representing 60%) if not provided. - output: true - - !ruby/object:Api::Type::NestedObject - name: automaticResources - description: A description of resources that to large degree are decided by Vertex AI, and require only a modest additional configuration. - output: true - properties: - - !ruby/object:Api::Type::Integer - name: minReplicaCount - description: The minimum number of replicas this DeployedModel will be always deployed on. If traffic against it increases, it may dynamically be deployed onto more replicas up to max_replica_count, and as traffic decreases, some of these extra replicas may be freed. If the requested value is too large, the deployment will error. - output: true - - !ruby/object:Api::Type::Integer - name: maxReplicaCount - description: The maximum number of replicas this DeployedModel may be deployed on when the traffic against it increases. If the requested value is too large, the deployment will error, but if deployment succeeds then the ability to scale the model to that many replicas is guaranteed (barring service outages). If traffic against the DeployedModel increases beyond what its replicas at maximum may handle, a portion of the traffic will be dropped. If this value is not provided, a no upper bound for scaling under heavy traffic will be assume, though Vertex AI may be unable to scale beyond certain replica number. - output: true - - !ruby/object:Api::Type::String - name: id - description: The ID of the DeployedModel. If not provided upon deployment, Vertex AI will generate a value for this ID. This value should be 1-10 characters, and valid characters are /[0-9]/. - output: true - - !ruby/object:Api::Type::String - name: model - description: The name of the Model that this is the deployment of. Note that the Model may be in a different location than the DeployedModel's Endpoint. - output: true - - !ruby/object:Api::Type::String - name: modelVersionId - description: Output only. The version ID of the model that is deployed. - output: true - - !ruby/object:Api::Type::String - name: displayName - description: The display name of the DeployedModel. If not provided upon creation, the Model's display_name is used. - output: true - - !ruby/object:Api::Type::String - name: createTime - description: Output only. Timestamp when the DeployedModel was created. - output: true - - !ruby/object:Api::Type::String - name: serviceAccount - description: The service account that the DeployedModel's container runs as. Specify the email address of the service account. If this service account is not specified, the container runs as a service account that doesn't have access to the resource project. Users deploying the Model must have the `iam.serviceAccounts.actAs` permission on this service account. - output: true - - !ruby/object:Api::Type::Boolean - name: enableAccessLogging - description: These logs are like standard server access logs, containing information like timestamp and latency for each prediction request. Note that Stackdriver logs may incur a cost, especially if your project receives prediction requests at a high queries per second rate (QPS). Estimate your costs before enabling this option. - output: true - - !ruby/object:Api::Type::NestedObject - name: privateEndpoints - description: Output only. Provide paths for users to send predict/explain/health requests directly to the deployed model services running on Cloud via private services access. This field is populated if network is configured. - output: true - properties: - - !ruby/object:Api::Type::String - name: predictHttpUri - description: Output only. Http(s) path to send prediction requests. - output: true - - !ruby/object:Api::Type::String - name: explainHttpUri - description: Output only. Http(s) path to send explain requests. - output: true - - !ruby/object:Api::Type::String - name: healthHttpUri - description: Output only. Http(s) path to send health check requests. - output: true - - !ruby/object:Api::Type::String - name: serviceAttachment - description: Output only. The name of the service attachment resource. Populated if private service connect is enabled. - output: true - - !ruby/object:Api::Type::String - name: sharedResources - description: 'The resource name of the shared DeploymentResourcePool to deploy on. Format: projects/{project}/locations/{location}/deploymentResourcePools/{deployment_resource_pool}' - output: true - - !ruby/object:Api::Type::Boolean - name: enableContainerLogging - description: If true, the container of the DeployedModel instances will send `stderr` and `stdout` streams to Stackdriver Logging. Only supported for custom-trained Models and AutoML Tabular Models. - output: true - - !ruby/object:Api::Type::String - name: etag - description: Used to perform consistent read-modify-write updates. If not set, a blind "overwrite" update happens. - output: true - - !ruby/object:Api::Type::KeyValuePairs - 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), can only contain lowercase letters, numeric characters, underscores and dashes. International characters are allowed. See https://goo.gl/xmQnxf for more information and examples of labels. - - !ruby/object:Api::Type::String - name: createTime - description: Output only. Timestamp when this Endpoint was created. - output: true - - !ruby/object:Api::Type::String - name: updateTime - description: Output only. Timestamp when this Endpoint was last updated. - output: true - - !ruby/object:Api::Type::NestedObject - name: encryptionSpec - description: Customer-managed encryption key spec for an Endpoint. If set, this Endpoint and all sub-resources of this Endpoint will be secured by this key. - input: true - properties: - - !ruby/object:Api::Type::String - name: kmsKeyName - description: 'Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: `projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key`. The key needs to be in the same region as where the compute resource is created.' - required: true - input: true - - !ruby/object:Api::Type::String - name: network - description: 'The full name of the Google Compute Engine [network](https://cloud.google.com//compute/docs/networks-and-firewalls#networks) to which the Endpoint should be peered. Private services access must already be configured for the network. If left unspecified, the Endpoint is not peered with any network. Only one of the fields, network or enable_private_service_connect, can be set. [Format](https://cloud.google.com/compute/docs/reference/rest/v1/networks/insert): `projects/{project}/global/networks/{network}`. Where `{project}` is a project number, as in `12345`, and `{network}` is network name.' - input: true - - !ruby/object:Api::Type::String - name: modelDeploymentMonitoringJob - description: 'Output only. Resource name of the Model Monitoring job associated with this Endpoint if monitoring is enabled by CreateModelDeploymentMonitoringJob. Format: `projects/{project}/locations/{location}/modelDeploymentMonitoringJobs/{model_deployment_monitoring_job}`' - output: true - # Vertex AI Featurestores - !ruby/object:Api::Resource name: Featurestore @@ -631,7 +422,6 @@ objects: description: | Required. The Cloud KMS resource identifier of the customer managed encryption key used to protect a resource. Has the form: projects/my-project/locations/my-region/keyRings/my-kr/cryptoKeys/my-key. The key needs to be in the same region as where the resource is created. - required: true input: true - !ruby/object:Api::Type::NestedObject name: 'state' diff --git a/mmv1/products/vertexai/terraform.yaml b/mmv1/products/vertexai/terraform.yaml index a4d1e8e08a68..a8edc29f1d2e 100644 --- a/mmv1/products/vertexai/terraform.yaml +++ b/mmv1/products/vertexai/terraform.yaml @@ -30,25 +30,6 @@ overrides: !ruby/object:Overrides::ResourceOverrides default_from_api: true region: !ruby/object:Overrides::Terraform::PropertyOverride default_from_api: true - Endpoint: !ruby/object:Overrides::Terraform::ResourceOverride - examples: - - !ruby/object:Provider::Terraform::Examples - name: "vertex_ai_endpoint_network" - primary_resource_id: "endpoint" - vars: - name: "vertex_ai_endpoint" - project: "vertex-ai" - address_name: "address-name" - kms_key_name: "kms-name" - network_name: "network-name" - test_vars_overrides: - kms_key_name: 'BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' - network_name: 'BootstrapSharedTestNetwork(t, "vertex")' - properties: - etag: !ruby/object:Overrides::Terraform::PropertyOverride - ignore_read: true - name: !ruby/object:Overrides::Terraform::PropertyOverride - custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb Featurestore: !ruby/object:Overrides::Terraform::ResourceOverride autogen_async: false skip_sweeper: true diff --git a/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb b/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb deleted file mode 100644 index 4de7864561db..000000000000 --- a/mmv1/templates/terraform/examples/vertex_ai_endpoint_network.tf.erb +++ /dev/null @@ -1,41 +0,0 @@ -resource "google_vertex_ai_endpoint" "<%= ctx[:primary_resource_id] %>" { - display_name = "sample-endpoint" - description = "A sample vertex endpoint" - location = "us-central1" - labels = { - label-one = "value-one" - } - network = "projects/${data.google_project.project.number}/global/networks/${data.google_compute_network.vertex_network.name}" - encryption_spec { - kms_key_name = "<%= ctx[:vars]['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 = "<%= ctx[:vars]['address_name'] %>" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 24 - network = data.google_compute_network.vertex_network.id -} - -data "google_compute_network" "vertex_network" { - name = "<%= ctx[:vars]['network_name'] %>" -} - -resource "google_kms_crypto_key_iam_member" "crypto_key" { - crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-aiplatform.iam.gserviceaccount.com" -} - -data "google_project" "project" {}