From 337e6ac22304a75cf0c1dfe0f7a7fa68fec4ba0e Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Mon, 20 Nov 2023 20:20:55 +0000 Subject: [PATCH 001/107] Update `SKIP_PROJECT_SWEEPER` value in TeamCity configuration files (#9500) --- .../terraform/.teamcity/components/generated/project.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/.teamcity/components/generated/project.erb b/mmv1/third_party/terraform/.teamcity/components/generated/project.erb index 142df723ffac..65e95bbff895 100644 --- a/mmv1/third_party/terraform/.teamcity/components/generated/project.erb +++ b/mmv1/third_party/terraform/.teamcity/components/generated/project.erb @@ -64,7 +64,7 @@ fun Google<%= version.capitalize unless version == 'ga' -%>(environment: String, param("BRANCH_NAME", branchRef) <% unless version == 'ga' -%> // Skip the sweeper for project resources in the Beta tests only - param("env.SKIP_PROJECT_SWEEPER", 1) + param("env.SKIP_PROJECT_SWEEPER", "1") <% end -%> // Not used, but making `environment` a param makes the value visible to non-admins in TeamCity param("ENVIRONMENT", environment) @@ -118,4 +118,4 @@ class NightlyTriggerConfiguration(environment: String, branchRef: String, nightl var daysOfWeek = daysOfWeek var daysOfMonth = daysOfMonth -} \ No newline at end of file +} From 779dab0095ec40f8a5062a1b8ff21cdf811c4857 Mon Sep 17 00:00:00 2001 From: Edward Sun <42220489+edwardmedia@users.noreply.github.com> Date: Mon, 20 Nov 2023 12:28:23 -0800 Subject: [PATCH 002/107] fix random_suffix (#9476) * fix resource_name * update * add tf-test- --------- Co-authored-by: Edward Sun --- mmv1/products/gkehub2/Scope.yaml | 4 +++- mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mmv1/products/gkehub2/Scope.yaml b/mmv1/products/gkehub2/Scope.yaml index 70ffbabfdaac..7c12b64c03b4 100644 --- a/mmv1/products/gkehub2/Scope.yaml +++ b/mmv1/products/gkehub2/Scope.yaml @@ -56,8 +56,10 @@ iam_policy: !ruby/object:Api::Resource::IamPolicy examples: - !ruby/object:Provider::Terraform::Examples name: 'gkehub_scope_basic' - primary_resource_name: 'fmt.Sprintf("tf-test-scope%s", context["random_suffix"])' + primary_resource_name: 'fmt.Sprintf("tf-test-my-scope%s", context["random_suffix"])' primary_resource_id: 'scope' + vars: + resource_name: 'my-scope' test_env_vars: project: :PROJECT_NAME # Skip sweeper gen since this is a child resource. diff --git a/mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb index 9585375e4e1f..107fa956c82d 100644 --- a/mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb @@ -1,5 +1,5 @@ resource "google_gke_hub_scope" "<%= ctx[:primary_resource_id] %>" { - scope_id = "tf-test-scope%{random_suffix}" + scope_id = "<%= ctx[:vars]['resource_name'] %>" labels = { keyb = "valueb" keya = "valuea" From 8b4bc60ab3336bc995e016c7a56f5d241b641d7c Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 20 Nov 2023 13:23:27 -0800 Subject: [PATCH 003/107] Move tpgtools/handwritten folder to mmv1/third_party/terraform/tpgdclresource (#9477) --- mmv1/provider/terraform/common~copy.yaml | 7 + .../terraform/tpgdclresource}/dcl.go | 0 .../terraform/tpgdclresource}/expanders.go | 0 .../tpgdclresource}/expanders_test.go | 0 .../terraform/tpgdclresource}/flatteners.go | 0 .../tpgdclresource}/orgpolicy_utils.go | 0 .../tpgdclresource}/tpgtools_utils.go | 0 tpgtools/handwritten.go | 118 ----- tpgtools/handwritten/go.mod | 91 ---- tpgtools/handwritten/go.sum | 425 ------------------ tpgtools/main.go | 2 - 11 files changed, 7 insertions(+), 636 deletions(-) rename {tpgtools/handwritten => mmv1/third_party/terraform/tpgdclresource}/dcl.go (100%) rename {tpgtools/handwritten => mmv1/third_party/terraform/tpgdclresource}/expanders.go (100%) rename {tpgtools/handwritten => mmv1/third_party/terraform/tpgdclresource}/expanders_test.go (100%) rename {tpgtools/handwritten => mmv1/third_party/terraform/tpgdclresource}/flatteners.go (100%) rename {tpgtools/handwritten => mmv1/third_party/terraform/tpgdclresource}/orgpolicy_utils.go (100%) rename {tpgtools/handwritten => mmv1/third_party/terraform/tpgdclresource}/tpgtools_utils.go (100%) delete mode 100644 tpgtools/handwritten.go delete mode 100644 tpgtools/handwritten/go.mod delete mode 100644 tpgtools/handwritten/go.sum diff --git a/mmv1/provider/terraform/common~copy.yaml b/mmv1/provider/terraform/common~copy.yaml index 59f18e3508b2..4953b9ccca91 100644 --- a/mmv1/provider/terraform/common~copy.yaml +++ b/mmv1/provider/terraform/common~copy.yaml @@ -52,6 +52,13 @@ '<%= dir -%>/provider/<%= fname -%>': 'third_party/terraform/provider/<%= fname -%>' <% end -%> +<% + Dir["third_party/terraform/tpgdclresource/*.go"].each do |file_path| + fname = file_path.split('/')[-1] +-%> +'<%= dir -%>/tpgdclresource/<%= fname -%>': 'third_party/terraform/tpgdclresource/<%= fname -%>' +<% end -%> + <% Dir["third_party/terraform/tpgiamresource/*.go"].each do |file_path| fname = file_path.split('/')[-1] diff --git a/tpgtools/handwritten/dcl.go b/mmv1/third_party/terraform/tpgdclresource/dcl.go similarity index 100% rename from tpgtools/handwritten/dcl.go rename to mmv1/third_party/terraform/tpgdclresource/dcl.go diff --git a/tpgtools/handwritten/expanders.go b/mmv1/third_party/terraform/tpgdclresource/expanders.go similarity index 100% rename from tpgtools/handwritten/expanders.go rename to mmv1/third_party/terraform/tpgdclresource/expanders.go diff --git a/tpgtools/handwritten/expanders_test.go b/mmv1/third_party/terraform/tpgdclresource/expanders_test.go similarity index 100% rename from tpgtools/handwritten/expanders_test.go rename to mmv1/third_party/terraform/tpgdclresource/expanders_test.go diff --git a/tpgtools/handwritten/flatteners.go b/mmv1/third_party/terraform/tpgdclresource/flatteners.go similarity index 100% rename from tpgtools/handwritten/flatteners.go rename to mmv1/third_party/terraform/tpgdclresource/flatteners.go diff --git a/tpgtools/handwritten/orgpolicy_utils.go b/mmv1/third_party/terraform/tpgdclresource/orgpolicy_utils.go similarity index 100% rename from tpgtools/handwritten/orgpolicy_utils.go rename to mmv1/third_party/terraform/tpgdclresource/orgpolicy_utils.go diff --git a/tpgtools/handwritten/tpgtools_utils.go b/mmv1/third_party/terraform/tpgdclresource/tpgtools_utils.go similarity index 100% rename from tpgtools/handwritten/tpgtools_utils.go rename to mmv1/third_party/terraform/tpgdclresource/tpgtools_utils.go diff --git a/tpgtools/handwritten.go b/tpgtools/handwritten.go deleted file mode 100644 index ec89143ea7ae..000000000000 --- a/tpgtools/handwritten.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "bytes" - "io/ioutil" - "os" - "path" - "strings" - - "github.com/golang/glog" -) - -func copyHandwrittenFiles(inPath string, outPath string) { - if inPath == "" || outPath == "" { - glog.Info("Skipping copying handwritten files, empty path specified") - return - } - - glog.Info("copying handwritten files") - - _, err := os.Stat(outPath) - if os.IsNotExist(err) { - errDir := os.MkdirAll(outPath, 0755) - if errDir != nil { - glog.Fatal(err) - } - } - - // Log warning about unexpected outPath values before adding copyright headers - // Matches equivalent in MMv1, see below: - // https://github.com/hashicorp/magic-modules/blob/48ce1004bafd4b4ef1be7565eaa6727adabd0670/mmv1/provider/core.rb#L202-L206 - if !isOutputFolderExpected(outPath) { - glog.Infof("Unexpected output folder (%s) detected when deciding to add HashiCorp copyright headers. Watch out for unexpected changes to copied files", outPath) - } - - fs, err := ioutil.ReadDir(inPath) - if err != nil { - glog.Fatal(err) - } - for _, f := range fs { - if f.IsDir() { - copyHandwrittenFiles(path.Join(inPath, f.Name()), path.Join(outPath, f.Name())) - return - } - - // Ignore empty go.mod - if f.Name() == "go.mod" { - continue - } - - b, err := ioutil.ReadFile(path.Join(inPath, f.Name())) - if err != nil { - if !os.IsNotExist(err) { - glog.Exit(err) - } - // Ignore the error if the file just doesn't exist - continue - } - - // Add HashiCorp copyright header only if generating TPG/TPGB - if strings.HasSuffix(outPath, "/terraform-provider-google") || strings.HasSuffix(outPath, "/terraform-provider-google-beta") { - if strings.HasSuffix(f.Name(), ".go") { - copyrightHeader := []byte("// Copyright (c) HashiCorp, Inc.\n// SPDX-License-Identifier: MPL-2.0\n") - b = append(copyrightHeader, b...) - } - } - - // Format file if ending in .go - if strings.HasSuffix(f.Name(), ".go") { - b, err = formatSource(bytes.NewBuffer(b)) - if err != nil { - glog.Error("error formatting %s: %v", f.Name(), err) - continue - } - } - - // Write copied file. - err = ioutil.WriteFile(path.Join(outPath, terraformResourceDirectory, "tpgdclresource", f.Name()), b, 0644) - if err != nil { - glog.Exit(err) - } - } -} - -// isOutputFolderExpected returns a boolean indicating if the output folder is present in an allow list. -// Intention is to warn users about unexpected diffs if they have renamed their cloned copy of downstream repos, -// as this affects detecting which downstream they're building and whether to add copyright headers. -// Written to match `expected_output_folder?` method in MMv1, see below: -// https://github.com/hashicorp/magic-modules/blob/48ce1004bafd4b4ef1be7565eaa6727adabd0670/mmv1/provider/core.rb#L266-L282 -func isOutputFolderExpected(outPath string) bool { - pathComponents := strings.Split(outPath, "/") - folderName := pathComponents[len(pathComponents)-1] // last element - - switch folderName { - case "terraform-provider-google", - "terraform-provider-google-beta", - "terraform-next", - "terraform-google-conversion", - "tfplan2cai": - return true - default: - return false - } -} diff --git a/tpgtools/handwritten/go.mod b/tpgtools/handwritten/go.mod deleted file mode 100644 index 76e09ab92198..000000000000 --- a/tpgtools/handwritten/go.mod +++ /dev/null @@ -1,91 +0,0 @@ -module github.com/GoogleCloudPlatform/magic-modules/tpgtools/handwritten - -go 1.20 - -require ( - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.56.0 - github.com/hashicorp/errwrap v1.0.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 - github.com/hashicorp/terraform-provider-google v1.20.1-0.20231113222601-e981ec3cd87f -) - -require ( - bitbucket.org/creachadair/stringset v0.0.8 // indirect - cloud.google.com/go v0.110.8 // indirect - cloud.google.com/go/bigtable v1.19.0 // indirect - cloud.google.com/go/compute v1.23.0 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.2 // indirect - cloud.google.com/go/longrunning v0.5.1 // indirect - github.com/agext/levenshtein v1.2.2 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect - github.com/cenkalti/backoff v2.2.1+incompatible // indirect - github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect - github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/envoyproxy/go-control-plane v0.11.1 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect - github.com/fatih/color v1.13.0 // indirect - github.com/golang/glog v1.1.0 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 // indirect - github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect - github.com/hashicorp/go-checkpoint v0.5.0 // indirect - github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect - github.com/hashicorp/go-hclog v1.2.1 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.8 // indirect - github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect - github.com/hashicorp/hc-install v0.4.0 // indirect - github.com/hashicorp/hcl/v2 v2.14.1 // indirect - github.com/hashicorp/logutils v1.0.0 // indirect - github.com/hashicorp/terraform-exec v0.17.3 // indirect - github.com/hashicorp/terraform-json v0.14.0 // indirect - github.com/hashicorp/terraform-plugin-framework v1.1.1 // indirect - github.com/hashicorp/terraform-plugin-framework-validators v0.9.0 // indirect - github.com/hashicorp/terraform-plugin-go v0.14.3 // indirect - github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect - github.com/hashicorp/terraform-registry-address v0.1.0 // indirect - github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect - github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect - github.com/kylelemons/godebug v1.1.0 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/go-testing-interface v1.14.1 // indirect - github.com/mitchellh/go-wordwrap v1.0.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/oklog/run v1.0.0 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect - github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect - github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect - github.com/vmihailenco/tagparser v0.1.2 // indirect - github.com/zclconf/go-cty v1.11.0 // indirect - go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.13.0 // indirect - golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.148.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect - google.golang.org/grpc v1.58.3 // indirect - google.golang.org/protobuf v1.31.0 // indirect -) diff --git a/tpgtools/handwritten/go.sum b/tpgtools/handwritten/go.sum deleted file mode 100644 index c1e8e1527698..000000000000 --- a/tpgtools/handwritten/go.sum +++ /dev/null @@ -1,425 +0,0 @@ -bitbucket.org/creachadair/stringset v0.0.8 h1:gQqe4vs8XWgMyijfyKE6K8o4TcyGGrRXe0JvHgx5H+M= -bitbucket.org/creachadair/stringset v0.0.8/go.mod h1:AgthVMyMxC/6FK1KBJ2ALdqkZObGN8hOetgpwXyMn34= -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= -cloud.google.com/go/bigtable v1.19.0 h1:wiq9LT0kukfInzvy1joMDijCw/OD1UChpSbORXYn0LI= -cloud.google.com/go/bigtable v1.19.0/go.mod h1:xl5kPa8PTkJjdBxg6qdGH88464nNqmbISHSRU+D2yFE= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/iam v1.1.2 h1:gacbrBdWcoVmGLozRuStX45YKvJtzIjJdAolzUs1sm4= -cloud.google.com/go/iam v1.1.2/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.56.0 h1:R8zbp/2oVfPbMF1u6RTkf5s+J4hA6sWAEo8E7xsrbpY= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.56.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= -github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= -github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= -github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= -github.com/apparentlymart/go-dump v0.0.0-20190214190832-042adf3cf4a0 h1:MzVXffFUye+ZcSR6opIgz9Co7WcDx6ZcY+RjfFHoA0I= -github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= -github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= -github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= -github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= -github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= -github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/creachadair/staticfile v0.1.2/go.mod h1:a3qySzCIXEprDGxk6tSxSI+dBBdLzqeBOMhZ+o2d3pM= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.11.1 h1:wSUXTlLfiAQRWs2F+p+EKOY9rUyis1MyGqJ2DIk5HpM= -github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 h1:R+19WKQClnfMXS60cP5BmMe1wjZ4u0evY2p2Ar0ZTXo= -github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= -github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= -github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= -github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= -github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= -github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= -github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 h1:5/4TSDzpDnHQ8rKEEQBjRlYx77mHOvXu08oGchxej7o= -github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932/go.mod h1:cC6EdPbj/17GFCPDK39NRarlMI+kt+O60S12cNB5J9Y= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= -github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= -github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= -github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= -github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw= -github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-plugin v1.4.8 h1:CHGwpxYDOttQOY7HOWgETU9dyVjOXzniXDqJcYJE1zM= -github.com/hashicorp/go-plugin v1.4.8/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= -github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= -github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/hc-install v0.4.0 h1:cZkRFr1WVa0Ty6x5fTvL1TuO1flul231rWkGH92oYYk= -github.com/hashicorp/hc-install v0.4.0/go.mod h1:5d155H8EC5ewegao9A4PUTMNPZaq+TbOzkJJZ4vrXeI= -github.com/hashicorp/hcl/v2 v2.14.1 h1:x0BpjfZ+CYdbiz+8yZTQ+gdLO7IXvOut7Da+XJayx34= -github.com/hashicorp/hcl/v2 v2.14.1/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= -github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/terraform-exec v0.17.3 h1:MX14Kvnka/oWGmIkyuyvL6POx25ZmKrjlaclkx3eErU= -github.com/hashicorp/terraform-exec v0.17.3/go.mod h1:+NELG0EqQekJzhvikkeQsOAZpsw0cv/03rbeQJqscAI= -github.com/hashicorp/terraform-json v0.14.0 h1:sh9iZ1Y8IFJLx+xQiKHGud6/TSUCM0N8e17dKDpqV7s= -github.com/hashicorp/terraform-json v0.14.0/go.mod h1:5A9HIWPkk4e5aeeXIBbkcOvaZbIYnAIkEyqP2pNSckM= -github.com/hashicorp/terraform-plugin-framework v1.1.1 h1:PbnEKHsIU8KTTzoztHQGgjZUWx7Kk8uGtpGMMc1p+oI= -github.com/hashicorp/terraform-plugin-framework v1.1.1/go.mod h1:DyZPxQA+4OKK5ELxFIIcqggcszqdWWUpTLPHAhS/tkY= -github.com/hashicorp/terraform-plugin-framework-validators v0.9.0 h1:LYz4bXh3t7bTEydXOmPDPupRRnA480B/9+jV8yZvxBA= -github.com/hashicorp/terraform-plugin-framework-validators v0.9.0/go.mod h1:+BVERsnfdlhYR2YkXMBtPnmn9UsL19U3qUtSZ+Y/5MY= -github.com/hashicorp/terraform-plugin-go v0.14.3 h1:nlnJ1GXKdMwsC8g1Nh05tK2wsC3+3BL/DBBxFEki+j0= -github.com/hashicorp/terraform-plugin-go v0.14.3/go.mod h1:7ees7DMZ263q8wQ6E4RdIdR6nHHJtrdt4ogX5lPkX1A= -github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs= -github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= -github.com/hashicorp/terraform-plugin-mux v0.8.0 h1:WCTP66mZ+iIaIrCNJnjPEYnVjawTshnDJu12BcXK1EI= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 h1:FtCLTiTcykdsURXPt/ku7fYXm3y19nbzbZcUxHx9RbI= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0/go.mod h1:80wf5oad1tW+oLnbXS4UTYmDCrl7BuN1Q+IA91X1a4Y= -github.com/hashicorp/terraform-provider-google v1.20.1-0.20231113222601-e981ec3cd87f h1:7P1lhzOm1t9lbb7oJdtQgvNUM8VC+fChwdMRZJJyPMg= -github.com/hashicorp/terraform-provider-google v1.20.1-0.20231113222601-e981ec3cd87f/go.mod h1:gaJCkC+8oXws80wiApIdE3giwP9vjc5YiPXTGooleq0= -github.com/hashicorp/terraform-registry-address v0.1.0 h1:W6JkV9wbum+m516rCl5/NjKxCyTVaaUBbzYcMzBDO3U= -github.com/hashicorp/terraform-registry-address v0.1.0/go.mod h1:EnyO2jYO6j29DTHbJcm00E5nQTFeTtyZH3H5ycydQ5A= -github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0= -github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d h1:kJCB4vdITiW1eC1vq2e6IsrXKrZit1bv/TDYFGMp4BQ= -github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck= -github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/hashstructure v1.1.0 h1:P6P1hdjqAAknpY/M1CGipelZgp+4y9ja9kmUZPXP+H0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= -github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= -github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= -github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvCazn8G65U= -github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= -github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= -github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= -github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/zclconf/go-cty v1.1.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= -github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.10.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= -github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0= -github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= -github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.148.0 h1:HBq4TZlN4/1pNcu0geJZ/Q50vIwIXT532UIMYoo0vOs= -google.golang.org/api v0.148.0/go.mod h1:8/TBgwaKjfqTdacOJrOv2+2Q6fBDU1uHKK06oGSkxzU= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= diff --git a/tpgtools/main.go b/tpgtools/main.go index df265cd1721a..19ff83fa5e4e 100644 --- a/tpgtools/main.go +++ b/tpgtools/main.go @@ -128,8 +128,6 @@ func main() { if err := os.MkdirAll(dirPath, os.ModePerm); err != nil { glog.Error(fmt.Errorf("error creating Terraform tpgdclresource directory %v: %v", dirPath, err)) } - - copyHandwrittenFiles(*cPath, *oPath) } func skipResource(r *Resource) bool { From 9c999c0c5e21e4d4158eea1c8ea81f4d2c2f9002 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 20 Nov 2023 13:48:55 -0800 Subject: [PATCH 004/107] Remove overrides folder (#9472) --- mmv1/api/type.rb | 1 + mmv1/overrides/resources.rb | 98 --------- mmv1/overrides/runner.rb | 193 ------------------ mmv1/overrides/terraform/property_override.rb | 93 --------- mmv1/overrides/terraform/resource_override.rb | 54 ----- mmv1/overrides/validator.rb | 122 ----------- mmv1/provider/config.rb | 7 +- mmv1/provider/core.rb | 1 - mmv1/provider/terraform.rb | 2 - mmv1/provider/terraform/config.rb | 8 - .../terraform/validation.rb} | 32 ++- mmv1/spec/data/good-file.yaml | 15 +- mmv1/spec/data/terraform-config.yaml | 16 +- mmv1/spec/override_runner_spec.rb | 173 ---------------- mmv1/spec/override_validator_spec.rb | 102 --------- mmv1/spec/provider_terraform_import_spec.rb | 5 +- ...ovider_terraform_resource_override_spec.rb | 141 ------------- mmv1/spec/provider_terraform_spec.rb | 5 +- 18 files changed, 37 insertions(+), 1031 deletions(-) delete mode 100644 mmv1/overrides/resources.rb delete mode 100644 mmv1/overrides/runner.rb delete mode 100644 mmv1/overrides/terraform/property_override.rb delete mode 100644 mmv1/overrides/terraform/resource_override.rb delete mode 100644 mmv1/overrides/validator.rb rename mmv1/{spec/data/good-tf-override.yaml => provider/terraform/validation.rb} (51%) delete mode 100644 mmv1/spec/override_runner_spec.rb delete mode 100644 mmv1/spec/override_validator_spec.rb delete mode 100644 mmv1/spec/provider_terraform_resource_override_spec.rb diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index f050ead7652a..d9bac98786b2 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -13,6 +13,7 @@ require 'api/object' require 'google/string_utils' +require 'provider/terraform/validation' module Api # Represents a property type diff --git a/mmv1/overrides/resources.rb b/mmv1/overrides/resources.rb deleted file mode 100644 index 7ecf4cf6bd5c..000000000000 --- a/mmv1/overrides/resources.rb +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright 2018 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. - -require 'google/yaml_validator' - -module Overrides - # All overrides act as a Hash under-the-hood. - # This class allows them to get access to - # Hash functions + lets the YAML parser import them. - class OverrideResource < Google::YamlValidator - # This is the list of additional attributes that a provider - # can add through overrides - def self.attributes - [] - end - - attr_accessor(*attributes) - - # Used for testing. - def initialize(hash = {}) - super() - - hash.each { |k, v| instance_variable_set("@#{k}", v) } - end - - # All keys in this "hash" are actually instance_variables with - # the @name notation. - # We're abstracting away the @name notation and allowing - # for @name or `name` to be valid. - def [](key) - if key.to_s[0] == '@' - instance_variable_get(key.to_sym) - else - instance_variable_get("@#{key}") - end - end - - def empty? - instance_variables.empty? - end - - # This allows OverrideResource to take advantage of - # the YAMLValidator's validation without being tied down - # to it. - def validate - instance_variables.each do |var_name| - var = instance_variable_get(var_name) - var.validate if var.respond_to?(:validate) - end - end - end - - # A hash of Provider::ResourceOverride objects where the key is the api name - # for that object. - # - # Example usage in a provider.yaml file where you want to extend a resource - # description: - # - # overrides: !ruby/object:Provider::ResourceOverrides - # SomeResource: !ruby/object:Provider::MyProvider::ResourceOverride - # description: '{{description}} A tool-specific description complement' - # parameters: - # someParameter: !ruby/object:Provider::MyProvider::PropertyOverride - # description: 'foobar' # replaces description - # properties: - # someProperty: !ruby/object:Provider::MyProvider::PropertyOverride - # description: 'foobar' # replaces description - # anotherProperty.someNestedProperty: - # !ruby/object:Provider::MyProvider::PropertyOverride - # description: 'baz' - # ... - class ResourceOverrides < OverrideResource - end - - # Override to an Api::Resource in ResourceName.yaml - class ResourceOverride < OverrideResource - def apply(_resource) - self - end - end - - # Override to a Api::Type in ResourceName.yaml - class PropertyOverride < OverrideResource - def apply(_resource) - self - end - end -end diff --git a/mmv1/overrides/runner.rb b/mmv1/overrides/runner.rb deleted file mode 100644 index 8c3e1c223dfe..000000000000 --- a/mmv1/overrides/runner.rb +++ /dev/null @@ -1,193 +0,0 @@ -# Copyright 2018 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. - -require 'api/product' -require 'overrides/resources' -require 'overrides/validator' - -module Overrides - # This runner takes an Api::Product and applies a set of Overrides::ResourceOverrides - # It does this by building a brand new Api::Product object from scratch, using - # the values from either the original Api::Product or the override values. - # Example usage in a provider.yaml file where you want to extend a resource - # description: - # - # overrides: !ruby/object:Overrides::ResourceOverrides - # SomeResource: !ruby/object:Provider::MyProvider::ResourceOverride - # description: '{{description}} A tool-specific description complement' - # parameters: - # someParameter: !ruby/object:Provider::MyProvider::PropertyOverride - # description: 'foobar' # replaces description - # properties: - # someProperty: !ruby/object:Provider::MyProvider::PropertyOverride - # description: 'foobar' # replaces description - # anotherProperty.someNestedProperty: - # !ruby/object:Provider::MyProvider::PropertyOverride - # description: 'baz' - # anotherProperty[].someNestedPropertyInAnArray: - # !ruby/object:Provider::MyProvider::PropertyOverride - # description: 'baz' - # ... - class Runner - class << self - def initialize(api, overrides, - res_override_class = Overrides::ResourceOverride, - prop_override_class = Overrides::PropertyOverride) - @api = api - @overrides = overrides - @res_override_class = res_override_class - @prop_override_class = prop_override_class - end - - def build(api, overrides, res_override_class = Overrides::ResourceOverride, - prop_override_class = Overrides::PropertyOverride) - - overrides = Overrides::ResourceOverrides.new if overrides.nil? - - validator = Overrides::Validator.new(api, overrides) - validator.run - - build_product(api, overrides, resource: res_override_class, property: prop_override_class) - end - - def build_single_property(api_property, property_override, prop_override_class) - build_property(api_property, property_override, { property: prop_override_class }, '') - end - - private - - # Given a old Api::Product, and Overrides::ResourceOverrides, - # returns a new Api::Product with overrides applied - def build_product(old_prod, all_overrides, override_classes) - prod = Api::Product.new - old_prod.instance_variables - .reject { |o| o == :@objects }.each do |var_name| - if (all_overrides['product'] || {})[var_name] - prod.instance_variable_set(var_name, all_overrides['product'][var_name]) - else - prod.instance_variable_set(var_name, old_prod.instance_variable_get(var_name)) - end - end - prod.instance_variable_set('@objects', - old_prod.objects - .map do |o| - build_resource(o, all_overrides[o.name], - override_classes) - end) - prod - end - - # Given a Api::Resource and Provider::Override::ResourceOverride, - # return a new Api::Resource with overrides applied. - def build_resource(old_resource, res_override, override_classes) - res_override = override_classes[:resource].new if res_override.nil? || res_override.empty? - - res_override.validate - res_override.apply old_resource - - res = Api::Resource.new - set_additional_values(res, res_override) - - variables = (old_resource.instance_variables + res_override.instance_variables).uniq - variables.reject { |o| %i[@properties @parameters].include?(o) } - .each do |var_name| - if res_override[var_name].nil? - res.instance_variable_set(var_name, old_resource.instance_variable_get(var_name)) - else - res.instance_variable_set(var_name, res_override[var_name]) - end - end - - # Using instance_variable_get('properties') to make sure we get `exclude: true` properties - ['@properties', '@parameters'].each do |val| - new_props = ((old_resource.instance_variable_get(val) || [])).map do |p| - build_property(p, res_override['properties'], override_classes) - end - res.instance_variable_set(val, new_props) - end - res - end - - # Given a Api::Type property and a hash of properties, create a new Api::Type property - # This will handle NestedObjects, Arrays of NestedObjects of arbitrary length - def build_property(old_property, property_overrides, override_classes, prefix = '') - property_overrides = {} if property_overrides.nil? - new_prop = build_primitive_property(old_property, - property_overrides["#{prefix}#{old_property.name}"], - override_classes) - 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}.") - end - - if old_property.is_a?(Api::Type::NestedObject) - new_prop.instance_variable_set('@properties', new_props) - elsif old_property.is_a?(Api::Type::Map) && \ - old_property.value_type.is_a?(Api::Type::NestedObject) - new_prop.instance_variable_set('@value_type', Api::Type::NestedObject.new) - new_prop.value_type.instance_variable_set('@properties', new_props) - elsif old_property.is_a?(Api::Type::Array) && \ - old_property.item_type.is_a?(Api::Type::NestedObject) - new_prop.instance_variable_set('@item_type', Api::Type::NestedObject.new) - new_prop.item_type.instance_variable_set('@properties', new_props) - end - end - new_prop - end - - # Given a primitive Api::Type (string, integers, times, etc) and override, - # return a new Api::Type with overrides applied. - # This will be called by build_property, which handles nesting. - def build_primitive_property(old_property, prop_override, override_classes) - prop_override = override_classes[:property].new \ - if prop_override.nil? || prop_override.empty? - - prop_override.validate - prop_override.apply old_property - - prop = if prop_override['type'] - Module.const_get(prop_override['type']).new - else - old_property.class.new - end - - set_additional_values(prop, prop_override) - variables = (old_property.instance_variables + prop_override.instance_variables).uniq - - # Set api_name with old property so that a potential new name doesn't override it. - prop.instance_variable_set('@api_name', old_property.api_name || old_property.name) - - variables.reject { |o| o == :@properties } - .each do |var_name| - if prop_override[var_name].nil? - prop.instance_variable_set(var_name, old_property.instance_variable_get(var_name)) - else # and not default - prop.instance_variable_set(var_name, prop_override[var_name]) - end - end - prop - end - - # Overrides have additional values inside the override that do not regularly belong - # on the Api::* object. These values need to be set + they need getters so they - # can be accessed properly in the templates. - def set_additional_values(object, override) - override.class.attributes.each do |o| - object.instance_variable_set("@#{o}", override[o]) - object.define_singleton_method(o.to_sym) { instance_variable_get("@#{o}") } - end - end - end - end -end diff --git a/mmv1/overrides/terraform/property_override.rb b/mmv1/overrides/terraform/property_override.rb deleted file mode 100644 index 590742e23590..000000000000 --- a/mmv1/overrides/terraform/property_override.rb +++ /dev/null @@ -1,93 +0,0 @@ -# Copyright 2017 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. - -require 'api/object' -require 'overrides/resources' - -module Provider - class Terraform - # Support for schema ValidateFunc functionality. - class Validation < Api::Object - # Ensures the value matches this regex - attr_reader :regex - attr_reader :function - - def validate - super - - check :regex, type: String - check :function, type: String - end - end - end -end - -module Overrides - module Terraform - # Terraform-specific overrides to ResourceName.yaml. - class PropertyOverride < Overrides::PropertyOverride - # Collection of fields allowed in the PropertyOverride section for - # Terraform. All fields should be `attr_reader :` - def self.attributes - [] - end - - attr_reader(*attributes) - - # Used to allow us to easily access these values in `apply` - # without resorting to "instance_variable_get" - attr_reader :description - - def apply(api_property) - unless description.nil? - @description = format_string(:description, @description, - api_property.description) - end - - if @flatten_object && !api_property.is_a?(Api::Type::NestedObject) - raise 'Only NestedObjects can be flattened with flatten_object. Type ' \ - "is #{api_property.class} for property #{api_property.name}" - end - - unless api_property.is_a?(Api::Type::Array) || - api_property.is_a?(Api::Type::Map) - if @is_set - raise 'Set can only be specified for Api::Type::Array ' \ - 'or Api::Type:Map. ' \ - "Type is #{api_property.class} for property " \ - "'#{api_property.name}'" - end - - if @schema_mode_config_attr && !@default_from_api - raise 'default_from_api must be true on a nested block to set' \ - 'schema_mode_config_attr' - end - end - - super - end - - private - - # Formats the string and potentially uses its old value as part of the new - # value. The marker should be in the form `{{name}}` where `name` is the - # field being formatted. - # - # Note: This function only supports the variable with the same name as the - # property being updated. - def format_string(name, mask, current_value) - mask.gsub "{{#{name.id2name}}}", current_value - end - end - end -end diff --git a/mmv1/overrides/terraform/resource_override.rb b/mmv1/overrides/terraform/resource_override.rb deleted file mode 100644 index 65df0c10ddfa..000000000000 --- a/mmv1/overrides/terraform/resource_override.rb +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright 2017 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. - -require 'overrides/resources' -require 'provider/terraform/custom_code' -require 'provider/terraform/docs' -require 'provider/terraform/examples' -require 'provider/terraform/virtual_fields' - -module Overrides - module Terraform - # A class to control overridden properties on terraform.yaml in lieu of - # values from ResourceName.yaml. - class ResourceOverride < Overrides::ResourceOverride - def self.attributes - [] - end - - attr_reader(*attributes) - attr_reader :description - - def apply(resource) - unless description.nil? - @description = format_string(:description, @description, - resource.description) - end - - super - end - - private - - # Formats the string and potentially uses its old value as part of the new - # value. The marker should be in the form `{{name}}` where `name` is the - # field being formatted. - # - # Note: This function only supports the variable with the same name as the - # property being updated. - def format_string(name, mask, current_value) - mask.gsub "{{#{name.id2name}}}", current_value - end - end - end -end diff --git a/mmv1/overrides/validator.rb b/mmv1/overrides/validator.rb deleted file mode 100644 index 119439544ccf..000000000000 --- a/mmv1/overrides/validator.rb +++ /dev/null @@ -1,122 +0,0 @@ -# Copyright 2018 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. - -require 'api/product' -require 'overrides/resources' - -module Overrides - # Validates that the overrides will be valid as intended. - # Throws errors if something invalid will be overridden. - # Validation is split from Application to check for unused overrides, - # provide better errors, split up code, and allow for validation in different places - # than application. - class Validator - def initialize(api, overrides) - @api = api - @overrides = overrides - end - - def run - verify_resources(@api.objects) if @api.objects - end - - private - - # Verify all resources in overrides exist in api - def verify_resources(objects) - @overrides.instance_variables.reject { |i| i == :@product }.each do |var| - obj_array = objects.select { |o| o.name == var[1..] } - raise "#{var[1..]} not found" if obj_array.empty? - - verify_resource(obj_array.first, @overrides[var]) - end - end - - # Verify top-level fields exist on resource - def verify_resource(res, overrides) - overrides.instance_variables.reject { |i| %i[@properties @parameters].include?(i) } - .each do |field_name| - # Check override object. - field_symbol = field_name[1..].to_sym - next if check_if_exists(res, field_symbol, overrides.class.attributes) - - raise "#{field_name} does not exist on #{res.name}" - end - # Use instance_variable_get to get excluded properties - verify_properties((res.instance_variable_get('@properties') || []) + - (res.instance_variable_get('@parameters') || []), overrides['properties'], - res.name) - end - - # Verify a list of properties (parameters or properties on an API::Resource) - def verify_properties(properties, overrides, res_name = '') - overrides ||= {} - overrides.each do |k, v| - path = property_path(k) - verify_property(find_property(properties, path, res_name), v) - end - end - - # Returns a property (or throws an error if it does not exist) - def find_property(properties, path, res_name = '') - # Add context for debugging property name typos - available = [] - prefix = '' - - prop = nil - path.each do |part| - available = properties.map { |p| prefix + p.name } unless properties.empty? - prefix = "#{prefix}#{part}." - - prop = properties.select { |o| o.name == part }.first - properties = prop&.nested_properties || [] - end - raise "#{path.join('.')} does not exist on #{res_name}.\n Possible values #{available}" \ - unless prop - - prop - end - - def verify_property(property, overrides) - overrides.instance_variables - .reject { |i| %i[@properties @item_type @type].include?(i) } - .each do |field_name| - # Check override object. - field_symbol = field_name[1..].to_sym - next if check_if_exists(property, field_symbol, overrides.class.attributes, - overrides['@type']) - - raise "#{field_name} does not exist on #{property.name}" - end - end - - # Check if this field exists on this object. - # The best way (sadly) to do this is to see if a getter exists. - def check_if_exists(obj, field, attributes = [], override_type = nil) - # Not all types share the same values. - # If we're changing types, the new type's getters matter, not the old type. - return true if attributes.include?(field) - - if override_type - Module.const_get(override_type).new.respond_to? field - else - obj.respond_to? field - end - end - - # This keeps the [] brackets in place. - def property_path(prop_name) - prop_name.split('.') - end - end -end diff --git a/mmv1/provider/config.rb b/mmv1/provider/config.rb index d88a718b7b77..a306cda5caa4 100644 --- a/mmv1/provider/config.rb +++ b/mmv1/provider/config.rb @@ -13,7 +13,6 @@ require 'api/object' require 'compile/core' -require 'overrides/runner' module Provider # Settings for the provider @@ -68,12 +67,9 @@ def self.parse(cfg_file, api = nil, version_name = 'ga', provider_override_path raise "Config #{cfg_file}(#{config.class}) is not a Provider::Config" \ unless config.class <= Provider::Config - api = Overrides::Runner.build(api, config.overrides, - config.resource_override, - config.property_override) config.spread_api config, api, [], '' unless api.nil? config.validate - api.validate + api&.validate [api, config] end @@ -89,7 +85,6 @@ def validate super check :files, type: Provider::Config::Files - check :overrides, type: Overrides::ResourceOverrides end # Provides the API object to any type that requires, e.g. for validation diff --git a/mmv1/provider/core.rb b/mmv1/provider/core.rb index 873a0c226bbd..cd3499839a6b 100644 --- a/mmv1/provider/core.rb +++ b/mmv1/provider/core.rb @@ -16,7 +16,6 @@ require 'google/extensions' require 'google/logger' require 'json' -require 'overrides/runner' require 'provider/file_template' module Provider diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 6a261e34ec84..fe90182e8462 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -18,8 +18,6 @@ require 'provider/terraform/custom_code' require 'provider/terraform/docs' require 'provider/terraform/examples' -require 'overrides/terraform/resource_override' -require 'overrides/terraform/property_override' require 'provider/terraform/sub_template' require 'google/golang_utils' diff --git a/mmv1/provider/terraform/config.rb b/mmv1/provider/terraform/config.rb index dd05a78b68a4..4b0021ae6a6a 100644 --- a/mmv1/provider/terraform/config.rb +++ b/mmv1/provider/terraform/config.rb @@ -21,14 +21,6 @@ class Config < Provider::Config def provider Provider::Terraform end - - def resource_override - Overrides::Terraform::ResourceOverride - end - - def property_override - Overrides::Terraform::PropertyOverride - end end end end diff --git a/mmv1/spec/data/good-tf-override.yaml b/mmv1/provider/terraform/validation.rb similarity index 51% rename from mmv1/spec/data/good-tf-override.yaml rename to mmv1/provider/terraform/validation.rb index 83180541b559..944f4ce6034e 100644 --- a/mmv1/spec/data/good-tf-override.yaml +++ b/mmv1/provider/terraform/validation.rb @@ -1,4 +1,4 @@ -# Copyright 2017 Google Inc. +# Copyright 2023 Google Inc. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -11,13 +11,23 @@ # See the License for the specific language governing permissions and # limitations under the License. ---- !ruby/object:Provider::Terraform::Config -overrides: !ruby/object:Overrides::ResourceOverrides - ResourceWithTerraformOverride: !ruby/object:Overrides::Terraform::ResourceOverride - properties: - objectTwoFlattened: !ruby/object:Overrides::Terraform::PropertyOverride - flatten_object: true - objectTwoFlattened.objectTwoNestedObject: !ruby/object:Overrides::Terraform::PropertyOverride - update_mask_fields: - - 'overrideFoo' - - 'nested.overrideBar' +require 'api/object' +require 'provider/abstract_core' + +module Provider + class Terraform < Provider::AbstractCore + # Support for schema ValidateFunc functionality. + class Validation < Api::Object + # Ensures the value matches this regex + attr_reader :regex + attr_reader :function + + def validate + super + + check :regex, type: String + check :function, type: String + end + end + end +end diff --git a/mmv1/spec/data/good-file.yaml b/mmv1/spec/data/good-file.yaml index 3890f67adc4a..d434463c52cd 100644 --- a/mmv1/spec/data/good-file.yaml +++ b/mmv1/spec/data/good-file.yaml @@ -115,16 +115,16 @@ objects: name: 'nv-prop1' description: 'the first property in my namevalues' - !ruby/object:Api::Resource - name: 'ResourceWithTerraformOverride' - kind: 'terraform#resourceWithTerraformOverride' - base_url: 'resourceWithTerraformOverride' + name: 'ThirdResource' + kind: 'myproduct#thirdresource' + base_url: 'thirdResource' description: 'a description' properties: - !ruby/object:Api::Type::String name: 'stringOne' description: 'a string property (depth 0)' - !ruby/object:Api::Type::String - name: 'stringRename' + name: 'stringRenamed' description: 'a string property (depth 0)' - !ruby/object:Api::Type::NestedObject name: 'objectOne' @@ -136,20 +136,25 @@ objects: - !ruby/object:Api::Type::NestedObject name: 'objectOneFlattenedObject' description: 'a nested NestedObject (depth 1)' + flatten_object: true properties: - !ruby/object:Api::Type::Integer name: 'objectOneNestedNestedInteger' description: 'a nested integer (depth 2)' - !ruby/object:Api::Type::String - name: 'objectOneRename' + name: 'objectOneRenamed' description: 'a string property (depth 1)' - !ruby/object:Api::Type::NestedObject name: 'objectTwoFlattened' description: 'a NestedObject property that is flattened (depth 0)' + flatten_object: true properties: - !ruby/object:Api::Type::String name: 'objectTwoString' description: 'a nested string (depth 1)' + update_mask_fields: + - 'overrideFoo' + - 'nested.overrideBar' - !ruby/object:Api::Type::NestedObject name: 'objectTwoNestedObject' description: 'a nested NestedObject (depth 1)' diff --git a/mmv1/spec/data/terraform-config.yaml b/mmv1/spec/data/terraform-config.yaml index 5c923a4cf6b7..105333b37016 100644 --- a/mmv1/spec/data/terraform-config.yaml +++ b/mmv1/spec/data/terraform-config.yaml @@ -12,18 +12,4 @@ # limitations under the License. --- !ruby/object:Provider::Terraform::Config -overrides: !ruby/object:Overrides::ResourceOverrides - ResourceWithTerraformOverride: !ruby/object:Overrides::Terraform::ResourceOverride - properties: - stringRename: !ruby/object:Overrides::Terraform::PropertyOverride - name: 'stringRenamed' - objectOne.objectOneRename: !ruby/object:Overrides::Terraform::PropertyOverride - name: 'objectOneRenamed' - objectOne.objectOneFlattenedObject: !ruby/object:Overrides::Terraform::PropertyOverride - flatten_object: true - objectTwoFlattened: !ruby/object:Overrides::Terraform::PropertyOverride - flatten_object: true - objectTwoFlattened.objectTwoString: !ruby/object:Overrides::Terraform::PropertyOverride - update_mask_fields: - - 'overrideFoo' - - 'nested.overrideBar' +files: !ruby/object:Provider::Config::Files diff --git a/mmv1/spec/override_runner_spec.rb b/mmv1/spec/override_runner_spec.rb deleted file mode 100644 index 614697f67fec..000000000000 --- a/mmv1/spec/override_runner_spec.rb +++ /dev/null @@ -1,173 +0,0 @@ -# Copyright 2017 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. - -require 'spec_helper' - -class TestResourceOverride < Overrides::ResourceOverride - def self.attributes - [:test_field] - end -end - -describe Overrides::Runner do - context 'simple overrides' do - describe 'should be able to override a product field' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'product' => Overrides::ResourceOverride.new( - 'name' => 'My Test Product' - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides) - expect(new_api.name).to eq(overrides['product']['name']) - } - end - - describe 'should be able to override a resource field' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'MyResource' => Overrides::ResourceOverride.new( - 'description' => 'A description' - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides) - resource = new_api.objects.select { |p| p.name == 'MyResource' }.first - expect(resource.description).to eq(overrides['MyResource']['description']) - } - end - - describe 'should be able to override a property field' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'ReferencedResource' => Overrides::ResourceOverride.new( - 'properties' => { - 'name' => Overrides::PropertyOverride.new( - 'description' => 'My overridden description' - ) - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides) - resource = new_api.objects.select { |p| p.name == 'ReferencedResource' }.first - prop = resource.properties.select { |p| p.name == 'name' }.first - expect(prop.description).to eq( - overrides['ReferencedResource']['properties']['name']['description'] - ) - } - end - - describe 'should be able to override a property type' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'ReferencedResource' => Overrides::ResourceOverride.new( - 'properties' => { - 'name' => Overrides::PropertyOverride.new( - 'type' => 'Api::Type::Integer' - ) - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides) - resource = new_api.objects.select { |p| p.name == 'ReferencedResource' }.first - prop = resource.properties.select { |p| p.name == 'name' }.first - expect(prop.class).to eq(Api::Type::Integer) - } - end - - describe 'should be able to override a nested-nested property' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::ResourceOverride.new( - 'properties' => { - 'nested-property2.property1.property1-nested' => - Overrides::PropertyOverride.new( - 'type' => 'Api::Type::Integer' - ) - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides) - resource = new_api.objects.select { |p| p.name == 'AnotherResource' }.first - prop = resource.properties.select { |p| p.name == 'nested-property2' }.first - expect(prop.properties[0].properties[0].class).to eq(Api::Type::Integer) - } - end - - describe 'should be able to override a nested array property' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::ResourceOverride.new( - 'properties' => { - 'array-property.property1' => Overrides::PropertyOverride.new( - 'type' => 'Api::Type::Integer' - ) - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides) - resource = new_api.objects.select { |p| p.name == 'AnotherResource' }.first - prop = resource.properties.select { |p| p.name == 'array-property' }.first - expect(prop.item_type.properties[0].class).to eq(Api::Type::Integer) - } - end - - describe 'should be able to override a namevalue -> object map' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => TestResourceOverride.new( - 'properties' => { - 'namevalue-property.nv-prop1' => Overrides::PropertyOverride.new( - 'description' => 'overridden' - ) - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides, TestResourceOverride) - resource = new_api.objects.select { |p| p.name == 'AnotherResource' }.first - prop = resource.properties.select { |p| p.name == 'namevalue-property' } - .first - .value_type - .properties.first - expect(prop.description).to eq('overridden') - } - end - end -end diff --git a/mmv1/spec/override_validator_spec.rb b/mmv1/spec/override_validator_spec.rb deleted file mode 100644 index d37318e30c92..000000000000 --- a/mmv1/spec/override_validator_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2017 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. - -require 'spec_helper' - -class TestResourceOverride < Overrides::ResourceOverride - def self.attributes - [:test_field] - end -end - -describe Overrides::Validator do - context 'simple overrides' do - describe 'should be able identify a bad field' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::ResourceOverride.new( - 'blahbad' => 'A description' - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - runner = Overrides::Validator.new(api, overrides) - expect { runner.run }.to raise_error(RuntimeError, - /@blahbad does not exist on AnotherResource/) - } - end - describe 'should be able identify a bad property' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::ResourceOverride.new( - 'properties' => { - 'blahbad' => TestResourceOverride.new( - 'description' => 'A description' - ) - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - runner = Overrides::Validator.new(api, overrides) - expect { runner.run }.to raise_error(RuntimeError, - /blahbad does not exist on AnotherResource/) - } - end - - describe 'should be able validate a namevalues nestedobject properly' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::ResourceOverride.new( - 'properties' => { - 'namevalue-property.nv-prop1' => TestResourceOverride.new( - 'description' => 'A description' - ) - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - runner = Overrides::Validator.new(api, overrides) - expect { runner.run }.not_to raise_error - } - end - - describe 'should be able validate a changed type with new properties' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::ResourceOverride.new( - 'properties' => { - 'namevalue-property.nv-prop1' => TestResourceOverride.new( - 'type' => 'Api::Type::Enum', - 'values' => %i[test1 test2] - ) - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - runner = Overrides::Validator.new(api, overrides) - expect { runner.run }.not_to raise_error - } - end - end -end diff --git a/mmv1/spec/provider_terraform_import_spec.rb b/mmv1/spec/provider_terraform_import_spec.rb index 77d478b564b4..ba8a930c602b 100644 --- a/mmv1/spec/provider_terraform_import_spec.rb +++ b/mmv1/spec/provider_terraform_import_spec.rb @@ -66,10 +66,7 @@ def resource(*data) .concat(data) .join("\n")) product.objects.append(res) - new_product = Overrides::Runner.build(product, config.overrides, - config.resource_override, - config.property_override) - new_product.objects.last + product.objects.last end end end diff --git a/mmv1/spec/provider_terraform_resource_override_spec.rb b/mmv1/spec/provider_terraform_resource_override_spec.rb deleted file mode 100644 index 08a256d75d62..000000000000 --- a/mmv1/spec/provider_terraform_resource_override_spec.rb +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright 2017 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. - -require 'spec_helper' -require 'google/yaml_validator' -require 'overrides/terraform/resource_override' - -class File - class << self - alias real_open open - alias real_read read - end -end - -describe Overrides::Terraform::ResourceOverride do - context 'advanced overrides' do - describe 'should not override a previously overridden property with a default' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::Terraform::ResourceOverride.new( - 'properties' => { - 'array-property' => Overrides::Terraform::PropertyOverride.new( - 'is_set' => true - ) - } - ) - ) - end - let(:overrides2) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::Terraform::ResourceOverride.new( - 'properties' => { - 'array-property' => Overrides::Terraform::PropertyOverride.new - } - ) - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides, - Overrides::Terraform::ResourceOverride, - Overrides::Terraform::PropertyOverride) - final_api = Overrides::Runner.build(new_api, overrides2, - Overrides::Terraform::ResourceOverride, - Overrides::Terraform::PropertyOverride) - resource = final_api.objects.select { |p| p.name == 'AnotherResource' }.first - prop = resource.properties.select { |p| p.name == 'array-property' }.first - expect(prop.is_set).to eq( - true - ) - } - end - - describe 'should not override a previously overridden resource field with a default' do - let(:overrides) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::Terraform::ResourceOverride.new( - 'exclude_import' => true - ) - ) - end - let(:overrides2) do - Overrides::ResourceOverrides.new( - 'AnotherResource' => Overrides::Terraform::ResourceOverride.new - ) - end - let(:api) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } - - it { - new_api = Overrides::Runner.build(api, overrides, - Overrides::Terraform::ResourceOverride, - Overrides::Terraform::PropertyOverride) - final_api = Overrides::Runner.build(new_api, overrides2, - Overrides::Terraform::ResourceOverride, - Overrides::Terraform::PropertyOverride) - resource = final_api.objects.select { |p| p.name == 'AnotherResource' }.first - expect(resource.exclude_import).to eq( - true - ) - } - end - end - - context 'good resource' do - let(:resource) do - Overrides::Terraform::ResourceOverride.parse( - File.read('spec/data/good-resource.yaml') - ) - end - - before(:each) do - allow_open 'spec/data/good-resource.yaml' - - resource.validate - end - - # The ResourceOverride object will get the new description. - # During the application phase, if the ResourceOverride object - # has a description, it'll be applied to the new Api Object. - subject { override.description } - - context 'with extend description' do - let(:override) { create_override('description', '{{description}}bar') } - subject { override.description } - before(:each) { override.apply resource } - it { is_expected.to eq 'foobar' } - end - - context 'with override description' do - let(:override) { create_override('description', 'bar') } - subject { override.description } - before(:each) { override.apply resource } - it { is_expected.to eq 'bar' } - end - end - - private - - def allow_open(file_name) - IO.expects(:read).with(file_name).returns(File.real_read(file_name)) - .at_least(1) - end - - def create_override(property_name, override_val) - Google::YamlValidator.parse( - ['--- !ruby/object:Overrides::Terraform::ResourceOverride', - "#{property_name}: '#{override_val}'"].join("\n") - ) - end -end diff --git a/mmv1/spec/provider_terraform_spec.rb b/mmv1/spec/provider_terraform_spec.rb index 61adb0c6b4cf..e15684aba6ba 100644 --- a/mmv1/spec/provider_terraform_spec.rb +++ b/mmv1/spec/provider_terraform_spec.rb @@ -25,11 +25,10 @@ class << self let(:product) { Api::Compiler.new(File.read('spec/data/good-file.yaml')).run } let(:parsed) { Provider::Config.parse('spec/data/terraform-config.yaml', product) } let(:config) { parsed[1] } - let(:override_product) { parsed[0] } let(:provider) { Provider::Terraform.new(config, product, 'ga', Time.now) } let(:resource) { product.objects[0] } let(:override_resource) do - override_product.objects.find { |o| o.name == 'ResourceWithTerraformOverride' } + product.objects.find { |o| o.name == 'ThirdResource' } end before do @@ -152,7 +151,7 @@ class << self is_expected.to eq( [ ['string_one', ['stringOne']], - ['string_renamed', ['stringRename']], + ['string_renamed', ['stringRenamed']], ['object_one', ['objectOne']], ['object_two_string', ['overrideFoo', 'nested.overrideBar']], [ From 7a20c9cc77f933c0085225b00e59556e8ae3b57c Mon Sep 17 00:00:00 2001 From: G-NamanGupta <98808262+G-NamanGupta@users.noreply.github.com> Date: Tue, 21 Nov 2023 19:05:55 +0530 Subject: [PATCH 005/107] updated storage_pool (#9229) --- mmv1/products/netapp/product.yaml | 28 ++++ mmv1/products/netapp/storagePool.yaml | 133 ++++++++++++++++ .../examples/Storage_pool_create.tf.erb | 28 ++++ .../resource_netapp_storage_pool_test.go | 142 ++++++++++++++++++ 4 files changed, 331 insertions(+) create mode 100644 mmv1/products/netapp/product.yaml create mode 100644 mmv1/products/netapp/storagePool.yaml create mode 100644 mmv1/templates/terraform/examples/Storage_pool_create.tf.erb create mode 100644 mmv1/third_party/terraform/services/netapp/resource_netapp_storage_pool_test.go diff --git a/mmv1/products/netapp/product.yaml b/mmv1/products/netapp/product.yaml new file mode 100644 index 000000000000..72491c25ad23 --- /dev/null +++ b/mmv1/products/netapp/product.yaml @@ -0,0 +1,28 @@ +# Copyright 2018 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: Netapp +display_name: Netapp +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://netapp.googleapis.com/v1/ + - !ruby/object:Api::Product::Version + name: beta + base_url: https://netapp.googleapis.com/v1beta1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform +apis_required: + - !ruby/object:Api::Product::ApiReference + name: Cloud Volume API + url: https://console.cloud.google.com/apis/library/cloudvolumesgcp-api.netapp.com diff --git a/mmv1/products/netapp/storagePool.yaml b/mmv1/products/netapp/storagePool.yaml new file mode 100644 index 000000000000..4c1bec5e725f --- /dev/null +++ b/mmv1/products/netapp/storagePool.yaml @@ -0,0 +1,133 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'storagePool' +description: | + Storage pools act as containers for volumes. All volumes in a storage pool share the following information: + * Location + * Service level + * Virtual Private Cloud (VPC) network + * Active Directory policy + * LDAP use for NFS volumes, if applicable + * Customer-managed encryption key (CMEK) policy + + The capacity of the pool can be split up and assigned to volumes within the pool. Storage pools are a billable component of NetApp Volumes. Billing is based on the location, service level, and capacity allocated to a pool independent of consumption at the volume level. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'QUICKSTART_TITLE': 'https://cloud.google.com/netapp/volumes/docs/get-started/quickstarts/create-storage-pool' + api: 'https://cloud.google.com/netapp/volumes/docs/reference/rest/v1/projects.locations.storagePools' +base_url: projects/{{project}}/locations/{{location}}/storagePools +self_link: projects/{{project}}/locations/{{location}}/storagePools/{{name}} +create_url: projects/{{project}}/locations/{{location}}/storagePools?storagePoolId={{name}} +update_url: projects/{{project}}/locations/{{location}}/storagePools/{{name}} +update_verb: :PATCH +update_mask: true +delete_url: projects/{{project}}/locations/{{location}}/storagePools/{{name}} +autogen_async: true +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + base_url: '{{op_id}}' +id_format: 'projects/{{project}}/locations/{{location}}/storagePools/{{name}}' +import_format: ['projects/{{project}}/locations/{{location}}/storagePools/{{name}}'] +parameters: + - !ruby/object:Api::Type::String + name: 'location' + required: true + immutable: true + url_param_only: true + description: | + Name of the location. Usually a region name, expect for some STANDARD service level pools which require a zone name. + - !ruby/object:Api::Type::String + name: 'name' + description: + The resource name of the storage pool. Needs to be unique per location. + required: true + immutable: true + url_param_only: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'Storage_pool_create' + primary_resource_id: 'test_pool' + vars: + pool_name: 'test-pool' + network_name: 'test-network' + global_name: 'test-address' +properties: + # Fields go here + - !ruby/object:Api::Type::Enum + name: 'serviceLevel' + description: | + Service level of the storage pool. + values: + - :PREMIUM + - :EXTREME + - :STANDARD + required: true + immutable: true + - !ruby/object:Api::Type::String + name: 'capacityGib' + description: | + Capacity of the storage pool (in GiB). + required: true + - !ruby/object:Api::Type::String + name: 'volumeCapacityGib' + description: | + Size allocated to volumes in the storage pool (in GiB). + output: true + - !ruby/object:Api::Type::Integer + name: 'volumeCount' + description: | + Number of volume in the storage pool. + output: true + - !ruby/object:Api::Type::String + name: 'description' + description: | + An optional description of this resource. + - !ruby/object:Api::Type::KeyValueLabels + name: labels + description: | + Labels as key value pairs. Example: `{ "owner": "Bob", "department": "finance", "purpose": "testing" }`. + - !ruby/object:Api::Type::String + name: 'network' + description: | + VPC network name with format: `projects/{{project}}/global/networks/{{network}}` + required: true + immutable: true + diff_suppress_func: tpgresource.ProjectNumberDiffSuppress + - !ruby/object:Api::Type::String + name: 'activeDirectory' + description: | + Specifies the Active Directory policy to be used. Format: `projects/{{project}}/locations/{{location}}/activeDirectories/{{name}}`. + The policy needs to be in the same location as the storage pool. + - !ruby/object:Api::Type::String + name: 'kmsConfig' + description: | + Specifies the CMEK policy to be used for volume encryption. Format: `projects/{{project}}/locations/{{location}}/kmsConfigs/{{name}}`. + The policy needs to be in the same location as the storage pool. + immutable: true + - !ruby/object:Api::Type::Boolean + name: 'ldapEnabled' + description: | + When enabled, the volumes uses Active Directory as LDAP name service for UID/GID lookups. Required to enable extended group support for NFSv3, + using security identifiers for NFSv4.1 or principal names for kerberized NFSv4.1. + immutable: true + - !ruby/object:Api::Type::Enum + name: 'encryptionType' + description: | + Reports if volumes in the pool are encrypted using a Google-managed encryption key or CMEK. + values: + - :ENCRYPTION_TYPE_UNSPECIFIED + - :SERVICE_MANAGED + - :CLOUD_KMS + output: true diff --git a/mmv1/templates/terraform/examples/Storage_pool_create.tf.erb b/mmv1/templates/terraform/examples/Storage_pool_create.tf.erb new file mode 100644 index 000000000000..d13c7687b317 --- /dev/null +++ b/mmv1/templates/terraform/examples/Storage_pool_create.tf.erb @@ -0,0 +1,28 @@ + +resource "google_compute_network" "peering_network" { + name = "<%= ctx[:vars]['network_name'] %>" +} + +# Create an IP address +resource "google_compute_global_address" "private_ip_alloc" { + name = "<%= ctx[:vars]['global_name'] %>" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = google_compute_network.peering_network.id +} + +# Create a private connection +resource "google_service_networking_connection" "default" { + network = google_compute_network.peering_network.id + service = "netapp.servicenetworking.goog" + reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] +} + +resource "google_netapp_storage_pool" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['pool_name'] %>" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = "2048" + network = google_compute_network.peering_network.id +} diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_storage_pool_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_storage_pool_test.go new file mode 100644 index 000000000000..b39cd4d8d0c6 --- /dev/null +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_storage_pool_test.go @@ -0,0 +1,142 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package netapp_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccNetappstoragePool_storagePoolCreateExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccNetappstoragePool_storagePoolCreateExample_full(context), + }, + { + ResourceName: "google_netapp_storage_pool.test_pool", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name", "labels", "terraform_labels"}, + }, + { + Config: testAccNetappstoragePool_storagePoolCreateExample_update(context), + }, + { + ResourceName: "google_netapp_storage_pool.test_pool", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetappstoragePool_storagePoolCreateExample_full(context map[string]interface{}) string { + return acctest.Nprintf(` + +resource "google_compute_network" "peering_network" { + name = "tf-test-network%{random_suffix}" +} + +# Create an IP address +resource "google_compute_global_address" "private_ip_alloc" { + name = "tf-test-address%{random_suffix}" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = google_compute_network.peering_network.id +} + +# Create a private connection +resource "google_service_networking_connection" "default" { + network = google_compute_network.peering_network.id + service = "netapp.servicenetworking.goog" + reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] +} + +resource "google_netapp_storage_pool" "test_pool" { + name = "tf-test-pool%{random_suffix}" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = "2048" + network = google_compute_network.peering_network.id + active_directory = "" + description = "this is a test description" + kms_config = "" + labels = { + key= "test" + value= "pool" + } + ldap_enabled = false + +} +`, context) +} + +func testAccNetappstoragePool_storagePoolCreateExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` + +resource "google_compute_network" "peering_network" { + name = "tf-test-network%{random_suffix}" +} + +# Create an IP address +resource "google_compute_global_address" "private_ip_alloc" { + name = "tf-test-address%{random_suffix}" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = google_compute_network.peering_network.id +} + +# Create a private connection +resource "google_service_networking_connection" "default" { + network = google_compute_network.peering_network.id + service = "netapp.servicenetworking.goog" + reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] +} + +resource "google_netapp_storage_pool" "test_pool" { + name = "tf-test-pool%{random_suffix}" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = "4096" + network = google_compute_network.peering_network.id + active_directory = "" + description = "this is test" + kms_config = "" + labels = { + key= "test" + value= "pool" + } + ldap_enabled = false + +} +`, context) +} From 4829cc4a4f604db5d6e1d09a7c85df6250ebc19a Mon Sep 17 00:00:00 2001 From: "Bob \"Wombat\" Hogg" Date: Tue, 21 Nov 2023 12:10:05 -0500 Subject: [PATCH 006/107] Support deleting Firestore databases (#9450) Due to backwards compatibility concerns, the default behavior remains to abandon the database upon destroy rather than to actually delete it. To actually delete the database, you must set deletion_policy to DELETE, and apply if necessary, before running `terraform destroy`. This also cleans up some related deletion-related docs and bugs: * Updates the delete protection docs * delete_protection_state being enabled with deletion_policy = DELETE fails the destroy Fixes https://github.com/hashicorp/terraform-provider-google/issues/16488 Fixes https://github.com/hashicorp/terraform-provider-google/issues/16404 Fixes https://github.com/hashicorp/terraform-provider-google/issues/16325 --- mmv1/products/firestore/Database.yaml | 55 +++++++++++++------ .../examples/firestore_database.tf.erb | 2 + ...irestore_database_in_datastore_mode.tf.erb | 2 + ...ore_database_with_delete_protection.tf.erb | 11 ---- .../firestore_default_database.tf.erb | 31 ++--------- ..._default_database_in_datastore_mode.tf.erb | 32 ++--------- .../pre_delete/firestore_database.go.erb | 7 +++ 7 files changed, 62 insertions(+), 78 deletions(-) delete mode 100644 mmv1/templates/terraform/examples/firestore_database_with_delete_protection.tf.erb create mode 100644 mmv1/templates/terraform/pre_delete/firestore_database.go.erb diff --git a/mmv1/products/firestore/Database.yaml b/mmv1/products/firestore/Database.yaml index 26f8371bdf8f..0a34b7b7e051 100644 --- a/mmv1/products/firestore/Database.yaml +++ b/mmv1/products/firestore/Database.yaml @@ -47,7 +47,6 @@ async: !ruby/object:Api::OpAsync error: !ruby/object:Api::OpAsync::Error path: 'error' message: 'message' -skip_delete: true autogen_async: true id_format: 'projects/{{project}}/databases/{{name}}' import_format: @@ -59,52 +58,73 @@ examples: name: 'firestore_default_database' primary_resource_id: 'database' pull_external: true + vars: + delete_protection_state: "DELETE_PROTECTION_ENABLED" test_env_vars: - org_id: :ORG_ID + project_id: :PROJECT_NAME + test_vars_overrides: + delete_protection_state: '"DELETE_PROTECTION_DISABLED"' ignore_read_extra: - project - etag - vars: - project_id: 'my-project' + - deletion_policy - !ruby/object:Provider::Terraform::Examples name: 'firestore_database' primary_resource_id: 'database' vars: name: "example-database-id" + delete_protection_state: "DELETE_PROTECTION_ENABLED" test_env_vars: project_id: :PROJECT_NAME + test_vars_overrides: + delete_protection_state: '"DELETE_PROTECTION_DISABLED"' ignore_read_extra: - project - etag + - deletion_policy - !ruby/object:Provider::Terraform::Examples name: 'firestore_default_database_in_datastore_mode' primary_resource_id: 'datastore_mode_database' - pull_external: true + vars: + delete_protection_state: "DELETE_PROTECTION_ENABLED" test_env_vars: - org_id: :ORG_ID + project_id: :PROJECT_NAME + test_vars_overrides: + delete_protection_state: '"DELETE_PROTECTION_DISABLED"' ignore_read_extra: - project - etag - vars: - project_id: 'my-project' + - deletion_policy + skip_test: true - !ruby/object:Provider::Terraform::Examples name: 'firestore_database_in_datastore_mode' primary_resource_id: 'datastore_mode_database' vars: name: "example-database-id" + delete_protection_state: "DELETE_PROTECTION_ENABLED" test_env_vars: project_id: :PROJECT_NAME + test_vars_overrides: + delete_protection_state: '"DELETE_PROTECTION_DISABLED"' ignore_read_extra: - project - etag - - !ruby/object:Provider::Terraform::Examples - name: 'firestore_database_with_delete_protection' - primary_resource_id: 'database' - vars: - name: "example-database-id" - test_env_vars: - project_id: :PROJECT_NAME - skip_test: true + - deletion_policy +virtual_fields: + - !ruby/object:Api::Type::Enum + name: 'deletion_policy' + description: | + Deletion behavior for this database. + If the deletion policy is `ABANDON`, the database will be removed from Terraform state but not deleted from Google Cloud upon destruction. + If the deletion policy is `DELETE`, the database will both be removed from Terraform state and deleted from Google Cloud upon destruction. + The default value is `ABANDON`. + See also `delete_protection`. + values: + - :ABANDON + - :DELETE + default_value: :ABANDON +custom_code: !ruby/object:Provider::Terraform::CustomCode + pre_delete: templates/terraform/pre_delete/firestore_database.go.erb properties: - !ruby/object:Api::Type::String name: name @@ -177,6 +197,9 @@ properties: name: deleteProtectionState description: | State of delete protection for the database. + When delete protection is enabled, this database cannot be deleted. + The default value is `DELETE_PROTECTION_STATE_UNSPECIFIED`, which is currently equivalent to `DELETE_PROTECTION_DISABLED`. + **Note:** Additionally, to delete this database using `terraform destroy`, `deletion_policy` must be set to `DELETE`. values: - :DELETE_PROTECTION_STATE_UNSPECIFIED - :DELETE_PROTECTION_ENABLED diff --git a/mmv1/templates/terraform/examples/firestore_database.tf.erb b/mmv1/templates/terraform/examples/firestore_database.tf.erb index 771b58393b1c..28e699531919 100644 --- a/mmv1/templates/terraform/examples/firestore_database.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_database.tf.erb @@ -6,4 +6,6 @@ resource "google_firestore_database" "<%= ctx[:primary_resource_id] %>" { concurrency_mode = "OPTIMISTIC" app_engine_integration_mode = "DISABLED" point_in_time_recovery_enablement = "POINT_IN_TIME_RECOVERY_ENABLED" + delete_protection_state = "<%= ctx[:vars]['delete_protection_state'] %>" + deletion_policy = "DELETE" } diff --git a/mmv1/templates/terraform/examples/firestore_database_in_datastore_mode.tf.erb b/mmv1/templates/terraform/examples/firestore_database_in_datastore_mode.tf.erb index 1f5233c2e884..7604cb2e31f8 100644 --- a/mmv1/templates/terraform/examples/firestore_database_in_datastore_mode.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_database_in_datastore_mode.tf.erb @@ -6,4 +6,6 @@ resource "google_firestore_database" "<%= ctx[:primary_resource_id] %>" { concurrency_mode = "OPTIMISTIC" app_engine_integration_mode = "DISABLED" point_in_time_recovery_enablement = "POINT_IN_TIME_RECOVERY_ENABLED" + delete_protection_state = "<%= ctx[:vars]['delete_protection_state'] %>" + deletion_policy = "DELETE" } diff --git a/mmv1/templates/terraform/examples/firestore_database_with_delete_protection.tf.erb b/mmv1/templates/terraform/examples/firestore_database_with_delete_protection.tf.erb deleted file mode 100644 index 126899e3a47b..000000000000 --- a/mmv1/templates/terraform/examples/firestore_database_with_delete_protection.tf.erb +++ /dev/null @@ -1,11 +0,0 @@ -resource "google_firestore_database" "<%= ctx[:primary_resource_id] %>" { - project = "<%= ctx[:test_env_vars]['project_id'] %>" - name = "<%= ctx[:vars]['name']%>" - location_id = "nam5" - type = "FIRESTORE_NATIVE" - - # Prevents accidental deletion of the database. - # To delete the database, first set this field to `DELETE_PROTECTION_DISABLED`, apply the changes. - # Then delete the database resource and apply the changes again. - delete_protection_state = "DELETE_PROTECTION_ENABLED" -} diff --git a/mmv1/templates/terraform/examples/firestore_default_database.tf.erb b/mmv1/templates/terraform/examples/firestore_default_database.tf.erb index 36bc28e2c752..ab0574cf0b45 100644 --- a/mmv1/templates/terraform/examples/firestore_default_database.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_default_database.tf.erb @@ -1,27 +1,8 @@ -resource "google_project" "project" { - project_id = "<%= ctx[:vars]['project_id'] %>" - name = "<%= ctx[:vars]['project_id'] %>" - org_id = "<%= ctx[:test_env_vars]['org_id'] %>" -} - -resource "time_sleep" "wait_60_seconds" { - depends_on = [google_project.project] - - create_duration = "60s" -} - -resource "google_project_service" "firestore" { - project = google_project.project.project_id - service = "firestore.googleapis.com" - # Needed for CI tests for permissions to propagate, should not be needed for actual usage - depends_on = [time_sleep.wait_60_seconds] -} - resource "google_firestore_database" "<%= ctx[:primary_resource_id] %>" { - project = google_project.project.project_id - name = "(default)" - location_id = "nam5" - type = "FIRESTORE_NATIVE" - - depends_on = [google_project_service.firestore] + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "(default)" + location_id = "nam5" + type = "FIRESTORE_NATIVE" + delete_protection_state = "<%= ctx[:vars]['delete_protection_state'] %>" + deletion_policy = "DELETE" } diff --git a/mmv1/templates/terraform/examples/firestore_default_database_in_datastore_mode.tf.erb b/mmv1/templates/terraform/examples/firestore_default_database_in_datastore_mode.tf.erb index afdd7aa4146e..d87c069932bb 100644 --- a/mmv1/templates/terraform/examples/firestore_default_database_in_datastore_mode.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_default_database_in_datastore_mode.tf.erb @@ -1,28 +1,8 @@ -resource "google_project" "project" { - project_id = "tf-test%{random_suffix}" - name = "tf-test%{random_suffix}" - org_id = "<%= ctx[:test_env_vars]['org_id'] %>" -} - -resource "time_sleep" "wait_60_seconds" { - depends_on = [google_project.project] - create_duration = "60s" -} - -resource "google_project_service" "firestore" { - project = google_project.project.project_id - service = "firestore.googleapis.com" - # Needed for CI tests for permissions to propagate, should not be needed for actual usage - depends_on = [time_sleep.wait_60_seconds] -} - resource "google_firestore_database" "<%= ctx[:primary_resource_id] %>" { - project = google_project.project.project_id - - name = "(default)" - - location_id = "nam5" - type = "DATASTORE_MODE" - - depends_on = [google_project_service.firestore] + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "(default)" + location_id = "nam5" + type = "DATASTORE_MODE" + delete_protection_state = "<%= ctx[:vars]['delete_protection_state'] %>" + deletion_policy = "DELETE" } diff --git a/mmv1/templates/terraform/pre_delete/firestore_database.go.erb b/mmv1/templates/terraform/pre_delete/firestore_database.go.erb new file mode 100644 index 000000000000..2f396d07df3d --- /dev/null +++ b/mmv1/templates/terraform/pre_delete/firestore_database.go.erb @@ -0,0 +1,7 @@ +if deletionPolicy := d.Get("deletion_policy"); deletionPolicy != "DELETE" { + log.Printf("[WARN] Firestore database %q deletion_policy is not set to 'DELETE', skipping deletion", d.Get("name").(string)) + return nil +} +if deleteProtection := d.Get("delete_protection_state"); deleteProtection == "DELETE_PROTECTION_ENABLED" { + return fmt.Errorf("Cannot delete Firestore database %s: Delete Protection is enabled. Set delete_protection_state to DELETE_PROTECTION_DISABLED for this resource and run \"terraform apply\" before attempting to delete it.", d.Get("name").(string)) +} From 064da4a296663f8b9b213fa667b843c4674f1913 Mon Sep 17 00:00:00 2001 From: Ian Milligan Date: Tue, 21 Nov 2023 11:09:16 -0800 Subject: [PATCH 007/107] Remove beta from the Cloud Run Service dependsOn container field (#9496) --- mmv1/products/cloudrunv2/Service.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index b80e9faeb092..a1cede779aad 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -660,7 +660,6 @@ properties: name: 'dependsOn' description: |- Containers which should be started before this container. If specified the container will wait to start until all containers with the listed names are healthy. - min_version: beta item_type: Api::Type::String - !ruby/object:Api::Type::Array name: 'volumes' From 05e14a25287adfa933db8be44f4da737dfe38197 Mon Sep 17 00:00:00 2001 From: omkark-google <150975505+omkark-google@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:12:10 -0800 Subject: [PATCH 008/107] Add access restrictions field for google_iam_workforce_pool resource (#9490) --- .../iamworkforcepool/WorkforcePool.yaml | 24 +++++++++++ .../examples/iam_workforce_pool_full.tf.erb | 20 +++++---- .../resource_iam_workforce_pool_test.go.erb | 42 +++++++++++++++---- 3 files changed, 71 insertions(+), 15 deletions(-) diff --git a/mmv1/products/iamworkforcepool/WorkforcePool.yaml b/mmv1/products/iamworkforcepool/WorkforcePool.yaml index d495d0c11351..873b11836460 100644 --- a/mmv1/products/iamworkforcepool/WorkforcePool.yaml +++ b/mmv1/products/iamworkforcepool/WorkforcePool.yaml @@ -121,3 +121,27 @@ properties: If `sessionDuration` is not configured, minted credentials have a default duration of one hour (3600s). A duration in seconds with up to nine fractional digits, ending with '`s`'. Example: "`3.5s`". default_value: '3600s' + - !ruby/object:Api::Type::NestedObject + name: 'accessRestrictions' + immutable: true + description: | + Configure access restrictions on the workforce pool users. This is an optional field. If specified web + sign-in can be restricted to given set of services or programmatic sign-in can be disabled for pool users. + properties: + - !ruby/object:Api::Type::Array + name: 'allowedServices' + description: | + Services allowed for web sign-in with the workforce pool. + If not set by default there are no restrictions. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'domain' + description: | + Domain name of the service. + Example: console.cloud.google + - !ruby/object:Api::Type::Boolean + name: 'disableProgrammaticSignin' + description: | + Disable programmatic sign-in by disabling token issue via the Security Token API endpoint. + See [Security Token Service API](https://cloud.google.com/iam/docs/reference/sts/rest). diff --git a/mmv1/templates/terraform/examples/iam_workforce_pool_full.tf.erb b/mmv1/templates/terraform/examples/iam_workforce_pool_full.tf.erb index 0027d8d179f5..47f011c8fe8c 100644 --- a/mmv1/templates/terraform/examples/iam_workforce_pool_full.tf.erb +++ b/mmv1/templates/terraform/examples/iam_workforce_pool_full.tf.erb @@ -1,9 +1,15 @@ resource "google_iam_workforce_pool" "<%= ctx[:primary_resource_id] %>" { - workforce_pool_id = "<%= ctx[:vars]["workforce_pool_id"] %>" - parent = "organizations/<%= ctx[:test_env_vars]["org_id"] %>" - location = "global" - display_name = "Display name" - description = "A sample workforce pool." - disabled = false - session_duration = "7200s" + workforce_pool_id = "<%= ctx[:vars]["workforce_pool_id"] %>" + parent = "organizations/<%= ctx[:test_env_vars]["org_id"] %>" + location = "global" + display_name = "Display name" + description = "A sample workforce pool." + disabled = false + session_duration = "7200s" + access_restrictions { + allowed_services { + domain = "backstory.chronicle.security" + } + disable_programmatic_signin = false + } } diff --git a/mmv1/third_party/terraform/services/iamworkforcepool/resource_iam_workforce_pool_test.go.erb b/mmv1/third_party/terraform/services/iamworkforcepool/resource_iam_workforce_pool_test.go.erb index 70abc45723a6..e256666c2a1c 100644 --- a/mmv1/third_party/terraform/services/iamworkforcepool/resource_iam_workforce_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/iamworkforcepool/resource_iam_workforce_pool_test.go.erb @@ -30,7 +30,7 @@ func TestAccIAMWorkforcePoolWorkforcePool_full(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccIAMWorkforcePoolWorkforcePool_update(context), + Config: testAccIAMWorkforcePoolWorkforcePool_full_update(context), }, { ResourceName: "google_iam_workforce_pool.my_pool", @@ -63,7 +63,7 @@ func TestAccIAMWorkforcePoolWorkforcePool_minimal(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccIAMWorkforcePoolWorkforcePool_update(context), + Config: testAccIAMWorkforcePoolWorkforcePool_minimal_update(context), }, { ResourceName: "google_iam_workforce_pool.my_pool", @@ -76,29 +76,55 @@ func TestAccIAMWorkforcePoolWorkforcePool_minimal(t *testing.T) { func testAccIAMWorkforcePoolWorkforcePool_full(context map[string]interface{}) string { return acctest.Nprintf(` +resource "google_iam_workforce_pool" "my_pool" { + workforce_pool_id = "my-pool-%{random_suffix}" + parent = "organizations/%{org_id}" + location = "global" + display_name = "Display name" + description = "A sample workforce pool." + disabled = false + session_duration = "7200s" + access_restrictions { + allowed_services { + domain = "backstory.chronicle.security" + } + disable_programmatic_signin = false + } +} +`, context) +} + +func testAccIAMWorkforcePoolWorkforcePool_minimal(context map[string]interface{}) string { + return acctest.Nprintf(` resource "google_iam_workforce_pool" "my_pool" { workforce_pool_id = "my-pool-%{random_suffix}" parent = "organizations/%{org_id}" location = "global" - display_name = "Display name" - description = "A sample workforce pool." - disabled = false - session_duration = "7200s" } `, context) } -func testAccIAMWorkforcePoolWorkforcePool_minimal(context map[string]interface{}) string { +func testAccIAMWorkforcePoolWorkforcePool_full_update(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_iam_workforce_pool" "my_pool" { workforce_pool_id = "my-pool-%{random_suffix}" parent = "organizations/%{org_id}" location = "global" + display_name = "New display name" + description = "A sample workforce pool with updated description." + disabled = true + session_duration = "3600s" + access_restrictions { + allowed_services { + domain = "backstory.chronicle.security" + } + disable_programmatic_signin = false + } } `, context) } -func testAccIAMWorkforcePoolWorkforcePool_update(context map[string]interface{}) string { +func testAccIAMWorkforcePoolWorkforcePool_minimal_update(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_iam_workforce_pool" "my_pool" { workforce_pool_id = "my-pool-%{random_suffix}" From 087da54a4ca10340c889be9a11487eaa6e93bd99 Mon Sep 17 00:00:00 2001 From: Arnab Dasgupta <150280802+arnabadg-google@users.noreply.github.com> Date: Tue, 21 Nov 2023 23:01:20 +0100 Subject: [PATCH 009/107] Add serviceDirectoryRegistrations message to resource google_compute_global_forwarding_rule (#9485) * Add serviceDirectoryRegistrations in google_compute_global_forwarding_rule * Add service_directory_registration message in example private_service_connect_google_apis.tf.erb * Remove service field from service_directory_registration message as it is not currently applicable for globalForwardingRule --- .../compute/GlobalForwardingRule.yaml | 26 +++++++++++++++++++ ...private_service_connect_google_apis.tf.erb | 4 +++ 2 files changed, 30 insertions(+) diff --git a/mmv1/products/compute/GlobalForwardingRule.yaml b/mmv1/products/compute/GlobalForwardingRule.yaml index f3b30c449c44..b287c5445545 100644 --- a/mmv1/products/compute/GlobalForwardingRule.yaml +++ b/mmv1/products/compute/GlobalForwardingRule.yaml @@ -484,6 +484,32 @@ properties: update_verb: :POST update_url: 'projects/{{project}}/global/forwardingRules/{{name}}/setTarget' diff_suppress_func: 'tpgresource.CompareSelfLinkRelativePaths' + - !ruby/object:Api::Type::Array + name: 'serviceDirectoryRegistrations' + description: | + Service Directory resources to register this forwarding rule with. + + Currently, only supports a single Service Directory resource. + min_size: 0 + max_size: 1 + immutable: true + default_from_api: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'namespace' + description: | + Service Directory namespace to register the forwarding rule under. + immutable: true + default_from_api: true + - !ruby/object:Api::Type::String + name: 'serviceDirectoryRegion' + description: | + [Optional] Service Directory region to register this global forwarding rule under. + Default to "us-central1". Only used for PSC for Google APIs. All PSC for + Google APIs Forwarding Rules on the same network should use the same Service + Directory region. + immutable: true - !ruby/object:Api::Type::Array name: sourceIpRanges description: If not empty, this Forwarding Rule will only forward the traffic when the source IP address matches one of the IP addresses or CIDR ranges set here. Note that a Forwarding Rule can only have up to 64 source IP ranges, and this field can only be used with a regional Forwarding Rule whose scheme is EXTERNAL. Each sourceIpRange entry should be either an IP address (for example, 1.2.3.4) or a CIDR range (for example, 1.2.3.0/24). diff --git a/mmv1/templates/terraform/examples/private_service_connect_google_apis.tf.erb b/mmv1/templates/terraform/examples/private_service_connect_google_apis.tf.erb index fe239362a9ee..a106bf40d440 100644 --- a/mmv1/templates/terraform/examples/private_service_connect_google_apis.tf.erb +++ b/mmv1/templates/terraform/examples/private_service_connect_google_apis.tf.erb @@ -38,5 +38,9 @@ resource "google_compute_global_forwarding_rule" "default" { network = google_compute_network.network.id ip_address = google_compute_global_address.default.id load_balancing_scheme = "" + service_directory_registrations { + namespace = "sd-namespace" + service_directory_region = "europe-west3" + } } # [END compute_forwarding_rule_private_access] From 120ffc30e5bd3be8c1e99615861ea745c01ffc9e Mon Sep 17 00:00:00 2001 From: sahsagar-google <126025352+sahsagar-google@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:09:12 -0800 Subject: [PATCH 010/107] Updating the documentation for feature membership with the current state of the resource. Adding the membership_location field to the resource (#9508) * Adding Terraform resources for Tenancy APIs in GKEHub * Segregating MembershipBinding and MembershipRBACRoleBinding to keep things simpler in the review * Fixing the docu URIs * Adding TF support for Tenancy API for Membership Binding * Adding dependent membership binding to the same commit chain * Making Scope un-updatable and replacing hard coded project number with the one from test env * Making Scope RRBAC updatable * Making Namespace immutable * Adding update test cases * Removing all memberships field from Scope since it is no longer supported * Removing all_memberships field for Scope from all test cases * Making naming in examples consistent across Tenancy APIs documentation * Update mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Update mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Update mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Fixing typo in the resource name * Adding state migrations for Membership * Updating the feature_membership documentation with the current resource state. Adding membership_location field to the doc --------- Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> --- .../gke_hub_feature_membership.html.markdown | 66 ++++++++++++++----- 1 file changed, 50 insertions(+), 16 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/r/gke_hub_feature_membership.html.markdown b/mmv1/third_party/terraform/website/docs/r/gke_hub_feature_membership.html.markdown index 9d45db679f95..4ae995b89173 100644 --- a/mmv1/third_party/terraform/website/docs/r/gke_hub_feature_membership.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/gke_hub_feature_membership.html.markdown @@ -15,7 +15,6 @@ resource "google_container_cluster" "cluster" { name = "my-cluster" location = "us-central1-a" initial_node_count = 1 - provider = google-beta } resource "google_gke_hub_membership" "membership" { @@ -25,7 +24,6 @@ resource "google_gke_hub_membership" "membership" { resource_link = "//container.googleapis.com/${google_container_cluster.cluster.id}" } } - provider = google-beta } resource "google_gke_hub_feature" "feature" { @@ -35,7 +33,6 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - provider = google-beta } resource "google_gke_hub_feature_membership" "feature_member" { @@ -50,7 +47,6 @@ resource "google_gke_hub_feature_membership" "feature_member" { } } } - provider = google-beta } ``` ## Example Usage - Config Management with OCI @@ -60,7 +56,6 @@ resource "google_container_cluster" "cluster" { name = "my-cluster" location = "us-central1-a" initial_node_count = 1 - provider = google-beta } resource "google_gke_hub_membership" "membership" { @@ -70,7 +65,6 @@ resource "google_gke_hub_membership" "membership" { resource_link = "//container.googleapis.com/${google_container_cluster.cluster.id}" } } - provider = google-beta } resource "google_gke_hub_feature" "feature" { @@ -80,7 +74,6 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - provider = google-beta } resource "google_gke_hub_feature_membership" "feature_member" { @@ -99,7 +92,6 @@ resource "google_gke_hub_feature_membership" "feature_member" { } } } - provider = google-beta } ``` @@ -112,7 +104,6 @@ resource "google_gke_hub_feature" "feature" { labels = { foo = "bar" } - provider = google-beta } ``` @@ -123,7 +114,6 @@ resource "google_container_cluster" "cluster" { name = "my-cluster" location = "us-central1-a" initial_node_count = 1 - provider = google-beta } resource "google_gke_hub_membership" "membership" { @@ -133,14 +123,11 @@ resource "google_gke_hub_membership" "membership" { resource_link = "//container.googleapis.com/${google_container_cluster.cluster.id}" } } - provider = google-beta } resource "google_gke_hub_feature" "feature" { name = "servicemesh" location = "global" - - provider = google-beta } resource "google_gke_hub_feature_membership" "feature_member" { @@ -150,7 +137,50 @@ resource "google_gke_hub_feature_membership" "feature_member" { mesh { management = "MANAGEMENT_AUTOMATIC" } - provider = google-beta +} +``` + +## Example Usage - Config Management with Regional Membership + +```hcl +resource "google_container_cluster" "cluster" { + name = "my-cluster" + location = "us-central1-a" + initial_node_count = 1 +} + +resource "google_gke_hub_membership" "membership" { + membership_id = "my-membership" + location = "us-central1" + endpoint { + gke_cluster { + resource_link = "//container.googleapis.com/${google_container_cluster.cluster.id}" + } + } +} + +resource "google_gke_hub_feature" "feature" { + name = "configmanagement" + location = "global" + + labels = { + foo = "bar" + } +} + +resource "google_gke_hub_feature_membership" "feature_member" { + location = "global" + feature = google_gke_hub_feature.feature.name + membership = google_gke_hub_membership.membership.membership_id + membership_location = google_gke_hub_membership.membership.location + configmanagement { + version = "1.6.2" + config_sync { + git { + sync_repo = "https://github.com/hashicorp/terraform" + } + } + } } ``` @@ -178,7 +208,11 @@ The following arguments are supported: * `membership` - (Optional) - The name of the membership + The name of the membership + +* `membership_location` - + (Optional) + The location of the membership, for example, "us-central1". Default is "global". * `project` - (Optional) @@ -334,7 +368,7 @@ The following arguments are supported: * `monitoring` - (Optional) - Specifies the backends Policy Controller should export metrics to. For example, to specify metrics should be exported to Cloud Monitoring and Prometheus, specify backends: [\"cloudmonitoring\", \"prometheus\"]. Default: [\"cloudmonitoring\", \"prometheus\"] + Specifies the backends Policy Controller should export metrics to. For example, to specify metrics should be exported to Cloud Monitoring and Prometheus, specify backends: ["cloudmonitoring", "prometheus"]. Default: ["cloudmonitoring", "prometheus"] The `mesh` block supports: From 3c8fa12bf730a1dd944fc4334f1f5486219fbd8a Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Wed, 22 Nov 2023 04:06:33 +0530 Subject: [PATCH 011/107] add standard type vmwareengine network (#9416) --- mmv1/products/vmwareengine/Network.yaml | 7 +- mmv1/products/vmwareengine/product.yaml | 3 + .../vmware_engine_network_legacy.tf.erb | 2 +- .../vmware_engine_network_standard.tf.erb | 6 ++ .../provider/provider_mmv1_resources.go.erb | 2 +- ...ata_source_google_vmwareengine_network.go} | 5 +- ...source_google_vmwareengine_network_test.go | 49 +++++++++++ ...ce_google_vmwareengine_network_test.go.erb | 87 ------------------- ... => resource_vmwareengine_network_test.go} | 11 +-- .../docs/d/vmwareengine_network.html.markdown | 4 - 10 files changed, 68 insertions(+), 108 deletions(-) create mode 100644 mmv1/templates/terraform/examples/vmware_engine_network_standard.tf.erb rename mmv1/third_party/terraform/services/vmwareengine/{data_source_google_vmwareengine_network.go.erb => data_source_google_vmwareengine_network.go} (94%) create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_test.go delete mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_test.go.erb rename mmv1/third_party/terraform/services/vmwareengine/{resource_vmwareengine_network_test.go.erb => resource_vmwareengine_network_test.go} (92%) diff --git a/mmv1/products/vmwareengine/Network.yaml b/mmv1/products/vmwareengine/Network.yaml index 16c4dee0f92f..8d260ac7dccb 100644 --- a/mmv1/products/vmwareengine/Network.yaml +++ b/mmv1/products/vmwareengine/Network.yaml @@ -14,7 +14,6 @@ --- !ruby/object:Api::Resource name: "Network" -min_version: beta base_url: "projects/{{project}}/locations/{{location}}/vmwareEngineNetworks" self_link: "projects/{{project}}/locations/{{location}}/vmwareEngineNetworks/{{name}}" create_url: "projects/{{project}}/locations/{{location}}/vmwareEngineNetworks?vmwareEngineNetworkId={{name}}" @@ -45,11 +44,14 @@ import_format: ["projects/{{project}}/locations/{{location}}/vmwareEngineNetworks/{{name}}"] autogen_async: true examples: + - !ruby/object:Provider::Terraform::Examples + name: "vmware_engine_network_standard" + primary_resource_id: "vmw-engine-network" - !ruby/object:Provider::Terraform::Examples name: "vmware_engine_network_legacy" pull_external: true - min_version: beta primary_resource_id: "vmw-engine-network" + skip_test: true # update tests will take care of create and update. Legacy network needs to be created on an isolated project. vars: proj_id: "vmw-proj" test_env_vars: @@ -119,6 +121,7 @@ properties: VMware Engine network type. values: - :LEGACY + - :STANDARD - !ruby/object:Api::Type::String name: "uid" diff --git a/mmv1/products/vmwareengine/product.yaml b/mmv1/products/vmwareengine/product.yaml index 5d6e08562005..4e2c2b4f8663 100644 --- a/mmv1/products/vmwareengine/product.yaml +++ b/mmv1/products/vmwareengine/product.yaml @@ -15,6 +15,9 @@ name: Vmwareengine display_name: Cloud VMware Engine versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://vmwareengine.googleapis.com/v1/ - !ruby/object:Api::Product::Version name: beta base_url: https://vmwareengine.googleapis.com/v1/ diff --git a/mmv1/templates/terraform/examples/vmware_engine_network_legacy.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_network_legacy.tf.erb index 152363dbd104..04aa17580f98 100644 --- a/mmv1/templates/terraform/examples/vmware_engine_network_legacy.tf.erb +++ b/mmv1/templates/terraform/examples/vmware_engine_network_legacy.tf.erb @@ -30,4 +30,4 @@ resource "time_sleep" "wait_60_seconds" { depends_on = [google_project.acceptance] create_duration = "60s" -} +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/vmware_engine_network_standard.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_network_standard.tf.erb new file mode 100644 index 000000000000..1c889bb09f78 --- /dev/null +++ b/mmv1/templates/terraform/examples/vmware_engine_network_standard.tf.erb @@ -0,0 +1,6 @@ +resource "google_vmwareengine_network" "<%= ctx[:primary_resource_id] %>" { + name = "standard-nw" + location = "global" # Standard network needs to be global + type = "STANDARD" + description = "VMwareEngine standard network sample" +} diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 14b20dc56094..6a06e716b915 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -196,8 +196,8 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_vpc_access_connector": vpcaccess.DataSourceVPCAccessConnector(), "google_redis_instance": redis.DataSourceGoogleRedisInstance(), "google_vertex_ai_index": vertexai.DataSourceVertexAIIndex(), - <% unless version == 'ga' -%> "google_vmwareengine_network": vmwareengine.DataSourceVmwareengineNetwork(), + <% unless version == 'ga' -%> "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), "google_vmwareengine_cluster": vmwareengine.DataSourceVmwareengineCluster(), <% end -%> diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go similarity index 94% rename from mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb rename to mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go index 87465bef390a..dc6c0a8ce0aa 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network.go @@ -1,6 +1,5 @@ -<% autogen_exception -%> package vmwareengine -<% unless version == 'ga' -%> + import ( "fmt" @@ -14,7 +13,6 @@ func DataSourceVmwareengineNetwork() *schema.Resource { dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceVmwareengineNetwork().Schema) tpgresource.AddRequiredFieldsToSchema(dsSchema, "location", "name") tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") - return &schema.Resource{ Read: dataSourceVmwareengineNetworkRead, Schema: dsSchema, @@ -40,4 +38,3 @@ func dataSourceVmwareengineNetworkRead(d *schema.ResourceData, meta interface{}) } return nil } -<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_test.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_test.go new file mode 100644 index 000000000000..2f1685ae4f7f --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_test.go @@ -0,0 +1,49 @@ +package vmwareengine_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccDataSourceVmwareEngineNetwork_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineNetworkDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceVmwareEngineNetworkConfig(context), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_network.ds", "google_vmwareengine_network.nw", map[string]struct{}{}), + ), + }, + }, + }) +} + +func testAccDataSourceVmwareEngineNetworkConfig(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_vmwareengine_network" "nw" { + name = "tf-test-sample-network%{random_suffix}" + location = "global" # Standard network needs to be global + type = "STANDARD" + description = "VMwareEngine standard network sample" +} + +data "google_vmwareengine_network" "ds" { + name = google_vmwareengine_network.nw.name + location = "global" + depends_on = [ + google_vmwareengine_network.nw, + ] +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_test.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_test.go.erb deleted file mode 100644 index f5c534afedd0..000000000000 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_test.go.erb +++ /dev/null @@ -1,87 +0,0 @@ -<% autogen_exception -%> -package vmwareengine_test -<% unless version == 'ga' -%> - -import ( - "github.com/hashicorp/terraform-provider-google/google/acctest" - "github.com/hashicorp/terraform-provider-google/google/envvar" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" -) - -func TestAccDataSourceVmwareEngineNetwork_basic(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "region": envvar.GetTestRegionFromEnv(), - "random_suffix": acctest.RandString(t, 10), - "organization": envvar.GetTestOrgFromEnv(t), - "billing_account": envvar.GetTestBillingAccountFromEnv(t), - } - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), - CheckDestroy: testAccCheckVmwareengineNetworkDestroyProducer(t), - ExternalProviders: map[string]resource.ExternalProvider{ - "time": {}, - }, - Steps: []resource.TestStep{ - { - Config: testAccDataSourceVmwareEngineNetworkConfig(context), - Check: resource.ComposeTestCheckFunc( - acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_network.ds", "google_vmwareengine_network.nw", map[string]struct{}{}), - ), - }, - }, - }) -} - -func testAccDataSourceVmwareEngineNetworkConfig(context map[string]interface{}) string { - return acctest.Nprintf(` - # there can be only 1 Legacy network per region for a given project, so creating new project to isolate tests. -resource "google_project" "acceptance" { - name = "tf-test-%{random_suffix}" - provider = google-beta - project_id = "tf-test-%{random_suffix}" - org_id = "%{organization}" - billing_account = "%{billing_account}" -} - -resource "google_project_service" "acceptance" { - project = google_project.acceptance.project_id - provider = google-beta - service = "vmwareengine.googleapis.com" - - # Needed for CI tests for permissions to propagate, should not be needed for actual usage - depends_on = [time_sleep.wait_60_seconds] -} - -resource "time_sleep" "wait_60_seconds" { - depends_on = [google_project.acceptance] - - create_duration = "60s" -} - -resource "google_vmwareengine_network" "nw" { - project = google_project_service.acceptance.project - name = "%{region}-default" #Legacy network IDs are in the format: {region-id}-default - provider = google-beta - location = "%{region}" - type = "LEGACY" - description = "VMwareEngine legacy network sample" -} - -data "google_vmwareengine_network" "ds" { - name = google_vmwareengine_network.nw.name - project = google_project_service.acceptance.project - provider = google-beta - location = "%{region}" - depends_on = [ - google_vmwareengine_network.nw, - ] -} -`, context) -} -<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_test.go.erb b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_test.go similarity index 92% rename from mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_test.go.erb rename to mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_test.go index b06c33be4b2b..521210061b86 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_test.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_test.go @@ -1,15 +1,12 @@ -<% autogen_exception -%> package vmwareengine_test -<% unless version == 'ga' -%> import ( "fmt" "testing" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/envvar" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" ) func TestAccVmwareengineNetwork_vmwareEngineNetworkUpdate(t *testing.T) { @@ -24,7 +21,7 @@ func TestAccVmwareengineNetwork_vmwareEngineNetworkUpdate(t *testing.T) { configTemplate := vmwareEngineNetworkConfigTemplate(context) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckVmwareengineNetworkDestroyProducer(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, @@ -56,7 +53,6 @@ func TestAccVmwareengineNetwork_vmwareEngineNetworkUpdate(t *testing.T) { func vmwareEngineNetworkConfigTemplate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_vmwareengine_network" "default-nw" { - provider = google-beta project = google_project_service.acceptance.project name = "%{region}-default" location = "%{region}" @@ -67,7 +63,6 @@ resource "google_vmwareengine_network" "default-nw" { # there can be only 1 Legacy network per region for a given project, so creating new project to isolate tests. resource "google_project" "acceptance" { name = "tf-test-%{random_suffix}" - provider = google-beta project_id = "tf-test-%{random_suffix}" org_id = "%{organization}" billing_account = "%{billing_account}" @@ -75,7 +70,6 @@ resource "google_project" "acceptance" { resource "google_project_service" "acceptance" { project = google_project.acceptance.project_id - provider = google-beta service = "vmwareengine.googleapis.com" # Needed for CI tests for permissions to propagate, should not be needed for actual usage @@ -89,4 +83,3 @@ resource "time_sleep" "wait_60_seconds" { } `, context) } -<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_network.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_network.html.markdown index 6870f7a4080d..2b6a98a48d4b 100644 --- a/mmv1/third_party/terraform/website/docs/d/vmwareengine_network.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_network.html.markdown @@ -8,9 +8,6 @@ description: |- Use this data source to get details about a VMwareEngine network resource. -~> **Warning:** This data source is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. - To get more information about VMwareEngine Network, see: * [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.vmwareEngineNetworks) @@ -18,7 +15,6 @@ To get more information about VMwareEngine Network, see: ```hcl data "google_vmwareengine_network" "my_nw" { - provider = google-beta name = "us-central1-default" location = "us-central1" } From 0cb996cba9865e8ddc06bae505e28b70b51e6fe9 Mon Sep 17 00:00:00 2001 From: sagi yosefia <7414322+sagiyosefia@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:32:09 +0200 Subject: [PATCH 012/107] add included table (#9499) Co-authored-by: Sagi Yosefia --- .../templates/terraform/examples/datastream_stream_full.tf.erb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mmv1/templates/terraform/examples/datastream_stream_full.tf.erb b/mmv1/templates/terraform/examples/datastream_stream_full.tf.erb index e1c05fa1ac66..4c57f84110fd 100644 --- a/mmv1/templates/terraform/examples/datastream_stream_full.tf.erb +++ b/mmv1/templates/terraform/examples/datastream_stream_full.tf.erb @@ -138,6 +138,9 @@ resource "google_datastream_stream" "<%= ctx[:primary_resource_id] %>" { ordinal_position = 0 } } + mysql_tables { + table = "includedTable_2" + } } } exclude_objects { From fe2040c449bf2070c1b7c8a60bbb7c4a75d19369 Mon Sep 17 00:00:00 2001 From: sagi yosefia <7414322+sagiyosefia@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:44:51 +0200 Subject: [PATCH 013/107] Fix Datastream private connectivity docs (#9455) Co-authored-by: Sagi Yosefia --- .../datastream/ConnectionProfile.yaml | 19 +++- mmv1/products/datastream/Stream.yaml | 7 +- ...profile_bigquery_private_connection.tf.erb | 30 ------- ...ofile_postgresql_private_connection.tf.erb | 86 +++++++++++++++++++ 4 files changed, 107 insertions(+), 35 deletions(-) delete mode 100644 mmv1/templates/terraform/examples/datastream_connection_profile_bigquery_private_connection.tf.erb create mode 100644 mmv1/templates/terraform/examples/datastream_connection_profile_postgresql_private_connection.tf.erb diff --git a/mmv1/products/datastream/ConnectionProfile.yaml b/mmv1/products/datastream/ConnectionProfile.yaml index 3a8a4d94879f..9dcb84d8186c 100644 --- a/mmv1/products/datastream/ConnectionProfile.yaml +++ b/mmv1/products/datastream/ConnectionProfile.yaml @@ -36,12 +36,21 @@ examples: vars: connection_profile_id: 'my-profile' - !ruby/object:Provider::Terraform::Examples - name: 'datastream_connection_profile_bigquery_private_connection' + name: 'datastream_connection_profile_postgresql_private_connection' + pull_external: true primary_resource_id: 'default' + # Random provider + skip_vcr: true vars: private_connection_id: 'my-connection' connection_profile_id: 'my-profile' network_name: 'my-network' + database_instance_name: 'my-instance' + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'datastream_connection_profile_full' primary_resource_id: @@ -57,9 +66,11 @@ examples: vars: connection_profile_id: 'my-profile' database_instance_name: 'my-instance' - deletion_protection: - 'true' - # This is covered by the update tests. + deletion_protection: 'true' + test_vars_overrides: + deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' skip_test: true parameters: - !ruby/object:Api::Type::String diff --git a/mmv1/products/datastream/Stream.yaml b/mmv1/products/datastream/Stream.yaml index a88ed1eeb73c..3168af7640ff 100644 --- a/mmv1/products/datastream/Stream.yaml +++ b/mmv1/products/datastream/Stream.yaml @@ -67,6 +67,8 @@ examples: destination_connection_profile_id: 'destination-profile' test_vars_overrides: deletion_protection: 'false' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'datastream_stream_full' pull_external: true @@ -87,6 +89,8 @@ examples: test_vars_overrides: deletion_protection: 'false' stream_cmek: 'acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' + oics_vars_overrides: + deletion_protection: 'false' - !ruby/object:Provider::Terraform::Examples name: 'datastream_stream_postgresql' primary_resource_id: 'default' @@ -136,7 +140,8 @@ examples: deletion_protection: 'false' bigquery_destination_table_kms_key_name: 'acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' - + oics_vars_overrides: + deletion_protection: 'false' parameters: - !ruby/object:Api::Type::String name: streamId diff --git a/mmv1/templates/terraform/examples/datastream_connection_profile_bigquery_private_connection.tf.erb b/mmv1/templates/terraform/examples/datastream_connection_profile_bigquery_private_connection.tf.erb deleted file mode 100644 index 05222e1a84da..000000000000 --- a/mmv1/templates/terraform/examples/datastream_connection_profile_bigquery_private_connection.tf.erb +++ /dev/null @@ -1,30 +0,0 @@ -resource "google_datastream_private_connection" "private_connection" { - display_name = "Connection profile" - location = "us-central1" - private_connection_id = "<%= ctx[:vars]['private_connection_id'] %>" - - labels = { - key = "value" - } - - vpc_peering_config { - vpc = google_compute_network.default.id - subnet = "10.0.0.0/29" - } -} - -resource "google_compute_network" "default" { - name = "<%= ctx[:vars]['network_name'] %>" -} - -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 {} - - private_connectivity { - private_connection = google_datastream_private_connection.private_connection.id - } -} diff --git a/mmv1/templates/terraform/examples/datastream_connection_profile_postgresql_private_connection.tf.erb b/mmv1/templates/terraform/examples/datastream_connection_profile_postgresql_private_connection.tf.erb new file mode 100644 index 000000000000..5df86ff5990e --- /dev/null +++ b/mmv1/templates/terraform/examples/datastream_connection_profile_postgresql_private_connection.tf.erb @@ -0,0 +1,86 @@ +resource "google_datastream_private_connection" "private_connection" { + display_name = "Connection profile" + location = "us-central1" + private_connection_id = "<%= ctx[:vars]['private_connection_id'] %>" + + labels = { + key = "value" + } + + vpc_peering_config { + vpc = google_compute_network.default.id + subnet = "10.0.0.0/29" + } +} + +resource "google_compute_network" "default" { + name = "<%= ctx[:vars]['network_name'] %>" +} + +resource "google_sql_database_instance" "instance" { + name = "<%= ctx[:vars]['database_instance_name'] %>" + database_version = "POSTGRES_14" + region = "us-central1" + settings { + tier = "db-f1-micro" + + ip_configuration { + + // Datastream IPs will vary by region. + authorized_networks { + value = "34.71.242.81" + } + + authorized_networks { + value = "34.72.28.29" + } + + authorized_networks { + value = "34.67.6.157" + } + + authorized_networks { + value = "34.67.234.134" + } + + authorized_networks { + value = "34.72.239.218" + } + } + } + + deletion_protection = "<%= ctx[:vars]['deletion_protection'] %>" +} + +resource "google_sql_database" "db" { + instance = google_sql_database_instance.instance.name + name = "db" +} + +resource "random_password" "pwd" { + length = 16 + special = false +} + +resource "google_sql_user" "user" { + name = "user" + instance = google_sql_database_instance.instance.name + password = random_password.pwd.result +} + +resource "google_datastream_connection_profile" "<%= ctx[:primary_resource_id] %>" { + display_name = "Connection profile" + location = "us-central1" + connection_profile_id = "<%= ctx[:vars]['connection_profile_id'] %>" + + postgresql_profile { + hostname = google_sql_database_instance.instance.public_ip_address + username = google_sql_user.user.name + password = google_sql_user.user.password + database = google_sql_database.db.name + } + + private_connectivity { + private_connection = google_datastream_private_connection.private_connection.id + } +} From 5365d2d0a4aa41fccdc9fde47bbe860da0e78cf3 Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Wed, 22 Nov 2023 11:49:28 -0800 Subject: [PATCH 014/107] Clean up the alternative route for base branch building.. (#9479) --- .../downstream-builder/generate_downstream.sh | 99 ++++--------------- 1 file changed, 19 insertions(+), 80 deletions(-) diff --git a/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh b/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh index 68d26e190dde..8165e3ea8e24 100755 --- a/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh +++ b/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh @@ -98,90 +98,29 @@ elif [ "$COMMAND" == "downstream" ]; then COMMIT_MESSAGE="$ORIGINAL_MESSAGE$NEWLINE[upstream:$REFERENCE]" fi -if [ "$COMMAND" == "base" ]; then - pushd mmv1 - if [ "$REPO" == "terraform" ]; then - pushd $LOCAL_PATH - go mod download - find . -type f -not -wholename "./.git*" -not -wholename "./.changelog*" -not -name ".travis.yml" -not -name ".golangci.yml" -not -name "CHANGELOG.md" -not -name "CHANGELOG_v*.md" -not -name "GNUmakefile" -not -name "docscheck.sh" -not -name "LICENSE" -not -name "README.md" -not -wholename "./examples*" -not -name ".go-version" -not -name ".hashibot.hcl" -print0 | xargs -0 git rm - popd - fi - if [ "$REPO" == "terraform-google-conversion" ]; then - # Generate tfplan2cai - pushd $LOCAL_PATH - # clear out the templates as they are copied during - # generation from mmv1/third_party/validator/tests/data - rm -rf ./tfplan2cai/testdata/templates/ - rm -rf ./tfplan2cai/testdata/generatedconvert/ - rm -rf ./tfplan2cai/converters/google/provider - rm -rf ./tfplan2cai/converters/google/resources - find ./tfplan2cai/test/** -type f -exec git rm {} \; - popd - - bundle exec compiler.rb -a -e terraform -f validator -o $LOCAL_PATH/tfplan2cai -v $VERSION - - # Generate cai2hcl - pushd $LOCAL_PATH - rm -rf ./cai2hcl/* - popd - - bundle exec compiler.rb -a -e terraform -f tgc_cai2hcl -o $LOCAL_PATH/cai2hcl -v $VERSION - - if [ "$COMMAND" == "downstream" ]; then - pushd $LOCAL_PATH - go get -d github.com/hashicorp/terraform-provider-google-beta@$BASE_BRANCH - go mod tidy - set +e - make build - set -e - popd - fi - elif [ "$REPO" == "tf-oics" ]; then - # use terraform generator with oics override - bundle exec compiler.rb -a -e terraform -f oics -o $LOCAL_PATH -v $VERSION - else - if [ "$REPO" == "terraform" ]; then - if [ "$VERSION" == "ga" ]; then - bundle exec compiler.rb -a -e $REPO -o $LOCAL_PATH -v $VERSION --no-docs - bundle exec compiler.rb -a -e $REPO -o $LOCAL_PATH -v beta --no-code - else - bundle exec compiler.rb -a -e $REPO -o $LOCAL_PATH -v $VERSION - fi - pushd ../ - make tpgtools OUTPUT_PATH=$LOCAL_PATH VERSION=$VERSION - - # Only generate TeamCity-related file for TPG and TPGB - if [ "$VERSION" == "ga" ] || [ "$VERSION" == "beta" ]; then - make teamcity-servicemap-generate OUTPUT_PATH=$LOCAL_PATH VERSION=$VERSION - fi - popd - fi - fi - popd -else - if [ "$REPO" == "terraform-google-conversion" ]; then - make clean-tgc OUTPUT_PATH="$LOCAL_PATH" - make tgc OUTPUT_PATH="$LOCAL_PATH" - - if [ "$COMMAND" == "downstream" ]; then - pushd $LOCAL_PATH - go get -d github.com/hashicorp/terraform-provider-google-beta@$BASE_BRANCH - go mod tidy - set +e - make build - set -e - popd - fi - elif [ "$REPO" == "tf-oics" ]; then - # use terraform generator with oics override - make tf-oics OUTPUT_PATH="$LOCAL_PATH" - elif [ "$REPO" == "terraform" ]; then - make clean-provider OUTPUT_PATH="$LOCAL_PATH" - make provider OUTPUT_PATH="$LOCAL_PATH" VERSION=$VERSION +if [ "$REPO" == "terraform-google-conversion" ]; then + make clean-tgc OUTPUT_PATH="$LOCAL_PATH" + make tgc OUTPUT_PATH="$LOCAL_PATH" + + if [ "$COMMAND" == "downstream" ]; then + pushd $LOCAL_PATH + go get -d github.com/hashicorp/terraform-provider-google-beta@$BASE_BRANCH + go mod tidy + set +e + make build + set -e + popd fi +elif [ "$REPO" == "tf-oics" ]; then + # use terraform generator with oics override + make tf-oics OUTPUT_PATH="$LOCAL_PATH" +elif [ "$REPO" == "terraform" ]; then + make clean-provider OUTPUT_PATH="$LOCAL_PATH" + make provider OUTPUT_PATH="$LOCAL_PATH" VERSION=$VERSION fi + pushd $LOCAL_PATH git config --local user.name "Modular Magician" From f15568033fa2adc02c1871f8f9d46d83609ccc53 Mon Sep 17 00:00:00 2001 From: Edward Sun <42220489+edwardmedia@users.noreply.github.com> Date: Mon, 27 Nov 2023 08:39:15 -0800 Subject: [PATCH 015/107] fix fleet_default_member_config (#9522) Co-authored-by: Edward Sun --- .../enable_fleet_default_member_config_configmanagement.tf.erb | 2 +- .../enable_fleet_default_member_config_service_mesh.tf.erb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/templates/terraform/examples/enable_fleet_default_member_config_configmanagement.tf.erb b/mmv1/templates/terraform/examples/enable_fleet_default_member_config_configmanagement.tf.erb index 17e7f4fe4f53..ee32445cf049 100644 --- a/mmv1/templates/terraform/examples/enable_fleet_default_member_config_configmanagement.tf.erb +++ b/mmv1/templates/terraform/examples/enable_fleet_default_member_config_configmanagement.tf.erb @@ -1,7 +1,7 @@ resource "google_gke_hub_feature" "feature" { name = "configmanagement" location = "global" - fleetDefaultMemberConfig { + fleet_default_member_config { configmanagement { config_sync { git { diff --git a/mmv1/templates/terraform/examples/enable_fleet_default_member_config_service_mesh.tf.erb b/mmv1/templates/terraform/examples/enable_fleet_default_member_config_service_mesh.tf.erb index f495c0ba2b96..97455d34a37d 100644 --- a/mmv1/templates/terraform/examples/enable_fleet_default_member_config_service_mesh.tf.erb +++ b/mmv1/templates/terraform/examples/enable_fleet_default_member_config_service_mesh.tf.erb @@ -1,7 +1,7 @@ resource "google_gke_hub_feature" "feature" { name = "servicemesh" location = "global" - fleetDefaultMemberConfig { + fleet_default_member_config { mesh { management = "MANAGEMENT_AUTOMATIC" } From 06cc2305748419a58cde2d098932df902d413066 Mon Sep 17 00:00:00 2001 From: Edward Sun <42220489+edwardmedia@users.noreply.github.com> Date: Mon, 27 Nov 2023 08:41:56 -0800 Subject: [PATCH 016/107] change to GA in doc (#9491) Co-authored-by: Edward Sun From 2961b6855c799fc8fa2a31c2f4849aeb6c6b279a Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Tue, 28 Nov 2023 21:27:00 +0530 Subject: [PATCH 017/107] Promote PC to GA (#9510) --- mmv1/products/vmwareengine/PrivateCloud.yaml | 9 +++-- .../vmware_engine_network_legacy.tf.erb | 3 -- .../vmware_engine_private_cloud_basic.tf.erb | 8 ++--- .../vmware_engine_private_cloud_full.tf.erb | 11 +++--- .../provider/provider_mmv1_resources.go.erb | 7 ++-- ...urce_google_vmwareengine_private_cloud.go} | 5 +-- ...source_vmwareengine_private_cloud_test.go} | 34 ++++++++++--------- .../vmwareengine_private_cloud.html.markdown | 4 --- 8 files changed, 36 insertions(+), 45 deletions(-) rename mmv1/third_party/terraform/services/vmwareengine/{data_source_google_vmwareengine_private_cloud.go.erb => data_source_google_vmwareengine_private_cloud.go} (94%) rename mmv1/third_party/terraform/services/vmwareengine/{resource_vmwareengine_private_cloud_test.go.erb => resource_vmwareengine_private_cloud_test.go} (83%) diff --git a/mmv1/products/vmwareengine/PrivateCloud.yaml b/mmv1/products/vmwareengine/PrivateCloud.yaml index 72676d4e1b99..662dbe755cdb 100644 --- a/mmv1/products/vmwareengine/PrivateCloud.yaml +++ b/mmv1/products/vmwareengine/PrivateCloud.yaml @@ -13,7 +13,6 @@ --- !ruby/object:Api::Resource name: 'PrivateCloud' -min_version: beta base_url: 'projects/{{project}}/locations/{{location}}/privateClouds' self_link: 'projects/{{project}}/locations/{{location}}/privateClouds/{{name}}' delete_url: 'projects/{{project}}/locations/{{location}}/privateClouds/{{name}}?delay_hours=0' @@ -55,7 +54,6 @@ examples: name: "vmware_engine_private_cloud_basic" config_path: "templates/terraform/examples/vmware_engine_private_cloud_basic.tf.erb" primary_resource_id: "vmw-engine-pc" - min_version: beta skip_test: true # update tests will take care of create and update. PC creation is expensive and node reservation is required. vars: private_cloud_id: "sample-pc" @@ -66,7 +64,6 @@ examples: - !ruby/object:Provider::Terraform::Examples name: "vmware_engine_private_cloud_full" config_path: "templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb" - min_version: beta primary_resource_id: "vmw-engine-pc" skip_test: true # update tests will take care of create and update. PC creation is expensive and node reservation is required. vars: @@ -155,6 +152,12 @@ properties: * managementIpAddressLayoutVersion=2: Indicates the latest IP address layout used by all newly created private clouds. This version supports all current features. + - !ruby/object:Api::Type::String + name: 'dnsServerIp' + output: true + description: | + DNS Server IP of the Private Cloud. + - !ruby/object:Api::Type::NestedObject name: 'managementCluster' required: true diff --git a/mmv1/templates/terraform/examples/vmware_engine_network_legacy.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_network_legacy.tf.erb index 04aa17580f98..2e339d7b0113 100644 --- a/mmv1/templates/terraform/examples/vmware_engine_network_legacy.tf.erb +++ b/mmv1/templates/terraform/examples/vmware_engine_network_legacy.tf.erb @@ -1,5 +1,4 @@ resource "google_vmwareengine_network" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta project = google_project_service.acceptance.project name = "<%= ctx[:test_env_vars]['location'] %>-default" #Legacy network IDs are in the format: {region-id}-default location = "<%= ctx[:test_env_vars]['location'] %>" @@ -9,7 +8,6 @@ resource "google_vmwareengine_network" "<%= ctx[:primary_resource_id] %>" { resource "google_project_service" "acceptance" { project = google_project.acceptance.project_id - provider = google-beta service = "vmwareengine.googleapis.com" # Needed for CI tests for permissions to propagate, should not be needed for actual usage @@ -20,7 +18,6 @@ resource "google_project_service" "acceptance" { # so creating new project for isolation in CI. resource "google_project" "acceptance" { name = "<%= ctx[:vars]['proj_id'] %>" - provider = google-beta project_id = "<%= ctx[:vars]['proj_id'] %>" org_id = "<%= ctx[:test_env_vars]['org_id'] %>" billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" diff --git a/mmv1/templates/terraform/examples/vmware_engine_private_cloud_basic.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_private_cloud_basic.tf.erb index 987f23164d0b..03e7508c7bb3 100644 --- a/mmv1/templates/terraform/examples/vmware_engine_private_cloud_basic.tf.erb +++ b/mmv1/templates/terraform/examples/vmware_engine_private_cloud_basic.tf.erb @@ -1,5 +1,4 @@ resource "google_vmwareengine_private_cloud" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta location = "<%= ctx[:test_env_vars]['region'] %>-a" name = "<%= ctx[:vars]['private_cloud_id'] %>" description = "Sample test PC." @@ -18,9 +17,8 @@ resource "google_vmwareengine_private_cloud" "<%= ctx[:primary_resource_id] %>" } resource "google_vmwareengine_network" "pc-nw" { - provider = google-beta - name = "<%= ctx[:test_env_vars]['region'] %>-default" - location = "<%= ctx[:test_env_vars]['region'] %>" - type = "LEGACY" + name = "<%= ctx[:vars]['network_id'] %>" + location = "global" + type = "STANDARD" description = "PC network description." } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb index 3542bd28da52..d246a3576538 100644 --- a/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb +++ b/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb @@ -1,5 +1,4 @@ resource "google_vmwareengine_private_cloud" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta location = "<%= ctx[:test_env_vars]['region'] %>-a" name = "<%= ctx[:vars]['private_cloud_id'] %>" description = "Sample test PC." @@ -19,9 +18,7 @@ resource "google_vmwareengine_private_cloud" "<%= ctx[:primary_resource_id] %>" } resource "google_vmwareengine_network" "pc-nw" { - provider = google-beta - name = "<%= ctx[:test_env_vars]['region'] %>-default" - location = "<%= ctx[:test_env_vars]['region'] %>" - type = "LEGACY" - description = "PC network description." -} \ No newline at end of file + name = "<%= ctx[:vars]['network_id'] %>" + location = "global" + type = "STANDARD" + description = "PC network description." \ No newline at end of file diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 6a06e716b915..a1f905b01b1d 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -196,11 +196,12 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_vpc_access_connector": vpcaccess.DataSourceVPCAccessConnector(), "google_redis_instance": redis.DataSourceGoogleRedisInstance(), "google_vertex_ai_index": vertexai.DataSourceVertexAIIndex(), - "google_vmwareengine_network": vmwareengine.DataSourceVmwareengineNetwork(), <% unless version == 'ga' -%> - "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), - "google_vmwareengine_cluster": vmwareengine.DataSourceVmwareengineCluster(), + "google_vmwareengine_cluster": vmwareengine.DataSourceVmwareengineCluster(), <% end -%> + "google_vmwareengine_network": vmwareengine.DataSourceVmwareengineNetwork(), + "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), + // ####### END handwritten datasources ########### } diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go similarity index 94% rename from mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb rename to mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go index 915240857698..4afc7d5899fa 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_private_cloud.go @@ -1,6 +1,5 @@ -<% autogen_exception -%> package vmwareengine -<% unless version == 'ga' -%> + import ( "fmt" @@ -14,7 +13,6 @@ func DataSourceVmwareenginePrivateCloud() *schema.Resource { dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceVmwareenginePrivateCloud().Schema) tpgresource.AddRequiredFieldsToSchema(dsSchema, "name", "location") tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") - return &schema.Resource{ Read: dataSourceVmwareenginePrivateCloudRead, Schema: dsSchema, @@ -40,4 +38,3 @@ func dataSourceVmwareenginePrivateCloudRead(d *schema.ResourceData, meta interfa } return nil } -<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go.erb b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go similarity index 83% rename from mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go.erb rename to mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go index 8f7ced9a58d0..563dfa8d3f86 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go @@ -1,7 +1,5 @@ -<% autogen_exception -%> package vmwareengine_test -<% unless version == 'ga' -%> import ( "fmt" "strings" @@ -9,7 +7,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" @@ -20,20 +17,20 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T t.Parallel() context := map[string]interface{}{ - "region": "southamerica-east1", - "random_suffix": acctest.RandString(t, 10), + "region": "southamerica-west1", + "random_suffix": acctest.RandString(t, 10), } acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckVmwareenginePrivateCloudDestroyProducer(t), - ExternalProviders: map[string]resource.ExternalProvider { - "time": {}, - }, Steps: []resource.TestStep{ { Config: testPrivateCloudUpdateConfig(context, "description1", 3), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_private_cloud.ds", "google_vmwareengine_private_cloud.vmw-engine-pc", map[string]struct{}{}), + ), }, { ResourceName: "google_vmwareengine_private_cloud.vmw-engine-pc", @@ -69,17 +66,15 @@ func testPrivateCloudUpdateConfig(context map[string]interface{}, description st return acctest.Nprintf(` resource "google_vmwareengine_network" "default-nw" { - provider = google-beta - name = "%{region}-default" - location = "%{region}" - type = "LEGACY" + name = "tf-test-pc-nw-%{random_suffix}" + location = "global" + type = "STANDARD" description = "PC network description." } resource "google_vmwareengine_private_cloud" "vmw-engine-pc" { location = "%{region}-a" name = "tf-test-sample-pc%{random_suffix}" - provider = google-beta description = "%{description}" network_config { management_cidr = "192.168.30.0/24" @@ -94,6 +89,15 @@ resource "google_vmwareengine_private_cloud" "vmw-engine-pc" { } } } + +data "google_vmwareengine_private_cloud" ds { + location = "%{region}-a" + name = "tf-test-sample-pc%{random_suffix}" + depends_on = [ + google_vmwareengine_private_cloud.vmw-engine-pc, + ] +} + `, context) } @@ -129,5 +133,3 @@ func testAccCheckVmwareenginePrivateCloudDestroyProducer(t *testing.T) func(s *t return nil } } - -<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_private_cloud.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_private_cloud.html.markdown index 83f8998b88ea..6f7da273ed5b 100644 --- a/mmv1/third_party/terraform/website/docs/d/vmwareengine_private_cloud.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_private_cloud.html.markdown @@ -8,9 +8,6 @@ description: |- Use this data source to get details about a private cloud resource. -~> **Warning:** This data source is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. - To get more information about private cloud, see: * [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds) @@ -18,7 +15,6 @@ To get more information about private cloud, see: ```hcl data "google_vmwareengine_private_cloud" "my_pc" { - provider = google-beta name = "my-pc" location = "us-central1-a" } From 0ad441f5158f943bb8aaa52543d854fcd9bc632d Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Tue, 28 Nov 2023 09:18:55 -0800 Subject: [PATCH 018/107] Update vacations (#9525) --- .ci/magician/github/membership.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index 53038d7fb4df..71e6656535d2 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -34,11 +34,7 @@ var ( // This is for reviewers who are "on vacation": will not receive new review assignments but will still receive re-requests for assigned PRs. onVacationReviewers = []string{ "hao-nan-li", - "SarahFrench", "c2thorn", - "shuyama1", - "melinath", - "trodge", } ) From 7f1989d9e2ccd1bbeaedb21a86ee57ce385aa0c0 Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Tue, 28 Nov 2023 09:25:25 -0800 Subject: [PATCH 019/107] Add netapp service (#9046) --- .ci/infra/terraform/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index b5487a331617..dc4db226b03b 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -265,6 +265,7 @@ module "project-services" { "mobilecrashreporting.googleapis.com", "monitoring.googleapis.com", "multiclustermetering.googleapis.com", + "netapp.googleapis.com", "networkconnectivity.googleapis.com", "networkmanagement.googleapis.com", "networksecurity.googleapis.com", From 49640f7044c8e931bb869d4445d6b5320757a826 Mon Sep 17 00:00:00 2001 From: pratikgarg10 <33780624+pratikgarg10@users.noreply.github.com> Date: Wed, 29 Nov 2023 00:23:47 +0530 Subject: [PATCH 020/107] add support for IAM Group authentication to google_sql_user (#9505) --- .../terraform/services/sql/resource_sql_user.go | 6 ++++-- .../terraform/services/sql/resource_sql_user_test.go | 11 +++++++++++ .../terraform/website/docs/r/sql_user.html.markdown | 3 ++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user.go b/mmv1/third_party/terraform/services/sql/resource_sql_user.go index 599e55df39f7..15bf8061b05d 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user.go @@ -102,8 +102,10 @@ func ResourceSqlUser() *schema.Resource { ForceNew: true, DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("BUILT_IN"), Description: `The user type. It determines the method to authenticate the user during login. - The default is the database's built-in user type. Flags include "BUILT_IN", "CLOUD_IAM_USER", or "CLOUD_IAM_SERVICE_ACCOUNT".`, - ValidateFunc: validation.StringInSlice([]string{"BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", ""}, false), + The default is the database's built-in user type. Flags include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", + "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" or "CLOUD_IAM_GROUP_SERVICE_ACCOUNT".`, + ValidateFunc: validation.StringInSlice([]string{"BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", + "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER", "CLOUD_IAM_GROUP_SERVICE_ACCOUNT", ""}, false), }, "sql_server_user_details": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go index efcf0d5f5962..9091ef56a534 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go @@ -26,6 +26,7 @@ func TestAccSqlUser_mysql(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"), testAccCheckGoogleSqlUserExists(t, "google_sql_user.user2"), + testAccCheckGoogleSqlUserExists(t, "google_sql_user.user3"), ), }, { @@ -34,6 +35,7 @@ func TestAccSqlUser_mysql(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"), testAccCheckGoogleSqlUserExists(t, "google_sql_user.user2"), + testAccCheckGoogleSqlUserExists(t, "google_sql_user.user3"), ), }, { @@ -311,6 +313,15 @@ resource "google_sql_user" "user2" { instance = google_sql_database_instance.instance.name host = "gmail.com" password = "hunter2" + type = "CLOUD_IAM_USER" +} + +resource "google_sql_user" "user3" { + name = "admin" + instance = google_sql_database_instance.instance.name + host = "gmail.com" + password = "hunter3" + type = "CLOUD_IAM_GROUP" } `, instance, password) } diff --git a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown index 9b96d4463a22..bc2cb270b5ee 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown @@ -91,7 +91,8 @@ The following arguments are supported: * `type` - (Optional) The user type. It determines the method to authenticate the user during login. The default is the database's built-in user type. Flags - include "BUILT_IN", "CLOUD_IAM_USER", or "CLOUD_IAM_SERVICE_ACCOUNT". + include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", or + "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" or "CLOUD_IAM_GROUP_SERVICE_ACCOUNT". * `deletion_policy` - (Optional) The deletion policy for the user. Setting `ABANDON` allows the resource to be abandoned rather than deleted. This is useful From 5fe6974a331f156d294aba25e9b582b9b5f7b768 Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Wed, 29 Nov 2023 01:06:40 +0530 Subject: [PATCH 021/107] Add Network Peering resource to Vmwareengine (#9511) --- .../products/vmwareengine/NetworkPeering.yaml | 172 ++++++++++++++++++ ...are_engine_network_peering_standard.tf.erb | 15 ++ .../vmware_engine_network_peering_ven.tf.erb | 21 +++ .../provider/provider_mmv1_resources.go.erb | 1 + ...rce_google_vmwareengine_network_peering.go | 40 ++++ ...oogle_vmwareengine_network_peering_test.go | 61 +++++++ ...ource_vmwareengine_network_peering_test.go | 67 +++++++ ...vmwareengine_network_peering.html.markdown | 30 +++ 8 files changed, 407 insertions(+) create mode 100644 mmv1/products/vmwareengine/NetworkPeering.yaml create mode 100644 mmv1/templates/terraform/examples/vmware_engine_network_peering_standard.tf.erb create mode 100644 mmv1/templates/terraform/examples/vmware_engine_network_peering_ven.tf.erb create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_peering.go create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_peering_test.go create mode 100644 mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_peering_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/vmwareengine_network_peering.html.markdown diff --git a/mmv1/products/vmwareengine/NetworkPeering.yaml b/mmv1/products/vmwareengine/NetworkPeering.yaml new file mode 100644 index 000000000000..c9b54ae0f07b --- /dev/null +++ b/mmv1/products/vmwareengine/NetworkPeering.yaml @@ -0,0 +1,172 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'NetworkPeering' +base_url: 'projects/{{project}}/locations/global/networkPeering' +self_link: 'projects/{{project}}/locations/global/networkPeerings/{{name}}' +create_url: 'projects/{{project}}/locations/global/networkPeerings?networkPeeringId={{name}}' +update_verb: :PATCH +references: !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/compute/docs/reference/rest/v1/networks/addPeering' +description: | + Represents a network peering resource. Network peerings are global resources. +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" + status: !ruby/object:Api::OpAsync::Status + path: "done" + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: "error" + message: "message" + +import_format: ["projects/{{project}}/locations/global/networkPeerings/{{name}}"] +autogen_async: true + +examples: + - !ruby/object:Provider::Terraform::Examples + name: "vmware_engine_network_peering_ven" + primary_resource_id: "vmw-engine-network-peering" + vars: + name: "sample-network-peering" + test_env_vars: + region: :REGION + - !ruby/object:Provider::Terraform::Examples + name: "vmware_engine_network_peering_standard" + primary_resource_id: "vmw-engine-network-peering" + vars: + name: "sample-network-peering" + test_env_vars: + region: :REGION + +parameters: + - !ruby/object:Api::Type::String + name: "name" + required: true + immutable: true + url_param_only: true + description: | + The ID of the Network Peering. + +properties: + - !ruby/object:Api::Type::Time + name: 'createTime' + output: true + description: | + Creation time of this resource. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and + up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + + - !ruby/object:Api::Type::Time + name: 'updateTime' + output: true + description: | + Last updated time of this resource. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine + fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + + - !ruby/object:Api::Type::String + name: 'peerNetwork' + required: true + description: | + The relative resource name of the network to peer with a standard VMware Engine network. + The provided network can be a consumer VPC network or another standard VMware Engine network. + + - !ruby/object:Api::Type::Boolean + name: exportCustomRoutes + default_value: true + send_empty_value: true + description: | + True if custom routes are exported to the peered network; false otherwise. + + - !ruby/object:Api::Type::Boolean + name: importCustomRoutes + default_value: true + send_empty_value: true + description: | + True if custom routes are imported from the peered network; false otherwise. + + - !ruby/object:Api::Type::Boolean + name: exportCustomRoutesWithPublicIp + default_value: true + send_empty_value: true + description: | + True if all subnet routes with a public IP address range are exported; false otherwise. + + - !ruby/object:Api::Type::Boolean + name: importCustomRoutesWithPublicIp + default_value: true + send_empty_value: true + description: | + True if custom routes are imported from the peered network; false otherwise. + + - !ruby/object:Api::Type::String + name: 'state' + output: true + description: | + State of the network peering. + This field has a value of 'ACTIVE' when there's a matching configuration in the peer network. + New values may be added to this enum when appropriate. + + - !ruby/object:Api::Type::String + name: 'stateDetails' + output: true + description: | + Details about the current state of the network peering. + + - !ruby/object:Api::Type::Enum + name: 'peerNetworkType' + required: true + description: | + The type of the network to peer with the VMware Engine network. + values: + - :STANDARD + - :VMWARE_ENGINE_NETWORK + - :PRIVATE_SERVICES_ACCESS + - :NETAPP_CLOUD_VOLUMES + - :THIRD_PARTY_SERVICE + - :DELL_POWERSCALE + + - !ruby/object:Api::Type::String + name: 'uid' + output: true + description: | + System-generated unique identifier for the resource. + + - !ruby/object:Api::Type::String + name: 'vmwareEngineNetwork' + required: true + description: | + The relative resource name of the VMware Engine network. Specify the name in the following form: + projects/{project}/locations/{location}/vmwareEngineNetworks/{vmwareEngineNetworkId} where {project} + can either be a project number or a project ID. + + - !ruby/object:Api::Type::String + name: 'description' + description: | + User-provided description for this network peering. + + - !ruby/object:Api::Type::String + name: 'vmwareEngineNetworkCanonical' + output: true + description: | + The canonical name of the VMware Engine network in the form: + projects/{project_number}/locations/{location}/vmwareEngineNetworks/{vmwareEngineNetworkId} diff --git a/mmv1/templates/terraform/examples/vmware_engine_network_peering_standard.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_network_peering_standard.tf.erb new file mode 100644 index 000000000000..0f298b862cf3 --- /dev/null +++ b/mmv1/templates/terraform/examples/vmware_engine_network_peering_standard.tf.erb @@ -0,0 +1,15 @@ +resource "google_compute_network" "network-peering-vpc" { + name = "default-vpc" +} +resource "google_vmwareengine_network" "network-peering-standard-nw" { + name = "default-standard-nw-np" + location = "global" + type = "STANDARD" +} +resource "google_vmwareengine_network_peering" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['name'] %>" + description = "Sample description" + peer_network = google_compute_network.network-peering-vpc.id + peer_network_type = "STANDARD" + vmware_engine_network = google_vmwareengine_network.network-peering-standard-nw.id +} diff --git a/mmv1/templates/terraform/examples/vmware_engine_network_peering_ven.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_network_peering_ven.tf.erb new file mode 100644 index 000000000000..1b11b0e49414 --- /dev/null +++ b/mmv1/templates/terraform/examples/vmware_engine_network_peering_ven.tf.erb @@ -0,0 +1,21 @@ +resource "google_vmwareengine_network" "network-peering-nw" { + name = "default-np-nw" + location = "global" + type = "STANDARD" +} +resource "google_vmwareengine_network" "network-peering-peer-nw" { + name = "peer-np-nw" + location = "global" + type = "STANDARD" +} +resource "google_vmwareengine_network_peering" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['name'] %>" + description = "Sample description" + vmware_engine_network = google_vmwareengine_network.network-peering-nw.id + peer_network = google_vmwareengine_network.network-peering-peer-nw.id + peer_network_type = "VMWARE_ENGINE_NETWORK" + export_custom_routes = false + import_custom_routes = false + export_custom_routes_with_public_ip = false + import_custom_routes_with_public_ip = false +} diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index a1f905b01b1d..249dd8e0c988 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -200,6 +200,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_vmwareengine_cluster": vmwareengine.DataSourceVmwareengineCluster(), <% end -%> "google_vmwareengine_network": vmwareengine.DataSourceVmwareengineNetwork(), + "google_vmwareengine_network_peering": vmwareengine.DataSourceVmwareengineNetworkPeering(), "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), // ####### END handwritten datasources ########### diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_peering.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_peering.go new file mode 100644 index 000000000000..00524c0412c9 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_peering.go @@ -0,0 +1,40 @@ +package vmwareengine + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceVmwareengineNetworkPeering() *schema.Resource { + + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceVmwareengineNetworkPeering().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "name") + tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") + return &schema.Resource{ + Read: dataSourceVmwareengineNetworkPeeringRead, + Schema: dsSchema, + } +} + +func dataSourceVmwareengineNetworkPeeringRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/global/networkPeerings/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + err = resourceVmwareengineNetworkPeeringRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_peering_test.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_peering_test.go new file mode 100644 index 000000000000..a486d1c97a55 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_peering_test.go @@ -0,0 +1,61 @@ +package vmwareengine_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccDataSourceVmwareengineNetworkPeering_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineNetworkPeeringDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVmwareengineNetworkPeering_ds(context), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_network_peering.ds", "google_vmwareengine_network_peering.vmw-engine-network-peering", map[string]struct{}{}), + ), + }, + }, + }) +} + +func testAccVmwareengineNetworkPeering_ds(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_vmwareengine_network" "network-peering-nw" { + name = "tf-test-sample-nw%{random_suffix}" + location = "global" + type = "STANDARD" +} + +resource "google_vmwareengine_network" "network-peering-peer-nw" { + name = "tf-test-peer-nw%{random_suffix}" + location = "global" + type = "STANDARD" +} + +resource "google_vmwareengine_network_peering" "vmw-engine-network-peering" { + name = "tf-test-sample-network-peering%{random_suffix}" + description = "Sample description" + vmware_engine_network = google_vmwareengine_network.network-peering-nw.id + peer_network = google_vmwareengine_network.network-peering-peer-nw.id + peer_network_type = "VMWARE_ENGINE_NETWORK" +} + +data "google_vmwareengine_network_peering" "ds" { + name = google_vmwareengine_network_peering.vmw-engine-network-peering.name + depends_on = [ + google_vmwareengine_network_peering.vmw-engine-network-peering, + ] +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_peering_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_peering_test.go new file mode 100644 index 000000000000..5c914de578d4 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_peering_test.go @@ -0,0 +1,67 @@ +package vmwareengine_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccVmwareengineNetworkPeering_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineNetworkPeeringDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVmwareengineNetworkPeering_config(context, "Sample description."), + }, + { + ResourceName: "google_vmwareengine_network_peering.vmw-engine-network-peering", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name"}, + }, + { + Config: testAccVmwareengineNetworkPeering_config(context, "Updated description."), + }, + { + ResourceName: "google_vmwareengine_network_peering.vmw-engine-network-peering", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name"}, + }, + }, + }) +} + +func testAccVmwareengineNetworkPeering_config(context map[string]interface{}, description string) string { + context["description"] = description + return acctest.Nprintf(` +resource "google_vmwareengine_network" "network-peering-nw" { + name = "tf-test-sample-nw%{random_suffix}" + location = "global" + type = "STANDARD" +} + +resource "google_vmwareengine_network" "network-peering-peer-nw" { + name = "tf-test-peer-nw%{random_suffix}" + location = "global" + type = "STANDARD" +} + +resource "google_vmwareengine_network_peering" "vmw-engine-network-peering" { + name = "tf-test-sample-network-peering%{random_suffix}" + description = "%{description}" + vmware_engine_network = google_vmwareengine_network.network-peering-nw.id + peer_network = google_vmwareengine_network.network-peering-peer-nw.id + peer_network_type = "VMWARE_ENGINE_NETWORK" +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_network_peering.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_network_peering.html.markdown new file mode 100644 index 000000000000..6bb4c9813f16 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_network_peering.html.markdown @@ -0,0 +1,30 @@ +--- +subcategory: "Cloud VMware Engine" +description: |- + Get information about a network peering. +--- + +# google\_vmwareengine\_network_peering + +Use this data source to get details about a network peering resource. + +To get more information about network peering, see: +* [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.networkPeerings) + +## Example Usage + +```hcl +data "google_vmwareengine_network_peering" "my_network_peering" { + name = "my-network-peering" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Name of the resource. + +## Attributes Reference + +See [google_vmwareengine_network_peering](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/vmwareengine_network_peering#attributes-reference) resource for details of all the available attributes. \ No newline at end of file From 1f33fbccb5dd8ac8128088bd51cd3dcc87c5e966 Mon Sep 17 00:00:00 2001 From: Edward Hartwell Goose Date: Tue, 28 Nov 2023 20:12:50 +0000 Subject: [PATCH 022/107] Fix reference to role (#9497) It says service account, but it should be custom role. --- .../website/docs/r/google_project_iam_custom_role.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/website/docs/r/google_project_iam_custom_role.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_project_iam_custom_role.html.markdown index a703f4cb76ad..b3ea67839f0b 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_project_iam_custom_role.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_project_iam_custom_role.html.markdown @@ -41,7 +41,7 @@ The following arguments are supported: * `permissions` (Required) The names of the permissions this role grants when bound in an IAM policy. At least one permission must be specified. -* `project` - (Optional) The project that the service account will be created in. +* `project` - (Optional) The project that the custom role will be created in. Defaults to the provider project configuration. * `stage` - (Optional) The current launch stage of the role. From f0d74c684318c06fd19b360fba1ea5446eac5007 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Tue, 28 Nov 2023 15:35:17 -0600 Subject: [PATCH 023/107] Update vacation list (#9532) --- .ci/magician/github/membership.go | 1 - 1 file changed, 1 deletion(-) diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index 71e6656535d2..98af81827746 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -34,7 +34,6 @@ var ( // This is for reviewers who are "on vacation": will not receive new review assignments but will still receive re-requests for assigned PRs. onVacationReviewers = []string{ "hao-nan-li", - "c2thorn", } ) From 0126c3d731f79d8e38905271a8430b3d1676544f Mon Sep 17 00:00:00 2001 From: Raz Amir <88726761+ramir-savvy@users.noreply.github.com> Date: Tue, 28 Nov 2023 23:37:13 +0200 Subject: [PATCH 024/107] Retry on firestore index create 409 with 'cross-transaction contention' (#9515) --- mmv1/products/firestore/Index.yaml | 2 ++ .../terraform/transport/error_retry_predicates.go | 10 ++++++++++ .../transport/error_retry_predicates_test.go | 11 +++++++++++ 3 files changed, 23 insertions(+) diff --git a/mmv1/products/firestore/Index.yaml b/mmv1/products/firestore/Index.yaml index 1b9ec7323130..877cdca86cb3 100644 --- a/mmv1/products/firestore/Index.yaml +++ b/mmv1/products/firestore/Index.yaml @@ -16,6 +16,8 @@ name: 'Index' base_url: projects/{{project}}/databases/{{database}}/collectionGroups/{{collection}}/indexes self_link: '{{name}}' immutable: true +error_retry_predicates: + ["transport_tpg.FirestoreIndex409CrossTransactionContetion"] description: | Cloud Firestore indexes enable simple and complex queries against documents in a database. This resource manages composite indexes and not single diff --git a/mmv1/third_party/terraform/transport/error_retry_predicates.go b/mmv1/third_party/terraform/transport/error_retry_predicates.go index d7c21e6fef94..c37cce72c484 100644 --- a/mmv1/third_party/terraform/transport/error_retry_predicates.go +++ b/mmv1/third_party/terraform/transport/error_retry_predicates.go @@ -330,6 +330,16 @@ func FirestoreField409RetryUnderlyingDataChanged(err error) (bool, string) { return false, "" } +// relevant for firestore in datastore mode +func FirestoreIndex409CrossTransactionContetion(err error) (bool, string) { + if gerr, ok := err.(*googleapi.Error); ok { + if gerr.Code == 409 && strings.Contains(gerr.Body, "Aborted due to cross-transaction contention") { + return true, "aborted due to cross-transaction contention - retrying" + } + } + return false, "" +} + func IapClient409Operation(err error) (bool, string) { if gerr, ok := err.(*googleapi.Error); ok { if gerr.Code == 409 && strings.Contains(strings.ToLower(gerr.Body), "operation was aborted") { diff --git a/mmv1/third_party/terraform/transport/error_retry_predicates_test.go b/mmv1/third_party/terraform/transport/error_retry_predicates_test.go index a5f9b61e044a..317a7b0da9e9 100644 --- a/mmv1/third_party/terraform/transport/error_retry_predicates_test.go +++ b/mmv1/third_party/terraform/transport/error_retry_predicates_test.go @@ -181,3 +181,14 @@ func TestFirestoreField409_retryUnderlyingDataChanged(t *testing.T) { t.Errorf("Error not detected as retryable") } } + +func TestFirestoreIndex409_crossTransactionContetion(t *testing.T) { + err := googleapi.Error{ + Code: 409, + Body: "Aborted due to cross-transaction contention", + } + isRetryable, _ := FirestoreIndex409CrossTransactionContetion(&err) + if !isRetryable { + t.Errorf("Error not detected as retryable") + } +} From 95a1894283604a2884986a424a0966a61791d52d Mon Sep 17 00:00:00 2001 From: Antoni Zawodny Date: Wed, 29 Nov 2023 19:13:34 +0100 Subject: [PATCH 025/107] Add support for Queued Provisioning feature for GKE node pools (#9540) --- mmv1/third_party/terraform/go.mod.erb | 37 ++++---- mmv1/third_party/terraform/go.sum | 84 +++++++++---------- .../resource_container_node_pool.go.erb | 41 +++++++++ .../resource_container_node_pool_test.go.erb | 74 ++++++++++++++++ .../docs/r/container_node_pool.html.markdown | 7 ++ 5 files changed, 182 insertions(+), 61 deletions(-) diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index 10b3c8bc2d7e..c75615613c2f 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -24,21 +24,21 @@ require ( github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/hashstructure v1.1.0 github.com/sirupsen/logrus v1.8.1 - golang.org/x/net v0.17.0 - golang.org/x/oauth2 v0.13.0 - google.golang.org/api v0.148.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a - google.golang.org/grpc v1.58.3 + golang.org/x/net v0.18.0 + golang.org/x/oauth2 v0.14.0 + google.golang.org/api v0.152.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f + google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 ) require ( bitbucket.org/creachadair/stringset v0.0.8 // indirect - cloud.google.com/go v0.110.8 // indirect - cloud.google.com/go/compute v1.23.0 // indirect + cloud.google.com/go v0.110.10 // indirect + cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.2 // indirect - cloud.google.com/go/longrunning v0.5.1 // indirect + cloud.google.com/go/iam v1.1.5 // indirect + cloud.google.com/go/longrunning v0.5.4 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect @@ -50,14 +50,14 @@ require ( github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect github.com/fatih/color v1.13.0 // indirect github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/google/uuid v1.3.1 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-hclog v1.2.1 // indirect @@ -85,13 +85,14 @@ require ( github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/zclconf/go-cty v1.11.0 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/sync v0.4.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/crypto v0.15.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 8b9bc3c22337..1644657b191a 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -2,21 +2,21 @@ bitbucket.org/creachadair/stringset v0.0.8 h1:gQqe4vs8XWgMyijfyKE6K8o4TcyGGrRXe0 bitbucket.org/creachadair/stringset v0.0.8/go.mod h1:AgthVMyMxC/6FK1KBJ2ALdqkZObGN8hOetgpwXyMn34= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= -cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= cloud.google.com/go/bigtable v1.19.0 h1:wiq9LT0kukfInzvy1joMDijCw/OD1UChpSbORXYn0LI= cloud.google.com/go/bigtable v1.19.0/go.mod h1:xl5kPa8PTkJjdBxg6qdGH88464nNqmbISHSRU+D2yFE= -cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/iam v1.1.2 h1:gacbrBdWcoVmGLozRuStX45YKvJtzIjJdAolzUs1sm4= -cloud.google.com/go/iam v1.1.2/go.mod h1:A5avdyVL2tCppe4unb0951eI9jreack+RJ0/d+KUZOU= -cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= -cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= +cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.56.0 h1:R8zbp/2oVfPbMF1u6RTkf5s+J4hA6sWAEo8E7xsrbpY= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.56.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0 h1:Rz/Jlnt195m9B8CJPQejuTbXaPCoB1w1QYQjD4oKHMk= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= @@ -89,8 +89,8 @@ github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -128,10 +128,10 @@ github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932/go.mod h1:cC6EdPbj/1 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= -github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= @@ -289,8 +289,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -314,20 +314,20 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -348,16 +348,18 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -372,8 +374,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.148.0 h1:HBq4TZlN4/1pNcu0geJZ/Q50vIwIXT532UIMYoo0vOs= -google.golang.org/api v0.148.0/go.mod h1:8/TBgwaKjfqTdacOJrOv2+2Q6fBDU1uHKK06oGSkxzU= +google.golang.org/api v0.152.0 h1:t0r1vPnfMc260S2Ci+en7kfCZaLOPs5KI0sVV/6jZrY= +google.golang.org/api v0.152.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= @@ -383,20 +385,20 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= -google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= -google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -429,7 +431,3 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.56.0 h1:R8zbp/2oVfPbMF1u6RTkf5s+J4hA6sWAEo8E7xsrbpY= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.56.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0 h1:Rz/Jlnt195m9B8CJPQejuTbXaPCoB1w1QYQjD4oKHMk= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb index 1bd538dd9794..4350958d6a64 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb @@ -207,6 +207,26 @@ var schemaNodePool = map[string]*schema.Schema{ }, }, +<% unless version == 'ga' -%> + "queued_provisioning": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Specifies the configuration of queued provisioning`, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + ForceNew: true, + Description: `Whether nodes in this node pool are obtainable solely through the ProvisioningRequest API`, + }, + }, + }, + }, +<% end -%> + "max_pods_per_node": &schema.Schema{ Type: schema.TypeInt, Optional: true, @@ -953,6 +973,17 @@ func expandNodePool(d *schema.ResourceData, prefix string) (*container.NodePool, } } +<% unless version == 'ga' -%> + if v, ok := d.GetOk(prefix + "queued_provisioning"); ok { + if v.([]interface{}) != nil && v.([]interface{})[0] != nil { + queued_provisioning := v.([]interface{})[0].(map[string]interface{}) + np.QueuedProvisioning = &container.QueuedProvisioning{ + Enabled: queued_provisioning["enabled"].(bool), + } + } + } +<% end -%> + if v, ok := d.GetOk(prefix + "max_pods_per_node"); ok { np.MaxPodsConstraint = &container.MaxPodsConstraint{ MaxPodsPerNode: int64(v.(int)), @@ -1146,6 +1177,16 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c } } +<% unless version == 'ga' -%> + if np.QueuedProvisioning != nil { + nodePool["queued_provisioning"] = []map[string]interface{}{ + { + "enabled": np.QueuedProvisioning.Enabled, + }, + } + } +<% end -%> + if np.MaxPodsConstraint != nil { nodePool["max_pods_per_node"] = np.MaxPodsConstraint.MaxPodsPerNode } diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb index aac2bfc21ce3..7f2d7d7aeb31 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb @@ -1849,6 +1849,80 @@ resource "google_container_node_pool" "np" { `, cluster, networkName, subnetworkName, policyName, np) } +<% unless version == 'ga' -%> +func TestAccContainerNodePool_enableQueuedProvisioning(t *testing.T) { + t.Parallel() + + cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + np := fmt.Sprintf("tf-test-nodepool-%s", acctest.RandString(t, 10)) + networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster") + subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerNodePoolDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerNodePool_enableQueuedProvisioning(cluster, np, networkName, subnetworkName, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_container_node_pool.np", "node_config.0.machine_type", "n1-standard-2"), + resource.TestCheckResourceAttr("google_container_node_pool.np", + "node_config.0.reservation_affinity.0.consume_reservation_type", "NO_RESERVATION"), + resource.TestCheckResourceAttr("google_container_node_pool.np", "queued_provisioning.0.enabled", "true"), + ), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccContainerNodePool_enableQueuedProvisioning(cluster, np, networkName, subnetworkName string, enabled bool) string { + return fmt.Sprintf(` +resource "google_container_cluster" "cluster" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + min_master_version = "1.28" + deletion_protection = false + network = "%s" + subnetwork = "%s" +} + +resource "google_container_node_pool" "np" { + name = "%s" + location = "us-central1-a" + cluster = google_container_cluster.cluster.name + autoscaling { + total_min_node_count = 0 + total_max_node_count = 1 + } + + node_config { + machine_type = "n1-standard-2" + guest_accelerator { + type = "nvidia-tesla-t4" + count = 1 + gpu_driver_installation_config { + gpu_driver_version = "LATEST" + } + } + reservation_affinity { + consume_reservation_type = "NO_RESERVATION" + } + } + queued_provisioning { + enabled = %t + } +} +`, cluster, networkName, subnetworkName, np, enabled) +} +<% end -%> + func TestAccContainerNodePool_threadsPerCore(t *testing.T) { t.Parallel() diff --git a/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown index c0e7fb8a90f1..3649ce923de7 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_node_pool.html.markdown @@ -172,6 +172,9 @@ cluster. * `placement_policy` - (Optional) Specifies a custom placement policy for the nodes. +* `queued_provisioning` - (Optional, Beta) Specifies node pool-level settings of queued provisioning. + Structure is [documented below](#nested_queued_provisioning). + The `autoscaling` block supports (either total or per zone limits are required): * `min_node_count` - (Optional) Minimum number of nodes per zone in the NodePool. @@ -275,6 +278,10 @@ cluster. * `tpu_topology` - (Optional) The [TPU placement topology](https://cloud.google.com/tpu/docs/types-topologies#tpu_topologies) for pod slice node pool. + The `queued_provisioning` block supports: + +* `enabled` (Required) - Makes nodes obtainable through the [ProvisioningRequest API](https://cloud.google.com/kubernetes-engine/docs/how-to/provisioningrequest) exclusively. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: From 41912a69ea11db386dfc59e713e09ad7cdb5747f Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Wed, 29 Nov 2023 10:15:10 -0800 Subject: [PATCH 026/107] Add new QIR to infra doc (#9542) --- .ci/infra/terraform/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/infra/terraform/README.md b/.ci/infra/terraform/README.md index 6d09096610fd..942219f6e9ab 100644 --- a/.ci/infra/terraform/README.md +++ b/.ci/infra/terraform/README.md @@ -67,3 +67,4 @@ Quotas that will need to be adjusted to support all tests: - compute.googleapis.com/regional_static_addresses (us-central1) - compute.googleapis.com/routers - compute.googleapis.com/c2_cpus (us-central1) +- compute.googleapis.com/n2_cpus (us-central1) to 36+ From ce2d84b886cbd808d650624170695b564128d861 Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Wed, 29 Nov 2023 10:29:08 -0800 Subject: [PATCH 027/107] Revert "add support for IAM Group authentication to google_sql_user (#9505)" (#9534) This reverts commit 49640f7044c8e931bb869d4445d6b5320757a826. --- .../terraform/services/sql/resource_sql_user.go | 6 ++---- .../terraform/services/sql/resource_sql_user_test.go | 11 ----------- .../terraform/website/docs/r/sql_user.html.markdown | 3 +-- 3 files changed, 3 insertions(+), 17 deletions(-) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user.go b/mmv1/third_party/terraform/services/sql/resource_sql_user.go index 15bf8061b05d..599e55df39f7 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user.go @@ -102,10 +102,8 @@ func ResourceSqlUser() *schema.Resource { ForceNew: true, DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("BUILT_IN"), Description: `The user type. It determines the method to authenticate the user during login. - The default is the database's built-in user type. Flags include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", - "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" or "CLOUD_IAM_GROUP_SERVICE_ACCOUNT".`, - ValidateFunc: validation.StringInSlice([]string{"BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", - "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER", "CLOUD_IAM_GROUP_SERVICE_ACCOUNT", ""}, false), + The default is the database's built-in user type. Flags include "BUILT_IN", "CLOUD_IAM_USER", or "CLOUD_IAM_SERVICE_ACCOUNT".`, + ValidateFunc: validation.StringInSlice([]string{"BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", ""}, false), }, "sql_server_user_details": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go index 9091ef56a534..efcf0d5f5962 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go @@ -26,7 +26,6 @@ func TestAccSqlUser_mysql(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"), testAccCheckGoogleSqlUserExists(t, "google_sql_user.user2"), - testAccCheckGoogleSqlUserExists(t, "google_sql_user.user3"), ), }, { @@ -35,7 +34,6 @@ func TestAccSqlUser_mysql(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"), testAccCheckGoogleSqlUserExists(t, "google_sql_user.user2"), - testAccCheckGoogleSqlUserExists(t, "google_sql_user.user3"), ), }, { @@ -313,15 +311,6 @@ resource "google_sql_user" "user2" { instance = google_sql_database_instance.instance.name host = "gmail.com" password = "hunter2" - type = "CLOUD_IAM_USER" -} - -resource "google_sql_user" "user3" { - name = "admin" - instance = google_sql_database_instance.instance.name - host = "gmail.com" - password = "hunter3" - type = "CLOUD_IAM_GROUP" } `, instance, password) } diff --git a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown index bc2cb270b5ee..9b96d4463a22 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown @@ -91,8 +91,7 @@ The following arguments are supported: * `type` - (Optional) The user type. It determines the method to authenticate the user during login. The default is the database's built-in user type. Flags - include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", or - "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" or "CLOUD_IAM_GROUP_SERVICE_ACCOUNT". + include "BUILT_IN", "CLOUD_IAM_USER", or "CLOUD_IAM_SERVICE_ACCOUNT". * `deletion_policy` - (Optional) The deletion policy for the user. Setting `ABANDON` allows the resource to be abandoned rather than deleted. This is useful From c1b9a0615197ebdf8aaa3dac60a0c69a1fd993a0 Mon Sep 17 00:00:00 2001 From: Davide Cendron <52994395+davcen@users.noreply.github.com> Date: Wed, 29 Nov 2023 22:32:31 +0100 Subject: [PATCH 028/107] redefine as optional all attributes in timespan_config block for dlp job trigger (#9467) --- mmv1/products/dlp/JobTrigger.yaml | 31 +++++++++++----- ...ge_optional_timespan_autopopulation.tf.erb | 36 +++++++++++++++++++ 2 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 mmv1/templates/terraform/examples/dlp_job_trigger_cloud_storage_optional_timespan_autopopulation.tf.erb diff --git a/mmv1/products/dlp/JobTrigger.yaml b/mmv1/products/dlp/JobTrigger.yaml index 61f7c8645937..e788d5672c7a 100644 --- a/mmv1/products/dlp/JobTrigger.yaml +++ b/mmv1/products/dlp/JobTrigger.yaml @@ -110,6 +110,13 @@ examples: trigger: 'trigger' test_env_vars: project: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: 'dlp_job_trigger_cloud_storage_optional_timespan_autopopulation' + primary_resource_id: 'basic' + vars: + trigger: 'trigger' + test_env_vars: + project: :PROJECT_NAME custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/dlp_job_trigger.go.erb decoder: templates/terraform/decoders/dlp_job_trigger.go.erb @@ -716,32 +723,40 @@ properties: properties: - !ruby/object:Api::Type::NestedObject name: 'timespanConfig' - description: Information on where to inspect + description: Configuration of the timespan of the items to include in scanning properties: - !ruby/object:Api::Type::String name: 'startTime' + description: Exclude files, tables, or rows older than this value. If not set, no lower time limit is applied. at_least_one_of: - inspect_job.0.storage_config.0.timespan_config.0.start_time - inspect_job.0.storage_config.0.timespan_config.0.end_time - description: Exclude files or rows older than this value. + - inspect_job.0.storage_config.0.timespan_config.0.enable_auto_population_of_timespan_config + conflicts: + - inspect_job.0.storage_config.0.timespan_config.0.enable_auto_population_of_timespan_config - !ruby/object:Api::Type::String name: 'endTime' + description: Exclude files, tables, or rows newer than this value. If not set, no upper time limit is applied. at_least_one_of: - inspect_job.0.storage_config.0.timespan_config.0.start_time - inspect_job.0.storage_config.0.timespan_config.0.end_time - description: - Exclude files or rows newer than this value. If set to zero, - no upper time limit is applied. + - inspect_job.0.storage_config.0.timespan_config.0.enable_auto_population_of_timespan_config - !ruby/object:Api::Type::Boolean name: 'enableAutoPopulationOfTimespanConfig' description: | When the job is started by a JobTrigger we will automatically figure out a valid startTime to avoid scanning files that have not been modified since the last time the JobTrigger executed. This will - be based on the time of the execution of the last run of the JobTrigger. + be based on the time of the execution of the last run of the JobTrigger or the timespan endTime + used in the last run of the JobTrigger. + at_least_one_of: + - inspect_job.0.storage_config.0.timespan_config.0.start_time + - inspect_job.0.storage_config.0.timespan_config.0.end_time + - inspect_job.0.storage_config.0.timespan_config.0.enable_auto_population_of_timespan_config + conflicts: + - inspect_job.0.storage_config.0.timespan_config.0.start_time - !ruby/object:Api::Type::NestedObject name: 'timestampField' - description: Information on where to inspect - required: true + description: Specification of the field containing the timestamp of scanned items. properties: - !ruby/object:Api::Type::String name: 'name' diff --git a/mmv1/templates/terraform/examples/dlp_job_trigger_cloud_storage_optional_timespan_autopopulation.tf.erb b/mmv1/templates/terraform/examples/dlp_job_trigger_cloud_storage_optional_timespan_autopopulation.tf.erb new file mode 100644 index 000000000000..abdfdf5f3a02 --- /dev/null +++ b/mmv1/templates/terraform/examples/dlp_job_trigger_cloud_storage_optional_timespan_autopopulation.tf.erb @@ -0,0 +1,36 @@ +resource "google_data_loss_prevention_job_trigger" "<%= ctx[:primary_resource_id] %>" { + parent = "projects/<%= ctx[:test_env_vars]['project'] %>" + description = "Description" + display_name = "Displayname" + + triggers { + schedule { + recurrence_period_duration = "86400s" + } + } + + inspect_job { + inspect_template_name = "fake" + actions { + save_findings { + output_config { + table { + project_id = "project" + dataset_id = "dataset" + } + } + } + } + storage_config { + timespan_config { + enable_auto_population_of_timespan_config = true + } + + cloud_storage_options { + file_set { + url = "gs://mybucket/directory/" + } + } + } + } +} From 7d66718fdc666160536ff9c7aa3d7c62150c4f2a Mon Sep 17 00:00:00 2001 From: Henry Wang Date: Wed, 29 Nov 2023 21:49:08 +0000 Subject: [PATCH 029/107] Upgrade and downgrade edition and datacache in sql instance (#9483) --- .../sql/resource_sql_database_instance.go.erb | 28 ++++ .../resource_sql_database_instance_test.go | 134 ++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb index 2e89cfea5ed3..91099e68b3e3 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb @@ -1880,6 +1880,34 @@ func resourceSqlDatabaseInstanceUpdate(d *schema.ResourceData, meta interface{}) } } + // Check if the edition is being updated, because patching edition is an atomic operation and can not be + // performed with other fields, we first patch edition, tier and data cache config before updating the rest of the fields. + if d.HasChange("settings.0.edition") { + edition := d.Get("settings.0.edition").(string) + tier := d.Get("settings.0.tier").(string) + dataCacheConfig := expandDataCacheConfig(d.Get("settings.0.data_cache_config").([]interface{})) + instance = &sqladmin.DatabaseInstance{Settings: &sqladmin.Settings{Edition: edition, Tier: tier, DataCacheConfig: dataCacheConfig}} + err = transport_tpg.Retry(transport_tpg.RetryOptions{ + RetryFunc: func() (rerr error) { + op, rerr = config.NewSqlAdminClient(userAgent).Instances.Patch(project, d.Get("name").(string), instance).Do() + return rerr + }, + Timeout: d.Timeout(schema.TimeoutUpdate), + ErrorRetryPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.IsSqlOperationInProgressError}, + }) + if err != nil { + return fmt.Errorf("Error, failed to patch instance settings for %s: %s", instance.Name, err) + } + err = SqlAdminOperationWaitTime(config, op, project, "Patch Instance", userAgent, d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return err + } + err = resourceSqlDatabaseInstanceRead(d, meta) + if err != nil { + return err + } + } + s := d.Get("settings") instance = &sqladmin.DatabaseInstance{ Settings: expandSqlDatabaseInstanceSettings(desiredSetting.([]interface{}), databaseVersion), diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index 6227aad58e80..af63bbd48ee1 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -1562,6 +1562,9 @@ func TestAccSQLDatabaseInstance_sqlMysqlDataCacheConfig(t *testing.T) { Steps: []resource.TestStep{ { Config: testGoogleSqlDatabaseInstance_sqlMysqlDataCacheConfig(instanceName), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_sql_database_instance.instance", "settings.0.data_cache_config.0.data_cache_enabled", "true"), + ), }, { ResourceName: "google_sql_database_instance.instance", @@ -1605,6 +1608,120 @@ func TestAccSQLDatabaseInstance_sqlPostgresDataCacheConfig(t *testing.T) { }) } +func TestAccSqlDatabaseInstance_Mysql_Edition_Upgrade(t *testing.T) { + t.Parallel() + enterpriseTier := "db-custom-2-13312" + editionUpgrade := "tf-test-enterprise-upgrade-" + acctest.RandString(t, 10) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testGoogleSqlDatabaseInstance_sqlMysql(editionUpgrade, enterpriseTier), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_sql_database_instance.instance", "settings.0.edition", "ENTERPRISE"), + ), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testGoogleSqlDatabaseInstance_sqlMysqlDataCacheConfig(editionUpgrade), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_sql_database_instance.instance", "settings.0.edition", "ENTERPRISE_PLUS"), + resource.TestCheckResourceAttr("google_sql_database_instance.instance", "settings.0.data_cache_config.0.data_cache_enabled", "true"), + ), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +func TestAccSqlDatabaseInstance_Postgres_Edition_Upgrade(t *testing.T) { + t.Parallel() + enterpriseTier := "db-custom-2-13312" + enterprisePlusTier := "db-perf-optimized-N-2" + editionUpgrade := "tf-test-enterprise-upgrade-" + acctest.RandString(t, 10) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testGoogleSqlDatabaseInstance_EditionConfig_noEdition(editionUpgrade, enterpriseTier), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_sql_database_instance.instance", "settings.0.edition", "ENTERPRISE"), + ), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testGoogleSqlDatabaseInstance_EditionConfig(editionUpgrade, enterprisePlusTier, "ENTERPRISE_PLUS"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_sql_database_instance.instance", "settings.0.edition", "ENTERPRISE_PLUS"), + ), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + +func TestAccSqlDatabaseInstance_Edition_Downgrade(t *testing.T) { + t.Parallel() + enterprisePlusTier := "db-perf-optimized-N-2" + enterpriseTier := "db-custom-2-13312" + editionDowngrade := "tf-test-enterprise-downgrade-" + acctest.RandString(t, 10) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testGoogleSqlDatabaseInstance_EditionConfig(editionDowngrade, enterprisePlusTier, "ENTERPRISE_PLUS"), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_sql_database_instance.instance", "settings.0.edition", "ENTERPRISE_PLUS"), + ), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + { + Config: testGoogleSqlDatabaseInstance_EditionConfig_noEdition(editionDowngrade, enterpriseTier), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("google_sql_database_instance.instance", "settings.0.edition", "ENTERPRISE"), + ), + }, + { + ResourceName: "google_sql_database_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, + }, + }) +} + func TestAccSqlDatabaseInstance_SqlServerAuditConfig(t *testing.T) { // Service Networking acctest.SkipIfVcr(t) @@ -2376,6 +2493,9 @@ resource "google_sql_database_instance" "instance" { deletion_protection = false settings { tier = "%s" + backup_configuration { + transaction_log_retention_days = 7 + } } }`, databaseName, tier) } @@ -2395,6 +2515,20 @@ resource "google_sql_database_instance" "instance" { }`, databaseName, tier, edition) } +func testGoogleSqlDatabaseInstance_sqlMysql(databaseName, tier string) string { + return fmt.Sprintf(` + +resource "google_sql_database_instance" "instance" { + name = "%s" + region = "us-east1" + database_version = "MYSQL_8_0_31" + deletion_protection = false + settings { + tier = "%s" + } +}`, databaseName, tier) +} + func testGoogleSqlDatabaseInstance_sqlMysqlDataCacheConfig(instanceName string) string { return fmt.Sprintf(` From ad73996797c4a3c361f10da573e6d5394db5d162 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 29 Nov 2023 13:50:18 -0800 Subject: [PATCH 030/107] Fix terraform-google-conversion v5 imports (#9543) * Re-enabled TestAccContainerCluster_withAddons * Updated TGC imports to reference v5 * Removed unrelated change --- mmv1/templates/tgc/resource_converter.go.erb | 2 +- mmv1/templates/tgc/resource_converter_iam.go.erb | 2 +- mmv1/templates/tgc/resource_converters.go.erb | 6 +++--- mmv1/third_party/cai2hcl/common/converter.go | 2 +- mmv1/third_party/cai2hcl/common/utils.go | 2 +- mmv1/third_party/cai2hcl/convert.go | 4 ++-- mmv1/third_party/cai2hcl/convert_test.go | 6 +++--- mmv1/third_party/cai2hcl/converter_map.go | 6 +++--- .../services/compute/compute_forwarding_rule.go | 4 ++-- .../services/compute/compute_forwarding_rule_test.go | 2 +- .../cai2hcl/services/compute/compute_instance.go | 4 ++-- .../cai2hcl/services/compute/compute_instance_test.go | 2 +- .../cai2hcl/services/compute/converter_map.go | 2 +- .../cai2hcl/services/resourcemanager/converter_map.go | 2 +- .../cai2hcl/services/resourcemanager/project.go | 4 ++-- .../cai2hcl/services/resourcemanager/project_test.go | 2 +- mmv1/third_party/cai2hcl/testing/assert_test_files.go | 4 ++-- .../third_party/tgc/ancestrymanager/ancestrymanager.go | 2 +- .../tgc/ancestrymanager/ancestrymanager_test.go | 4 ++-- mmv1/third_party/tgc/ancestrymanager/ancestryutil.go | 2 +- .../tgc/ancestrymanager/ancestryutil_test.go | 2 +- mmv1/third_party/tgc/bigquery_dataset_iam.go | 2 +- mmv1/third_party/tgc/bigquery_table.go | 2 +- mmv1/third_party/tgc/bigtable_cluster.go | 2 +- mmv1/third_party/tgc/bigtable_instance.go | 2 +- mmv1/third_party/tgc/cai.go | 2 +- mmv1/third_party/tgc/cloudfunctions_cloud_function.go | 2 +- mmv1/third_party/tgc/cloudfunctions_function.go | 2 +- mmv1/third_party/tgc/compute_instance.go.erb | 2 +- mmv1/third_party/tgc/compute_security_policy.go | 2 +- mmv1/third_party/tgc/constants.go | 2 +- mmv1/third_party/tgc/container.go | 2 +- mmv1/third_party/tgc/convert.go | 10 +++++----- mmv1/third_party/tgc/convert_test.go | 8 ++++---- mmv1/third_party/tgc/folder.go | 2 +- mmv1/third_party/tgc/folder_iam.go | 2 +- mmv1/third_party/tgc/folder_organization_policy.go | 2 +- mmv1/third_party/tgc/iam_helpers.go | 2 +- mmv1/third_party/tgc/json_map.go | 2 +- mmv1/third_party/tgc/kms_crypto_key_iam.go | 2 +- mmv1/third_party/tgc/kms_key_ring_iam.go | 2 +- mmv1/third_party/tgc/org_policy_policy.go | 2 +- mmv1/third_party/tgc/organization_iam.go | 2 +- mmv1/third_party/tgc/organization_iam_custom_role.go | 2 +- mmv1/third_party/tgc/organization_policy.go | 2 +- mmv1/third_party/tgc/project.go | 2 +- mmv1/third_party/tgc/project_iam.go | 2 +- mmv1/third_party/tgc/project_iam_custom_role.go | 2 +- mmv1/third_party/tgc/project_organization_policy.go | 2 +- mmv1/third_party/tgc/project_service.go | 2 +- mmv1/third_party/tgc/pubsub_subscription_iam.go | 2 +- mmv1/third_party/tgc/service_account.go | 2 +- mmv1/third_party/tgc/spanner_database_iam.go | 2 +- mmv1/third_party/tgc/spanner_instance_iam.go | 2 +- mmv1/third_party/tgc/sql_database_instance.go | 2 +- mmv1/third_party/tgc/storage_bucket.go | 2 +- mmv1/third_party/tgc/storage_bucket_iam.go | 2 +- mmv1/third_party/tgc/tests/source/cli_test.go.erb | 2 +- mmv1/third_party/tgc/tests/source/iam_test.go.erb | 6 +++--- mmv1/third_party/tgc/tests/source/init_test.go | 2 +- mmv1/third_party/tgc/tests/source/read_test.go.erb | 2 +- mmv1/third_party/tgc/tests/source/utils_test.go | 4 ++-- 62 files changed, 84 insertions(+), 84 deletions(-) diff --git a/mmv1/templates/tgc/resource_converter.go.erb b/mmv1/templates/tgc/resource_converter.go.erb index cbd05113e3fe..83d7bd26b6b9 100644 --- a/mmv1/templates/tgc/resource_converter.go.erb +++ b/mmv1/templates/tgc/resource_converter.go.erb @@ -17,7 +17,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging" "google.golang.org/api/bigtableadmin/v2" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" diff --git a/mmv1/templates/tgc/resource_converter_iam.go.erb b/mmv1/templates/tgc/resource_converter_iam.go.erb index 4943dae39f3d..70855ebe5908 100644 --- a/mmv1/templates/tgc/resource_converter_iam.go.erb +++ b/mmv1/templates/tgc/resource_converter_iam.go.erb @@ -37,7 +37,7 @@ package <%= product_ns.downcase -%> import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/templates/tgc/resource_converters.go.erb b/mmv1/templates/tgc/resource_converters.go.erb index 018bbf1f3684..6f2e4f37e154 100644 --- a/mmv1/templates/tgc/resource_converters.go.erb +++ b/mmv1/templates/tgc/resource_converters.go.erb @@ -18,9 +18,9 @@ package google import ( "sort" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/services/compute" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/services/resourcemanager" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/services/spanner" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/compute" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/resourcemanager" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/services/spanner" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" ) diff --git a/mmv1/third_party/cai2hcl/common/converter.go b/mmv1/third_party/cai2hcl/common/converter.go index d0bccc4cdfb5..17f6a652daac 100644 --- a/mmv1/third_party/cai2hcl/common/converter.go +++ b/mmv1/third_party/cai2hcl/common/converter.go @@ -1,7 +1,7 @@ package common import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/zclconf/go-cty/cty" ) diff --git a/mmv1/third_party/cai2hcl/common/utils.go b/mmv1/third_party/cai2hcl/common/utils.go index f2d163f2825b..0325957d9b3e 100644 --- a/mmv1/third_party/cai2hcl/common/utils.go +++ b/mmv1/third_party/cai2hcl/common/utils.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" hashicorpcty "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/hcl/hcl/printer" "github.com/hashicorp/hcl/v2/hclwrite" diff --git a/mmv1/third_party/cai2hcl/convert.go b/mmv1/third_party/cai2hcl/convert.go index 82af21826754..c1983f052775 100644 --- a/mmv1/third_party/cai2hcl/convert.go +++ b/mmv1/third_party/cai2hcl/convert.go @@ -3,9 +3,9 @@ package cai2hcl import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" "go.uber.org/zap" ) diff --git a/mmv1/third_party/cai2hcl/convert_test.go b/mmv1/third_party/cai2hcl/convert_test.go index bf9208825217..18ca6a9ba26e 100644 --- a/mmv1/third_party/cai2hcl/convert_test.go +++ b/mmv1/third_party/cai2hcl/convert_test.go @@ -3,9 +3,9 @@ package cai2hcl import ( "testing" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/services/compute" - cai2hclTesting "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/testing" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/services/compute" + cai2hclTesting "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/testing" ) func TestConvertCompute(t *testing.T) { diff --git a/mmv1/third_party/cai2hcl/converter_map.go b/mmv1/third_party/cai2hcl/converter_map.go index f562d1a72279..cf66000d221e 100644 --- a/mmv1/third_party/cai2hcl/converter_map.go +++ b/mmv1/third_party/cai2hcl/converter_map.go @@ -1,9 +1,9 @@ package cai2hcl import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/services/compute" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/services/resourcemanager" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/services/compute" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/services/resourcemanager" ) var allConverterNames = []map[string]string{ diff --git a/mmv1/third_party/cai2hcl/services/compute/compute_forwarding_rule.go b/mmv1/third_party/cai2hcl/services/compute/compute_forwarding_rule.go index c36b4cb6fbfc..c821ebb52f43 100644 --- a/mmv1/third_party/cai2hcl/services/compute/compute_forwarding_rule.go +++ b/mmv1/third_party/cai2hcl/services/compute/compute_forwarding_rule.go @@ -3,8 +3,8 @@ package compute import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" tfschema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" computeV1 "google.golang.org/api/compute/v1" diff --git a/mmv1/third_party/cai2hcl/services/compute/compute_forwarding_rule_test.go b/mmv1/third_party/cai2hcl/services/compute/compute_forwarding_rule_test.go index 4a7cfb3c89d3..21a237724f6b 100644 --- a/mmv1/third_party/cai2hcl/services/compute/compute_forwarding_rule_test.go +++ b/mmv1/third_party/cai2hcl/services/compute/compute_forwarding_rule_test.go @@ -3,7 +3,7 @@ package compute import ( "testing" - cai2hclTesting "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/testing" + cai2hclTesting "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/testing" ) func TestComputeForwardingRule(t *testing.T) { diff --git a/mmv1/third_party/cai2hcl/services/compute/compute_instance.go b/mmv1/third_party/cai2hcl/services/compute/compute_instance.go index d6356a2e3ede..8453eb892327 100644 --- a/mmv1/third_party/cai2hcl/services/compute/compute_instance.go +++ b/mmv1/third_party/cai2hcl/services/compute/compute_instance.go @@ -4,9 +4,9 @@ import ( "encoding/json" "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" tfschema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/zclconf/go-cty/cty" "google.golang.org/api/compute/v1" diff --git a/mmv1/third_party/cai2hcl/services/compute/compute_instance_test.go b/mmv1/third_party/cai2hcl/services/compute/compute_instance_test.go index 0772913b5277..0b7eaf876d39 100644 --- a/mmv1/third_party/cai2hcl/services/compute/compute_instance_test.go +++ b/mmv1/third_party/cai2hcl/services/compute/compute_instance_test.go @@ -3,7 +3,7 @@ package compute import ( "testing" - cai2hclTesting "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/testing" + cai2hclTesting "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/testing" ) func TestComputeInstance(t *testing.T) { diff --git a/mmv1/third_party/cai2hcl/services/compute/converter_map.go b/mmv1/third_party/cai2hcl/services/compute/converter_map.go index 4532694d57cd..48c782727116 100644 --- a/mmv1/third_party/cai2hcl/services/compute/converter_map.go +++ b/mmv1/third_party/cai2hcl/services/compute/converter_map.go @@ -1,7 +1,7 @@ package compute import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" ) var ConverterNames = map[string]string{ diff --git a/mmv1/third_party/cai2hcl/services/resourcemanager/converter_map.go b/mmv1/third_party/cai2hcl/services/resourcemanager/converter_map.go index 9c5e2a0db0b2..e999a92ec0f5 100644 --- a/mmv1/third_party/cai2hcl/services/resourcemanager/converter_map.go +++ b/mmv1/third_party/cai2hcl/services/resourcemanager/converter_map.go @@ -1,7 +1,7 @@ package resourcemanager import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" ) var ConverterNames = map[string]string{ diff --git a/mmv1/third_party/cai2hcl/services/resourcemanager/project.go b/mmv1/third_party/cai2hcl/services/resourcemanager/project.go index 01b3431d8a62..e0fe0a2296fe 100644 --- a/mmv1/third_party/cai2hcl/services/resourcemanager/project.go +++ b/mmv1/third_party/cai2hcl/services/resourcemanager/project.go @@ -5,8 +5,8 @@ import ( "fmt" "strings" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" tfschema "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/zclconf/go-cty/cty" diff --git a/mmv1/third_party/cai2hcl/services/resourcemanager/project_test.go b/mmv1/third_party/cai2hcl/services/resourcemanager/project_test.go index d29d4a71abcb..9d6d0bb11a07 100644 --- a/mmv1/third_party/cai2hcl/services/resourcemanager/project_test.go +++ b/mmv1/third_party/cai2hcl/services/resourcemanager/project_test.go @@ -3,7 +3,7 @@ package resourcemanager import ( "testing" - cai2hclTesting "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/testing" + cai2hclTesting "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/testing" ) func TestComputeInstance(t *testing.T) { diff --git a/mmv1/third_party/cai2hcl/testing/assert_test_files.go b/mmv1/third_party/cai2hcl/testing/assert_test_files.go index e7393402d266..e020e4f0d59d 100644 --- a/mmv1/third_party/cai2hcl/testing/assert_test_files.go +++ b/mmv1/third_party/cai2hcl/testing/assert_test_files.go @@ -6,8 +6,8 @@ import ( "os" "testing" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/cai2hcl/common" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/cai2hcl/common" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" "go.uber.org/zap" "github.com/google/go-cmp/cmp" diff --git a/mmv1/third_party/tgc/ancestrymanager/ancestrymanager.go b/mmv1/third_party/tgc/ancestrymanager/ancestrymanager.go index 6663e0decf3b..4dd99e15de04 100644 --- a/mmv1/third_party/tgc/ancestrymanager/ancestrymanager.go +++ b/mmv1/third_party/tgc/ancestrymanager/ancestrymanager.go @@ -10,7 +10,7 @@ import ( crmv3 "google.golang.org/api/cloudresourcemanager/v3" "google.golang.org/api/storage/v1" - resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources" + resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/ancestrymanager/ancestrymanager_test.go b/mmv1/third_party/tgc/ancestrymanager/ancestrymanager_test.go index 852f7ae659a7..6b1f511f1048 100644 --- a/mmv1/third_party/tgc/ancestrymanager/ancestrymanager_test.go +++ b/mmv1/third_party/tgc/ancestrymanager/ancestrymanager_test.go @@ -9,8 +9,8 @@ import ( "strings" "testing" - resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/tfdata" + resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/tfdata" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/ancestrymanager/ancestryutil.go b/mmv1/third_party/tgc/ancestrymanager/ancestryutil.go index 1942495d42c5..d04479fca7f5 100644 --- a/mmv1/third_party/tgc/ancestrymanager/ancestryutil.go +++ b/mmv1/third_party/tgc/ancestrymanager/ancestryutil.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources" + resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources" "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/ancestrymanager/ancestryutil_test.go b/mmv1/third_party/tgc/ancestrymanager/ancestryutil_test.go index 67de5baaf2f8..a5cdeae54fe5 100644 --- a/mmv1/third_party/tgc/ancestrymanager/ancestryutil_test.go +++ b/mmv1/third_party/tgc/ancestrymanager/ancestryutil_test.go @@ -3,7 +3,7 @@ package ancestrymanager import ( "testing" - resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources" + resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" ) diff --git a/mmv1/third_party/tgc/bigquery_dataset_iam.go b/mmv1/third_party/tgc/bigquery_dataset_iam.go index 2a840a10ea69..b8bd199d3ad6 100644 --- a/mmv1/third_party/tgc/bigquery_dataset_iam.go +++ b/mmv1/third_party/tgc/bigquery_dataset_iam.go @@ -3,7 +3,7 @@ package bigquery import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/bigquery_table.go b/mmv1/third_party/tgc/bigquery_table.go index b2f227a9acf0..20ede57cc956 100644 --- a/mmv1/third_party/tgc/bigquery_table.go +++ b/mmv1/third_party/tgc/bigquery_table.go @@ -3,7 +3,7 @@ package google import ( "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/bigtable_cluster.go b/mmv1/third_party/tgc/bigtable_cluster.go index f2bc4fe3b5e3..99ce6e523b4b 100644 --- a/mmv1/third_party/tgc/bigtable_cluster.go +++ b/mmv1/third_party/tgc/bigtable_cluster.go @@ -3,7 +3,7 @@ package google import ( "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/bigtable_instance.go b/mmv1/third_party/tgc/bigtable_instance.go index 1358439277b9..6403eb378c23 100644 --- a/mmv1/third_party/tgc/bigtable_instance.go +++ b/mmv1/third_party/tgc/bigtable_instance.go @@ -3,7 +3,7 @@ package google import ( "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/cai.go b/mmv1/third_party/tgc/cai.go index eefc5d2d22d7..0652ca3b2d5d 100644 --- a/mmv1/third_party/tgc/cai.go +++ b/mmv1/third_party/tgc/cai.go @@ -1,7 +1,7 @@ package google import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/cloudfunctions_cloud_function.go b/mmv1/third_party/tgc/cloudfunctions_cloud_function.go index 131c33bfac9e..dbc8f4f9bc27 100644 --- a/mmv1/third_party/tgc/cloudfunctions_cloud_function.go +++ b/mmv1/third_party/tgc/cloudfunctions_cloud_function.go @@ -3,7 +3,7 @@ package google import ( "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/cloudfunctions_function.go b/mmv1/third_party/tgc/cloudfunctions_function.go index 5a7cc7e5a843..1f1d917d2739 100644 --- a/mmv1/third_party/tgc/cloudfunctions_function.go +++ b/mmv1/third_party/tgc/cloudfunctions_function.go @@ -3,7 +3,7 @@ package google import ( "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/compute_instance.go.erb b/mmv1/third_party/tgc/compute_instance.go.erb index b27f33613e61..1bcd136acc8a 100644 --- a/mmv1/third_party/tgc/compute_instance.go.erb +++ b/mmv1/third_party/tgc/compute_instance.go.erb @@ -22,7 +22,7 @@ import ( compute "google.golang.org/api/compute/v0.beta" <% end -%> - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/compute_security_policy.go b/mmv1/third_party/tgc/compute_security_policy.go index ed11eb953215..7107d175c41f 100644 --- a/mmv1/third_party/tgc/compute_security_policy.go +++ b/mmv1/third_party/tgc/compute_security_policy.go @@ -3,7 +3,7 @@ package google import ( "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/constants.go b/mmv1/third_party/tgc/constants.go index e7eba3e4404f..3f25d4a126c7 100644 --- a/mmv1/third_party/tgc/constants.go +++ b/mmv1/third_party/tgc/constants.go @@ -1,7 +1,7 @@ package google import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/container.go b/mmv1/third_party/tgc/container.go index 806b64e228b4..65fdf748fbcb 100644 --- a/mmv1/third_party/tgc/container.go +++ b/mmv1/third_party/tgc/container.go @@ -10,7 +10,7 @@ import ( "fmt" "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/convert.go b/mmv1/third_party/tgc/convert.go index 8f4cb9595656..2d4c9d08bd16 100644 --- a/mmv1/third_party/tgc/convert.go +++ b/mmv1/third_party/tgc/convert.go @@ -22,11 +22,11 @@ import ( "strings" "time" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/ancestrymanager" - resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/tfdata" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/tfplan" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/ancestrymanager" + resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/tfdata" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/tfplan" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/convert_test.go b/mmv1/third_party/tgc/convert_test.go index 5e110fd4e251..5854e823c574 100644 --- a/mmv1/third_party/tgc/convert_test.go +++ b/mmv1/third_party/tgc/convert_test.go @@ -9,10 +9,10 @@ import ( "testing" "time" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/ancestrymanager" - resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/tfdata" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/ancestrymanager" + resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/tfdata" tfjson "github.com/hashicorp/terraform-json" provider "github.com/hashicorp/terraform-provider-google-beta/google-beta/provider" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" diff --git a/mmv1/third_party/tgc/folder.go b/mmv1/third_party/tgc/folder.go index 924d4f100aae..cdcf1b5644ba 100644 --- a/mmv1/third_party/tgc/folder.go +++ b/mmv1/third_party/tgc/folder.go @@ -3,7 +3,7 @@ package google import ( "time" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/folder_iam.go b/mmv1/third_party/tgc/folder_iam.go index a809067b5191..7d6d2ebc90af 100644 --- a/mmv1/third_party/tgc/folder_iam.go +++ b/mmv1/third_party/tgc/folder_iam.go @@ -3,7 +3,7 @@ package resourcemanager import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/folder_organization_policy.go b/mmv1/third_party/tgc/folder_organization_policy.go index df7a095baca9..275743e35f47 100644 --- a/mmv1/third_party/tgc/folder_organization_policy.go +++ b/mmv1/third_party/tgc/folder_organization_policy.go @@ -1,7 +1,7 @@ package google import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/iam_helpers.go b/mmv1/third_party/tgc/iam_helpers.go index f5cbf238c632..918f0fff186d 100644 --- a/mmv1/third_party/tgc/iam_helpers.go +++ b/mmv1/third_party/tgc/iam_helpers.go @@ -1,7 +1,7 @@ package google import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgiamresource" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/json_map.go b/mmv1/third_party/tgc/json_map.go index 21b885b28075..acec548462fb 100644 --- a/mmv1/third_party/tgc/json_map.go +++ b/mmv1/third_party/tgc/json_map.go @@ -1,6 +1,6 @@ package google -import "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" +import "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" // JsonMap converts a given value to a map[string]interface{} that // matches its JSON format. diff --git a/mmv1/third_party/tgc/kms_crypto_key_iam.go b/mmv1/third_party/tgc/kms_crypto_key_iam.go index 8ae7e67f110c..201cef86cfc5 100644 --- a/mmv1/third_party/tgc/kms_crypto_key_iam.go +++ b/mmv1/third_party/tgc/kms_crypto_key_iam.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/kms" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/kms_key_ring_iam.go b/mmv1/third_party/tgc/kms_key_ring_iam.go index 26edb08cd699..57404f81445c 100644 --- a/mmv1/third_party/tgc/kms_key_ring_iam.go +++ b/mmv1/third_party/tgc/kms_key_ring_iam.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/services/kms" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/org_policy_policy.go b/mmv1/third_party/tgc/org_policy_policy.go index 15866cc341cd..bf14d9a52050 100644 --- a/mmv1/third_party/tgc/org_policy_policy.go +++ b/mmv1/third_party/tgc/org_policy_policy.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/organization_iam.go b/mmv1/third_party/tgc/organization_iam.go index 6f150d127bc4..3661cec804b5 100644 --- a/mmv1/third_party/tgc/organization_iam.go +++ b/mmv1/third_party/tgc/organization_iam.go @@ -3,7 +3,7 @@ package resourcemanager import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/organization_iam_custom_role.go b/mmv1/third_party/tgc/organization_iam_custom_role.go index 75c695f9babf..439975955708 100644 --- a/mmv1/third_party/tgc/organization_iam_custom_role.go +++ b/mmv1/third_party/tgc/organization_iam_custom_role.go @@ -3,7 +3,7 @@ package google import ( "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/organization_policy.go b/mmv1/third_party/tgc/organization_policy.go index 8e327d0a3158..123689001755 100644 --- a/mmv1/third_party/tgc/organization_policy.go +++ b/mmv1/third_party/tgc/organization_policy.go @@ -1,7 +1,7 @@ package google import ( - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/project.go b/mmv1/third_party/tgc/project.go index c1d33a25bc4d..9f33a8a95d8d 100644 --- a/mmv1/third_party/tgc/project.go +++ b/mmv1/third_party/tgc/project.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" "google.golang.org/api/cloudbilling/v1" diff --git a/mmv1/third_party/tgc/project_iam.go b/mmv1/third_party/tgc/project_iam.go index ec30fd0e79c9..ea04b3ca378d 100644 --- a/mmv1/third_party/tgc/project_iam.go +++ b/mmv1/third_party/tgc/project_iam.go @@ -3,7 +3,7 @@ package resourcemanager import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/project_iam_custom_role.go b/mmv1/third_party/tgc/project_iam_custom_role.go index 35e79e70d445..e16bbcc15dc7 100644 --- a/mmv1/third_party/tgc/project_iam_custom_role.go +++ b/mmv1/third_party/tgc/project_iam_custom_role.go @@ -3,7 +3,7 @@ package google import ( "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/project_organization_policy.go b/mmv1/third_party/tgc/project_organization_policy.go index 05681e0bd94f..16a9b73f7568 100644 --- a/mmv1/third_party/tgc/project_organization_policy.go +++ b/mmv1/third_party/tgc/project_organization_policy.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" diff --git a/mmv1/third_party/tgc/project_service.go b/mmv1/third_party/tgc/project_service.go index 16cbfdb1546e..50eeae0ba462 100644 --- a/mmv1/third_party/tgc/project_service.go +++ b/mmv1/third_party/tgc/project_service.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/pubsub_subscription_iam.go b/mmv1/third_party/tgc/pubsub_subscription_iam.go index e9a68c53f297..0d59f11fd6b3 100644 --- a/mmv1/third_party/tgc/pubsub_subscription_iam.go +++ b/mmv1/third_party/tgc/pubsub_subscription_iam.go @@ -3,7 +3,7 @@ package pubsub import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/service_account.go b/mmv1/third_party/tgc/service_account.go index 6bebd3dca783..b9cc14038515 100644 --- a/mmv1/third_party/tgc/service_account.go +++ b/mmv1/third_party/tgc/service_account.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/spanner_database_iam.go b/mmv1/third_party/tgc/spanner_database_iam.go index c72548d669b1..658b21ebb28c 100644 --- a/mmv1/third_party/tgc/spanner_database_iam.go +++ b/mmv1/third_party/tgc/spanner_database_iam.go @@ -3,7 +3,7 @@ package spanner import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/spanner_instance_iam.go b/mmv1/third_party/tgc/spanner_instance_iam.go index ef89723b1f0c..78c08c8549ea 100644 --- a/mmv1/third_party/tgc/spanner_instance_iam.go +++ b/mmv1/third_party/tgc/spanner_instance_iam.go @@ -3,7 +3,7 @@ package spanner import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/sql_database_instance.go b/mmv1/third_party/tgc/sql_database_instance.go index add0a43f459c..cb844f1dc8b1 100644 --- a/mmv1/third_party/tgc/sql_database_instance.go +++ b/mmv1/third_party/tgc/sql_database_instance.go @@ -14,7 +14,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" sqladmin "google.golang.org/api/sqladmin/v1beta4" diff --git a/mmv1/third_party/tgc/storage_bucket.go b/mmv1/third_party/tgc/storage_bucket.go index cba4577754be..79261a0bd83a 100644 --- a/mmv1/third_party/tgc/storage_bucket.go +++ b/mmv1/third_party/tgc/storage_bucket.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" "google.golang.org/api/storage/v1" diff --git a/mmv1/third_party/tgc/storage_bucket_iam.go b/mmv1/third_party/tgc/storage_bucket_iam.go index 45da2c4b776a..f88e54c5d908 100644 --- a/mmv1/third_party/tgc/storage_bucket_iam.go +++ b/mmv1/third_party/tgc/storage_bucket_iam.go @@ -3,7 +3,7 @@ package google import ( "fmt" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources/cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources/cai" "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" ) diff --git a/mmv1/third_party/tgc/tests/source/cli_test.go.erb b/mmv1/third_party/tgc/tests/source/cli_test.go.erb index 7ca376144e5b..a1a648bdb899 100644 --- a/mmv1/third_party/tgc/tests/source/cli_test.go.erb +++ b/mmv1/third_party/tgc/tests/source/cli_test.go.erb @@ -28,7 +28,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" ) // TestCLI tests the "convert" and "validate" subcommand against a generated .tfplan file. diff --git a/mmv1/third_party/tgc/tests/source/iam_test.go.erb b/mmv1/third_party/tgc/tests/source/iam_test.go.erb index 76c084b07146..a4c3f2a7a131 100644 --- a/mmv1/third_party/tgc/tests/source/iam_test.go.erb +++ b/mmv1/third_party/tgc/tests/source/iam_test.go.erb @@ -11,9 +11,9 @@ import ( crmv1 "google.golang.org/api/cloudresourcemanager/v1" - resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/converters/google/resources" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/tfdata" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai/tfplan" + resources "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/converters/google/resources" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/tfdata" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai/tfplan" provider "github.com/hashicorp/terraform-provider-google-beta/google-beta/provider" ) diff --git a/mmv1/third_party/tgc/tests/source/init_test.go b/mmv1/third_party/tgc/tests/source/init_test.go index 0ae1ecb73149..072c1741e96c 100644 --- a/mmv1/third_party/tgc/tests/source/init_test.go +++ b/mmv1/third_party/tgc/tests/source/init_test.go @@ -13,7 +13,7 @@ import ( "text/template" "time" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" ) var ( diff --git a/mmv1/third_party/tgc/tests/source/read_test.go.erb b/mmv1/third_party/tgc/tests/source/read_test.go.erb index acf7e0d4c450..21a93d888ab0 100644 --- a/mmv1/third_party/tgc/tests/source/read_test.go.erb +++ b/mmv1/third_party/tgc/tests/source/read_test.go.erb @@ -10,7 +10,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai" "go.uber.org/zap/zaptest" ) diff --git a/mmv1/third_party/tgc/tests/source/utils_test.go b/mmv1/third_party/tgc/tests/source/utils_test.go index 4cdfa6d88b0f..29410e1749e2 100644 --- a/mmv1/third_party/tgc/tests/source/utils_test.go +++ b/mmv1/third_party/tgc/tests/source/utils_test.go @@ -14,8 +14,8 @@ import ( "strings" "testing" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/caiasset" - "github.com/GoogleCloudPlatform/terraform-google-conversion/v2/tfplan2cai" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" + "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/tfplan2cai" "github.com/google/go-cmp/cmp" transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" "go.uber.org/zap/zaptest" From a23d520591dcd0500bef368d33d428dce7db8fe7 Mon Sep 17 00:00:00 2001 From: Aaron Liberatore Date: Wed, 29 Nov 2023 14:34:52 -0800 Subject: [PATCH 031/107] [GKE Hub]: Add Fleet default cluster config (#9389) * [GKE Hub]: Add Fleet default cluster config * Adds SecurityPosture Config * [GKE Hub]: Retrigger review * [GKE Hub]: Retrigger review --- mmv1/products/gkehub2/Fleet.yaml | 24 ++++++++++++++++++- .../examples/gkehub_fleet_basic.tf.erb | 6 +++++ .../resource_gke_hub_fleet_test.go.erb | 20 ++++++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/mmv1/products/gkehub2/Fleet.yaml b/mmv1/products/gkehub2/Fleet.yaml index 9a03d3b8fb48..0c9de65f03b6 100644 --- a/mmv1/products/gkehub2/Fleet.yaml +++ b/mmv1/products/gkehub2/Fleet.yaml @@ -49,7 +49,7 @@ examples: - !ruby/object:Provider::Terraform::Examples name: "gkehub_fleet_basic" skip_test: true - primary_resource_id: 'default' + primary_resource_id: "default" id_format: "projects/{{project}}/locations/global/fleets/default" import_format: ["projects/{{project}}/locations/global/fleets/default"] properties: @@ -95,3 +95,25 @@ properties: - READY - DELETING - UPDATING + - !ruby/object:Api::Type::NestedObject + name: "defaultClusterConfig" + description: The default cluster configurations to apply across the fleet. + properties: + - !ruby/object:Api::Type::NestedObject + name: "securityPostureConfig" + description: Enable/Disable Security Posture features for the cluster. + properties: + - !ruby/object:Api::Type::Enum + name: "mode" + description: Sets which mode to use for Security Posture features. + values: + - DISABLED + - BASIC + - ENTERPRISE + - !ruby/object:Api::Type::Enum + name: "vulnerabilityMode" + description: Sets which mode to use for vulnerability scanning. + values: + - VULNERABILITY_DISABLED + - VULNERABILITY_BASIC + - VULNERABILITY_ENTERPRISE diff --git a/mmv1/templates/terraform/examples/gkehub_fleet_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_fleet_basic.tf.erb index be6737b95efd..b31d3770c71c 100644 --- a/mmv1/templates/terraform/examples/gkehub_fleet_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_fleet_basic.tf.erb @@ -1,3 +1,9 @@ resource "google_gke_hub_fleet" "default" { display_name = "my production fleet" + default_cluster_config { + security_posture_config { + mode = "DISABLED" + vulnerability_mode = "VULNERABILITY_DISABLED" + } + } } diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb index d18e7c5ce5d7..b25e1b57789a 100755 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb @@ -57,7 +57,12 @@ func testAccGKEHub2Fleet_basic(context map[string]interface{}) string { resource "google_gke_hub_fleet" "default" { project = google_project.project.project_id display_name = "my production fleet" - + default_cluster_config { + security_posture_config { + mode = "DISABLED" + vulnerability_mode = "VULNERABILITY_DISABLED" + } + } depends_on = [time_sleep.wait_for_gkehub_enablement] } `, context) @@ -68,7 +73,12 @@ func testAccGKEHub2Fleet_update(context map[string]interface{}) string { resource "google_gke_hub_fleet" "default" { project = google_project.project.project_id display_name = "my staging fleet" - + default_cluster_config { + security_posture_config { + mode = "BASIC" + vulnerability_mode = "VULNERABILITY_BASIC" + } + } depends_on = [time_sleep.wait_for_gkehub_enablement] } `, context) @@ -89,6 +99,12 @@ resource "google_project_service" "gkehub" { disable_on_destroy = false } +resource "google_project_service" "anthos" { + project = google_project.project.project_id + service = "anthos.googleapis.com" + disable_on_destroy = false +} + resource "time_sleep" "wait_for_gkehub_enablement" { create_duration = "150s" depends_on = [google_project_service.gkehub] From e06981ab153016b6c49db1fd134685fc09d9a71b Mon Sep 17 00:00:00 2001 From: Eric Pang Date: Thu, 30 Nov 2023 11:55:10 -0500 Subject: [PATCH 032/107] Add Secure Source Manager product and Instance resource (#9415) * Add ssm product and instance.yaml * Add instance id parameter and keep name as output property * move to beta * Add createTime, updateTime, state fields * Add basic instance test * Remove blank lines * Add one blank line back * Move back to GA provider * Fix iam policy * move iam definition up * Add iam roles * Add iam tests * Add test to examples * Remove iam policy, adjust context and variable names * Revert "Remove iam policy, adjust context and variable names" This reverts commit 8e99a3997af8d96ebe58dc15e6d614ff5f245ae2. * remove iam policy, use ctx var for instance id * Use format with random suffix * Slight change import_format for iam, remove provider explicit * Fix instance_id in generated iam test * Remove iam test * Remove reference to the iam test * edit to test again * add iam conditions to test * Update import format * remove iam condition test * revert import format * Fix links * Remove update fields from resource, remove enum values for output field, add iam_conditions_request_type * Add back values: * Add new line * add unknown value back * Remove iam_conditions_request_type --- .../securesourcemanager/Instance.yaml | 112 ++++++++++++++++++ .../products/securesourcemanager/product.yaml | 26 ++++ ...ecure_source_manager_instance_basic.tf.erb | 7 ++ 3 files changed, 145 insertions(+) create mode 100644 mmv1/products/securesourcemanager/Instance.yaml create mode 100644 mmv1/products/securesourcemanager/product.yaml create mode 100644 mmv1/templates/terraform/examples/secure_source_manager_instance_basic.tf.erb diff --git a/mmv1/products/securesourcemanager/Instance.yaml b/mmv1/products/securesourcemanager/Instance.yaml new file mode 100644 index 000000000000..a058f6a75064 --- /dev/null +++ b/mmv1/products/securesourcemanager/Instance.yaml @@ -0,0 +1,112 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'Instance' +kind: 'securesourcemanager#instance' +base_url: 'projects/{{project}}/locations/{{location}}/instances?instance_id={{instance_id}}' +self_link: 'projects/{{project}}/locations/{{location}}/instances/{{instance_id}}' +immutable: true +description: 'Instances are deployed to an available Google Cloud region and are accessible via their web interface.' +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': 'https://cloud.google.com/secure-source-manager/overview/overview' +import_format: ['projects/{{project}}/locations/{{location}}/instances/{{instance_id}}', '{{instance_id}}'] +autogen_async: true +async: !ruby/object:Api::OpAsync + actions: ['create', 'delete'] + operation: !ruby/object:Api::OpAsync::Operation + path: 'name' + base_url: '{{op_id}}' + wait_ms: 1000 + timeouts: !ruby/object:Api::Timeouts + insert_minutes: 60 + update_minutes: 60 + delete_minutes: 60 + result: !ruby/object:Api::OpAsync::Result + path: 'response' + status: !ruby/object:Api::OpAsync::Status + path: 'done' + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: 'error' + message: 'message' +iam_policy: !ruby/object:Api::Resource::IamPolicy + parent_resource_attribute: 'instance_id' + method_name_separator: ':' + allowed_iam_role: 'roles/securesourcemanager.instanceManager' + admin_iam_role: 'roles/securesourcemanager.instanceOwner' + import_format: + [ + 'projects/{{project}}/locations/{{location}}/instances/{{instance_id}}', + '{{instance_id}}', + ] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'secure_source_manager_instance_basic' + primary_resource_id: 'default' + primary_resource_name: "fmt.Sprintf(\"tf-test-my-instance%s\", + context[\"random_suffix\"\ + ])" + vars: + instance_id: 'my-instance' +parameters: + - !ruby/object:Api::Type::String + name: 'location' + description: | + The location for the Instance. + required: true + immutable: true + url_param_only: true + - !ruby/object:Api::Type::String + name: 'instance_id' + description: | + The name for the Instance. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'name' + description: | + The resource name for the Instance. + output: true + immutable: true + - !ruby/object:Api::Type::Time + name: 'createTime' + description: | + Time the Instance was created in UTC. + output: true + - !ruby/object:Api::Type::Time + name: 'updateTime' + description: | + Time the Instance was updated in UTC. + output: true + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' + description: | + Labels as key value pairs. + - !ruby/object:Api::Type::Enum + name: 'state' + description: | + The current state of the Instance. + output: true + values: + - :CREATING + - :ACTIVE + - :DELETING + - :PAUSED + - :UNKNOWN diff --git a/mmv1/products/securesourcemanager/product.yaml b/mmv1/products/securesourcemanager/product.yaml new file mode 100644 index 000000000000..318cea164649 --- /dev/null +++ b/mmv1/products/securesourcemanager/product.yaml @@ -0,0 +1,26 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +name: SecureSourceManager +display_name: Secure Source Manager +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://securesourcemanager.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform +apis_required: + - !ruby/object:Api::Product::ApiReference + name: Secure Source Manager API + url: https://console.cloud.google.com/apis/library/securesourcemanager.googleapis.com/ diff --git a/mmv1/templates/terraform/examples/secure_source_manager_instance_basic.tf.erb b/mmv1/templates/terraform/examples/secure_source_manager_instance_basic.tf.erb new file mode 100644 index 000000000000..c94420da68ee --- /dev/null +++ b/mmv1/templates/terraform/examples/secure_source_manager_instance_basic.tf.erb @@ -0,0 +1,7 @@ +resource "google_secure_source_manager_instance" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + instance_id = "<%= ctx[:vars]['instance_id'] %>" + labels = { + "foo" = "bar" + } +} From e767a8ac8b5de0ffa5700a8aa227dc1238e73ee6 Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Thu, 30 Nov 2023 09:30:40 -0800 Subject: [PATCH 033/107] Add Secure Source Manager service (#9494) --- .ci/infra/terraform/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index dc4db226b03b..bed01ed1da2a 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -287,6 +287,7 @@ module "project-services" { "run.googleapis.com", "runtimeconfig.googleapis.com", "secretmanager.googleapis.com", + "securesourcemanager.googleapis.com", "securetoken.googleapis.com", "securitycenter.googleapis.com", "serviceconsumermanagement.googleapis.com", From ec4f59ea72a0c63c15188c6c13c7fb9d61699cf0 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 30 Nov 2023 09:50:28 -0800 Subject: [PATCH 034/107] Remove Api::Product::ApiReference (#9536) --- mmv1/api/product.rb | 2 -- mmv1/api/product/api_reference.rb | 30 ------------------- mmv1/products/accessapproval/product.yaml | 4 --- mmv1/products/alloydb/product.yaml | 4 --- mmv1/products/apigee/product.yaml | 4 --- mmv1/products/appengine/product.yaml | 4 --- mmv1/products/artifactregistry/product.yaml | 4 --- mmv1/products/backupdr/product.yaml | 4 --- mmv1/products/beyondcorp/product.yaml | 4 --- mmv1/products/biglake/product.yaml | 4 --- mmv1/products/bigquery/product.yaml | 4 --- .../bigqueryanalyticshub/product.yaml | 4 --- mmv1/products/bigqueryconnection/product.yaml | 4 --- mmv1/products/bigquerydatapolicy/product.yaml | 4 --- .../bigquerydatatransfer/product.yaml | 4 --- .../products/bigqueryreservation/product.yaml | 4 --- mmv1/products/bigtable/product.yaml | 4 --- mmv1/products/billing/product.yaml | 4 --- mmv1/products/billingbudget/product.yaml | 4 --- mmv1/products/certificatemanager/product.yaml | 4 --- mmv1/products/cloudasset/product.yaml | 4 --- mmv1/products/cloudbuild/product.yaml | 4 --- mmv1/products/cloudbuildv2/product.yaml | 4 --- mmv1/products/cloudfunctions/product.yaml | 4 --- mmv1/products/cloudfunctions2/product.yaml | 4 --- mmv1/products/cloudidentity/product.yaml | 4 --- mmv1/products/cloudids/product.yaml | 4 --- mmv1/products/cloudrunv2/product.yaml | 4 --- mmv1/products/cloudscheduler/product.yaml | 4 --- mmv1/products/cloudtasks/product.yaml | 4 --- mmv1/products/compute/product.yaml | 4 --- .../databasemigrationservice/product.yaml | 4 --- mmv1/products/datacatalog/product.yaml | 4 --- mmv1/products/datafusion/product.yaml | 4 --- mmv1/products/dataplex/product.yaml | 4 --- mmv1/products/dataproc/product.yaml | 4 --- mmv1/products/datastore/product.yaml | 4 --- mmv1/products/datastream/product.yaml | 4 --- mmv1/products/deploymentmanager/product.yaml | 4 --- mmv1/products/dialogflow/product.yaml | 4 --- mmv1/products/dialogflowcx/product.yaml | 4 --- mmv1/products/dns/product.yaml | 4 --- mmv1/products/documentai/product.yaml | 4 --- .../products/documentaiwarehouse/product.yaml | 4 --- mmv1/products/edgecontainer/product.yaml | 4 --- mmv1/products/edgenetwork/product.yaml | 4 --- mmv1/products/essentialcontacts/product.yaml | 4 --- mmv1/products/firebasedatabase/product.yaml | 4 --- mmv1/products/firebaseextensions/product.yaml | 4 --- mmv1/products/firestore/product.yaml | 4 --- mmv1/products/gkebackup/product.yaml | 4 --- mmv1/products/gkehub/product.yaml | 4 --- mmv1/products/gkehub2/product.yaml | 4 --- mmv1/products/gkeonprem/product.yaml | 4 --- mmv1/products/healthcare/product.yaml | 4 --- mmv1/products/iam2/product.yaml | 4 --- mmv1/products/iambeta/product.yaml | 4 --- mmv1/products/iamworkforcepool/product.yaml | 4 --- mmv1/products/iap/product.yaml | 4 --- mmv1/products/identityplatform/product.yaml | 4 --- .../integrationconnectors/product.yaml | 4 --- mmv1/products/kms/product.yaml | 4 --- mmv1/products/logging/product.yaml | 4 --- mmv1/products/looker/product.yaml | 4 --- mmv1/products/metastore/product.yaml | 4 --- mmv1/products/mlengine/product.yaml | 4 --- mmv1/products/monitoring/product.yaml | 4 --- mmv1/products/netapp/product.yaml | 4 --- .../products/networkconnectivity/product.yaml | 4 --- mmv1/products/networkmanagement/product.yaml | 4 --- mmv1/products/networksecurity/product.yaml | 4 --- mmv1/products/networkservices/product.yaml | 4 --- mmv1/products/notebooks/product.yaml | 4 --- mmv1/products/orgpolicy/product.yaml | 4 --- mmv1/products/osconfig/product.yaml | 4 --- mmv1/products/oslogin/product.yaml | 4 --- mmv1/products/privateca/product.yaml | 4 --- mmv1/products/publicca/product.yaml | 4 --- mmv1/products/pubsub/product.yaml | 4 --- mmv1/products/pubsublite/product.yaml | 4 --- mmv1/products/resourcemanager/product.yaml | 4 --- mmv1/products/runtimeconfig/product.yaml | 4 --- mmv1/products/secretmanager/product.yaml | 4 --- .../products/securesourcemanager/product.yaml | 4 --- mmv1/products/securityscanner/product.yaml | 4 --- mmv1/products/servicedirectory/product.yaml | 4 --- mmv1/products/servicemanagement/product.yaml | 4 --- mmv1/products/serviceusage/product.yaml | 4 --- mmv1/products/sourcerepo/product.yaml | 4 --- mmv1/products/spanner/product.yaml | 4 --- mmv1/products/sql/product.yaml | 4 --- mmv1/products/storage/product.yaml | 4 --- mmv1/products/storageinsights/product.yaml | 7 ----- mmv1/products/storagetransfer/product.yaml | 4 --- mmv1/products/tpuv2/product.yaml | 4 --- mmv1/products/vmwareengine/product.yaml | 4 --- mmv1/products/vpcaccess/product.yaml | 4 --- mmv1/products/workflows/product.yaml | 4 --- mmv1/products/workstations/product.yaml | 4 --- 99 files changed, 423 deletions(-) delete mode 100644 mmv1/api/product/api_reference.rb diff --git a/mmv1/api/product.rb b/mmv1/api/product.rb index 2faca615f254..05ad3f2c6503 100644 --- a/mmv1/api/product.rb +++ b/mmv1/api/product.rb @@ -12,7 +12,6 @@ # limitations under the License. require 'api/object' -require 'api/product/api_reference' require 'api/product/version' require 'google/logger' require 'compile/core' @@ -75,7 +74,6 @@ def validate check :display_name, type: String check :objects, type: Array, item_type: Api::Resource check :scopes, type: Array, item_type: String, required: true - check :apis_required, type: Array, item_type: Api::Product::ApiReference check :operation_retry, type: String check :async, type: Api::Async diff --git a/mmv1/api/product/api_reference.rb b/mmv1/api/product/api_reference.rb deleted file mode 100644 index aae8278f2438..000000000000 --- a/mmv1/api/product/api_reference.rb +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2019 Google Inc. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -require 'api/object' - -module Api - class Product < Api::Object::Named - # Represents any APIs that are required to be enabled to use this product - class ApiReference < Api::Object - attr_reader :name - attr_reader :url - - def validate - super - check :name, type: String, required: true - check :url, type: String, required: true - end - end - end -end diff --git a/mmv1/products/accessapproval/product.yaml b/mmv1/products/accessapproval/product.yaml index 70df0a4a85f0..ec7d98243638 100644 --- a/mmv1/products/accessapproval/product.yaml +++ b/mmv1/products/accessapproval/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://accessapproval.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Access Approval - url: https://console.cloud.google.com/apis/library/accessapproval.googleapis.com/ diff --git a/mmv1/products/alloydb/product.yaml b/mmv1/products/alloydb/product.yaml index dd03681b3583..b9f45eba5d98 100644 --- a/mmv1/products/alloydb/product.yaml +++ b/mmv1/products/alloydb/product.yaml @@ -23,7 +23,3 @@ versions: base_url: https://alloydb.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-identity -apis_required: - - !ruby/object:Api::Product::ApiReference - name: AlloyDB API - url: https://console.cloud.google.com/apis/library/alloydb.googleapis.com diff --git a/mmv1/products/apigee/product.yaml b/mmv1/products/apigee/product.yaml index b5187a753967..4f6c7104702f 100644 --- a/mmv1/products/apigee/product.yaml +++ b/mmv1/products/apigee/product.yaml @@ -27,7 +27,3 @@ versions: base_url: https://apigee.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Apigee API - url: https://console.cloud.google.com/apis/library/apigee.googleapis.com/ diff --git a/mmv1/products/appengine/product.yaml b/mmv1/products/appengine/product.yaml index 699ca84efae5..4c091be92ae5 100644 --- a/mmv1/products/appengine/product.yaml +++ b/mmv1/products/appengine/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://appengine.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: App Engine Admin API - url: https://console.cloud.google.com/apis/library/appengine.googleapis.com/ diff --git a/mmv1/products/artifactregistry/product.yaml b/mmv1/products/artifactregistry/product.yaml index e7eb589a7f91..068579383829 100644 --- a/mmv1/products/artifactregistry/product.yaml +++ b/mmv1/products/artifactregistry/product.yaml @@ -23,10 +23,6 @@ versions: - !ruby/object:Api::Product::Version name: ga base_url: https://artifactregistry.googleapis.com/v1/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Artifact Registry API - url: https://console.cloud.google.com/apis/library/artifactregistry.googleapis.com/ async: !ruby/object:Api::OpAsync actions: ['create', 'delete'] operation: !ruby/object:Api::OpAsync::Operation diff --git a/mmv1/products/backupdr/product.yaml b/mmv1/products/backupdr/product.yaml index 43ddaff88eb9..2156cac27c3b 100644 --- a/mmv1/products/backupdr/product.yaml +++ b/mmv1/products/backupdr/product.yaml @@ -20,10 +20,6 @@ versions: - !ruby/object:Api::Product::Version name: beta base_url: https://backupdr.googleapis.com/v1/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Backup and DR API - url: https://console.cloud.google.com/apis/library/backupdr.googleapis.com/ async: !ruby/object:Api::OpAsync actions: ['create', 'delete'] operation: !ruby/object:Api::OpAsync::Operation diff --git a/mmv1/products/beyondcorp/product.yaml b/mmv1/products/beyondcorp/product.yaml index eea11e715b7c..39be52f97c04 100644 --- a/mmv1/products/beyondcorp/product.yaml +++ b/mmv1/products/beyondcorp/product.yaml @@ -19,7 +19,3 @@ versions: base_url: https://beyondcorp.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Beyondcorp API - url: https://console.cloud.google.com/apis/library/beyondcorp.googleapis.com/ diff --git a/mmv1/products/biglake/product.yaml b/mmv1/products/biglake/product.yaml index 7d2070e9716f..93e6ec3f96a2 100644 --- a/mmv1/products/biglake/product.yaml +++ b/mmv1/products/biglake/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://biglake.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/bigquery -apis_required: - - !ruby/object:Api::Product::ApiReference - name: BigLake API - url: https://console.cloud.google.com/apis/library/biglake.googleapis.com/ diff --git a/mmv1/products/bigquery/product.yaml b/mmv1/products/bigquery/product.yaml index 8737e1242961..4738d4232d24 100644 --- a/mmv1/products/bigquery/product.yaml +++ b/mmv1/products/bigquery/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://bigquery.googleapis.com/bigquery/v2/ scopes: - https://www.googleapis.com/auth/bigquery -apis_required: - - !ruby/object:Api::Product::ApiReference - name: BigQuery API - url: https://console.cloud.google.com/apis/library/bigquery.googleapis.com/ diff --git a/mmv1/products/bigqueryanalyticshub/product.yaml b/mmv1/products/bigqueryanalyticshub/product.yaml index 5af9688704da..adefa3b29446 100644 --- a/mmv1/products/bigqueryanalyticshub/product.yaml +++ b/mmv1/products/bigqueryanalyticshub/product.yaml @@ -23,7 +23,3 @@ versions: - !ruby/object:Api::Product::Version name: ga base_url: https://analyticshub.googleapis.com/v1/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Bigquery Analytics Hub API - url: https://console.cloud.google.com/apis/library/analyticshub.googleapis.com/ diff --git a/mmv1/products/bigqueryconnection/product.yaml b/mmv1/products/bigqueryconnection/product.yaml index 3c20014a43c0..cad9df871600 100644 --- a/mmv1/products/bigqueryconnection/product.yaml +++ b/mmv1/products/bigqueryconnection/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://bigqueryconnection.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/bigquery -apis_required: - - !ruby/object:Api::Product::ApiReference - name: BigQueryConnection API - url: https://console.cloud.google.com/apis/api/bigqueryconnection.googleapis.com/ diff --git a/mmv1/products/bigquerydatapolicy/product.yaml b/mmv1/products/bigquerydatapolicy/product.yaml index 818b8604d18f..18dbd534c8e3 100644 --- a/mmv1/products/bigquerydatapolicy/product.yaml +++ b/mmv1/products/bigquerydatapolicy/product.yaml @@ -23,7 +23,3 @@ versions: - !ruby/object:Api::Product::Version name: ga base_url: https://bigquerydatapolicy.googleapis.com/v1/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: BigQuery Data Policy API - url: https://console.cloud.google.com/apis/library/bigquerydatapolicy.googleapis.com/ diff --git a/mmv1/products/bigquerydatatransfer/product.yaml b/mmv1/products/bigquerydatatransfer/product.yaml index a52590d74692..16ee455ab5f1 100644 --- a/mmv1/products/bigquerydatatransfer/product.yaml +++ b/mmv1/products/bigquerydatatransfer/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://bigquerydatatransfer.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/bigquery -apis_required: - - !ruby/object:Api::Product::ApiReference - name: BigQueryDataTransfer API - url: https://console.cloud.google.com/apis/api/bigquerydatatransfer.googleapis.com/ diff --git a/mmv1/products/bigqueryreservation/product.yaml b/mmv1/products/bigqueryreservation/product.yaml index 8449c84fb841..1361f10043c9 100644 --- a/mmv1/products/bigqueryreservation/product.yaml +++ b/mmv1/products/bigqueryreservation/product.yaml @@ -24,7 +24,3 @@ versions: base_url: https://bigqueryreservation.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/bigquery -apis_required: - - !ruby/object:Api::Product::ApiReference - name: BigQueryReservation API - url: https://console.cloud.google.com/apis/api/bigqueryreservation.googleapis.com/ diff --git a/mmv1/products/bigtable/product.yaml b/mmv1/products/bigtable/product.yaml index e41aa47579a0..68ad240371df 100644 --- a/mmv1/products/bigtable/product.yaml +++ b/mmv1/products/bigtable/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://bigtableadmin.googleapis.com/v2/ scopes: - https://www.googleapis.com/auth/bigtable -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Bigtable API - url: https://console.cloud.google.com/apis/library/bigtable.googleapis.com/ diff --git a/mmv1/products/billing/product.yaml b/mmv1/products/billing/product.yaml index 6b0711b6282c..926d88d2c360 100644 --- a/mmv1/products/billing/product.yaml +++ b/mmv1/products/billing/product.yaml @@ -24,7 +24,3 @@ versions: base_url: https://cloudbilling.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Billing - url: https://console.cloud.google.com/apis/library/cloudbilling.googleapis.com/ diff --git a/mmv1/products/billingbudget/product.yaml b/mmv1/products/billingbudget/product.yaml index 2363868c22ef..327c5b10e622 100644 --- a/mmv1/products/billingbudget/product.yaml +++ b/mmv1/products/billingbudget/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://billingbudgets.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Billing Budget - url: https://console.cloud.google.com/apis/library/billingbudgets.googleapis.com/ diff --git a/mmv1/products/certificatemanager/product.yaml b/mmv1/products/certificatemanager/product.yaml index 5753577bcc35..f147b0e1a1a7 100644 --- a/mmv1/products/certificatemanager/product.yaml +++ b/mmv1/products/certificatemanager/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://certificatemanager.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-identity -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Network Services API - url: https://console.cloud.google.com/apis/library/certificatemanager.googleapis.com diff --git a/mmv1/products/cloudasset/product.yaml b/mmv1/products/cloudasset/product.yaml index 75ac4015241d..02ac179c5306 100644 --- a/mmv1/products/cloudasset/product.yaml +++ b/mmv1/products/cloudasset/product.yaml @@ -19,7 +19,3 @@ versions: base_url: https://cloudasset.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Asset API - url: https://console.cloud.google.com/apis/library/cloudasset.googleapis.com/ diff --git a/mmv1/products/cloudbuild/product.yaml b/mmv1/products/cloudbuild/product.yaml index b7d86da1f056..fb8740f5d960 100644 --- a/mmv1/products/cloudbuild/product.yaml +++ b/mmv1/products/cloudbuild/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://cloudbuild.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Build API - url: https://console.cloud.google.com/apis/library/cloudbuild.googleapis.com/ diff --git a/mmv1/products/cloudbuildv2/product.yaml b/mmv1/products/cloudbuildv2/product.yaml index 863190a0f4b7..d0d9616ec001 100644 --- a/mmv1/products/cloudbuildv2/product.yaml +++ b/mmv1/products/cloudbuildv2/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://cloudbuild.googleapis.com/v2/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Build API - url: https://console.cloud.google.com/apis/library/cloudbuild.googleapis.com/ diff --git a/mmv1/products/cloudfunctions/product.yaml b/mmv1/products/cloudfunctions/product.yaml index de4fa4922111..4f796f0f2867 100644 --- a/mmv1/products/cloudfunctions/product.yaml +++ b/mmv1/products/cloudfunctions/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://cloudfunctions.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Functions API - url: https://console.cloud.google.com/apis/library/cloudfunctions.googleapis.com/ diff --git a/mmv1/products/cloudfunctions2/product.yaml b/mmv1/products/cloudfunctions2/product.yaml index 29ca314a1513..09fbf22fa7dc 100644 --- a/mmv1/products/cloudfunctions2/product.yaml +++ b/mmv1/products/cloudfunctions2/product.yaml @@ -23,7 +23,3 @@ versions: - !ruby/object:Api::Product::Version name: ga base_url: https://cloudfunctions.googleapis.com/v2/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Functions API - url: https://console.cloud.google.com/apis/library/cloudfunctions.googleapis.com/ diff --git a/mmv1/products/cloudidentity/product.yaml b/mmv1/products/cloudidentity/product.yaml index 3821d8bd6555..47233708b0a0 100644 --- a/mmv1/products/cloudidentity/product.yaml +++ b/mmv1/products/cloudidentity/product.yaml @@ -23,7 +23,3 @@ versions: base_url: https://cloudidentity.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloud-identity -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Identity API - url: https://console.cloud.google.com/apis/api/cloudidentity.googleapis.com/overview diff --git a/mmv1/products/cloudids/product.yaml b/mmv1/products/cloudids/product.yaml index e9ce6f1d1451..36f529f6ed64 100644 --- a/mmv1/products/cloudids/product.yaml +++ b/mmv1/products/cloudids/product.yaml @@ -20,10 +20,6 @@ versions: base_url: https://ids.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloudids -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Intrusion Detection Service (IDS) API - url: https://console.cloud.google.com/apis/library/ids.googleapis.com/ async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/cloudrunv2/product.yaml b/mmv1/products/cloudrunv2/product.yaml index ac223d16fc08..62b66cb326c8 100644 --- a/mmv1/products/cloudrunv2/product.yaml +++ b/mmv1/products/cloudrunv2/product.yaml @@ -23,7 +23,3 @@ versions: - !ruby/object:Api::Product::Version name: beta base_url: https://run.googleapis.com/v2/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Run API - url: https://console.cloud.google.com/apis/library/run.googleapis.com/ diff --git a/mmv1/products/cloudscheduler/product.yaml b/mmv1/products/cloudscheduler/product.yaml index 9c0b2bde6fa0..66e60b0e5433 100644 --- a/mmv1/products/cloudscheduler/product.yaml +++ b/mmv1/products/cloudscheduler/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://cloudscheduler.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Scheduler - url: https://console.cloud.google.com/apis/library/cloudscheduler.googleapis.com/ diff --git a/mmv1/products/cloudtasks/product.yaml b/mmv1/products/cloudtasks/product.yaml index 3530c72845d3..bd5687ce1488 100644 --- a/mmv1/products/cloudtasks/product.yaml +++ b/mmv1/products/cloudtasks/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://cloudtasks.googleapis.com/v2/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Tasks - url: https://console.cloud.google.com/apis/library/cloudtasks.googleapis.com/ diff --git a/mmv1/products/compute/product.yaml b/mmv1/products/compute/product.yaml index 8d9fd06ef595..1cd722004bf4 100644 --- a/mmv1/products/compute/product.yaml +++ b/mmv1/products/compute/product.yaml @@ -25,7 +25,3 @@ versions: base_url: https://compute.googleapis.com/compute/beta/ scopes: - https://www.googleapis.com/auth/compute -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Compute Engine API - url: https://console.cloud.google.com/apis/library/compute.googleapis.com/ diff --git a/mmv1/products/databasemigrationservice/product.yaml b/mmv1/products/databasemigrationservice/product.yaml index dd57cfde660f..0024866ca6e8 100644 --- a/mmv1/products/databasemigrationservice/product.yaml +++ b/mmv1/products/databasemigrationservice/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://datamigration.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Database Migration API - url: https://console.cloud.google.com/apis/library/datamigration.googleapis.com diff --git a/mmv1/products/datacatalog/product.yaml b/mmv1/products/datacatalog/product.yaml index a44cfe0acb6f..44b331563d2c 100644 --- a/mmv1/products/datacatalog/product.yaml +++ b/mmv1/products/datacatalog/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://datacatalog.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Google Cloud Data Catalog API - url: https://console.cloud.google.com/apis/library/datacatalog.googleapis.com diff --git a/mmv1/products/datafusion/product.yaml b/mmv1/products/datafusion/product.yaml index 1e7458d4a96d..b358c9be12ae 100644 --- a/mmv1/products/datafusion/product.yaml +++ b/mmv1/products/datafusion/product.yaml @@ -40,7 +40,3 @@ async: !ruby/object:Api::OpAsync error: !ruby/object:Api::OpAsync::Error path: 'error' message: 'message' -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Data Fusion API - url: https://console.cloud.google.com/apis/library/datafusion.googleapis.com diff --git a/mmv1/products/dataplex/product.yaml b/mmv1/products/dataplex/product.yaml index 7e6dea430ca9..7b4434bbf8ec 100644 --- a/mmv1/products/dataplex/product.yaml +++ b/mmv1/products/dataplex/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://dataplex.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Dataplex API - url: https://console.cloud.google.com/apis/library/dataplex.googleapis.com diff --git a/mmv1/products/dataproc/product.yaml b/mmv1/products/dataproc/product.yaml index ffe1034b0291..acf70992e563 100644 --- a/mmv1/products/dataproc/product.yaml +++ b/mmv1/products/dataproc/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://dataproc.googleapis.com/v1beta2/ scopes: - https://www.googleapis.com/auth/cloud-identity -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Dataproc API - url: https://console.cloud.google.com/apis/library/dataproc.googleapis.com diff --git a/mmv1/products/datastore/product.yaml b/mmv1/products/datastore/product.yaml index 837d2a1a840f..9326be25fa83 100644 --- a/mmv1/products/datastore/product.yaml +++ b/mmv1/products/datastore/product.yaml @@ -19,10 +19,6 @@ versions: base_url: https://datastore.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/datastore -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Datastore API - url: https://console.cloud.google.com/apis/library/datastore.googleapis.com async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/datastream/product.yaml b/mmv1/products/datastream/product.yaml index d5a3f720158d..db9e4a5a5af5 100644 --- a/mmv1/products/datastream/product.yaml +++ b/mmv1/products/datastream/product.yaml @@ -19,10 +19,6 @@ versions: base_url: https://datastream.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Datastream API - url: https://console.cloud.google.com/apis/library/datastream.googleapis.com async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/deploymentmanager/product.yaml b/mmv1/products/deploymentmanager/product.yaml index 3fe1235ed41f..119dd6f312f2 100644 --- a/mmv1/products/deploymentmanager/product.yaml +++ b/mmv1/products/deploymentmanager/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://www.googleapis.com/deploymentmanager/v2/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Deployment Manager API - url: https://console.cloud.google.com/apis/library/deploymentmanager.googleapis.com/ diff --git a/mmv1/products/dialogflow/product.yaml b/mmv1/products/dialogflow/product.yaml index 234d46d7597e..b071ad685efd 100644 --- a/mmv1/products/dialogflow/product.yaml +++ b/mmv1/products/dialogflow/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://dialogflow.googleapis.com/v2/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Dialogflow API - url: https://console.cloud.google.com/apis/library/dialogflow.googleapis.com diff --git a/mmv1/products/dialogflowcx/product.yaml b/mmv1/products/dialogflowcx/product.yaml index 620bc0c296c9..67a46f177180 100644 --- a/mmv1/products/dialogflowcx/product.yaml +++ b/mmv1/products/dialogflowcx/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://{{location}}-dialogflow.googleapis.com/v3/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Dialogflow API - url: https://console.cloud.google.com/apis/library/dialogflow.googleapis.com diff --git a/mmv1/products/dns/product.yaml b/mmv1/products/dns/product.yaml index e52c4bd86d18..b2c51b1cdfa4 100644 --- a/mmv1/products/dns/product.yaml +++ b/mmv1/products/dns/product.yaml @@ -23,7 +23,3 @@ versions: base_url: https://dns.googleapis.com/dns/v1beta2/ scopes: - https://www.googleapis.com/auth/ndev.clouddns.readwrite -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Google Cloud DNS API - url: https://console.cloud.google.com/apis/library/dns.googleapis.com/ diff --git a/mmv1/products/documentai/product.yaml b/mmv1/products/documentai/product.yaml index c4de1f3c2903..27c16a6a1a8d 100644 --- a/mmv1/products/documentai/product.yaml +++ b/mmv1/products/documentai/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://{{location}}-documentai.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Document AI API - url: https://console.cloud.google.com/apis/api/documentai.googleapis.com/overview diff --git a/mmv1/products/documentaiwarehouse/product.yaml b/mmv1/products/documentaiwarehouse/product.yaml index 5493a6660cb2..cf1bca6a298c 100644 --- a/mmv1/products/documentaiwarehouse/product.yaml +++ b/mmv1/products/documentaiwarehouse/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://contentwarehouse.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Document AI Warehouse API - url: https://console.cloud.google.com/apis/library/contentwarehouse.googleapis.com/ diff --git a/mmv1/products/edgecontainer/product.yaml b/mmv1/products/edgecontainer/product.yaml index 2a2c7d1cecfb..33a7f881cde9 100644 --- a/mmv1/products/edgecontainer/product.yaml +++ b/mmv1/products/edgecontainer/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://edgecontainer.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Edgecontainer API - url: https://console.cloud.google.com/apis/library/edgecontainer.googleapis.com diff --git a/mmv1/products/edgenetwork/product.yaml b/mmv1/products/edgenetwork/product.yaml index 29be977b4df3..5e4a296f5ce1 100644 --- a/mmv1/products/edgenetwork/product.yaml +++ b/mmv1/products/edgenetwork/product.yaml @@ -20,10 +20,6 @@ versions: base_url: https://edgenetwork.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Distributed Cloud Edge Network API - url: https://console.cloud.google.com/apis/library/edgenetwork.googleapis.com async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/essentialcontacts/product.yaml b/mmv1/products/essentialcontacts/product.yaml index 9664e3fc0bec..b8b67e02b161 100644 --- a/mmv1/products/essentialcontacts/product.yaml +++ b/mmv1/products/essentialcontacts/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://essentialcontacts.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Essential Contacts API - url: https://console.cloud.google.com/apis/api/essentialcontacts.googleapis.com/overview diff --git a/mmv1/products/firebasedatabase/product.yaml b/mmv1/products/firebasedatabase/product.yaml index 3352fdee1b3f..29d4d27545c3 100644 --- a/mmv1/products/firebasedatabase/product.yaml +++ b/mmv1/products/firebasedatabase/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://firebasedatabase.googleapis.com/v1beta/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Firebase Realtime Database API - url: https://console.cloud.google.com/apis/library/firebasedatabase.googleapis.com/ diff --git a/mmv1/products/firebaseextensions/product.yaml b/mmv1/products/firebaseextensions/product.yaml index c63efe3bbf20..fc53a7e667dd 100644 --- a/mmv1/products/firebaseextensions/product.yaml +++ b/mmv1/products/firebaseextensions/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://firebaseextensions.googleapis.com/v1beta/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Firebase Extensions API - url: https://console.cloud.google.com/apis/library/firebaseextensions.googleapis.com/ diff --git a/mmv1/products/firestore/product.yaml b/mmv1/products/firestore/product.yaml index 1f5a68462689..ddf124162d59 100644 --- a/mmv1/products/firestore/product.yaml +++ b/mmv1/products/firestore/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://firestore.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Google Cloud Firestore API - url: https://console.cloud.google.com/apis/library/firestore.googleapis.com diff --git a/mmv1/products/gkebackup/product.yaml b/mmv1/products/gkebackup/product.yaml index 243ef5390b52..ba858ce19ed3 100644 --- a/mmv1/products/gkebackup/product.yaml +++ b/mmv1/products/gkebackup/product.yaml @@ -40,7 +40,3 @@ async: !ruby/object:Api::OpAsync error: !ruby/object:Api::OpAsync::Error path: 'error' message: 'message' -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Backup for GKE API - url: https://console.cloud.google.com/apis/library/gkebackup.googleapis.com diff --git a/mmv1/products/gkehub/product.yaml b/mmv1/products/gkehub/product.yaml index bc9bebbe7800..7de11c5f4842 100644 --- a/mmv1/products/gkehub/product.yaml +++ b/mmv1/products/gkehub/product.yaml @@ -24,7 +24,3 @@ versions: base_url: https://gkehub.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: GKEHub API - url: https://console.cloud.google.com/apis/library/gkehub.googleapis.com diff --git a/mmv1/products/gkehub2/product.yaml b/mmv1/products/gkehub2/product.yaml index 1cdc7430a937..649e6246c4a1 100644 --- a/mmv1/products/gkehub2/product.yaml +++ b/mmv1/products/gkehub2/product.yaml @@ -24,7 +24,3 @@ versions: base_url: https://gkehub.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: GKEHub API - url: https://console.cloud.google.com/apis/library/gkehub.googleapis.com diff --git a/mmv1/products/gkeonprem/product.yaml b/mmv1/products/gkeonprem/product.yaml index a1272ba91c98..dd1d8350ca8e 100644 --- a/mmv1/products/gkeonprem/product.yaml +++ b/mmv1/products/gkeonprem/product.yaml @@ -23,10 +23,6 @@ versions: base_url: https://gkeonprem.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Anthos On-Prem API - url: https://console.cloud.google.com/apis/library/gkeonprem.googleapis.com async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation kind: 'gkeonprem#operation' diff --git a/mmv1/products/healthcare/product.yaml b/mmv1/products/healthcare/product.yaml index b75131d30f7d..98d508c164a6 100644 --- a/mmv1/products/healthcare/product.yaml +++ b/mmv1/products/healthcare/product.yaml @@ -23,7 +23,3 @@ versions: base_url: https://healthcare.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Healthcare API - url: https://console.cloud.google.com/apis/library/healthcare.googleapis.com/ diff --git a/mmv1/products/iam2/product.yaml b/mmv1/products/iam2/product.yaml index c856f35dea6d..7911ba2a12ab 100644 --- a/mmv1/products/iam2/product.yaml +++ b/mmv1/products/iam2/product.yaml @@ -24,10 +24,6 @@ versions: base_url: https://iam.googleapis.com/v2/ scopes: - https://www.googleapis.com/auth/iam -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Identity and Access Management (IAM) API - url: https://console.cloud.google.com/apis/library/iam.googleapis.com/ async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/iambeta/product.yaml b/mmv1/products/iambeta/product.yaml index 284843a60d2c..55786f97e1ec 100644 --- a/mmv1/products/iambeta/product.yaml +++ b/mmv1/products/iambeta/product.yaml @@ -24,10 +24,6 @@ versions: base_url: https://iam.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/iam -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Identity and Access Management (IAM) API - url: https://console.cloud.google.com/apis/library/iam.googleapis.com/ async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/iamworkforcepool/product.yaml b/mmv1/products/iamworkforcepool/product.yaml index 65b859518531..fb48c144d241 100644 --- a/mmv1/products/iamworkforcepool/product.yaml +++ b/mmv1/products/iamworkforcepool/product.yaml @@ -24,10 +24,6 @@ versions: base_url: https://iam.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/iam -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Identity and Access Management (IAM) API - url: https://console.cloud.google.com/apis/library/iam.googleapis.com/ async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/iap/product.yaml b/mmv1/products/iap/product.yaml index 851b68d1743c..6fbf8a2fbddc 100644 --- a/mmv1/products/iap/product.yaml +++ b/mmv1/products/iap/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://iap.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Identity-Aware Proxy - url: https://console.cloud.google.com/apis/library/iap.googleapis.com/ diff --git a/mmv1/products/identityplatform/product.yaml b/mmv1/products/identityplatform/product.yaml index c5ae1a8e323e..6a7766e64e11 100644 --- a/mmv1/products/identityplatform/product.yaml +++ b/mmv1/products/identityplatform/product.yaml @@ -22,7 +22,3 @@ scopes: - https://www.googleapis.com/auth/identitytoolkit - https://www.googleapis.com/auth/firebase - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Google Identity Platform - url: https://console.cloud.google.com/marketplace/details/google-cloud-platform/customer-identity/ diff --git a/mmv1/products/integrationconnectors/product.yaml b/mmv1/products/integrationconnectors/product.yaml index 7d154bee8856..2cfe348cf570 100644 --- a/mmv1/products/integrationconnectors/product.yaml +++ b/mmv1/products/integrationconnectors/product.yaml @@ -27,7 +27,3 @@ versions: base_url: https://connectors.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Connectors API - url: https://console.cloud.google.com/apis/api/connectors.googleapis.com/ diff --git a/mmv1/products/kms/product.yaml b/mmv1/products/kms/product.yaml index d49d04acc121..17295cea22e2 100644 --- a/mmv1/products/kms/product.yaml +++ b/mmv1/products/kms/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://cloudkms.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloudkms -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Key Management Service (KMS) API - url: https://console.cloud.google.com/apis/library/cloudkms.googleapis.com/ diff --git a/mmv1/products/logging/product.yaml b/mmv1/products/logging/product.yaml index 7e94a7db0860..e017f3f7f9e9 100644 --- a/mmv1/products/logging/product.yaml +++ b/mmv1/products/logging/product.yaml @@ -19,7 +19,3 @@ versions: base_url: https://logging.googleapis.com/v2/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Stackdriver Logging API - url: https://console.cloud.google.com/apis/library/logging.googleapis.com/ diff --git a/mmv1/products/looker/product.yaml b/mmv1/products/looker/product.yaml index 4d3d1aba79e1..39e6e9cd2e88 100644 --- a/mmv1/products/looker/product.yaml +++ b/mmv1/products/looker/product.yaml @@ -20,10 +20,6 @@ versions: base_url: https://looker.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Looker API - url: https://console.cloud.google.com/apis/library/looker.googleapis.com/ async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/metastore/product.yaml b/mmv1/products/metastore/product.yaml index 8e3a29fdf9b9..83eb3d87cb9d 100644 --- a/mmv1/products/metastore/product.yaml +++ b/mmv1/products/metastore/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://metastore.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-identity -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Dataproc Metastore API - url: https://console.cloud.google.com/apis/library/metastore.googleapis.com diff --git a/mmv1/products/mlengine/product.yaml b/mmv1/products/mlengine/product.yaml index a22ed3adcf55..88f09f7fe10c 100644 --- a/mmv1/products/mlengine/product.yaml +++ b/mmv1/products/mlengine/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://ml.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud ML - url: https://console.cloud.google.com/apis/library/ml.googleapis.com diff --git a/mmv1/products/monitoring/product.yaml b/mmv1/products/monitoring/product.yaml index deb7651d44fa..96e9992f5774 100644 --- a/mmv1/products/monitoring/product.yaml +++ b/mmv1/products/monitoring/product.yaml @@ -19,7 +19,3 @@ versions: base_url: https://monitoring.googleapis.com/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Stackdriver Monitoring API - url: https://console.cloud.google.com/apis/library/monitoring.googleapis.com/ diff --git a/mmv1/products/netapp/product.yaml b/mmv1/products/netapp/product.yaml index 72491c25ad23..36dce6e3005d 100644 --- a/mmv1/products/netapp/product.yaml +++ b/mmv1/products/netapp/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://netapp.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Volume API - url: https://console.cloud.google.com/apis/library/cloudvolumesgcp-api.netapp.com diff --git a/mmv1/products/networkconnectivity/product.yaml b/mmv1/products/networkconnectivity/product.yaml index 05c5bc0c3b44..6bea6bf40b70 100644 --- a/mmv1/products/networkconnectivity/product.yaml +++ b/mmv1/products/networkconnectivity/product.yaml @@ -20,7 +20,3 @@ versions: - !ruby/object:Api::Product::Version name: ga base_url: https://networkconnectivity.googleapis.com/v1/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Network Connectivity API - url: https://console.cloud.google.com/apis/library/networkconnectivity.googleapis.com/ diff --git a/mmv1/products/networkmanagement/product.yaml b/mmv1/products/networkmanagement/product.yaml index 90d8be0e69ba..63cc98193499 100644 --- a/mmv1/products/networkmanagement/product.yaml +++ b/mmv1/products/networkmanagement/product.yaml @@ -20,10 +20,6 @@ versions: - !ruby/object:Api::Product::Version name: ga base_url: https://networkmanagement.googleapis.com/v1/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Network Management API - url: https://console.cloud.google.com/apis/library/networkmanagement.googleapis.com/ async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/networksecurity/product.yaml b/mmv1/products/networksecurity/product.yaml index 85ae621d8459..0d308e900f86 100644 --- a/mmv1/products/networksecurity/product.yaml +++ b/mmv1/products/networksecurity/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://networksecurity.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Network Security API - url: https://console.cloud.google.com/apis/library/networksecurity.googleapis.com diff --git a/mmv1/products/networkservices/product.yaml b/mmv1/products/networkservices/product.yaml index 38556fd15847..fc962b336f27 100644 --- a/mmv1/products/networkservices/product.yaml +++ b/mmv1/products/networkservices/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://networkservices.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-identity -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Network Services API - url: https://console.cloud.google.com/apis/library/networkservices.googleapis.com diff --git a/mmv1/products/notebooks/product.yaml b/mmv1/products/notebooks/product.yaml index 179553c8f5a9..50d80716e490 100644 --- a/mmv1/products/notebooks/product.yaml +++ b/mmv1/products/notebooks/product.yaml @@ -27,10 +27,6 @@ versions: base_url: https://notebooks.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Notebooks API - url: https://console.cloud.google.com/apis/api/notebooks.googleapis.com async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation base_url: '{{op_id}}' diff --git a/mmv1/products/orgpolicy/product.yaml b/mmv1/products/orgpolicy/product.yaml index e24ab0ddb39b..303ef8a760a4 100644 --- a/mmv1/products/orgpolicy/product.yaml +++ b/mmv1/products/orgpolicy/product.yaml @@ -23,7 +23,3 @@ versions: 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 diff --git a/mmv1/products/osconfig/product.yaml b/mmv1/products/osconfig/product.yaml index e922b75bfacf..01d74be2526f 100644 --- a/mmv1/products/osconfig/product.yaml +++ b/mmv1/products/osconfig/product.yaml @@ -21,10 +21,6 @@ versions: - !ruby/object:Api::Product::Version name: beta base_url: https://osconfig.googleapis.com/v1beta/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Identity and Access Management (IAM) API - url: https://console.cloud.google.com/apis/library/iam.googleapis.com/ scopes: - https://www.googleapis.com/auth/cloud-platform - https://www.googleapis.com/auth/compute diff --git a/mmv1/products/oslogin/product.yaml b/mmv1/products/oslogin/product.yaml index 8aedca5e8727..62498a0f9bd6 100644 --- a/mmv1/products/oslogin/product.yaml +++ b/mmv1/products/oslogin/product.yaml @@ -18,10 +18,6 @@ versions: - !ruby/object:Api::Product::Version name: ga base_url: https://oslogin.googleapis.com/v1/ -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Identity and Access Management (IAM) API - url: https://console.cloud.google.com/apis/library/iam.googleapis.com/ scopes: - https://www.googleapis.com/auth/cloud-platform - https://www.googleapis.com/auth/compute diff --git a/mmv1/products/privateca/product.yaml b/mmv1/products/privateca/product.yaml index 11bf7804df5c..d310b6591787 100644 --- a/mmv1/products/privateca/product.yaml +++ b/mmv1/products/privateca/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://privateca.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Certificate Authority API - url: https://console.cloud.google.com/apis/api/privateca.googleapis.com diff --git a/mmv1/products/publicca/product.yaml b/mmv1/products/publicca/product.yaml index ea8152a52141..6243c8d6c677 100644 --- a/mmv1/products/publicca/product.yaml +++ b/mmv1/products/publicca/product.yaml @@ -22,7 +22,3 @@ versions: base_url: https://publicca.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Public Certificate Authority API - url: https://console.cloud.google.com/apis/library/publicca.googleapis.com diff --git a/mmv1/products/pubsub/product.yaml b/mmv1/products/pubsub/product.yaml index f63d92f5d171..fee2f465bb07 100644 --- a/mmv1/products/pubsub/product.yaml +++ b/mmv1/products/pubsub/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://pubsub.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/pubsub -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Pub/Sub API - url: https://console.cloud.google.com/apis/library/pubsub.googleapis.com/ diff --git a/mmv1/products/pubsublite/product.yaml b/mmv1/products/pubsublite/product.yaml index 236999876cb6..48e342b3ae62 100644 --- a/mmv1/products/pubsublite/product.yaml +++ b/mmv1/products/pubsublite/product.yaml @@ -21,7 +21,3 @@ versions: cai_base_url: https://pubsublite.googleapis.com/v1/admin/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Pub/Sub Lite API - url: https://console.cloud.google.com/apis/library/pubsublite.googleapis.com/ diff --git a/mmv1/products/resourcemanager/product.yaml b/mmv1/products/resourcemanager/product.yaml index 33569faf075f..f7ccd2fa3826 100644 --- a/mmv1/products/resourcemanager/product.yaml +++ b/mmv1/products/resourcemanager/product.yaml @@ -21,7 +21,3 @@ versions: scopes: # All access is needed to create projects. - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Resource Manager API - url: https://console.cloud.google.com/apis/library/cloudresourcemanager.googleapis.com/ diff --git a/mmv1/products/runtimeconfig/product.yaml b/mmv1/products/runtimeconfig/product.yaml index 9d7cbf6db3e5..0f5f582cdb8b 100644 --- a/mmv1/products/runtimeconfig/product.yaml +++ b/mmv1/products/runtimeconfig/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://runtimeconfig.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloudruntimeconfig -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Resource Manager API - url: https://console.cloud.google.com/apis/library/cloudresourcemanager.googleapis.com/ diff --git a/mmv1/products/secretmanager/product.yaml b/mmv1/products/secretmanager/product.yaml index a94a4f7e74cc..e08b510702c9 100644 --- a/mmv1/products/secretmanager/product.yaml +++ b/mmv1/products/secretmanager/product.yaml @@ -23,7 +23,3 @@ versions: base_url: https://secretmanager.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Secret Manager API - url: https://console.cloud.google.com/apis/library/secretmanager.googleapis.com/ diff --git a/mmv1/products/securesourcemanager/product.yaml b/mmv1/products/securesourcemanager/product.yaml index 318cea164649..aef4bcdb4a5a 100644 --- a/mmv1/products/securesourcemanager/product.yaml +++ b/mmv1/products/securesourcemanager/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://securesourcemanager.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Secure Source Manager API - url: https://console.cloud.google.com/apis/library/securesourcemanager.googleapis.com/ diff --git a/mmv1/products/securityscanner/product.yaml b/mmv1/products/securityscanner/product.yaml index 928368b06b9f..20f8504a48c3 100644 --- a/mmv1/products/securityscanner/product.yaml +++ b/mmv1/products/securityscanner/product.yaml @@ -19,7 +19,3 @@ versions: base_url: https://websecurityscanner.googleapis.com/v1beta/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Web Security Scanner API - url: https://console.cloud.google.com/apis/library/websecurityscanner.googleapis.com/ diff --git a/mmv1/products/servicedirectory/product.yaml b/mmv1/products/servicedirectory/product.yaml index 2fc20e6f77fd..964241bcf264 100644 --- a/mmv1/products/servicedirectory/product.yaml +++ b/mmv1/products/servicedirectory/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://servicedirectory.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Service Directory API - url: https://console.cloud.google.com/apis/library/servicedirectory.googleapis.com/ diff --git a/mmv1/products/servicemanagement/product.yaml b/mmv1/products/servicemanagement/product.yaml index cb3cc794a3eb..6152d8382140 100644 --- a/mmv1/products/servicemanagement/product.yaml +++ b/mmv1/products/servicemanagement/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://servicemanagement.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloudplatform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Service Management API - url: https://console.cloud.google.com/apis/library/servicemanagement.googleapis.com/ diff --git a/mmv1/products/serviceusage/product.yaml b/mmv1/products/serviceusage/product.yaml index 36672796aab6..27e40852210e 100644 --- a/mmv1/products/serviceusage/product.yaml +++ b/mmv1/products/serviceusage/product.yaml @@ -23,7 +23,3 @@ versions: base_url: https://serviceusage.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Service Usage API - url: https://console.cloud.google.com/apis/library/serviceusage.googleapis.com/ diff --git a/mmv1/products/sourcerepo/product.yaml b/mmv1/products/sourcerepo/product.yaml index d4717e5d1258..e78f0569cd34 100644 --- a/mmv1/products/sourcerepo/product.yaml +++ b/mmv1/products/sourcerepo/product.yaml @@ -21,7 +21,3 @@ versions: base_url: https://sourcerepo.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Source Repositories API - url: https://console.cloud.google.com/apis/library/sourcerepo.googleapis.com/ diff --git a/mmv1/products/spanner/product.yaml b/mmv1/products/spanner/product.yaml index 87e0f1204e19..883226d15cd3 100644 --- a/mmv1/products/spanner/product.yaml +++ b/mmv1/products/spanner/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://spanner.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/spanner.admin -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Spanner API - url: https://console.cloud.google.com/apis/library/spanner.googleapis.com/ diff --git a/mmv1/products/sql/product.yaml b/mmv1/products/sql/product.yaml index 42fdd7a2100d..5658ae7e1975 100644 --- a/mmv1/products/sql/product.yaml +++ b/mmv1/products/sql/product.yaml @@ -21,10 +21,6 @@ versions: base_url: https://sqladmin.googleapis.com/sql/v1beta4/ scopes: - https://www.googleapis.com/auth/sqlservice.admin -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud SQL Admin API - url: https://console.cloud.google.com/apis/library/sqladmin.googleapis.com/ async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation kind: 'sql#operation' diff --git a/mmv1/products/storage/product.yaml b/mmv1/products/storage/product.yaml index 4d380b12ef79..458a2e7f5e19 100644 --- a/mmv1/products/storage/product.yaml +++ b/mmv1/products/storage/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://storage.googleapis.com/storage/v1/ scopes: - https://www.googleapis.com/auth/devstorage.full_control -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Google Cloud Storage - url: https://console.cloud.google.com/apis/library/storage-component.googleapis.com/ diff --git a/mmv1/products/storageinsights/product.yaml b/mmv1/products/storageinsights/product.yaml index 7f7a0b22e93c..e43481d0e456 100644 --- a/mmv1/products/storageinsights/product.yaml +++ b/mmv1/products/storageinsights/product.yaml @@ -20,10 +20,3 @@ versions: base_url: https://storageinsights.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/devstorage.full_control -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Google Cloud Storage - url: https://console.cloud.google.com/apis/library/storage-component.googleapis.com/ - - !ruby/object:Api::Product::ApiReference - name: Google Cloud Storage Insights - url: https://console.cloud.google.com/apis/library/storageinsights.googleapis.com/ diff --git a/mmv1/products/storagetransfer/product.yaml b/mmv1/products/storagetransfer/product.yaml index 31709ea7c94c..62d3765c7a91 100644 --- a/mmv1/products/storagetransfer/product.yaml +++ b/mmv1/products/storagetransfer/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://storagetransfer.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Storage Transfer API - url: https://console.cloud.google.com/apis/library/storagetransfer.googleapis.com/ diff --git a/mmv1/products/tpuv2/product.yaml b/mmv1/products/tpuv2/product.yaml index 20dded6c52e6..cbfe0dd9137d 100644 --- a/mmv1/products/tpuv2/product.yaml +++ b/mmv1/products/tpuv2/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://tpu.googleapis.com/v2/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud TPU API - url: https://console.cloud.google.com/apis/library/tpu.googleapis.com/ diff --git a/mmv1/products/vmwareengine/product.yaml b/mmv1/products/vmwareengine/product.yaml index 4e2c2b4f8663..da6176f08acd 100644 --- a/mmv1/products/vmwareengine/product.yaml +++ b/mmv1/products/vmwareengine/product.yaml @@ -23,7 +23,3 @@ versions: base_url: https://vmwareengine.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: VMwareEngine API - url: https://console.cloud.google.com/apis/library/vmwareengine.googleapis.com/ diff --git a/mmv1/products/vpcaccess/product.yaml b/mmv1/products/vpcaccess/product.yaml index 86e93dcd1a99..ff79d8e6791e 100644 --- a/mmv1/products/vpcaccess/product.yaml +++ b/mmv1/products/vpcaccess/product.yaml @@ -23,7 +23,3 @@ versions: base_url: https://vpcaccess.googleapis.com/v1beta1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Serverless VPC Access API - url: https://console.cloud.google.com/apis/library/vpcaccess.googleapis.com/ diff --git a/mmv1/products/workflows/product.yaml b/mmv1/products/workflows/product.yaml index 2f84e8ef20d4..f014e8edd8ae 100644 --- a/mmv1/products/workflows/product.yaml +++ b/mmv1/products/workflows/product.yaml @@ -23,10 +23,6 @@ versions: base_url: https://workflows.googleapis.com/v1/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Workflows API - url: https://console.cloud.google.com/apis/library/workflows.googleapis.com/ async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation path: 'name' diff --git a/mmv1/products/workstations/product.yaml b/mmv1/products/workstations/product.yaml index 751e8051212b..f219cbb130ad 100644 --- a/mmv1/products/workstations/product.yaml +++ b/mmv1/products/workstations/product.yaml @@ -20,7 +20,3 @@ versions: base_url: https://workstations.googleapis.com/v1beta/ scopes: - https://www.googleapis.com/auth/cloud-platform -apis_required: - - !ruby/object:Api::Product::ApiReference - name: Cloud Workstations API - url: https://console.cloud.google.com/apis/library/workstations.googleapis.com From 03342cd8a219335227e839405bc91f9b282d8007 Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Thu, 30 Nov 2023 23:53:49 +0530 Subject: [PATCH 035/107] Add NetworkPolicy resource to Vmwareengine (#9514) --- mmv1/products/vmwareengine/NetworkPolicy.yaml | 177 ++++++++++++++++++ .../vmware_engine_network_policy_basic.tf.erb | 13 ++ .../vmware_engine_network_policy_full.tf.erb | 20 ++ .../provider/provider_mmv1_resources.go.erb | 1 + ...urce_google_vmwareengine_network_policy.go | 40 ++++ ...google_vmwareengine_network_policy_test.go | 65 +++++++ ...source_vmwareengine_network_policy_test.go | 78 ++++++++ .../vmwareengine_network_policy.html.markdown | 32 ++++ 8 files changed, 426 insertions(+) create mode 100644 mmv1/products/vmwareengine/NetworkPolicy.yaml create mode 100644 mmv1/templates/terraform/examples/vmware_engine_network_policy_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/vmware_engine_network_policy_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_policy.go create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_policy_test.go create mode 100644 mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_policy_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/vmwareengine_network_policy.html.markdown diff --git a/mmv1/products/vmwareengine/NetworkPolicy.yaml b/mmv1/products/vmwareengine/NetworkPolicy.yaml new file mode 100644 index 000000000000..a3d6b60f7180 --- /dev/null +++ b/mmv1/products/vmwareengine/NetworkPolicy.yaml @@ -0,0 +1,177 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'NetworkPolicy' +base_url: 'projects/{{project}}/locations/{{location}}/networkPolicies' +self_link: 'projects/{{project}}/locations/{{location}}/networkPolicies/{{name}}' +create_url: 'projects/{{project}}/locations/{{location}}/networkPolicies?networkPolicyId={{name}}' +update_verb: :PATCH +references: !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.networkPolicies' +description: | + Represents a network policy resource. Network policies are regional resources. +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: "name" + base_url: "{{op_id}}" + wait_ms: 5000 + timeouts: !ruby/object:Api::Timeouts + insert_minutes: 60 + update_minutes: 60 + delete_minutes: 60 + result: !ruby/object:Api::OpAsync::Result + path: "response" + status: !ruby/object:Api::OpAsync::Status + path: "done" + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: "error" + message: "message" + +import_format: ["projects/{{project}}/locations/{{location}}/networkPolicies/{{name}}"] +autogen_async: true + +examples: + - !ruby/object:Provider::Terraform::Examples + name: "vmware_engine_network_policy_basic" + primary_resource_id: "vmw-engine-network-policy" + vars: + name: "sample-network-policy" + test_env_vars: + region: :REGION + - !ruby/object:Provider::Terraform::Examples + name: "vmware_engine_network_policy_full" + primary_resource_id: "vmw-engine-network-policy" + vars: + name: "sample-network-policy-full" + test_env_vars: + region: :REGION + +parameters: + - !ruby/object:Api::Type::String + name: "location" + required: true + immutable: true + url_param_only: true + description: | + The resource name of the location (region) to create the new network policy in. + Resource names are schemeless URIs that follow the conventions in https://cloud.google.com/apis/design/resource_names. + For example: projects/my-project/locations/us-central1 + - !ruby/object:Api::Type::String + name: "name" + required: true + immutable: true + url_param_only: true + description: | + The ID of the Network Policy. + +properties: + - !ruby/object:Api::Type::Time + name: 'createTime' + output: true + description: | + Creation time of this resource. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and + up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + + - !ruby/object:Api::Type::Time + name: 'updateTime' + output: true + description: | + Last updated time of this resource. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine + fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + + - !ruby/object:Api::Type::String + name: 'uid' + output: true + description: | + System-generated unique identifier for the resource. + + - !ruby/object:Api::Type::String + name: 'vmwareEngineNetworkCanonical' + output: true + description: | + The canonical name of the VMware Engine network in the form: + projects/{project_number}/locations/{location}/vmwareEngineNetworks/{vmwareEngineNetworkId} + + - !ruby/object:Api::Type::String + name: 'edgeServicesCidr' + required: true + description: | + IP address range in CIDR notation used to create internet access and external IP access. + An RFC 1918 CIDR block, with a "/26" prefix, is required. The range cannot overlap with any + prefixes either in the consumer VPC network or in use by the private clouds attached to that VPC network. + + - !ruby/object:Api::Type::String + name: 'description' + description: | + User-provided description for this network policy. + + - !ruby/object:Api::Type::String + name: 'vmwareEngineNetwork' + required: true + immutable: true + description: | + The relative resource name of the VMware Engine network. Specify the name in the following form: + projects/{project}/locations/{location}/vmwareEngineNetworks/{vmwareEngineNetworkId} where {project} + can either be a project number or a project ID. + + - !ruby/object:Api::Type::NestedObject + name: 'internetAccess' + description: | + Network service that allows VMware workloads to access the internet. + default_from_api: true + properties: + - !ruby/object:Api::Type::Boolean + name: enabled + send_empty_value: true + description: | + True if the service is enabled; false otherwise. + + - !ruby/object:Api::Type::Enum + name: 'state' + description: | + State of the service. New values may be added to this enum when appropriate. + output: true + values: + - :UNPROVISIONED + - :RECONCILING + - :ACTIVE + + - !ruby/object:Api::Type::NestedObject + name: 'externalIp' + description: | + Network service that allows External IP addresses to be assigned to VMware workloads. + This service can only be enabled when internetAccess is also enabled. + default_from_api: true + properties: + - !ruby/object:Api::Type::Boolean + name: enabled + send_empty_value: true + description: | + True if the service is enabled; false otherwise. + + - !ruby/object:Api::Type::Enum + name: 'state' + description: | + State of the service. New values may be added to this enum when appropriate. + output: true + values: + - :UNPROVISIONED + - :RECONCILING + - :ACTIVE diff --git a/mmv1/templates/terraform/examples/vmware_engine_network_policy_basic.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_network_policy_basic.tf.erb new file mode 100644 index 000000000000..369a2f5492e6 --- /dev/null +++ b/mmv1/templates/terraform/examples/vmware_engine_network_policy_basic.tf.erb @@ -0,0 +1,13 @@ +resource "google_vmwareengine_network" "network-policy-nw" { + name = "standard-nw" + location = "global" + type = "STANDARD" + description = "VMwareEngine standard network sample" +} + +resource "google_vmwareengine_network_policy" "<%= ctx[:primary_resource_id] %>" { + location = "<%= ctx[:test_env_vars]['region'] %>" + name = "<%= ctx[:vars]['name'] %>" + edge_services_cidr = "192.168.30.0/26" + vmware_engine_network = google_vmwareengine_network.network-policy-nw.id +} diff --git a/mmv1/templates/terraform/examples/vmware_engine_network_policy_full.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_network_policy_full.tf.erb new file mode 100644 index 000000000000..37c3563c4aac --- /dev/null +++ b/mmv1/templates/terraform/examples/vmware_engine_network_policy_full.tf.erb @@ -0,0 +1,20 @@ +resource "google_vmwareengine_network" "network-policy-nw" { + name = "standard-full-nw" + location = "global" + type = "STANDARD" + description = "VMwareEngine standard network sample" +} + +resource "google_vmwareengine_network_policy" "<%= ctx[:primary_resource_id] %>" { + location = "<%= ctx[:test_env_vars]['region'] %>" + name = "<%= ctx[:vars]['name'] %>" + edge_services_cidr = "192.168.30.0/26" + vmware_engine_network = google_vmwareengine_network.network-policy-nw.id + description = "Sample Network Policy" + internet_access { + enabled = true + } + external_ip { + enabled = true + } +} diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 249dd8e0c988..1e22b6979c63 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -201,6 +201,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ <% end -%> "google_vmwareengine_network": vmwareengine.DataSourceVmwareengineNetwork(), "google_vmwareengine_network_peering": vmwareengine.DataSourceVmwareengineNetworkPeering(), + "google_vmwareengine_network_policy": vmwareengine.DataSourceVmwareengineNetworkPolicy(), "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), // ####### END handwritten datasources ########### diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_policy.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_policy.go new file mode 100644 index 000000000000..7d54db528a7d --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_policy.go @@ -0,0 +1,40 @@ +package vmwareengine + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceVmwareengineNetworkPolicy() *schema.Resource { + + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceVmwareengineNetworkPolicy().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "location", "name") + tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") + return &schema.Resource{ + Read: dataSourceVmwareengineNetworkPolicyRead, + Schema: dsSchema, + } +} + +func dataSourceVmwareengineNetworkPolicyRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/networkPolicies/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + err = resourceVmwareengineNetworkPolicyRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_policy_test.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_policy_test.go new file mode 100644 index 000000000000..e29f967b684f --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_network_policy_test.go @@ -0,0 +1,65 @@ +package vmwareengine_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccDataSourceVmwareengineNetworkPolicy_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "region": envvar.GetTestRegionFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineNetworkPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVmwareengineNetworkPolicy_ds(context), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_network_policy.ds", "google_vmwareengine_network_policy.vmw-engine-network-policy", map[string]struct{}{}), + ), + }, + }, + }) +} + +func testAccVmwareengineNetworkPolicy_ds(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_vmwareengine_network" "network-policy-ds-nw" { + name = "tf-test-sample-nw%{random_suffix}" + location = "global" + type = "STANDARD" + description = "VMwareEngine standard network sample" +} + +resource "google_vmwareengine_network_policy" "vmw-engine-network-policy" { + location = "%{region}" + name = "tf-test-sample-network-policy%{random_suffix}" + internet_access { + enabled = true + } + external_ip { + enabled = true + } + edge_services_cidr = "192.168.30.0/26" + vmware_engine_network = google_vmwareengine_network.network-policy-ds-nw.id +} + +data "google_vmwareengine_network_policy" "ds" { + name = google_vmwareengine_network_policy.vmw-engine-network-policy.name + location = "%{region}" + depends_on = [ + google_vmwareengine_network_policy.vmw-engine-network-policy, + ] +} + +`, context) +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_policy_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_policy_test.go new file mode 100644 index 000000000000..f2b025a04505 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_network_policy_test.go @@ -0,0 +1,78 @@ +package vmwareengine_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccVmwareengineNetworkPolicy_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "region": envvar.GetTestRegionFromEnv(), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineNetworkPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccVmwareengineNetworkPolicy_config(context, "description1", "192.168.0.0/26", false, false), + }, + { + ResourceName: "google_vmwareengine_network_policy.vmw-engine-network-policy", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name"}, + }, + { + Config: testAccVmwareengineNetworkPolicy_config(context, "description2", "192.168.1.0/26", true, true), + }, + { + ResourceName: "google_vmwareengine_network_policy.vmw-engine-network-policy", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name"}, + }, + }, + }) +} + +func testAccVmwareengineNetworkPolicy_config(context map[string]interface{}, description string, edgeServicesCidr string, internetAccess bool, externalIp bool) string { + context["internet_access"] = internetAccess + context["external_ip"] = externalIp + context["edge_services_cidr"] = edgeServicesCidr + context["description"] = description + + return acctest.Nprintf(` +resource "google_vmwareengine_network" "network-policy-nw" { + name = "tf-test-sample-nw%{random_suffix}" + location = "global" + type = "STANDARD" + description = "VMwareEngine standard network sample" +} + +resource "google_vmwareengine_network_policy" "vmw-engine-network-policy" { + location = "%{region}" + name = "tf-test-sample-network-policy%{random_suffix}" + description = "%{description}" + + internet_access { + enabled = "%{internet_access}" + } + + external_ip { + enabled = "%{external_ip}" + } + + edge_services_cidr = "%{edge_services_cidr}" + vmware_engine_network = google_vmwareengine_network.network-policy-nw.id +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_network_policy.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_network_policy.html.markdown new file mode 100644 index 000000000000..3a7c74b3116c --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_network_policy.html.markdown @@ -0,0 +1,32 @@ +--- +subcategory: "Cloud VMware Engine" +description: |- + Get information about a network policy. +--- + +# google\_vmwareengine\_network_policy + +Use this data source to get details about a network policy resource. + +To get more information about network policy, see: +* [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.networkPolicies) + +## Example Usage + +```hcl +data "google_vmwareengine_network_policy" "my_network_policy" { + name = "my-network-policy" + location = "us-central1" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Name of the resource. +* `location` - (Required) Location of the resource. + +## Attributes Reference + +See [google_vmwareengine_network_policy](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/vmwareengine_network_policy#attributes-reference) resource for details of all the available attributes. \ No newline at end of file From 22cdfe3397674e249b1c06a8e035c40590480808 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 30 Nov 2023 10:37:18 -0800 Subject: [PATCH 036/107] Combine core.rb and terraform.rb (#9541) --- mmv1/provider/abstract_core.rb | 26 -- mmv1/provider/core.rb | 518 ---------------------- mmv1/provider/terraform.rb | 487 +++++++++++++++++++- mmv1/provider/terraform/async.rb | 3 +- mmv1/provider/terraform/config.rb | 3 +- mmv1/provider/terraform/custom_code.rb | 3 +- mmv1/provider/terraform/docs.rb | 3 +- mmv1/provider/terraform/examples.rb | 3 +- mmv1/provider/terraform/import.rb | 4 +- mmv1/provider/terraform/sub_template.rb | 4 +- mmv1/provider/terraform/validation.rb | 3 +- mmv1/provider/terraform/virtual_fields.rb | 3 +- mmv1/spec/hashicorp_copyright_spec.rb | 4 +- 13 files changed, 496 insertions(+), 568 deletions(-) delete mode 100644 mmv1/provider/abstract_core.rb delete mode 100644 mmv1/provider/core.rb diff --git a/mmv1/provider/abstract_core.rb b/mmv1/provider/abstract_core.rb deleted file mode 100644 index 56c8fb6226b3..000000000000 --- a/mmv1/provider/abstract_core.rb +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 2017 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. - -require 'provider/core' - -module Provider - # A boilerplate provider where all methods are optional. - class AbstractCore < Provider::Core - private - - def generate_resource(data) end - def generate_resource_tests(data) end - # Generates IAM policy support for the resource - def generate_iam_policy(data) end - end -end diff --git a/mmv1/provider/core.rb b/mmv1/provider/core.rb deleted file mode 100644 index cd3499839a6b..000000000000 --- a/mmv1/provider/core.rb +++ /dev/null @@ -1,518 +0,0 @@ -# Copyright 2017 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. - -require 'compile/core' -require 'fileutils' -require 'google/extensions' -require 'google/logger' -require 'json' -require 'provider/file_template' - -module Provider - # Basic functionality for code generator providers. Provides basic services, - # such as compiling and including files, formatting data, etc. - class Core - include Compile::Core - - TERRAFORM_PROVIDER_GA = 'github.com/hashicorp/terraform-provider-google'.freeze - TERRAFORM_PROVIDER_BETA = 'github.com/hashicorp/terraform-provider-google-beta'.freeze - TERRAFORM_PROVIDER_PRIVATE = 'internal/terraform-next'.freeze - RESOURCE_DIRECTORY_GA = 'google'.freeze - RESOURCE_DIRECTORY_BETA = 'google-beta'.freeze - RESOURCE_DIRECTORY_PRIVATE = 'google-private'.freeze - - def initialize(config, api, version_name, start_time) - @config = config - @api = api - - # @target_version_name is the version specified by MM for this generation - # run. That's distinct from @version below, which is the best-fit version - # supported by the product. - # These values will often match, but if a product supports only GA while - # MM is ran @ beta, @target_version_name will be at beta and @version will - # be @ GA. - # This matters for Terraform, where the primary folder for a provider - # needs to match the provider name. - @target_version_name = version_name - - @version = @api.version_obj_or_closest(version_name) - @api.set_properties_based_on_version(@version) - - # The compiler will error out if a file has been written in this compiler - # run already. Instead of storing all the modified files in state we'll - # use the time the file was modified. - @start_time = start_time - @go_format_enabled = check_goformat - end - - # This provides the ProductFileTemplate class with access to a provider. - def provider_binding - binding - end - - def check_goformat - if system('which gofmt > /dev/null') && system('which goimports > /dev/null') - true - else - Google::LOGGER.warn 'Either gofmt or goimports is not installed; go ' \ - 'code will be poorly formatted and will likely not compile.' - false - end - end - - # Main entry point for generation. - def generate(output_folder, types, product_path, dump_yaml, generate_code, generate_docs) - generate_objects(output_folder, types, generate_code, generate_docs) - - # Compilation has to be the last step, as some files (e.g. - # CONTRIBUTING.md) may depend on the list of all files previously copied - # or compiled. - # common-compile.yaml is a special file that will get compiled by the last product - # used in a single invocation of the compiled. It should not contain product-specific - # information; instead, it should be run-specific such as the version to compile at. - compile_product_files(output_folder) \ - unless @config.files.nil? || @config.files.compile.nil? - - FileUtils.mkpath output_folder - pwd = Dir.pwd - if generate_code - Dir.chdir output_folder - - generate_operation(pwd, output_folder, types) - Dir.chdir pwd - end - - # Write a file with the final version of the api, after overrides - # have been applied. - return unless dump_yaml - - raise 'Path to output the final yaml was not specified.' \ - if product_path.nil? || product_path == '' - - File.open("#{product_path}/final_api.yaml", 'w') do |file| - file.write("# This is a generated file, its contents will be overwritten.\n") - file.write(YAML.dump(@api)) - end - end - - def generate_operation(pwd, output_folder, types); end - - # generate_code and generate_docs are actually used because all of the variables - # in scope in this method are made available within the templates by the compile call. - # rubocop:disable Lint/UnusedMethodArgument - def copy_common_files(output_folder, generate_code, generate_docs, provider_name = nil) - # version_name is actually used because all of the variables in scope in this method - # are made available within the templates by the compile call. - # TODO: remove version_name, use @target_version_name or pass it in expicitly - # rubocop:disable Lint/UselessAssignment - version_name = @target_version_name - # rubocop:enable Lint/UselessAssignment - provider_name ||= self.class.name.split('::').last.downcase - return unless File.exist?("provider/#{provider_name}/common~copy.yaml") - - Google::LOGGER.info "Copying common files for #{provider_name}" - files = YAML.safe_load(compile("provider/#{provider_name}/common~copy.yaml")) - copy_file_list(output_folder, files) - end - # rubocop:enable Lint/UnusedMethodArgument - - def copy_file_list(output_folder, files) - files.map do |target, source| - Thread.new do - target_file = File.join(output_folder, target) - target_dir = File.dirname(target_file) - Google::LOGGER.debug "Copying #{source} => #{target}" - FileUtils.mkpath target_dir - - # If we've modified a file since starting an MM run, it's a reasonable - # assumption that it was this run that modified it. - if File.exist?(target_file) && File.mtime(target_file) > @start_time - raise "#{target_file} was already modified during this run. #{File.mtime(target_file)}" - end - - FileUtils.copy_entry source, target_file - - add_hashicorp_copyright_header(output_folder, target) if File.extname(target) == '.go' - if File.extname(target) == '.go' || File.extname(target) == '.mod' - replace_import_path(output_folder, target) - end - end - end.map(&:join) - end - - # Compiles files specified within the product - def compile_product_files(output_folder) - file_template = ProductFileTemplate.new( - output_folder, - nil, - @api, - @target_version_name, - build_env - ) - compile_file_list(output_folder, @config.files.compile, file_template) - end - - # Compiles files that are shared at the provider level - def compile_common_files( - output_folder, - products, - common_compile_file, - override_path = nil - ) - return unless File.exist?(common_compile_file) - - files = YAML.safe_load(compile(common_compile_file)) - return unless files - - file_template = ProviderFileTemplate.new( - output_folder, - @target_version_name, - build_env, - products, - override_path - ) - compile_file_list(output_folder, files, file_template) - end - - def compile_file_list(output_folder, files, file_template, pwd = Dir.pwd) - FileUtils.mkpath output_folder - Dir.chdir output_folder - files.map do |target, source| - Thread.new do - Google::LOGGER.debug "Compiling #{source} => #{target}" - file_template.generate(pwd, source, target, self) - - add_hashicorp_copyright_header(output_folder, target) - replace_import_path(output_folder, target) - end - end.map(&:join) - Dir.chdir pwd - end - - def add_hashicorp_copyright_header(output_folder, target) - unless expected_output_folder?(output_folder) - Google::LOGGER.info "Unexpected output folder (#{output_folder}) detected " \ - 'when deciding to add HashiCorp copyright headers. ' \ - 'Watch out for unexpected changes to copied files' - end - # only add copyright headers when generating TPG and TPGB - return unless output_folder.end_with?('terraform-provider-google') || - output_folder.end_with?('terraform-provider-google-beta') - - # Prevent adding copyright header to files with paths or names matching the strings below - # NOTE: these entries need to match the content of the .copywrite.hcl file originally - # created in https://github.com/GoogleCloudPlatform/magic-modules/pull/7336 - # The test-fixtures folder is not included here as it's copied as a whole, - # not file by file (see common~copy.yaml) - ignored_folders = [ - '.release/', - '.changelog/', - 'examples/', - 'scripts/', - 'META.d/' - ] - ignored_files = [ - 'go.mod', - '.goreleaser.yml', - '.golangci.yml', - 'terraform-registry-manifest.json' - ] - should_add_header = true - ignored_folders.each do |folder| - # folder will be path leading to file - next unless target.start_with? folder - - Google::LOGGER.debug 'Not adding HashiCorp copyright headers in ' \ - "ignored folder #{folder} : #{target}" - should_add_header = false - end - return unless should_add_header - - ignored_files.each do |file| - # file will be the filename and extension, with no preceding path - next unless target.end_with? file - - Google::LOGGER.debug 'Not adding HashiCorp copyright headers to ' \ - "ignored file #{file} : #{target}" - should_add_header = false - end - return unless should_add_header - - Google::LOGGER.debug "Adding HashiCorp copyright header to : #{target}" - data = File.read("#{output_folder}/#{target}") - - copyright_header = ['Copyright (c) HashiCorp, Inc.', 'SPDX-License-Identifier: MPL-2.0'] - lang = language_from_filename(target) - - # Some file types we don't want to add headers to - # e.g. .sh where headers are functional - # Also, this guards against new filetypes being added and triggering build errors - return unless lang != :unsupported - - # File is not ignored and is appropriate file type to add header to - header = comment_block(copyright_header, lang) - File.write("#{output_folder}/#{target}", header) - - File.write("#{output_folder}/#{target}", data, mode: 'a') # append mode - end - - def expected_output_folder?(output_folder) - expected_folders = %w[ - terraform-provider-google - terraform-provider-google-beta - terraform-next - terraform-google-conversion - tfplan2cai - ] - folder_name = output_folder.split('/')[-1] # Possible issue with Windows OS - is_expected = false - expected_folders.each do |folder| - next unless folder_name == folder - - is_expected = true - break - end - is_expected - end - - def replace_import_path(output_folder, target) - data = File.read("#{output_folder}/#{target}") - - if data.include? "#{TERRAFORM_PROVIDER_BETA}/#{RESOURCE_DIRECTORY_BETA}" - raise 'Importing a package from module ' \ - "#{TERRAFORM_PROVIDER_BETA}/#{RESOURCE_DIRECTORY_BETA} " \ - "is not allowed in file #{target.split('/').last}. " \ - 'Please import a package from module ' \ - "#{TERRAFORM_PROVIDER_GA}/#{RESOURCE_DIRECTORY_GA}." - end - - return if @target_version_name == 'ga' - - # Replace the import pathes in utility files - case @target_version_name - when 'beta' - tpg = TERRAFORM_PROVIDER_BETA - dir = RESOURCE_DIRECTORY_BETA - else - tpg = TERRAFORM_PROVIDER_PRIVATE - dir = RESOURCE_DIRECTORY_PRIVATE - end - - data = data.gsub( - "#{TERRAFORM_PROVIDER_GA}/#{RESOURCE_DIRECTORY_GA}", - "#{tpg}/#{dir}" - ) - data = data.gsub( - "#{TERRAFORM_PROVIDER_GA}/version", - "#{tpg}/version" - ) - - data = data.gsub( - "module #{TERRAFORM_PROVIDER_GA}", - "module #{tpg}" - ) - File.write("#{output_folder}/#{target}", data) - end - - def import_path - case @target_version_name - when 'ga' - "#{TERRAFORM_PROVIDER_GA}/#{RESOURCE_DIRECTORY_GA}" - when 'beta' - "#{TERRAFORM_PROVIDER_BETA}/#{RESOURCE_DIRECTORY_BETA}" - else - "#{TERRAFORM_PROVIDER_PRIVATE}/#{RESOURCE_DIRECTORY_PRIVATE}" - end - end - - def generate_objects(output_folder, types, generate_code, generate_docs) - (@api.objects || []).each do |object| - if !types.empty? && !types.include?(object.name) - Google::LOGGER.info "Excluding #{object.name} per user request" - elsif types.empty? && object.exclude - Google::LOGGER.info "Excluding #{object.name} per API catalog" - elsif types.empty? && object.not_in_version?(@version) - Google::LOGGER.info "Excluding #{object.name} per API version" - else - Google::LOGGER.info "Generating #{object.name}" - # exclude_if_not_in_version must be called in order to filter out - # beta properties that are nested within GA resources - object.exclude_if_not_in_version!(@version) - - # Make object immutable. - object.freeze - object.all_user_properties.each(&:freeze) - - generate_object object, output_folder, @target_version_name, generate_code, generate_docs - end - end - end - - def generate_object(object, output_folder, version_name, generate_code, generate_docs) - pwd = Dir.pwd - data = build_object_data(pwd, object, output_folder, version_name) - unless object.exclude_resource - FileUtils.mkpath output_folder - Dir.chdir output_folder - Google::LOGGER.debug "Generating #{object.name} resource" - generate_resource(pwd, data.clone, generate_code, generate_docs) - if generate_code - Google::LOGGER.debug "Generating #{object.name} tests" - generate_resource_tests(pwd, data.clone) - generate_resource_sweepers(pwd, data.clone) - generate_resource_files(pwd, data.clone) - end - Dir.chdir pwd - end - - # if iam_policy is not defined or excluded, don't generate it - return if object.iam_policy.nil? || object.iam_policy.exclude - - FileUtils.mkpath output_folder - Dir.chdir output_folder - Google::LOGGER.debug "Generating #{object.name} IAM policy" - generate_iam_policy(pwd, data.clone, generate_code, generate_docs) - Dir.chdir pwd - end - - # Generate files at a per-resource basis. - def generate_resource_files(pwd, data) end - - def build_object_data(_pwd, object, output_folder, version) - ProductFileTemplate.file_for_resource(output_folder, object, version, @config, build_env) - end - - def build_env - { - goformat_enabled: @go_format_enabled, - start_time: @start_time - } - end - - # used to determine and separate objects that have update methods - # that target individual fields - def field_specific_update_methods(properties) - properties_by_custom_update(properties).length.positive? - end - - # Filter the properties to keep only the ones requiring custom update - # method and group them by update url & verb. - def properties_by_custom_update(properties) - update_props = properties.reject do |p| - p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP || - p.is_a?(Api::Type::KeyValueTerraformLabels) || - p.is_a?(Api::Type::KeyValueLabels) # effective_labels is used for update - end - - update_props.group_by do |p| - { - update_url: p.update_url, - update_verb: p.update_verb, - update_id: p.update_id, - fingerprint_name: p.fingerprint_name - } - end - end - - # Filter the properties to keep only the ones don't have custom update - # method and group them by update url & verb. - def properties_without_custom_update(properties) - properties.select do |p| - p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP - end - end - - # Takes a update_url and returns the list of custom updatable properties - # that can be updated at that URL. This allows flattened objects - # to determine which parent property in the API should be updated with - # the contents of the flattened object - def custom_update_properties_by_key(properties, key) - properties_by_custom_update(properties).select do |k, _| - k[:update_url] == key[:update_url] && - k[:update_id] == key[:update_id] && - k[:fingerprint_name] == key[:fingerprint_name] - end.first.last - # .first is to grab the element from the select which returns a list - # .last is because properties_by_custom_update returns a list of - # [{update_url}, [properties,...]] and we only need the 2nd part - end - - def update_url(resource, url_part) - [resource.__product.base_url, update_uri(resource, url_part)].flatten.join - end - - def update_uri(resource, url_part) - return resource.self_link_uri if url_part.nil? - - url_part - end - - def generate_iam_policy(pwd, data, generate_code, generate_docs) end - - # TODO(nelsonjr): Review all object interfaces and move to private methods - # that should not be exposed outside the object hierarchy. - private - - def generate_requires(properties, requires = []) - requires.concat(properties.collect(&:requires)) - end - - def provider_name - self.class.name.split('::').last.downcase - end - - # Determines the copyright year. If the file already exists we'll attempt to - # recognize the copyright year, and if it finds it will keep it. - def effective_copyright_year(out_file) - copyright_mask = /# Copyright (?[0-9-]*) Google Inc./ - if File.exist?(out_file) - first_line = File.read(out_file).split("\n") - .select { |l| copyright_mask.match(l) } - .first - matcher = copyright_mask.match(first_line) - return matcher[:year] unless matcher.nil? - end - Time.now.year - end - - # Adapted from the method used in templating - # See: mmv1/compile/core.rb - def comment_block(text, lang) - case lang - when :ruby, :python, :yaml, :git, :gemfile - header = text.map { |t| t&.empty? ? '#' : "# #{t}" } - when :go - header = text.map { |t| t&.empty? ? '//' : "// #{t}" } - else - raise "Unknown language for comment: #{lang}" - end - - header_string = header.join("\n") - "#{header_string}\n" # add trailing newline to returned value - end - - def language_from_filename(filename) - extension = filename.split('.')[-1] - case extension - when 'go' - :go - when 'rb' - :ruby - when 'yaml', 'yml' - :yaml - else - :unsupported - end - end - end -end diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index fe90182e8462..f409f0c84967 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -11,7 +11,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'provider/abstract_core' +require 'compile/core' +require 'fileutils' +require 'google/extensions' +require 'google/logger' +require 'json' +require 'provider/file_template' require 'provider/terraform/async' require 'provider/terraform/config' require 'provider/terraform/import' @@ -24,11 +29,435 @@ module Provider # Code generator for Terraform Resources that manage Google Cloud Platform # resources. - class Terraform < Provider::AbstractCore + class Terraform + include Compile::Core include Provider::Terraform::Import include Provider::Terraform::SubTemplate include Google::GolangUtils + TERRAFORM_PROVIDER_GA = 'github.com/hashicorp/terraform-provider-google'.freeze + TERRAFORM_PROVIDER_BETA = 'github.com/hashicorp/terraform-provider-google-beta'.freeze + TERRAFORM_PROVIDER_PRIVATE = 'internal/terraform-next'.freeze + RESOURCE_DIRECTORY_GA = 'google'.freeze + RESOURCE_DIRECTORY_BETA = 'google-beta'.freeze + RESOURCE_DIRECTORY_PRIVATE = 'google-private'.freeze + + def initialize(config, api, version_name, start_time) + @config = config + @api = api + + # @target_version_name is the version specified by MM for this generation + # run. That's distinct from @version below, which is the best-fit version + # supported by the product. + # These values will often match, but if a product supports only GA while + # MM is ran @ beta, @target_version_name will be at beta and @version will + # be @ GA. + # This matters for Terraform, where the primary folder for a provider + # needs to match the provider name. + @target_version_name = version_name + + @version = @api.version_obj_or_closest(version_name) + @api.set_properties_based_on_version(@version) + + # The compiler will error out if a file has been written in this compiler + # run already. Instead of storing all the modified files in state we'll + # use the time the file was modified. + @start_time = start_time + @go_format_enabled = check_goformat + end + + # This provides the ProductFileTemplate class with access to a provider. + def provider_binding + binding + end + + def check_goformat + if system('which gofmt > /dev/null') && system('which goimports > /dev/null') + true + else + Google::LOGGER.warn 'Either gofmt or goimports is not installed; go ' \ + 'code will be poorly formatted and will likely not compile.' + false + end + end + + # Main entry point for generation. + def generate(output_folder, types, product_path, dump_yaml, generate_code, generate_docs) + generate_objects(output_folder, types, generate_code, generate_docs) + + # Compilation has to be the last step, as some files (e.g. + # CONTRIBUTING.md) may depend on the list of all files previously copied + # or compiled. + # common-compile.yaml is a special file that will get compiled by the last product + # used in a single invocation of the compiled. It should not contain product-specific + # information; instead, it should be run-specific such as the version to compile at. + compile_product_files(output_folder) \ + unless @config.files.nil? || @config.files.compile.nil? + + FileUtils.mkpath output_folder + pwd = Dir.pwd + if generate_code + Dir.chdir output_folder + + generate_operation(pwd, output_folder, types) + Dir.chdir pwd + end + + # Write a file with the final version of the api, after overrides + # have been applied. + return unless dump_yaml + + raise 'Path to output the final yaml was not specified.' \ + if product_path.nil? || product_path == '' + + File.open("#{product_path}/final_api.yaml", 'w') do |file| + file.write("# This is a generated file, its contents will be overwritten.\n") + file.write(YAML.dump(@api)) + end + end + + # generate_code and generate_docs are actually used because all of the variables + # in scope in this method are made available within the templates by the compile call. + # rubocop:disable Lint/UnusedMethodArgument + def copy_common_files(output_folder, generate_code, generate_docs, provider_name = nil) + # version_name is actually used because all of the variables in scope in this method + # are made available within the templates by the compile call. + # TODO: remove version_name, use @target_version_name or pass it in expicitly + # rubocop:disable Lint/UselessAssignment + version_name = @target_version_name + # rubocop:enable Lint/UselessAssignment + provider_name ||= self.class.name.split('::').last.downcase + return unless File.exist?("provider/#{provider_name}/common~copy.yaml") + + Google::LOGGER.info "Copying common files for #{provider_name}" + files = YAML.safe_load(compile("provider/#{provider_name}/common~copy.yaml")) + copy_file_list(output_folder, files) + end + # rubocop:enable Lint/UnusedMethodArgument + + def copy_file_list(output_folder, files) + files.map do |target, source| + Thread.new do + target_file = File.join(output_folder, target) + target_dir = File.dirname(target_file) + Google::LOGGER.debug "Copying #{source} => #{target}" + FileUtils.mkpath target_dir + + # If we've modified a file since starting an MM run, it's a reasonable + # assumption that it was this run that modified it. + if File.exist?(target_file) && File.mtime(target_file) > @start_time + raise "#{target_file} was already modified during this run. #{File.mtime(target_file)}" + end + + FileUtils.copy_entry source, target_file + + add_hashicorp_copyright_header(output_folder, target) if File.extname(target) == '.go' + if File.extname(target) == '.go' || File.extname(target) == '.mod' + replace_import_path(output_folder, target) + end + end + end.map(&:join) + end + + # Compiles files specified within the product + def compile_product_files(output_folder) + file_template = ProductFileTemplate.new( + output_folder, + nil, + @api, + @target_version_name, + build_env + ) + compile_file_list(output_folder, @config.files.compile, file_template) + end + + # Compiles files that are shared at the provider level + def compile_common_files( + output_folder, + products, + common_compile_file, + override_path = nil + ) + return unless File.exist?(common_compile_file) + + files = YAML.safe_load(compile(common_compile_file)) + return unless files + + file_template = ProviderFileTemplate.new( + output_folder, + @target_version_name, + build_env, + products, + override_path + ) + compile_file_list(output_folder, files, file_template) + end + + def compile_file_list(output_folder, files, file_template, pwd = Dir.pwd) + FileUtils.mkpath output_folder + Dir.chdir output_folder + files.map do |target, source| + Thread.new do + Google::LOGGER.debug "Compiling #{source} => #{target}" + file_template.generate(pwd, source, target, self) + + add_hashicorp_copyright_header(output_folder, target) + replace_import_path(output_folder, target) + end + end.map(&:join) + Dir.chdir pwd + end + + def add_hashicorp_copyright_header(output_folder, target) + unless expected_output_folder?(output_folder) + Google::LOGGER.info "Unexpected output folder (#{output_folder}) detected " \ + 'when deciding to add HashiCorp copyright headers. ' \ + 'Watch out for unexpected changes to copied files' + end + # only add copyright headers when generating TPG and TPGB + return unless output_folder.end_with?('terraform-provider-google') || + output_folder.end_with?('terraform-provider-google-beta') + + # Prevent adding copyright header to files with paths or names matching the strings below + # NOTE: these entries need to match the content of the .copywrite.hcl file originally + # created in https://github.com/GoogleCloudPlatform/magic-modules/pull/7336 + # The test-fixtures folder is not included here as it's copied as a whole, + # not file by file (see common~copy.yaml) + ignored_folders = [ + '.release/', + '.changelog/', + 'examples/', + 'scripts/', + 'META.d/' + ] + ignored_files = [ + 'go.mod', + '.goreleaser.yml', + '.golangci.yml', + 'terraform-registry-manifest.json' + ] + should_add_header = true + ignored_folders.each do |folder| + # folder will be path leading to file + next unless target.start_with? folder + + Google::LOGGER.debug 'Not adding HashiCorp copyright headers in ' \ + "ignored folder #{folder} : #{target}" + should_add_header = false + end + return unless should_add_header + + ignored_files.each do |file| + # file will be the filename and extension, with no preceding path + next unless target.end_with? file + + Google::LOGGER.debug 'Not adding HashiCorp copyright headers to ' \ + "ignored file #{file} : #{target}" + should_add_header = false + end + return unless should_add_header + + Google::LOGGER.debug "Adding HashiCorp copyright header to : #{target}" + data = File.read("#{output_folder}/#{target}") + + copyright_header = ['Copyright (c) HashiCorp, Inc.', 'SPDX-License-Identifier: MPL-2.0'] + lang = language_from_filename(target) + + # Some file types we don't want to add headers to + # e.g. .sh where headers are functional + # Also, this guards against new filetypes being added and triggering build errors + return unless lang != :unsupported + + # File is not ignored and is appropriate file type to add header to + header = comment_block(copyright_header, lang) + File.write("#{output_folder}/#{target}", header) + + File.write("#{output_folder}/#{target}", data, mode: 'a') # append mode + end + + def expected_output_folder?(output_folder) + expected_folders = %w[ + terraform-provider-google + terraform-provider-google-beta + terraform-next + terraform-google-conversion + tfplan2cai + ] + folder_name = output_folder.split('/')[-1] # Possible issue with Windows OS + is_expected = false + expected_folders.each do |folder| + next unless folder_name == folder + + is_expected = true + break + end + is_expected + end + + def replace_import_path(output_folder, target) + data = File.read("#{output_folder}/#{target}") + + if data.include? "#{TERRAFORM_PROVIDER_BETA}/#{RESOURCE_DIRECTORY_BETA}" + raise 'Importing a package from module ' \ + "#{TERRAFORM_PROVIDER_BETA}/#{RESOURCE_DIRECTORY_BETA} " \ + "is not allowed in file #{target.split('/').last}. " \ + 'Please import a package from module ' \ + "#{TERRAFORM_PROVIDER_GA}/#{RESOURCE_DIRECTORY_GA}." + end + + return if @target_version_name == 'ga' + + # Replace the import pathes in utility files + case @target_version_name + when 'beta' + tpg = TERRAFORM_PROVIDER_BETA + dir = RESOURCE_DIRECTORY_BETA + else + tpg = TERRAFORM_PROVIDER_PRIVATE + dir = RESOURCE_DIRECTORY_PRIVATE + end + + data = data.gsub( + "#{TERRAFORM_PROVIDER_GA}/#{RESOURCE_DIRECTORY_GA}", + "#{tpg}/#{dir}" + ) + data = data.gsub( + "#{TERRAFORM_PROVIDER_GA}/version", + "#{tpg}/version" + ) + + data = data.gsub( + "module #{TERRAFORM_PROVIDER_GA}", + "module #{tpg}" + ) + File.write("#{output_folder}/#{target}", data) + end + + def import_path + case @target_version_name + when 'ga' + "#{TERRAFORM_PROVIDER_GA}/#{RESOURCE_DIRECTORY_GA}" + when 'beta' + "#{TERRAFORM_PROVIDER_BETA}/#{RESOURCE_DIRECTORY_BETA}" + else + "#{TERRAFORM_PROVIDER_PRIVATE}/#{RESOURCE_DIRECTORY_PRIVATE}" + end + end + + def generate_objects(output_folder, types, generate_code, generate_docs) + (@api.objects || []).each do |object| + if !types.empty? && !types.include?(object.name) + Google::LOGGER.info "Excluding #{object.name} per user request" + elsif types.empty? && object.exclude + Google::LOGGER.info "Excluding #{object.name} per API catalog" + elsif types.empty? && object.not_in_version?(@version) + Google::LOGGER.info "Excluding #{object.name} per API version" + else + Google::LOGGER.info "Generating #{object.name}" + # exclude_if_not_in_version must be called in order to filter out + # beta properties that are nested within GA resources + object.exclude_if_not_in_version!(@version) + + # Make object immutable. + object.freeze + object.all_user_properties.each(&:freeze) + + generate_object object, output_folder, @target_version_name, generate_code, generate_docs + end + end + end + + def generate_object(object, output_folder, version_name, generate_code, generate_docs) + pwd = Dir.pwd + data = build_object_data(pwd, object, output_folder, version_name) + unless object.exclude_resource + FileUtils.mkpath output_folder + Dir.chdir output_folder + Google::LOGGER.debug "Generating #{object.name} resource" + generate_resource(pwd, data.clone, generate_code, generate_docs) + if generate_code + Google::LOGGER.debug "Generating #{object.name} tests" + generate_resource_tests(pwd, data.clone) + generate_resource_sweepers(pwd, data.clone) + end + Dir.chdir pwd + end + + # if iam_policy is not defined or excluded, don't generate it + return if object.iam_policy.nil? || object.iam_policy.exclude + + FileUtils.mkpath output_folder + Dir.chdir output_folder + Google::LOGGER.debug "Generating #{object.name} IAM policy" + generate_iam_policy(pwd, data.clone, generate_code, generate_docs) + Dir.chdir pwd + end + + def build_env + { + goformat_enabled: @go_format_enabled, + start_time: @start_time + } + end + + # used to determine and separate objects that have update methods + # that target individual fields + def field_specific_update_methods(properties) + properties_by_custom_update(properties).length.positive? + end + + # Filter the properties to keep only the ones requiring custom update + # method and group them by update url & verb. + def properties_by_custom_update(properties) + update_props = properties.reject do |p| + p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP || + p.is_a?(Api::Type::KeyValueTerraformLabels) || + p.is_a?(Api::Type::KeyValueLabels) # effective_labels is used for update + end + + update_props.group_by do |p| + { + update_url: p.update_url, + update_verb: p.update_verb, + update_id: p.update_id, + fingerprint_name: p.fingerprint_name + } + end + end + + # Filter the properties to keep only the ones don't have custom update + # method and group them by update url & verb. + def properties_without_custom_update(properties) + properties.select do |p| + p.update_url.nil? || p.update_verb.nil? || p.update_verb == :NOOP + end + end + + # Takes a update_url and returns the list of custom updatable properties + # that can be updated at that URL. This allows flattened objects + # to determine which parent property in the API should be updated with + # the contents of the flattened object + def custom_update_properties_by_key(properties, key) + properties_by_custom_update(properties).select do |k, _| + k[:update_url] == key[:update_url] && + k[:update_id] == key[:update_id] && + k[:fingerprint_name] == key[:fingerprint_name] + end.first.last + # .first is to grab the element from the select which returns a list + # .last is because properties_by_custom_update returns a list of + # [{update_url}, [properties,...]] and we only need the 2nd part + end + + def update_url(resource, url_part) + [resource.__product.base_url, update_uri(resource, url_part)].flatten.join + end + + def update_uri(resource, url_part) + return resource.self_link_uri if url_part.nil? + + url_part + end + def generating_hashicorp_repo? # The default Provider is used to generate TPG and TPGB in HashiCorp-owned repos. # The compiler deviates from the default behaviour with a -f flag to produce @@ -186,8 +615,62 @@ def titlelize_property(property) property.name.camelize(:upper) end + # TODO(nelsonjr): Review all object interfaces and move to private methods + # that should not be exposed outside the object hierarchy. private + def generate_requires(properties, requires = []) + requires.concat(properties.collect(&:requires)) + end + + def provider_name + self.class.name.split('::').last.downcase + end + + # Determines the copyright year. If the file already exists we'll attempt to + # recognize the copyright year, and if it finds it will keep it. + def effective_copyright_year(out_file) + copyright_mask = /# Copyright (?[0-9-]*) Google Inc./ + if File.exist?(out_file) + first_line = File.read(out_file).split("\n") + .select { |l| copyright_mask.match(l) } + .first + matcher = copyright_mask.match(first_line) + return matcher[:year] unless matcher.nil? + end + Time.now.year + end + + # Adapted from the method used in templating + # See: mmv1/compile/core.rb + def comment_block(text, lang) + case lang + when :ruby, :python, :yaml, :git, :gemfile + header = text.map { |t| t&.empty? ? '#' : "# #{t}" } + when :go + header = text.map { |t| t&.empty? ? '//' : "// #{t}" } + else + raise "Unknown language for comment: #{lang}" + end + + header_string = header.join("\n") + "#{header_string}\n" # add trailing newline to returned value + end + + def language_from_filename(filename) + extension = filename.split('.')[-1] + case extension + when 'go' + :go + when 'rb' + :ruby + when 'yaml', 'yml' + :yaml + else + :unsupported + end + end + # Finds the folder name for a given version of the terraform provider def folder_name(version) version == 'ga' ? 'google' : "google-#{version}" diff --git a/mmv1/provider/terraform/async.rb b/mmv1/provider/terraform/async.rb index 91eab2866005..9ab6716cb6b9 100644 --- a/mmv1/provider/terraform/async.rb +++ b/mmv1/provider/terraform/async.rb @@ -12,10 +12,9 @@ # limitations under the License. require 'api/async' -require 'provider/abstract_core' module Provider - class Terraform < Provider::AbstractCore + class Terraform # Async implementation for polling in Terraform class PollAsync < Api::Async # Details how to poll for an eventually-consistent resource state. diff --git a/mmv1/provider/terraform/config.rb b/mmv1/provider/terraform/config.rb index 4b0021ae6a6a..23f60d2deec9 100644 --- a/mmv1/provider/terraform/config.rb +++ b/mmv1/provider/terraform/config.rb @@ -11,11 +11,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'provider/abstract_core' require 'provider/config' module Provider - class Terraform < Provider::AbstractCore + class Terraform # Settings for the provider class Config < Provider::Config def provider diff --git a/mmv1/provider/terraform/custom_code.rb b/mmv1/provider/terraform/custom_code.rb index 30d781b20199..a51fb29d72da 100644 --- a/mmv1/provider/terraform/custom_code.rb +++ b/mmv1/provider/terraform/custom_code.rb @@ -15,10 +15,9 @@ require 'api/object' require 'compile/core' require 'google/golang_utils' -require 'provider/abstract_core' module Provider - class Terraform < Provider::AbstractCore + class Terraform # Inserts custom code into terraform resources. class CustomCode < Api::Object # Collection of fields allowed in the CustomCode section for diff --git a/mmv1/provider/terraform/docs.rb b/mmv1/provider/terraform/docs.rb index 330b9b28b05f..3cb64f464ad7 100644 --- a/mmv1/provider/terraform/docs.rb +++ b/mmv1/provider/terraform/docs.rb @@ -15,10 +15,9 @@ require 'api/object' require 'compile/core' require 'google/golang_utils' -require 'provider/abstract_core' module Provider - class Terraform < Provider::AbstractCore + class Terraform # Inserts custom strings into terraform resource docs. class Docs < Api::Object # All these values should be strings, which will be inserted diff --git a/mmv1/provider/terraform/examples.rb b/mmv1/provider/terraform/examples.rb index 441f2392c6df..6d9a5eb01754 100644 --- a/mmv1/provider/terraform/examples.rb +++ b/mmv1/provider/terraform/examples.rb @@ -15,10 +15,9 @@ require 'api/object' require 'compile/core' require 'google/golang_utils' -require 'provider/abstract_core' module Provider - class Terraform < Provider::AbstractCore + class Terraform # Generates configs to be shown as examples in docs and outputted as tests # from a shared template class Examples < Api::Object diff --git a/mmv1/provider/terraform/import.rb b/mmv1/provider/terraform/import.rb index aaa95ee06d58..62e7c625db5b 100644 --- a/mmv1/provider/terraform/import.rb +++ b/mmv1/provider/terraform/import.rb @@ -11,10 +11,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'provider/abstract_core' - module Provider - class Terraform < Provider::AbstractCore + class Terraform # Functions to support 'terraform import'. module Import def import_id_formats_from_resource(resource) diff --git a/mmv1/provider/terraform/sub_template.rb b/mmv1/provider/terraform/sub_template.rb index ebaf67678afd..e74d2ebce971 100644 --- a/mmv1/provider/terraform/sub_template.rb +++ b/mmv1/provider/terraform/sub_template.rb @@ -11,10 +11,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'provider/abstract_core' - module Provider - class Terraform < Provider::AbstractCore + class Terraform # Functions to compile sub-templates. module SubTemplate def build_schema_property(property, object, pwd) diff --git a/mmv1/provider/terraform/validation.rb b/mmv1/provider/terraform/validation.rb index 944f4ce6034e..b63f8a284c97 100644 --- a/mmv1/provider/terraform/validation.rb +++ b/mmv1/provider/terraform/validation.rb @@ -12,10 +12,9 @@ # limitations under the License. require 'api/object' -require 'provider/abstract_core' module Provider - class Terraform < Provider::AbstractCore + class Terraform # Support for schema ValidateFunc functionality. class Validation < Api::Object # Ensures the value matches this regex diff --git a/mmv1/provider/terraform/virtual_fields.rb b/mmv1/provider/terraform/virtual_fields.rb index 66acd30b3e03..ed88fabf7886 100644 --- a/mmv1/provider/terraform/virtual_fields.rb +++ b/mmv1/provider/terraform/virtual_fields.rb @@ -15,10 +15,9 @@ require 'api/object' require 'compile/core' require 'google/golang_utils' -require 'provider/abstract_core' module Provider - class Terraform < Provider::AbstractCore + class Terraform # Virtual fields are Terraform-only fields that control Terraform's # behaviour. They don't map to underlying API fields (although they # may map to parameters), and will require custom code to be added to diff --git a/mmv1/spec/hashicorp_copyright_spec.rb b/mmv1/spec/hashicorp_copyright_spec.rb index eae3af9f00b3..ea09907fba94 100644 --- a/mmv1/spec/hashicorp_copyright_spec.rb +++ b/mmv1/spec/hashicorp_copyright_spec.rb @@ -12,7 +12,7 @@ # limitations under the License. require 'spec_helper' -require 'provider/core' +require 'provider/terraform' describe 'Provider::Core.expected_output_folder?' do # Inputs for tests @@ -21,7 +21,7 @@ version_name = 'ga' start_time = Time.now - provider = Provider::Core.new(config, api, version_name, start_time) + provider = Provider::Terraform.new(config, api, version_name, start_time) # rubocop:disable Layout/LineLength it 'should identify `terraform-provider-google` as an expected output folder' do From d9e44319f1ee4d932731df6b783d8bfaee495840 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 30 Nov 2023 19:47:40 +0000 Subject: [PATCH 037/107] Update Dockerfiles to Go 1.20 (#9530) --- .ci/containers/build-environment/Dockerfile | 4 ++-- .ci/containers/go-plus/Dockerfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.ci/containers/build-environment/Dockerfile b/.ci/containers/build-environment/Dockerfile index f30e774b9e36..2f2dcb85ecf5 100644 --- a/.ci/containers/build-environment/Dockerfile +++ b/.ci/containers/build-environment/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Building Go dependencies -FROM golang:1.19-bullseye AS builder +FROM golang:1.20-bullseye AS builder # Set working directory WORKDIR /app @@ -15,7 +15,7 @@ RUN go mod download FROM ruby:3.1-bullseye # golang -COPY --from=golang:1.19-bullseye /usr/local/go /usr/local/go +COPY --from=golang:1.20-bullseye /usr/local/go /usr/local/go ENV GOPATH /go ENV PATH /usr/local/go/bin:$PATH ENV PATH $GOPATH/bin:$PATH diff --git a/.ci/containers/go-plus/Dockerfile b/.ci/containers/go-plus/Dockerfile index c7b8641eb297..ea9a70109dc8 100644 --- a/.ci/containers/go-plus/Dockerfile +++ b/.ci/containers/go-plus/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Download go module cache for builds -FROM golang:1.19-bullseye AS builder +FROM golang:1.20-bullseye AS builder ENV GOCACHE=/go/cache RUN apt-get update && apt-get install -y unzip @@ -12,7 +12,7 @@ WORKDIR /app1/magic-modules-main/.ci/magician RUN go build -o /dev/null . # Stage 2: Creating the final image -FROM golang:1.19-bullseye +FROM golang:1.20-bullseye SHELL ["/bin/bash", "-c"] ENV GOCACHE=/go/cache From 2e9ce47eed073f12e0387aea8883908872f5bc46 Mon Sep 17 00:00:00 2001 From: Adam Cole <39781606+accole@users.noreply.github.com> Date: Thu, 30 Nov 2023 15:34:41 -0600 Subject: [PATCH 038/107] Fixes https://github.com/hashicorp/terraform-provider-google/issues/16538 (#9551) Co-authored-by: Adam Cole --- mmv1/products/cloudfunctions2/Function.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index 5b0a0ff36b0a..0618283b0381 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -615,7 +615,10 @@ properties: default_from_api: true - !ruby/object:Api::Type::String name: 'serviceAccountEmail' - description: 'The email of the service account for this function.' + description: | + Optional. The email of the trigger's service account. The service account + must have permission to invoke Cloud Run services. If empty, defaults to the + Compute Engine default service account: {project_number}-compute@developer.gserviceaccount.com. default_from_api: true - !ruby/object:Api::Type::Enum name: 'retryPolicy' From 08dfecd2300850889a16251595a0bbca320b73a6 Mon Sep 17 00:00:00 2001 From: Suhong Qin <51539171+sqin2019@users.noreply.github.com> Date: Thu, 30 Nov 2023 13:46:54 -0800 Subject: [PATCH 039/107] add expiryDetail to google_cloud_identity_group_membership (#9427) --- .../cloudidentity/GroupMembership.yaml | 18 ++- .../cloud_identity_group_membership.go.erb | 139 ++++++++++++++++++ .../cloud_identity_group_membership.tf.erb | 2 +- .../cloud_identity_group_membership.go.erb | 26 ---- ...loud_identity_group_membership_test.go.erb | 3 + 5 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 mmv1/templates/terraform/custom_update/cloud_identity_group_membership.go.erb delete mode 100644 mmv1/templates/terraform/update_encoder/cloud_identity_group_membership.go.erb diff --git a/mmv1/products/cloudidentity/GroupMembership.yaml b/mmv1/products/cloudidentity/GroupMembership.yaml index 029ccea4bba9..bca79a961574 100644 --- a/mmv1/products/cloudidentity/GroupMembership.yaml +++ b/mmv1/products/cloudidentity/GroupMembership.yaml @@ -59,7 +59,7 @@ examples: custom_code: !ruby/object:Provider::Terraform::CustomCode post_create: templates/terraform/post_create/set_computed_name.erb post_import: templates/terraform/post_import/cloud_identity_group_membership.go.erb - update_encoder: templates/terraform/update_encoder/cloud_identity_group_membership.go.erb + custom_update: templates/terraform/custom_update/cloud_identity_group_membership.go.erb parameters: - !ruby/object:Api::Type::ResourceRef @@ -180,6 +180,22 @@ properties: - :OWNER - :MANAGER - :MEMBER + - !ruby/object:Api::Type::NestedObject + name: 'expiryDetail' + description: | + The MembershipRole expiry details, only supported for MEMBER role. + Other roles cannot be accompanied with MEMBER role having expiry. + properties: + - !ruby/object:Api::Type::String + name: 'expireTime' + required: true + description: | + The time at which the MembershipRole will expire. + + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond + resolution and up to nine fractional digits. + + Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". - !ruby/object:Api::Type::String name: 'type' output: true diff --git a/mmv1/templates/terraform/custom_update/cloud_identity_group_membership.go.erb b/mmv1/templates/terraform/custom_update/cloud_identity_group_membership.go.erb new file mode 100644 index 000000000000..b2320d173b6d --- /dev/null +++ b/mmv1/templates/terraform/custom_update/cloud_identity_group_membership.go.erb @@ -0,0 +1,139 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + d.Partial(true) + + if d.HasChange("roles") { + url, err := tpgresource.ReplaceVars(d, config, "{{CloudIdentityBasePath}}{{name}}:modifyMembershipRoles") + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + // Return object for modifyMembershipRoles (we build request object from scratch, without using `obj`) + b, a := d.GetChange("roles") + before := b.(*schema.Set) + after := a.(*schema.Set) + + ignoreUpdateR := make(map[string]struct{}) + addRoleList := after.Difference(before).List() + removeRoleList := before.Difference(after).List() + + var updateRolesParams []map[string]interface{} + for _, addR := range addRoleList { + ar := addR.(map[string]interface{})["name"].(string) + ae := addR.(map[string]interface{})["expiry_detail"].([]interface {}) + for _, removeR := range removeRoleList { + if ar == removeR.(map[string]interface{})["name"].(string) { + ignoreUpdateR[ar] = struct{}{} + var updateR map[string]interface{} + if len(ae) == 0 { + updateR = map[string]interface{}{"name": ar} + } else { + updateR = map[string]interface{}{"name": ar, "expiry_detail": ae[0]} + } + updateP := map[string]interface{}{"field_mask": "expiryDetail.expire_time", "membership_role": updateR} + updateRolesParams = append(updateRolesParams, updateP) + } + } + } + + var addRoles []map[string]interface{} + for _, r := range addRoleList { + name := r.(map[string]interface{})["name"].(string) + if _, ignore := ignoreUpdateR[name]; ignore { + continue + } + expiryDetail := r.(map[string]interface{})["expiry_detail"].([]interface {}) + if len(expiryDetail) == 0 { + addRoles = append(addRoles, map[string]interface{}{"name": name}) + } else { + addRoles = append(addRoles, map[string]interface{}{"name": name, "expiry_detail": expiryDetail[0]}) + } + } + var removeRoles []string + for _, r := range removeRoleList { + name := r.(map[string]interface{})["name"].(string) + if _, ignore := ignoreUpdateR[name]; ignore { + continue + } + removeRoles = append(removeRoles, name) + } + + // ref: https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/modifyMembershipRoles#request-body + // Only single operation per request is allowed. + if len(removeRoles) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: map[string]interface{}{"removeRoles": removeRoles}, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + if err != nil { + return fmt.Errorf("Error removing GroupMembership %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished removing GroupMembership %q: %#v", d.Id(), res) + } + } + if len(updateRolesParams) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: map[string]interface{}{"updateRolesParams": updateRolesParams}, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + if err != nil { + return fmt.Errorf("Error updating GroupMembership %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating GroupMembership %q: %#v", d.Id(), res) + } + } + if len(addRoles) > 0 { + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: map[string]interface{}{"addRoles": addRoles}, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + if err != nil { + return fmt.Errorf("Error adding GroupMembership %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished adding GroupMembership %q: %#v", d.Id(), res) + } + } + } + + d.Partial(false) + + return resourceCloudIdentityGroupMembershipRead(d, meta) diff --git a/mmv1/templates/terraform/examples/cloud_identity_group_membership.tf.erb b/mmv1/templates/terraform/examples/cloud_identity_group_membership.tf.erb index e259fdb2344f..ce660ca58e69 100644 --- a/mmv1/templates/terraform/examples/cloud_identity_group_membership.tf.erb +++ b/mmv1/templates/terraform/examples/cloud_identity_group_membership.tf.erb @@ -34,6 +34,6 @@ resource "google_cloud_identity_group_membership" "<%= ctx[:primary_resource_id] } roles { - name = "MEMBER" + name = "MEMBER" } } diff --git a/mmv1/templates/terraform/update_encoder/cloud_identity_group_membership.go.erb b/mmv1/templates/terraform/update_encoder/cloud_identity_group_membership.go.erb deleted file mode 100644 index 5f7357f1570d..000000000000 --- a/mmv1/templates/terraform/update_encoder/cloud_identity_group_membership.go.erb +++ /dev/null @@ -1,26 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2019 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. --%> - // Return object for modifyMembershipRoles (we build request object from scratch, without using `obj`) - b, a := d.GetChange("roles") - before := b.(*schema.Set) - after := a.(*schema.Set) - // ref: https://cloud.google.com/identity/docs/reference/rest/v1/groups.memberships/modifyMembershipRoles#request-body - addRoles := after.Difference(before).List() - var removeRoles []string - for _, r := range before.Difference(after).List() { - removeRoles = append(removeRoles, r.(map[string]interface{})["name"].(string)) - } - req := map[string]interface{}{"addRoles": addRoles, "removeRoles": removeRoles} - return req, nil diff --git a/mmv1/third_party/terraform/services/cloudidentity/resource_cloud_identity_group_membership_test.go.erb b/mmv1/third_party/terraform/services/cloudidentity/resource_cloud_identity_group_membership_test.go.erb index b4fcf66ecea6..08cb7d45b924 100644 --- a/mmv1/third_party/terraform/services/cloudidentity/resource_cloud_identity_group_membership_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudidentity/resource_cloud_identity_group_membership_test.go.erb @@ -81,6 +81,9 @@ resource "google_cloud_identity_group_membership" "basic" { roles { name = "MEMBER" + expiry_detail { + expire_time = "2215-10-02T15:01:23Z" + } } } From 61f0388d5ddf0c2bb42921c27d0bb3067840c92b Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:05:15 +0000 Subject: [PATCH 040/107] Upgrade to Go 1.20 (#9506) * Upgrade TPG/TPGB go.mod to Go 1.20 * Upgrade doctor script to check users have Go 1.20 for building the provider * Update workflows that interact with the provider codebase directly * Update tpgtools to Go 1.20 * Upgrade everything else from Go 1.19 to Go 1.20 --- .ci/magician/go.mod | 2 +- .github/workflows/build-downstream.yml | 2 +- .github/workflows/membership-checker.yml | 2 +- .github/workflows/test-tgc.yml | 2 +- .github/workflows/test-tpg.yml | 2 +- .github/workflows/unit-test-tgc.yml | 2 +- .github/workflows/unit-test-tpg.yml | 2 +- .github/workflows/unit-tests-diff-processor.yml | 2 +- docs/go.mod | 2 +- mmv1/third_party/terraform/go.mod.erb | 2 +- scripts/doctor | 4 ++-- tools/diff-processor/go.mod | 2 +- tools/issue-labeler/go.mod | 2 +- tools/missing-test-detector/go.mod | 2 +- tools/teamcity-generator/go.mod | 2 +- tpgtools/go.mod | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 4ebd7498dd30..7816d11ecd61 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -1,6 +1,6 @@ module magician -go 1.19 +go 1.20 require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/.github/workflows/build-downstream.yml b/.github/workflows/build-downstream.yml index 04312df88454..32fe3e526d37 100644 --- a/.github/workflows/build-downstream.yml +++ b/.github/workflows/build-downstream.yml @@ -47,7 +47,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '^1.19' + go-version: '^1.20' # Cache Go modules - name: Cache Go modules diff --git a/.github/workflows/membership-checker.yml b/.github/workflows/membership-checker.yml index fbc1d10bba62..2612f2c61679 100644 --- a/.github/workflows/membership-checker.yml +++ b/.github/workflows/membership-checker.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '^1.19.1' + go-version: '^1.20.1' - name: Run membership checker unit tests run: | cd .ci/magician diff --git a/.github/workflows/test-tgc.yml b/.github/workflows/test-tgc.yml index e1654f092c1e..1546a5c856ee 100644 --- a/.github/workflows/test-tgc.yml +++ b/.github/workflows/test-tgc.yml @@ -81,7 +81,7 @@ jobs: if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} uses: actions/setup-go@v3 with: - go-version: '^1.19' + go-version: '^1.20' - name: Build Terraform Google Conversion if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} run: | diff --git a/.github/workflows/test-tpg.yml b/.github/workflows/test-tpg.yml index de61efccb631..0b5148f7d1e2 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -82,7 +82,7 @@ jobs: if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} uses: actions/setup-go@v3 with: - go-version: '^1.19' + go-version: '^1.20' - name: Build Provider if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} run: | diff --git a/.github/workflows/unit-test-tgc.yml b/.github/workflows/unit-test-tgc.yml index e718ea8066f7..e1c983d92ba8 100644 --- a/.github/workflows/unit-test-tgc.yml +++ b/.github/workflows/unit-test-tgc.yml @@ -30,7 +30,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '^1.19' + go-version: '^1.20' - name: Cache Go modules and build cache uses: actions/cache@v3 diff --git a/.github/workflows/unit-test-tpg.yml b/.github/workflows/unit-test-tpg.yml index 4bfb4dd80d87..ddb48186ff43 100644 --- a/.github/workflows/unit-test-tpg.yml +++ b/.github/workflows/unit-test-tpg.yml @@ -28,7 +28,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v3 with: - go-version: '^1.19' + go-version: '^1.20' - name: Cache Go modules and build cache uses: actions/cache@v3 diff --git a/.github/workflows/unit-tests-diff-processor.yml b/.github/workflows/unit-tests-diff-processor.yml index 33efabed2a26..638fb42c60c5 100644 --- a/.github/workflows/unit-tests-diff-processor.yml +++ b/.github/workflows/unit-tests-diff-processor.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '^1.19.1' + go-version: '^1.20.1' - name: Build run: | diff --git a/docs/go.mod b/docs/go.mod index bb57693d8662..35af46f9dda9 100644 --- a/docs/go.mod +++ b/docs/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/docs -go 1.19 +go 1.20 require ( github.com/alex-shpak/hugo-book v0.0.0-20230424134111-d86d5e70c7c0 // indirect diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index c75615613c2f..e887f11fecab 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -1,6 +1,6 @@ <% autogen_exception -%> module github.com/hashicorp/terraform-provider-google -go 1.19 +go 1.20 require ( cloud.google.com/go/bigtable v1.19.0 diff --git a/scripts/doctor b/scripts/doctor index 3da2210779ac..ce131165d7f6 100755 --- a/scripts/doctor +++ b/scripts/doctor @@ -48,9 +48,9 @@ if [ $found -eq 0 ]; then else version=($(go version)) version=${version[2]} - if [[ "$version" < "go1.19.0" ]]; then + if [[ "$version" < "go1.20.0" ]]; then exitcode=1 - warn "yel" " $version is installed, but go 1.19 or later is required. See https://golang.org/doc/install for information on installing it." + warn "yel" " $version is installed, but go 1.20 or later is required. See https://golang.org/doc/install for information on installing it." fi if [[ -z "${GOPATH}" ]]; then exitcode=1 diff --git a/tools/diff-processor/go.mod b/tools/diff-processor/go.mod index 880f54da41c9..78da81c6aeaa 100644 --- a/tools/diff-processor/go.mod +++ b/tools/diff-processor/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor -go 1.19 +go 1.20 replace google/provider/old => ./old diff --git a/tools/issue-labeler/go.mod b/tools/issue-labeler/go.mod index d0e17c929f42..a1fcbec43647 100644 --- a/tools/issue-labeler/go.mod +++ b/tools/issue-labeler/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler -go 1.19 +go 1.20 require ( github.com/golang/glog v1.1.1 diff --git a/tools/missing-test-detector/go.mod b/tools/missing-test-detector/go.mod index 291b412ade2c..3e25a00ea6e2 100644 --- a/tools/missing-test-detector/go.mod +++ b/tools/missing-test-detector/go.mod @@ -1,6 +1,6 @@ module github.com/trodge/magic-modules/tools/missing-test-detector -go 1.19 +go 1.20 replace google/provider/old => github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230302220542-203a52c6e3e1 diff --git a/tools/teamcity-generator/go.mod b/tools/teamcity-generator/go.mod index e0b2073fc3a3..3f998f908e09 100644 --- a/tools/teamcity-generator/go.mod +++ b/tools/teamcity-generator/go.mod @@ -1,5 +1,5 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/teamcity-generator -go 1.19 +go 1.20 require golang.org/x/text v0.11.0 diff --git a/tpgtools/go.mod b/tpgtools/go.mod index 6ac80ea9b332..b8256b7777fc 100644 --- a/tpgtools/go.mod +++ b/tpgtools/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/tpgtools -go 1.19 +go 1.20 require ( bitbucket.org/creachadair/stringset v0.0.11 From 1f7bac74e25a7411afca00103bae09270eca85d7 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 30 Nov 2023 15:09:26 -0800 Subject: [PATCH 041/107] Fix release notes link (#9555) The colon gets lumped in with the link and doesn't exist - seehttps://github.com/GoogleCloudPlatform/magic-modules/actions/runs/7053029330/job/19199293155?pr=9554 for an example --- tools/go-changelog/cmd/changelog-pr-body-check/main.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/go-changelog/cmd/changelog-pr-body-check/main.go b/tools/go-changelog/cmd/changelog-pr-body-check/main.go index af317b1ed838..0a05e73bd1e3 100644 --- a/tools/go-changelog/cmd/changelog-pr-body-check/main.go +++ b/tools/go-changelog/cmd/changelog-pr-body-check/main.go @@ -63,9 +63,7 @@ func main() { case changelog.EntryErrorNotFound: body := "Oops! It looks like no changelog entry is attached to" + " this PR. Please include a release note block" + - " in the PR body, as described in https://googlecloudplatform.github.io/magic-modules/contribute/release-notes/:" + - "\n\n~~~\n```release-note:TYPE\nRelease note" + - "\n```\n~~~" + " in the PR body, as described in https://googlecloudplatform.github.io/magic-modules/contribute/release-notes/" log.Fatal(body) case changelog.EntryErrorUnknownTypes: unknownTypes := err.Details["unknownTypes"].([]string) From 9988136d1c8e3ef6dfb0506fe78fc07cd4a0097f Mon Sep 17 00:00:00 2001 From: Jared Date: Thu, 30 Nov 2023 17:58:48 -0800 Subject: [PATCH 042/107] fixed artifact_registry_repository permadiff in unordered array (#9376) * fixed permadiff in unordered array * changed permadiff fix strategy for upstream policies * removed no-op field * change diff semantics to use schema.Set * updated virtual example with intentional out-of-order priorities * update virtual policy comparison to not panic on bad cast (if possible) --- .../products/artifactregistry/Repository.yaml | 2 + .../artifact_registry_repository.go.erb | 47 +++++++++++++++++++ ...rtifact_registry_repository_virtual.tf.erb | 24 +++++++--- 3 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 mmv1/templates/terraform/constants/artifact_registry_repository.go.erb diff --git a/mmv1/products/artifactregistry/Repository.yaml b/mmv1/products/artifactregistry/Repository.yaml index 607387e85bf7..aaac06a984c4 100644 --- a/mmv1/products/artifactregistry/Repository.yaml +++ b/mmv1/products/artifactregistry/Repository.yaml @@ -112,6 +112,7 @@ examples: username: 'remote-username' secret_data: 'remote-password' custom_code: !ruby/object:Provider::Terraform::CustomCode + constants: templates/terraform/constants/artifact_registry_repository.go.erb encoder: templates/terraform/encoders/location_from_region.go.erb properties: - !ruby/object:Api::Type::String @@ -231,6 +232,7 @@ properties: properties: - !ruby/object:Api::Type::Array name: 'upstreamPolicies' + diff_suppress_func: 'upstreamPoliciesDiffSuppress' description: |- Policies that configure the upstream artifacts distributed by the Virtual Repository. Upstream policies cannot be set on a standard repository. diff --git a/mmv1/templates/terraform/constants/artifact_registry_repository.go.erb b/mmv1/templates/terraform/constants/artifact_registry_repository.go.erb new file mode 100644 index 000000000000..52e5b587d59c --- /dev/null +++ b/mmv1/templates/terraform/constants/artifact_registry_repository.go.erb @@ -0,0 +1,47 @@ +<%# The license inside this block applies to this file + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func upstreamPoliciesDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + o, n := d.GetChange("virtual_repository_config.0.upstream_policies") + oldPolicies, ok := o.([]any) + if !ok { + return false + } + newPolicies, ok := n.([]any) + if !ok { + return false + } + + var oldHashes, newHashes []interface{} + for _, policy := range oldPolicies { + data, ok := policy.(map[string]any) + if !ok { + return false + } + hashStr := fmt.Sprintf("[id:%v priority:%v repository:%v]", data["id"], data["priority"], data["repository"]) + oldHashes = append(oldHashes, hashStr) + } + for _, policy := range newPolicies { + data, ok := policy.(map[string]any) + if !ok { + return false + } + hashStr := fmt.Sprintf("[id:%v priority:%v repository:%v]", data["id"], data["priority"], data["repository"]) + newHashes = append(newHashes, hashStr) + } + + oldSet := schema.NewSet(schema.HashString, oldHashes) + newSet := schema.NewSet(schema.HashString, newHashes) + return oldSet.Equal(newSet) +} diff --git a/mmv1/templates/terraform/examples/artifact_registry_repository_virtual.tf.erb b/mmv1/templates/terraform/examples/artifact_registry_repository_virtual.tf.erb index b197d33709bc..4d20c408b80b 100644 --- a/mmv1/templates/terraform/examples/artifact_registry_repository_virtual.tf.erb +++ b/mmv1/templates/terraform/examples/artifact_registry_repository_virtual.tf.erb @@ -1,7 +1,14 @@ -resource "google_artifact_registry_repository" "<%= ctx[:primary_resource_id] %>-upstream" { +resource "google_artifact_registry_repository" "<%= ctx[:primary_resource_id] %>-upstream-1" { location = "us-central1" - repository_id = "<%= ctx[:vars]['upstream_repository_id'] %>" - description = "<%= ctx[:vars]['upstream_description'] %>" + repository_id = "<%= ctx[:vars]['upstream_repository_id'] %>-1" + description = "<%= ctx[:vars]['upstream_description'] %> 1" + format = "DOCKER" +} + +resource "google_artifact_registry_repository" "<%= ctx[:primary_resource_id] %>-upstream-2" { + location = "us-central1" + repository_id = "<%= ctx[:vars]['upstream_repository_id'] %>-2" + description = "<%= ctx[:vars]['upstream_description'] %> 2" format = "DOCKER" } @@ -14,9 +21,14 @@ resource "google_artifact_registry_repository" "<%= ctx[:primary_resource_id] %> mode = "VIRTUAL_REPOSITORY" virtual_repository_config { upstream_policies { - id = "<%= ctx[:vars]['upstream_policy_id'] %>" - repository = google_artifact_registry_repository.<%= ctx[:primary_resource_id] %>-upstream.id - priority = 1 + id = "<%= ctx[:vars]['upstream_policy_id'] %>-1" + repository = google_artifact_registry_repository.<%= ctx[:primary_resource_id] %>-upstream-1.id + priority = 20 + } + upstream_policies { + id = "<%= ctx[:vars]['upstream_policy_id'] %>-2" + repository = google_artifact_registry_repository.<%= ctx[:primary_resource_id] %>-upstream-2.id + priority = 10 } } } From ea6b3cd65b8589c54c7686a352edc5866dd2dae5 Mon Sep 17 00:00:00 2001 From: Edward Sun <42220489+edwardmedia@users.noreply.github.com> Date: Fri, 1 Dec 2023 06:16:13 -0800 Subject: [PATCH 043/107] update desc on web_server_network_access_control (#9548) Co-authored-by: Edward Sun --- .../services/composer/resource_composer_environment.go.erb | 2 +- .../terraform/website/docs/r/composer_environment.html.markdown | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb index 1e6d5ab46c9b..ef756d19ba7e 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment.go.erb @@ -559,7 +559,7 @@ func ResourceComposerEnvironment() *schema.Resource { Computed: true, AtLeastOneOf: composerConfigKeys, MaxItems: 1, - Description: `The network-level access control policy for the Airflow web server. If unspecified, no network-level access restrictions will be applied. This field is supported for Cloud Composer environments in versions composer-1.*.*-airflow-*.*.*.`, + Description: `Network-level access control policy for the Airflow web server.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "allowed_ip_range": { diff --git a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown index f50f286f42e5..c9efd3c5abe4 100644 --- a/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown @@ -302,7 +302,6 @@ The following arguments are supported: The configuration used for the Private IP Cloud Composer environment. Structure is [documented below](#nested_private_environment_config). * `web_server_network_access_control` - - (Optional, Cloud Composer 1 only) The network-level access control policy for the Airflow web server. If unspecified, no network-level access restrictions are applied. From 89588b2e92be508565b1530e52b39818c3be9acd Mon Sep 17 00:00:00 2001 From: Yi Xing Date: Fri, 1 Dec 2023 07:04:12 -0800 Subject: [PATCH 044/107] Add resource EventThreatDetectionCustomModule (#9509) * Add resource EventThreatDetectionCustomModule * Fix yaml format issue * Fix TestAccSecurityCenterEventThreatDetectionCustomModule test * Address comments * Change back to use GetTestOrgFromEnv in testing * Improve test example * Change parameter type to be immutable --- .../EventThreatDetectionCustomModule.yaml | 101 ++++++++++++++ ...vent_threat_detection_custom_module.tf.erb | 18 +++ ...ent_threat_detection_custom_module_test.go | 132 ++++++++++++++++++ 3 files changed, 251 insertions(+) create mode 100644 mmv1/products/securitycenter/EventThreatDetectionCustomModule.yaml create mode 100644 mmv1/templates/terraform/examples/scc_event_threat_detection_custom_module.tf.erb create mode 100644 mmv1/third_party/terraform/services/securitycenter/resource_scc_event_threat_detection_custom_module_test.go diff --git a/mmv1/products/securitycenter/EventThreatDetectionCustomModule.yaml b/mmv1/products/securitycenter/EventThreatDetectionCustomModule.yaml new file mode 100644 index 000000000000..7b31f99123e6 --- /dev/null +++ b/mmv1/products/securitycenter/EventThreatDetectionCustomModule.yaml @@ -0,0 +1,101 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'EventThreatDetectionCustomModule' +description: | + Represents an instance of an Event Threat Detection custom module, including + its full module name, display name, enablement state, andlast updated time. + You can create a custom module at the organization level only. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Overview of custom modules for Event Threat Detection': 'https://cloud.google.com/security-command-center/docs/custom-modules-etd-overview' + api: 'https://cloud.google.com/security-command-center/docs/reference/rest/v1/organizations.eventThreatDetectionSettings.customModules' +base_url: 'organizations/{{organization}}/eventThreatDetectionSettings/customModules' +self_link: 'organizations/{{organization}}/eventThreatDetectionSettings/customModules/{{name}}' +mutex: 'organizations/{{organization}}/eventThreatDetectionSettings/customModules' +update_verb: :PATCH +update_mask: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "scc_event_threat_detection_custom_module" + primary_resource_id: "example" + # Has a handwritten update test + skip_test: true + vars: + display_name: basic_custom_module + type: 'CONFIGURABLE_BAD_IP' + test_env_vars: + org_id: :ORG_ID + +parameters: + - !ruby/object:Api::Type::String + name: 'organization' + immutable: true + required: true + url_param_only: true + description: | + Numerical ID of the parent organization. + +properties: + - !ruby/object:Api::Type::String + name: 'name' + output: true + custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb + description: | + The resource name of the Event Threat Detection custom module. + Its format is "organizations/{organization}/eventThreatDetectionSettings/customModules/{module}". + - !ruby/object:Api::Type::String + name: 'config' + required: true + custom_expand: 'templates/terraform/custom_expand/json_schema.erb' + custom_flatten: 'templates/terraform/custom_flatten/json_schema.erb' + state_func: + 'func(v interface{}) string { s, _ := structure.NormalizeJsonString(v); + return s }' + description: | + Config for the module. For the resident module, its config value is defined at this level. + For the inherited module, its config value is inherited from the ancestor module. + validation: !ruby/object:Provider::Terraform::Validation + function: 'validation.StringIsJSON' + - !ruby/object:Api::Type::Enum + name: 'enablementState' + required: true + description: | + The state of enablement for the module at the given level of the hierarchy. + values: + - :ENABLED + - :DISABLED + - !ruby/object:Api::Type::String + name: 'type' + immutable: true + required: true + description: | + Immutable. Type for the module. e.g. CONFIGURABLE_BAD_IP. + - !ruby/object:Api::Type::String + name: 'displayName' + description: | + The human readable name to be displayed for the module. + - !ruby/object:Api::Type::String + name: 'updateTime' + output: true + description: | + The time at which the custom module was last updated. + + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and + up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + - !ruby/object:Api::Type::String + name: 'lastEditor' + output: true + description: | + The editor that last updated the custom module diff --git a/mmv1/templates/terraform/examples/scc_event_threat_detection_custom_module.tf.erb b/mmv1/templates/terraform/examples/scc_event_threat_detection_custom_module.tf.erb new file mode 100644 index 000000000000..34bb64ac066f --- /dev/null +++ b/mmv1/templates/terraform/examples/scc_event_threat_detection_custom_module.tf.erb @@ -0,0 +1,18 @@ +resource "google_scc_event_threat_detection_custom_module" "<%= ctx[:primary_resource_id] %>" { + organization = "<%= ctx[:test_env_vars]['org_id'] %>" + display_name = "<%= ctx[:vars]['display_name'] %>" + enablement_state = "ENABLED" + type = "<%= ctx[:vars]['type'] %>" + description = "My Event Threat Detection Custom Module" + cofig = jsonencode({ + "metadata": { + "severity": "LOW", + "description": "Flagged by Forcepoint as malicious", + "recommendation": "Contact the owner of the relevant project." + }, + "ips": [ + "192.0.2.1", + "192.0.2.0/24" + ] + }) +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/securitycenter/resource_scc_event_threat_detection_custom_module_test.go b/mmv1/third_party/terraform/services/securitycenter/resource_scc_event_threat_detection_custom_module_test.go new file mode 100644 index 000000000000..1328a65e9bfb --- /dev/null +++ b/mmv1/third_party/terraform/services/securitycenter/resource_scc_event_threat_detection_custom_module_test.go @@ -0,0 +1,132 @@ +package securitycenter_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccSecurityCenterEventThreatDetectionCustomModule(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccSecurityCenterEventThreatDetectionCustomModuleDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSecurityCenterEventThreatDetectionCustomModule_sccOrganizationCustomModuleExample(context), + }, + { + ResourceName: "google_scc_event_threat_detection_custom_module.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"organization"}, + }, + { + Config: testAccSecurityCenterEventThreatDetectionCustomModule_sccOrganizationCustomModuleUpdate(context), + }, + { + ResourceName: "google_scc_event_threat_detection_custom_module.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"organization"}, + }, + }, + }) +} + +func testAccSecurityCenterEventThreatDetectionCustomModule_sccOrganizationCustomModuleExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_scc_event_threat_detection_custom_module" "example" { + organization = "%{org_id}" + display_name = "tf_test_custom_module%{random_suffix}" + enablement_state = "ENABLED" + type="CONFIGURABLE_BAD_IP" + config = < Date: Fri, 1 Dec 2023 08:57:24 -0800 Subject: [PATCH 045/107] fixed TestAccGKEHub2Fleet_gkehubFleetBasicExample_update in replaying (#9552) --- .../services/gkehub2/resource_gke_hub_fleet_test.go.erb | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb index b25e1b57789a..d0f91aca472a 100755 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb @@ -97,6 +97,7 @@ resource "google_project_service" "gkehub" { project = google_project.project.project_id service = "gkehub.googleapis.com" disable_on_destroy = false + depends_on = [google_project_service.anthos] } resource "google_project_service" "anthos" { From 95bc4cc1c10e7ed012f9f67eb2e876d796cdf30d Mon Sep 17 00:00:00 2001 From: Khaled Hamed Date: Fri, 1 Dec 2023 18:47:18 +0100 Subject: [PATCH 046/107] Allow updating DNSConfig in-place (#9446) * Allow updating DNSConfig in-place * leave DNS_SCOPE_UNSPECIFIED as default for cluster_dns_scope * Revert expandDnsConfig() return change * Add DNSConfig update test step --- .../resource_container_cluster.go.erb | 17 ++++++++++++++- ...esource_container_cluster_migratev1.go.erb | 1 - .../resource_container_cluster_test.go.erb | 21 +++++++++++++------ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index 58ea973c8eda..82362f9b6e4c 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -2005,7 +2005,6 @@ func ResourceContainerCluster() *schema.Resource { Type: schema.TypeList, Optional: true, MaxItems: 1, - ForceNew: true, DiffSuppressFunc: suppressDiffForAutopilot, Description: `Configuration for Cloud DNS for Kubernetes Engine.`, Elem: &schema.Resource{ @@ -2956,6 +2955,22 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er log.Printf("[INFO] GKE cluster %s's cluster-wide autoscaling has been updated", d.Id()) } + if d.HasChange("dns_config") { + req := &container.UpdateClusterRequest{ + Update: &container.ClusterUpdate{ + DesiredDnsConfig: expandDnsConfig(d.Get("dns_config")), + }, + } + + updateF := updateFunc(req, "updating GKE cluster DNSConfig") + // Call update serially. + if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { + return err + } + + log.Printf("[INFO] GKE cluster %s's DNSConfig has been updated", d.Id()) + } + if d.HasChange("allow_net_admin") { allowed := d.Get("allow_net_admin").(bool) req := &container.UpdateClusterRequest{ diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb index 5e536d8b591b..2bce542a3925 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_migratev1.go.erb @@ -1793,7 +1793,6 @@ func resourceContainerClusterResourceV1() *schema.Resource { Type: schema.TypeList, Optional: true, MaxItems: 1, - ForceNew: true, DiffSuppressFunc: suppressDiffForAutopilot, Description: `Configuration for Cloud DNS for Kubernetes Engine.`, Elem: &schema.Resource{ diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index 8bb072c5bcae..b5ee59312822 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -4078,13 +4078,22 @@ func TestAccContainerCluster_withDNSConfig(t *testing.T) { ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_basic(clusterName, networkName, subnetworkName), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"deletion_protection"}, + }, { Config: testAccContainerCluster_withDNSConfig(clusterName, "CLOUD_DNS", domainName, "VPC_SCOPE", networkName, subnetworkName), }, { - ResourceName: "google_container_cluster.with_dns_config", - ImportState: true, - ImportStateVerify: true, + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{"deletion_protection"}, }, }, @@ -8398,9 +8407,9 @@ resource "google_container_cluster" "with_autopilot" { func testAccContainerCluster_withDNSConfig(clusterName, clusterDns, clusterDnsDomain, clusterDnsScope, networkName, subnetworkName string) string { return fmt.Sprintf(` -resource "google_container_cluster" "with_dns_config" { - name = "%s" - location = "us-central1-f" +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" initial_node_count = 1 dns_config { cluster_dns = "%s" From 3dca09e87444edae0fc05abf6936ebbff3145dbb Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Fri, 1 Dec 2023 10:31:41 -0800 Subject: [PATCH 047/107] document Cloud Identity Premium Plan needed for our test environment (#9489) --- .ci/infra/terraform/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/infra/terraform/README.md b/.ci/infra/terraform/README.md index 942219f6e9ab..99a467952681 100644 --- a/.ci/infra/terraform/README.md +++ b/.ci/infra/terraform/README.md @@ -47,6 +47,7 @@ After applying this configuration: - Add a new test user in the Google Workspace Admin Console: https://admin.google.com/ac/users - Create a `support@` group in the Google Workspace Admin Console, add new service account as a member, and make it an owner - Enroll in Cloud Armor Managed Protection Plus tier +- Add Cloud Identity Premium Plan to the Google Workspace domain Quotas that will need to be adjusted to support all tests: - Project quota for the new service account From 87e3546280174e47e7816596162f2a9148d25062 Mon Sep 17 00:00:00 2001 From: Daniel Marzini <44803752+danielmarzini@users.noreply.github.com> Date: Fri, 1 Dec 2023 19:53:01 +0100 Subject: [PATCH 048/107] Promoting GKE Autoscaling Profiles to GA (#9558) --- .../services/container/resource_container_cluster.go.erb | 6 ------ .../container/resource_container_cluster_test.go.erb | 8 ++------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb index 82362f9b6e4c..8b9fa8414480 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster.go.erb @@ -770,7 +770,6 @@ func ResourceContainerCluster() *schema.Resource { }, }, }, - <% unless version == 'ga' -%> "autoscaling_profile": { Type: schema.TypeString, Default: "BALANCED", @@ -779,7 +778,6 @@ func ResourceContainerCluster() *schema.Resource { ValidateFunc: validation.StringInSlice([]string{"BALANCED", "OPTIMIZE_UTILIZATION"}, false), Description: `Configuration options for the Autoscaling profile feature, which lets you choose whether the cluster autoscaler should optimize for resource utilization or resource availability when deciding to remove nodes from a cluster. Can be BALANCED or OPTIMIZE_UTILIZATION. Defaults to BALANCED.`, }, - <% end -%> }, }, }, @@ -4573,9 +4571,7 @@ func expandClusterAutoscaling(configured interface{}, d *schema.ResourceData) *c return &container.ClusterAutoscaling{ EnableNodeAutoprovisioning: config["enabled"].(bool), ResourceLimits: resourceLimits, - <% unless version == 'ga' -%> AutoscalingProfile: config["autoscaling_profile"].(string), - <% end -%> AutoprovisioningNodePoolDefaults: expandAutoProvisioningDefaults(config["auto_provisioning_defaults"], d), } } @@ -5810,9 +5806,7 @@ func flattenClusterAutoscaling(a *container.ClusterAutoscaling) []map[string]int } else { r["enabled"] = false } - <% unless version == 'ga' -%> r["autoscaling_profile"] = a.AutoscalingProfile - <% end -%> return []map[string]interface{}{r} } diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index b5ee59312822..2d04467b5c0f 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -3244,10 +3244,6 @@ func TestAccContainerCluster_withSoleTenantGroup(t *testing.T) { }) } -<% unless version == 'ga' -%> -// consider merging this test with TestAccContainerCluster_nodeAutoprovisioningDefaults -// once the feature is GA - func TestAccContainerCluster_withAutoscalingProfile(t *testing.T) { t.Parallel() clusterName := fmt.Sprintf("cluster-test-%s", acctest.RandString(t, 10)) @@ -3304,6 +3300,8 @@ func TestAccContainerCluster_withInvalidAutoscalingProfile(t *testing.T) { }) } +<% unless version == 'ga' -%> + func TestAccContainerCluster_sharedVpc(t *testing.T) { // Multiple fine-grained resources acctest.SkipIfVcr(t) @@ -6425,7 +6423,6 @@ resource "google_container_cluster" "with_node_pool" { `, cluster, nodePool, networkName, subnetworkName) } -<% unless version == 'ga' -%> func testAccContainerCluster_withAutoscalingProfile(cluster, autoscalingProfile, networkName, subnetworkName string) string { config := fmt.Sprintf(` resource "google_container_cluster" "autoscaling_with_profile" { @@ -6444,7 +6441,6 @@ resource "google_container_cluster" "autoscaling_with_profile" { `, cluster, autoscalingProfile, networkName, subnetworkName) return config } -<% end -%> func testAccContainerCluster_autoprovisioning(cluster, networkName, subnetworkName string, autoprovisioning, withNetworkTag bool) string { config := fmt.Sprintf(` From c9277a4c175155395f5873318b39c831c6309cbc Mon Sep 17 00:00:00 2001 From: Feng Zhe Date: Fri, 1 Dec 2023 11:25:17 -0800 Subject: [PATCH 049/107] docs: fix a wrong link. It should point to the one for PostgreSQL. (#9539) --- .../website/docs/r/sql_database_instance.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown index 67b1c0a27da3..027776ab0922 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown @@ -374,7 +374,7 @@ This setting can be updated, but it cannot be removed after it is set. * `require_ssl` - (Optional) Whether SSL connections over IP are enforced or not. To change this field, also set the corresponding value in `ssl_mode`. * `ssl_mode` - (Optional) Specify how SSL connection should be enforced in DB connections. This field provides more SSL enforcment options compared to `require_ssl`. To change this field, also set the correspoding value in `require_ssl`. - * For PostgreSQL instances, the value pairs are listed in the [API reference doc](https://cloud.google.com/sql/docs/mysql/admin-api/rest/v1beta4/instances#ipconfiguration) for `ssl_mode` field. + * For PostgreSQL instances, the value pairs are listed in the [API reference doc](https://cloud.google.com/sql/docs/postgres/admin-api/rest/v1beta4/instances#ipconfiguration) for `ssl_mode` field. * For MySQL instances, use the same value pairs as the PostgreSQL instances. * For SQL Server instances, set it to `ALLOW_UNENCRYPTED_AND_ENCRYPTED` when `require_ssl=false` and `ENCRYPTED_ONLY` otherwise. From 30d3f116bb169f721ac0b58e772d07c5bce289f0 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 1 Dec 2023 11:33:07 -0800 Subject: [PATCH 050/107] Remove usage of resource_definition (#9553) * Remove usage of resource_definition * Update mmv1/products/identityplatform/ProjectDefaultConfig.yaml Co-authored-by: Stephen Lewis (Burrows) --------- Co-authored-by: Stephen Lewis (Burrows) --- .../identityplatform/ProjectDefaultConfig.yaml | 6 +++++- mmv1/products/secretmanager/SecretVersion.yaml | 6 +++--- .../terraform/constants/secret_version.go.erb | 12 ------------ .../secret_version.go.erb | 9 +++++++-- ...rm_project_default_config_deprecation.go.erb | 17 ----------------- 5 files changed, 15 insertions(+), 35 deletions(-) delete mode 100644 mmv1/templates/terraform/constants/secret_version.go.erb rename mmv1/templates/terraform/{resource_definition => custom_update}/secret_version.go.erb (76%) delete mode 100644 mmv1/templates/terraform/resource_definition/identity_platform_project_default_config_deprecation.go.erb diff --git a/mmv1/products/identityplatform/ProjectDefaultConfig.yaml b/mmv1/products/identityplatform/ProjectDefaultConfig.yaml index 908d324f94c7..03873dceb91d 100644 --- a/mmv1/products/identityplatform/ProjectDefaultConfig.yaml +++ b/mmv1/products/identityplatform/ProjectDefaultConfig.yaml @@ -21,9 +21,13 @@ description: | There is no persistent data associated with this resource. create_verb: :PATCH delete_verb: :PATCH +deprecation_message: >- + `google_identity_platform_config` is deprecated and will be removed in the next major release + of the provider. Use the `google_identity_platform_config` resource instead. It contains a more + comprehensive list of fields, and was created before `google_identity_platform_project_default_config` + was added. custom_code: !ruby/object:Provider::Terraform::CustomCode test_check_destroy: templates/terraform/custom_check_destroy/identity_platform_project_default_config.go.erb - resource_definition: templates/terraform/resource_definition/identity_platform_project_default_config_deprecation.go.erb docs: !ruby/object:Provider::Terraform::Docs warning: | If you are using User ADCs (Application Default Credentials) with this resource, diff --git a/mmv1/products/secretmanager/SecretVersion.yaml b/mmv1/products/secretmanager/SecretVersion.yaml index 7170c3e426bc..0161b2e6d0d3 100644 --- a/mmv1/products/secretmanager/SecretVersion.yaml +++ b/mmv1/products/secretmanager/SecretVersion.yaml @@ -18,7 +18,6 @@ self_link: '{{name}}' create_url: '{{secret}}:addVersion' delete_url: '{{name}}:destroy' delete_verb: :POST -immutable: true description: | A secret version resource. skip_sweeper: true @@ -59,9 +58,8 @@ import_format: ['projects/{{%project}}/secrets/{{%secret_id}}/versions/{{%version}}'] custom_code: !ruby/object:Provider::Terraform::CustomCode post_create: templates/terraform/post_create/secret_version.go.erb - constants: templates/terraform/constants/secret_version.go.erb custom_import: templates/terraform/custom_import/secret_version.go.erb - resource_definition: templates/terraform/resource_definition/secret_version.go.erb + custom_update: templates/terraform/custom_update/secret_version.go.erb decoder: templates/terraform/decoders/treat_destroyed_state_as_gone.erb pre_delete: templates/terraform/pre_delete/secret_version_deletion_policy.go.erb pre_read: templates/terraform/pre_read/secret_version_is_secret_data_base64.go.erb @@ -91,6 +89,7 @@ parameters: resource: Secret imports: name required: true + immutable: true description: | Secret Manager secret resource properties: @@ -138,4 +137,5 @@ properties: required: true description: The secret data. Must be no larger than 64KiB. sensitive: true + immutable: true custom_expand: templates/terraform/custom_expand/secret_version_secret_data.go.erb diff --git a/mmv1/templates/terraform/constants/secret_version.go.erb b/mmv1/templates/terraform/constants/secret_version.go.erb deleted file mode 100644 index 0881353f43ca..000000000000 --- a/mmv1/templates/terraform/constants/secret_version.go.erb +++ /dev/null @@ -1,12 +0,0 @@ -<% unless compiler == "terraformgoogleconversion-codegen" -%> -func resourceSecretManagerSecretVersionUpdate(d *schema.ResourceData, meta interface{}) error { - config := meta.(*transport_tpg.Config) - - _, err := expandSecretManagerSecretVersionEnabled(d.Get("enabled"), d, config) - if err != nil { - return err - } - - return resourceSecretManagerSecretVersionRead(d, meta) -} -<% end -%> diff --git a/mmv1/templates/terraform/resource_definition/secret_version.go.erb b/mmv1/templates/terraform/custom_update/secret_version.go.erb similarity index 76% rename from mmv1/templates/terraform/resource_definition/secret_version.go.erb rename to mmv1/templates/terraform/custom_update/secret_version.go.erb index d07bf08a4b29..82de0d487efb 100644 --- a/mmv1/templates/terraform/resource_definition/secret_version.go.erb +++ b/mmv1/templates/terraform/custom_update/secret_version.go.erb @@ -1,5 +1,5 @@ <%# The license inside this block applies to this file. - # Copyright 2020 Google Inc. + # Copyright 2023 Google Inc. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -12,4 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -%> -Update: resourceSecretManagerSecretVersionUpdate, +_, err := expandSecretManagerSecretVersionEnabled(d.Get("enabled"), d, config) +if err != nil { + return err +} + +return resourceSecretManagerSecretVersionRead(d, meta) \ No newline at end of file diff --git a/mmv1/templates/terraform/resource_definition/identity_platform_project_default_config_deprecation.go.erb b/mmv1/templates/terraform/resource_definition/identity_platform_project_default_config_deprecation.go.erb deleted file mode 100644 index 9bdf1b6ba8eb..000000000000 --- a/mmv1/templates/terraform/resource_definition/identity_platform_project_default_config_deprecation.go.erb +++ /dev/null @@ -1,17 +0,0 @@ -<%# The license inside this block applies to this file. - # Copyright 2023 Google Inc. - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. --%> -DeprecationMessage: "Deprecated. Use the `google_identity_platform_config` resource instead. " + - "It contains a more comprehensive list of fields, and was created before " + - "`google_identity_platform_project_default_config` was added.", From 1ea0673f5cc562fca1d3517ffc998af062d68442 Mon Sep 17 00:00:00 2001 From: Zach Berger Date: Fri, 1 Dec 2023 14:17:14 -0800 Subject: [PATCH 051/107] Add Logging Settings datasources. (#9526) Co-authored-by: Riley Karson --- .../provider/provider_mmv1_resources.go.erb | 3 + ...a_source_google_logging_folder_settings.go | 100 ++++++++++++++++++ ...rce_google_logging_folder_settings_test.go | 46 ++++++++ ...ce_google_logging_organization_settings.go | 100 ++++++++++++++++++ ...ogle_logging_organization_settings_test.go | 40 +++++++ ..._source_google_logging_project_settings.go | 99 +++++++++++++++++ ...ce_google_logging_project_settings_test.go | 54 ++++++++++ .../d/logging_folder_settings.html.markdown | 61 +++++++++++ ...ogging_organization_settings.html.markdown | 61 +++++++++++ .../d/logging_project_settings.html.markdown | 61 +++++++++++ 10 files changed, 625 insertions(+) create mode 100644 mmv1/third_party/terraform/services/logging/data_source_google_logging_folder_settings.go create mode 100644 mmv1/third_party/terraform/services/logging/data_source_google_logging_folder_settings_test.go create mode 100644 mmv1/third_party/terraform/services/logging/data_source_google_logging_organization_settings.go create mode 100644 mmv1/third_party/terraform/services/logging/data_source_google_logging_organization_settings_test.go create mode 100644 mmv1/third_party/terraform/services/logging/data_source_google_logging_project_settings.go create mode 100644 mmv1/third_party/terraform/services/logging/data_source_google_logging_project_settings_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/logging_folder_settings.html.markdown create mode 100644 mmv1/third_party/terraform/website/docs/d/logging_organization_settings.html.markdown create mode 100644 mmv1/third_party/terraform/website/docs/d/logging_project_settings.html.markdown diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 1e22b6979c63..d2a58b745435 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -139,7 +139,10 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_folder": resourcemanager.DataSourceGoogleFolder(), "google_folders": resourcemanager.DataSourceGoogleFolders(), "google_folder_organization_policy": resourcemanager.DataSourceGoogleFolderOrganizationPolicy(), + "google_logging_folder_settings": logging.DataSourceGoogleLoggingFolderSettings(), + "google_logging_organization_settings": logging.DataSourceGoogleLoggingOrganizationSettings(), "google_logging_project_cmek_settings": logging.DataSourceGoogleLoggingProjectCmekSettings(), + "google_logging_project_settings": logging.DataSourceGoogleLoggingProjectSettings(), "google_logging_sink": logging.DataSourceGoogleLoggingSink(), "google_monitoring_notification_channel": monitoring.DataSourceMonitoringNotificationChannel(), "google_monitoring_cluster_istio_service": monitoring.DataSourceMonitoringServiceClusterIstio(), diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_folder_settings.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_folder_settings.go new file mode 100644 index 000000000000..f269d4e226cf --- /dev/null +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_folder_settings.go @@ -0,0 +1,100 @@ +package logging + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleLoggingFolderSettings() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleLoggingFolderSettingsRead, + Schema: map[string]*schema.Schema{ + "folder": { + Type: schema.TypeString, + Required: true, + Description: `The folder for which to retrieve settings.`, + }, + "disable_default_sink": { + Type: schema.TypeBool, + Computed: true, + Description: `If set to true, the _Default sink in newly created projects and folders will created in a disabled state. This can be used to automatically disable log storage if there is already an aggregated sink configured in the hierarchy. The _Default sink can be re-enabled manually if needed.`, + }, + "kms_key_name": { + Type: schema.TypeString, + Computed: true, + Description: `The resource name for the configured Cloud KMS key. + KMS key name format: + "projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]" + To enable CMEK for the bucket, set this field to a valid kmsKeyName for which the associated service account has the required cloudkms.cryptoKeyEncrypterDecrypter roles assigned for the key. + The Cloud KMS key used by the bucket can be updated by changing the kmsKeyName to a new valid key name. Encryption operations that are in progress will be completed with the key that was in use when they started. Decryption operations will be completed using the key that was used at the time of encryption unless access to that key has been revoked. + See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information.`, + }, + "storage_location": { + Type: schema.TypeString, + Computed: true, + Description: `The storage location that Cloud Logging will use to create new resources when a location is needed but not explicitly provided.`, + }, + "kms_service_account_id": { + Type: schema.TypeString, + Computed: true, + Description: `The service account associated with a project for which CMEK will apply. + Before enabling CMEK for a logging bucket, you must first assign the cloudkms.cryptoKeyEncrypterDecrypter role to the service account associated with the project for which CMEK will apply. Use [v2.getCmekSettings](https://cloud.google.com/logging/docs/reference/v2/rest/v2/TopLevel/getCmekSettings#google.logging.v2.ConfigServiceV2.GetCmekSettings) to obtain the service account ID. + See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information.`, + }, + "logging_service_account_id": { + Type: schema.TypeString, + Computed: true, + Description: `The service account for the given container. Sinks use this service account as their writerIdentity if no custom service account is provided.`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The resource name of the CMEK settings.`, + }, + }, + } +} + +func dataSourceGoogleLoggingFolderSettingsRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + folder := d.Get("folder").(string) + res, err := config.NewLoggingClient(userAgent).Folders.GetSettings(fmt.Sprintf("folders/%s", folder)).Do() + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("LoggingFolderSettings %q", d.Id()), d.Id()) + } + + d.SetId(fmt.Sprintf("folders/%s/settings", folder)) + + if err := d.Set("folder", folder); err != nil { + return fmt.Errorf("Error reading FolderSettings: %s", err) + } + + if err := d.Set("name", res.Name); err != nil { + return fmt.Errorf("Error reading FolderSettings: %s", err) + } + if err := d.Set("disable_default_sink", res.DisableDefaultSink); err != nil { + return fmt.Errorf("Error reading FolderSettings: %s", err) + } + if err := d.Set("kms_key_name", res.KmsKeyName); err != nil { + return fmt.Errorf("Error reading FolderSettings: %s", err) + } + if err := d.Set("storage_location", res.StorageLocation); err != nil { + return fmt.Errorf("Error reading FolderSettings: %s", err) + } + if err := d.Set("kms_service_account_id", res.KmsServiceAccountId); err != nil { + return fmt.Errorf("Error reading FolderSettings: %s", err) + } + if err := d.Set("logging_service_account_id", res.LoggingServiceAccountId); err != nil { + return fmt.Errorf("Error reading FolderSettings: %s", err) + } + + return nil +} diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_folder_settings_test.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_folder_settings_test.go new file mode 100644 index 000000000000..fb2595b2eb9f --- /dev/null +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_folder_settings_test.go @@ -0,0 +1,46 @@ +package logging_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccLoggingFolderSettings_datasource(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "folder_name": "tf-test-" + acctest.RandString(t, 10), + "org_id": envvar.GetTestOrgFromEnv(t), + } + resourceName := "data.google_logging_folder_settings.settings" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccLoggingFolderSettings_datasource(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "kms_service_account_id"), + resource.TestCheckResourceAttrSet(resourceName, "logging_service_account_id"), + ), + }, + }, + }) +} + +func testAccLoggingFolderSettings_datasource(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_folder" "default" { + display_name = "%{folder_name}" + parent = "organizations/%{org_id}" +} + +data "google_logging_folder_settings" "settings" { + folder = google_folder.default.folder_id +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_organization_settings.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_organization_settings.go new file mode 100644 index 000000000000..ec8974fce840 --- /dev/null +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_organization_settings.go @@ -0,0 +1,100 @@ +package logging + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleLoggingOrganizationSettings() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleLoggingOrganizationSettingsRead, + Schema: map[string]*schema.Schema{ + "organization": { + Type: schema.TypeString, + Required: true, + Description: `The organization for which to retrieve settings.`, + }, + "disable_default_sink": { + Type: schema.TypeBool, + Computed: true, + Description: `If set to true, the _Default sink in newly created projects and folders will created in a disabled state. This can be used to automatically disable log storage if there is already an aggregated sink configured in the hierarchy. The _Default sink can be re-enabled manually if needed.`, + }, + "kms_key_name": { + Type: schema.TypeString, + Computed: true, + Description: `The resource name for the configured Cloud KMS key. + KMS key name format: + "projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]" + To enable CMEK for the bucket, set this field to a valid kmsKeyName for which the associated service account has the required cloudkms.cryptoKeyEncrypterDecrypter roles assigned for the key. + The Cloud KMS key used by the bucket can be updated by changing the kmsKeyName to a new valid key name. Encryption operations that are in progress will be completed with the key that was in use when they started. Decryption operations will be completed using the key that was used at the time of encryption unless access to that key has been revoked. + See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information.`, + }, + "storage_location": { + Type: schema.TypeString, + Computed: true, + Description: `The storage location that Cloud Logging will use to create new resources when a location is needed but not explicitly provided.`, + }, + "kms_service_account_id": { + Type: schema.TypeString, + Computed: true, + Description: `The service account associated with a project for which CMEK will apply. + Before enabling CMEK for a logging bucket, you must first assign the cloudkms.cryptoKeyEncrypterDecrypter role to the service account associated with the project for which CMEK will apply. Use [v2.getCmekSettings](https://cloud.google.com/logging/docs/reference/v2/rest/v2/TopLevel/getCmekSettings#google.logging.v2.ConfigServiceV2.GetCmekSettings) to obtain the service account ID. + See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information.`, + }, + "logging_service_account_id": { + Type: schema.TypeString, + Computed: true, + Description: `The service account for the given container. Sinks use this service account as their writerIdentity if no custom service account is provided.`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The resource name of the CMEK settings.`, + }, + }, + } +} + +func dataSourceGoogleLoggingOrganizationSettingsRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + organization := d.Get("organization").(string) + res, err := config.NewLoggingClient(userAgent).Organizations.GetSettings(fmt.Sprintf("organizations/%s", organization)).Do() + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("LoggingOrganizationSettings %q", d.Id()), d.Id()) + } + + d.SetId(fmt.Sprintf("organizations/%s/settings", organization)) + + if err := d.Set("organization", organization); err != nil { + return fmt.Errorf("Error reading OrganizationSettings: %s", err) + } + + if err := d.Set("name", res.Name); err != nil { + return fmt.Errorf("Error reading OrganizationSettings: %s", err) + } + if err := d.Set("disable_default_sink", res.DisableDefaultSink); err != nil { + return fmt.Errorf("Error reading OrganizationSettings: %s", err) + } + if err := d.Set("kms_key_name", res.KmsKeyName); err != nil { + return fmt.Errorf("Error reading OrganizationSettings: %s", err) + } + if err := d.Set("storage_location", res.StorageLocation); err != nil { + return fmt.Errorf("Error reading OrganizationSettings: %s", err) + } + if err := d.Set("kms_service_account_id", res.KmsServiceAccountId); err != nil { + return fmt.Errorf("Error reading OrganizationSettings: %s", err) + } + if err := d.Set("logging_service_account_id", res.LoggingServiceAccountId); err != nil { + return fmt.Errorf("Error reading OrganizationSettings: %s", err) + } + + return nil +} diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_organization_settings_test.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_organization_settings_test.go new file mode 100644 index 000000000000..23c003dcb501 --- /dev/null +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_organization_settings_test.go @@ -0,0 +1,40 @@ +package logging_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccLoggingOrganizationSettings_datasource(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + } + resourceName := "data.google_logging_organization_settings.settings" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccLoggingOrganizationSettings_datasource(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "kms_service_account_id"), + resource.TestCheckResourceAttrSet(resourceName, "logging_service_account_id"), + ), + }, + }, + }) +} + +func testAccLoggingOrganizationSettings_datasource(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_logging_organization_settings" "settings" { + organization = "%{org_id}" +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_settings.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_settings.go new file mode 100644 index 000000000000..c1ea05795889 --- /dev/null +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_settings.go @@ -0,0 +1,99 @@ +package logging + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleLoggingProjectSettings() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleLoggingProjectSettingsRead, + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Required: true, + Description: `The project for which to retrieve settings.`, + }, + "disable_default_sink": { + Type: schema.TypeBool, + Computed: true, + Description: `If set to true, the _Default sink in newly created projects and folders will created in a disabled state. This can be used to automatically disable log storage if there is already an aggregated sink configured in the hierarchy. The _Default sink can be re-enabled manually if needed.`, + }, + "kms_key_name": { + Type: schema.TypeString, + Computed: true, + Description: `The resource name for the configured Cloud KMS key. + KMS key name format: + "projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]" + To enable CMEK for the bucket, set this field to a valid kmsKeyName for which the associated service account has the required cloudkms.cryptoKeyEncrypterDecrypter roles assigned for the key. + The Cloud KMS key used by the bucket can be updated by changing the kmsKeyName to a new valid key name. Encryption operations that are in progress will be completed with the key that was in use when they started. Decryption operations will be completed using the key that was used at the time of encryption unless access to that key has been revoked. + See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information.`, + }, + "storage_location": { + Type: schema.TypeString, + Computed: true, + Description: `The storage location that Cloud Logging will use to create new resources when a location is needed but not explicitly provided.`, + }, + "kms_service_account_id": { + Type: schema.TypeString, + Computed: true, + Description: `The service account associated with a project for which CMEK will apply. + Before enabling CMEK for a logging bucket, you must first assign the cloudkms.cryptoKeyEncrypterDecrypter role to the service account associated with the project for which CMEK will apply. Use [v2.getCmekSettings](https://cloud.google.com/logging/docs/reference/v2/rest/v2/TopLevel/getCmekSettings#google.logging.v2.ConfigServiceV2.GetCmekSettings) to obtain the service account ID. + See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information.`, + }, + "logging_service_account_id": { + Type: schema.TypeString, + Computed: true, + Description: `The service account for the given container. Sinks use this service account as their writerIdentity if no custom service account is provided.`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The resource name of the CMEK settings.`, + }, + }, + } +} + +func dataSourceGoogleLoggingProjectSettingsRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + project := d.Get("project").(string) + res, err := config.NewLoggingClient(userAgent).Projects.GetSettings(fmt.Sprintf("projects/%s", project)).Do() + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("LoggingProjectSettings %q", d.Id()), d.Id()) + } + + d.SetId(fmt.Sprintf("projects/%s/settings", project)) + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading ProjectSettings: %s", err) + } + + if err := d.Set("name", res.Name); err != nil { + return fmt.Errorf("Error reading ProjectSettings: %s", err) + } + if err := d.Set("disable_default_sink", res.DisableDefaultSink); err != nil { + return fmt.Errorf("Error reading ProjectSettings: %s", err) + } + if err := d.Set("kms_key_name", res.KmsKeyName); err != nil { + return fmt.Errorf("Error reading ProjectSettings: %s", err) + } + if err := d.Set("storage_location", res.StorageLocation); err != nil { + return fmt.Errorf("Error reading ProjectSettings: %s", err) + } + if err := d.Set("kms_service_account_id", res.KmsServiceAccountId); err != nil { + return fmt.Errorf("Error reading ProjectSettings: %s", err) + } + if err := d.Set("logging_service_account_id", res.LoggingServiceAccountId); err != nil { + return fmt.Errorf("Error reading ProjectSettings: %s", err) + } + return nil +} diff --git a/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_settings_test.go b/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_settings_test.go new file mode 100644 index 000000000000..22f088030a28 --- /dev/null +++ b/mmv1/third_party/terraform/services/logging/data_source_google_logging_project_settings_test.go @@ -0,0 +1,54 @@ +package logging_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccLoggingProjectSettings_datasource(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project_name": "tf-test-" + acctest.RandString(t, 10), + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + } + resourceName := "data.google_logging_project_settings.settings" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccLoggingProjectSettings_datasource(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "kms_service_account_id"), + resource.TestCheckResourceAttrSet(resourceName, "logging_service_account_id"), + ), + }, + }, + }) +} + +func testAccLoggingProjectSettings_datasource(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_project" "default" { + project_id = "%{project_name}" + name = "%{project_name}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + } + + resource "google_project_service" "logging_service" { + project = google_project.default.project_id + service = "logging.googleapis.com" + } + + data "google_logging_project_settings" "settings" { + project = google_project_service.logging_service.project + } +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/logging_folder_settings.html.markdown b/mmv1/third_party/terraform/website/docs/d/logging_folder_settings.html.markdown new file mode 100644 index 000000000000..bf97e1c52019 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/logging_folder_settings.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "Cloud (Stackdriver) Logging" +description: |- + Describes the settings associated with a folder. +--- + +# google\_logging\_folder\_settings + +Describes the settings associated with a folder. + +To get more information about LoggingFolderSettings, see: + +* [API documentation](https://cloud.google.com/logging/docs/reference/v2/rest/v2/folders/getSettings) +* [Configure default settings for organizations and folders](https://cloud.google.com/logging/docs/default-settings). + +## Example Usage - Logging Folder Settings Basic + +```hcl +data "google_logging_folder_settings" "settings" { + folder = "my-folder-name" +} +``` + +## Argument Reference + +The following arguments are supported: + +- - - + +* `folder` - (Required) The ID of the folder for which to retrieve settings. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `folders/{{folder}}/settings` + +* `name` - The resource name of the settings. + +* `kms_key_name` - The resource name for the configured Cloud KMS key. +KMS key name format: +`'projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]'` +To enable CMEK for the bucket, set this field to a valid kmsKeyName for which the associated service account has the required cloudkms.cryptoKeyEncrypterDecrypter roles assigned for the key. +The Cloud KMS key used by the bucket can be updated by changing the kmsKeyName to a new valid key name. Encryption operations that are in progress will be completed with the key that was in use when they started. Decryption operations will be completed using the key that was used at the time of encryption unless access to that key has been revoked. +See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information. + +* `kms_key_version_name` - The CryptoKeyVersion resource name for the configured Cloud KMS key. +KMS key name format: +`'projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]/cryptoKeyVersions/[VERSION]'` +For example: +"projects/my-project/locations/us-central1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1" +This is a read-only field used to convey the specific configured CryptoKeyVersion of kms_key that has been configured. It will be populated in cases where the CMEK settings are bound to a single key version. + +* `kms_service_account_id` - The service account associated with a project for which CMEK will apply. +Before enabling CMEK for a logging bucket, you must first assign the cloudkms.cryptoKeyEncrypterDecrypter role to the service account associated with the project for which CMEK will apply. See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information. + +* `logging_service_account_id` - The service account for the given container. Sinks use this service account as their writerIdentity if no custom service account is provided. + +* `disable_default_sink` - If set to true, the _Default sink in newly created projects and folders will created in a disabled state. This can be used to automatically disable log storage if there is already an aggregated sink configured in the hierarchy. The _Default sink can be re-enabled manually if needed. + +* `storage_location` - The storage location that Cloud Logging will use to create new resources when a location is needed but not explicitly provided. diff --git a/mmv1/third_party/terraform/website/docs/d/logging_organization_settings.html.markdown b/mmv1/third_party/terraform/website/docs/d/logging_organization_settings.html.markdown new file mode 100644 index 000000000000..bb3f82828da0 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/logging_organization_settings.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "Cloud (Stackdriver) Logging" +description: |- + Describes the settings associated with a organization. +--- + +# google\_logging\_organization\_settings + +Describes the settings associated with a organization. + +To get more information about LoggingOrganizationSettings, see: + +* [API documentation](https://cloud.google.com/logging/docs/reference/v2/rest/v2/organizations/getSettings) +* [Configure default settings for organizations and folders](https://cloud.google.com/logging/docs/default-settings). + +## Example Usage - Logging Organization Settings Basic + +```hcl +data "google_logging_organization_settings" "settings" { + organization = "my-organization-name" +} +``` + +## Argument Reference + +The following arguments are supported: + +- - - + +* `organization` - (Required) The ID of the organization for which to retrieve settings. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `organizations/{{organization}}/settings` + +* `name` - The resource name of the settings. + +* `kms_key_name` - The resource name for the configured Cloud KMS key. +KMS key name format: +`'projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]'` +To enable CMEK for the bucket, set this field to a valid kmsKeyName for which the associated service account has the required cloudkms.cryptoKeyEncrypterDecrypter roles assigned for the key. +The Cloud KMS key used by the bucket can be updated by changing the kmsKeyName to a new valid key name. Encryption operations that are in progress will be completed with the key that was in use when they started. Decryption operations will be completed using the key that was used at the time of encryption unless access to that key has been revoked. +See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information. + +* `kms_key_version_name` - The CryptoKeyVersion resource name for the configured Cloud KMS key. +KMS key name format: +`'projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]/cryptoKeyVersions/[VERSION]'` +For example: +"projects/my-project/locations/us-central1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1" +This is a read-only field used to convey the specific configured CryptoKeyVersion of kms_key that has been configured. It will be populated in cases where the CMEK settings are bound to a single key version. + +* `kms_service_account_id` - The service account associated with a project for which CMEK will apply. +Before enabling CMEK for a logging bucket, you must first assign the cloudkms.cryptoKeyEncrypterDecrypter role to the service account associated with the project for which CMEK will apply. See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information. + +* `logging_service_account_id` - The service account for the given container. Sinks use this service account as their writerIdentity if no custom service account is provided. + +* `disable_default_sink` - If set to true, the _Default sink in newly created projects and folders will created in a disabled state. This can be used to automatically disable log storage if there is already an aggregated sink configured in the hierarchy. The _Default sink can be re-enabled manually if needed. + +* `storage_location` - The storage location that Cloud Logging will use to create new resources when a location is needed but not explicitly provided. diff --git a/mmv1/third_party/terraform/website/docs/d/logging_project_settings.html.markdown b/mmv1/third_party/terraform/website/docs/d/logging_project_settings.html.markdown new file mode 100644 index 000000000000..615929c5fbaa --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/logging_project_settings.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "Cloud (Stackdriver) Logging" +description: |- + Describes the settings associated with a project. +--- + +# google\_logging\_project\_settings + +Describes the settings associated with a project. + +To get more information about LoggingProjectSettings, see: + +* [API documentation](https://cloud.google.com/logging/docs/reference/v2/rest/v2/projects/getSettings) +* [Configure default settings for organizations and folders](https://cloud.google.com/logging/docs/default-settings). + +## Example Usage - Logging Project Settings Basic + +```hcl +data "google_logging_project_settings" "settings" { + project = "my-project-name" +} +``` + +## Argument Reference + +The following arguments are supported: + +- - - + +* `project` - (Required) The ID of the project for which to retrieve settings. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/settings` + +* `name` - The resource name of the settings. + +* `kms_key_name` - The resource name for the configured Cloud KMS key. +KMS key name format: +`'projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]'` +To enable CMEK for the bucket, set this field to a valid kmsKeyName for which the associated service account has the required cloudkms.cryptoKeyEncrypterDecrypter roles assigned for the key. +The Cloud KMS key used by the bucket can be updated by changing the kmsKeyName to a new valid key name. Encryption operations that are in progress will be completed with the key that was in use when they started. Decryption operations will be completed using the key that was used at the time of encryption unless access to that key has been revoked. +See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information. + +* `kms_key_version_name` - The CryptoKeyVersion resource name for the configured Cloud KMS key. +KMS key name format: +`'projects/[PROJECT_ID]/locations/[LOCATION]/keyRings/[KEYRING]/cryptoKeys/[KEY]/cryptoKeyVersions/[VERSION]'` +For example: +"projects/my-project/locations/us-central1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1" +This is a read-only field used to convey the specific configured CryptoKeyVersion of kms_key that has been configured. It will be populated in cases where the CMEK settings are bound to a single key version. + +* `kms_service_account_id` - The service account associated with a project for which CMEK will apply. +Before enabling CMEK for a logging bucket, you must first assign the cloudkms.cryptoKeyEncrypterDecrypter role to the service account associated with the project for which CMEK will apply. See [Enabling CMEK for Logging Buckets](https://cloud.google.com/logging/docs/routing/managed-encryption-storage) for more information. + +* `logging_service_account_id` - The service account for the given container. Sinks use this service account as their writerIdentity if no custom service account is provided. + +* `disable_default_sink` - If set to true, the _Default sink in newly created projects and folders will created in a disabled state. This can be used to automatically disable log storage if there is already an aggregated sink configured in the hierarchy. The _Default sink can be re-enabled manually if needed. + +* `storage_location` - The storage location that Cloud Logging will use to create new resources when a location is needed but not explicitly provided. From 679194713e7699c7f5cca998a2c376a210f64a9e Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 4 Dec 2023 09:31:34 -0800 Subject: [PATCH 052/107] Remove obsolete methods and files (#9564) --- mmv1/api/compiler.rb | 3 - mmv1/api/resource.rb | 10 - mmv1/compile/core.rb | 5 - mmv1/provider/terraform.rb | 18 -- mmv1/templates/async.yaml.erb | 18 -- mmv1/templates/license.erb | 12 - mmv1/templates/stackdriver.json | 421 -------------------------------- 7 files changed, 487 deletions(-) delete mode 100644 mmv1/templates/async.yaml.erb delete mode 100644 mmv1/templates/license.erb delete mode 100644 mmv1/templates/stackdriver.json diff --git a/mmv1/api/compiler.rb b/mmv1/api/compiler.rb index 9e0eca812610..27a139afbc81 100644 --- a/mmv1/api/compiler.rb +++ b/mmv1/api/compiler.rb @@ -15,7 +15,6 @@ require 'api/product' require 'api/resource' require 'api/type' -require 'compile/core' require 'google/yaml_validator' module Api @@ -23,8 +22,6 @@ module Api class Compiler include Compile::Core - attr_reader :product - def initialize(catalog) @catalog = catalog end diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 4ccec699fb8d..1fd7d2a9711b 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -619,16 +619,6 @@ def collection_uri @base_url end - def async_operation_url - [@__product.base_url, async_operation_uri].flatten.join - end - - def async_operation_uri - raise 'Not an async resource' if async.nil? - - async.operation.base_url - end - def full_create_url [@__product.base_url, create_uri].flatten.join end diff --git a/mmv1/compile/core.rb b/mmv1/compile/core.rb index e90cc9c73462..2bdcf89f18be 100644 --- a/mmv1/compile/core.rb +++ b/mmv1/compile/core.rb @@ -16,11 +16,6 @@ require 'ostruct' module Compile - # Unique ID for the Google libraries to be compiled/used by modules - module Libraries - NETWORK = 'network'.freeze - end - # Helper functions to aid compiling and including files module Core def compiler diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index f409f0c84967..20c513bf5d6e 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -619,28 +619,10 @@ def titlelize_property(property) # that should not be exposed outside the object hierarchy. private - def generate_requires(properties, requires = []) - requires.concat(properties.collect(&:requires)) - end - def provider_name self.class.name.split('::').last.downcase end - # Determines the copyright year. If the file already exists we'll attempt to - # recognize the copyright year, and if it finds it will keep it. - def effective_copyright_year(out_file) - copyright_mask = /# Copyright (?[0-9-]*) Google Inc./ - if File.exist?(out_file) - first_line = File.read(out_file).split("\n") - .select { |l| copyright_mask.match(l) } - .first - matcher = copyright_mask.match(first_line) - return matcher[:year] unless matcher.nil? - end - Time.now.year - end - # Adapted from the method used in templating # See: mmv1/compile/core.rb def comment_block(text, lang) diff --git a/mmv1/templates/async.yaml.erb b/mmv1/templates/async.yaml.erb deleted file mode 100644 index 568a5b7516ae..000000000000 --- a/mmv1/templates/async.yaml.erb +++ /dev/null @@ -1,18 +0,0 @@ -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - kind: 'sql#operation' - path: 'name' - base_url: 'projects/{{project}}/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' diff --git a/mmv1/templates/license.erb b/mmv1/templates/license.erb deleted file mode 100644 index 2fd5d2f92d29..000000000000 --- a/mmv1/templates/license.erb +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright <%= effective_copyright_year(out_file) -%> 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. diff --git a/mmv1/templates/stackdriver.json b/mmv1/templates/stackdriver.json deleted file mode 100644 index 33430fbacff5..000000000000 --- a/mmv1/templates/stackdriver.json +++ /dev/null @@ -1,421 +0,0 @@ -{ - "parameters": { - "key": { - "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.", - "type": "string", - "location": "query" - }, - "access_token": { - "location": "query", - "description": "OAuth access token.", - "type": "string" - }, - "upload_protocol": { - "location": "query", - "description": "Upload protocol for media (e.g. \"raw\", \"multipart\").", - "type": "string" - }, - "prettyPrint": { - "location": "query", - "description": "Returns response with indentations and line breaks.", - "type": "boolean", - "default": "true" - }, - "quotaUser": { - "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.", - "type": "string", - "location": "query" - }, - "uploadType": { - "location": "query", - "description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").", - "type": "string" - }, - "fields": { - "type": "string", - "location": "query", - "description": "Selector specifying which fields to include in a partial response." - }, - "$.xgafv": { - "description": "V1 error format.", - "type": "string", - "enumDescriptions": [ - "v1 error format", - "v2 error format" - ], - "location": "query", - "enum": [ - "1", - "2" - ] - }, - "oauth_token": { - "description": "OAuth 2.0 token for the current user.", - "type": "string", - "location": "query" - }, - "callback": { - "description": "JSONP", - "type": "string", - "location": "query" - }, - "alt": { - "default": "json", - "enum": [ - "json", - "media", - "proto" - ], - "type": "string", - "enumDescriptions": [ - "Responses with Content-Type of application/json", - "Media download with context-dependent Content-Type", - "Responses with Content-Type of application/x-protobuf" - ], - "location": "query", - "description": "Data format for response." - } - }, - "version": "v2", - "baseUrl": "https://stackdriver.googleapis.com/", - "kind": "discovery#restDescription", - "description": "Provides users with programmatic access to Stackdriver endpoints that allow putting VM instances and other resources into maintenance mode.", - "servicePath": "", - "basePath": "", - "revision": "20200323", - "documentationLink": "https://cloud.google.com/stackdriver/docs/", - "id": "stackdriver:v2", - "discoveryVersion": "v1", - "version_module": true, - "schemas": { - "Status": { - "description": "The `Status` type defines a logical error model that is suitable for\ndifferent programming environments, including REST APIs and RPC APIs. It is\nused by [gRPC](https://github.com/grpc). Each `Status` message contains\nthree pieces of data: error code, error message, and error details.\n\nYou can find out more about this error model and how to work with it in the\n[API Design Guide](https://cloud.google.com/apis/design/errors).", - "type": "object", - "properties": { - "details": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": { - "type": "any", - "description": "Properties of the object. Contains field @type with type URL." - } - }, - "description": "A list of messages that carry the error details. There is a common set of\nmessage types for APIs to use." - }, - "code": { - "description": "The status code, which should be an enum value of google.rpc.Code.", - "format": "int32", - "type": "integer" - }, - "message": { - "description": "A developer-facing error message, which should be in English. Any\nuser-facing error message should be localized and sent in the\ngoogle.rpc.Status.details field, or localized by the client.", - "type": "string" - } - }, - "id": "Status" - }, - "Operation": { - "id": "Operation", - "description": "This resource represents a long-running operation that is the result of a\nnetwork API call.", - "type": "object", - "properties": { - "response": { - "description": "The normal response of the operation in case of success. If the original\nmethod returns no data on success, such as `Delete`, the response is\n`google.protobuf.Empty`. If the original method is standard\n`Get`/`Create`/`Update`, the response should be the resource. For other\nmethods, the response should have the type `XxxResponse`, where `Xxx`\nis the original method name. For example, if the original method name\nis `TakeSnapshot()`, the inferred response type is\n`TakeSnapshotResponse`.", - "type": "object", - "additionalProperties": { - "description": "Properties of the object. Contains field @type with type URL.", - "type": "any" - } - }, - "name": { - "description": "The server-assigned name, which is only unique within the same service that\noriginally returns it. If you use the default HTTP mapping, the\n`name` should be a resource name ending with `operations/{unique_id}`.", - "type": "string" - }, - "error": { - "$ref": "Status", - "description": "The error result of the operation in case of failure or cancellation." - }, - "metadata": { - "type": "object", - "additionalProperties": { - "type": "any", - "description": "Properties of the object. Contains field @type with type URL." - }, - "description": "Service-specific metadata associated with the operation. It typically\ncontains progress information and common metadata such as create time.\nSome services might not provide such metadata. Any method that returns a\nlong-running operation should document the metadata type, if any." - }, - "done": { - "description": "If the value is `false`, it means the operation is still in progress.\nIf `true`, the operation is completed, and either `error` or `response` is\navailable.", - "type": "boolean" - } - } - }, - "OperationMetadata": { - "id": "OperationMetadata", - "description": "Contains metadata for longrunning operations in the Stackdriver API.", - "type": "object", - "properties": { - "state": { - "enum": [ - "STATE_UNSPECIFIED", - "CREATED", - "RUNNING", - "DONE", - "CANCELLED" - ], - "description": "Current state of the batch operation.", - "type": "string", - "enumDescriptions": [ - "Invalid.", - "Request is received.", - "Request is actively being processed.", - "The batch processing is done.", - "The batch processing was cancelled." - ] - }, - "updateTime": { - "type": "string", - "description": "The time when the operation result was last updated.", - "format": "google-datetime" - }, - "createTime": { - "description": "The time when the batch request was received.", - "format": "google-datetime", - "type": "string" - } - } - }, - "MonitoredProject": { - "description": "A single cloud account being monitored within a Stackdriver account.", - "type": "object", - "properties": { - "projectNumber": { - "description": "Output only. The GCP-assigned project number.", - "format": "int64", - "type": "string" - }, - "createTime": { - "description": "Output only. The instant when this monitored project was created.", - "format": "google-datetime", - "type": "string" - }, - "updateTime": { - "description": "Output only. The instant when this monitored project was last updated.", - "format": "google-datetime", - "type": "string" - }, - "name": { - "description": "The resource name of the monitored project within a Stackdriver account.\nIncludes the host project id and monitored project id. On output it\nwill always contain the project number.\nExample: \u003ccode\u003eaccounts/my-project/projects/my-other-project\u003c/code\u003e", - "type": "string" - }, - "projectId": { - "description": "Output only. The GCP-assigned project id.\nExample: \u003ccode\u003eprojecty-project-101\u003c/code\u003e", - "type": "string" - }, - "organizationId": { - "description": "Optional, input only. The Id of the organization to hold the GCP Project\nfor a newly created monitored project.\nThis field is ignored if the GCP project already exists.", - "type": "string" - } - }, - "id": "MonitoredProject" - }, - "StackdriverAccount": { - "id": "StackdriverAccount", - "description": "A Workspace in Stackdriver Monitoring, which specifies one or more GCP\nprojects and zero or more AWS accounts to monitor together.\nOne GCP project acts as the Workspace's host.\nGCP projects and AWS accounts cannot be monitored until they are associated\nwith a Workspace.", - "type": "object", - "properties": { - "monitoredProjects": { - "description": "Output only. The GCP projects monitored in this Stackdriver account.", - "type": "array", - "items": { - "$ref": "MonitoredProject" - } - }, - "createTime": { - "type": "string", - "description": "Output only. The instant when this account was created.", - "format": "google-datetime" - }, - "hostProjectId": { - "description": "Output only. The GCP project id for the host project of this account.", - "type": "string" - }, - "updateTime": { - "description": "Output only. The instant when this account record was last updated.", - "format": "google-datetime", - "type": "string" - }, - "hostProjectNumber": { - "description": "Output only. The GCP project number for the host project of this account.", - "format": "int64", - "type": "string" - }, - "name": { - "description": "The resource name of the Stackdriver account, including the host project\nid or number. On output it will always be the host project number.\nExample: \u003ccode\u003eaccounts/[PROJECT_ID]\u003c/code\u003e or\n\u003ccode\u003eaccounts/[PROJECT_NUMBER]\u003c/code\u003e", - "type": "string" - }, - "organizationId": { - "description": "Optional, input only. The Id of the organization to hold the GCP Project\nfor a newly created Stackdriver account.\nThis field is ignored if the GCP project already exists.", - "type": "string" - } - } - } - }, - "protocol": "rest", - "icons": { - "x32": "http://www.google.com/images/icons/product/search-32.gif", - "x16": "http://www.google.com/images/icons/product/search-16.gif" - }, - "canonicalName": "Stackdriver", - "auth": { - "oauth2": { - "scopes": { - "https://www.googleapis.com/auth/monitoring": { - "description": "View and write monitoring data for all of your Google and third-party Cloud and API projects" - }, - "https://www.googleapis.com/auth/monitoring.write": { - "description": "Publish metric data to your Google Cloud projects" - }, - "https://www.googleapis.com/auth/cloud-platform": { - "description": "View and manage your data across Google Cloud Platform services" - }, - "https://www.googleapis.com/auth/monitoring.read": { - "description": "View monitoring data for all of your Google Cloud and third-party projects" - } - } - } - }, - "rootUrl": "https://stackdriver.googleapis.com/", - "ownerDomain": "google.com", - "name": "stackdriver", - "batchPath": "batch", - "mtlsRootUrl": "https://stackdriver.mtls.googleapis.com/", - "fullyEncodeReservedExpansion": true, - "title": "Stackdriver API", - "ownerName": "Google", - "resources": { - "accounts": { - "methods": { - "get": { - "httpMethod": "GET", - "parameterOrder": [ - "name" - ], - "response": { - "$ref": "StackdriverAccount" - }, - "parameters": { - "name": { - "location": "path", - "description": "The unique name of the Stackdriver account.\nCaller needs stackdriver.projects.get permission on the host project.", - "required": true, - "type": "string", - "pattern": "^accounts/[^/]+$" - }, - "includeProjects": { - "type": "boolean", - "location": "query", - "description": "If true the monitored_projects collection will be populated with any\nentries, if false it will be empty." - } - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/monitoring", - "https://www.googleapis.com/auth/monitoring.read" - ], - "flatPath": "v2/accounts/{accountsId}", - "id": "stackdriver.accounts.get", - "path": "v2/{+name}", - "description": "Fetches a specific Stackdriver account." - }, - "create": { - "response": { - "$ref": "Operation" - }, - "parameterOrder": [], - "httpMethod": "POST", - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/monitoring", - "https://www.googleapis.com/auth/monitoring.write" - ], - "parameters": {}, - "flatPath": "v2/accounts", - "path": "v2/accounts", - "id": "stackdriver.accounts.create", - "request": { - "$ref": "StackdriverAccount" - }, - "description": "Creates a new Stackdriver account with a given host project.\nA MonitoredProject for that project will be attached to it if successful.\n\nOperation\u003cresponse: StackdriverAccount\u003e" - } - }, - "resources": { - "projects": { - "methods": { - "create": { - "response": { - "$ref": "Operation" - }, - "parameterOrder": [ - "parent" - ], - "httpMethod": "POST", - "parameters": { - "parent": { - "description": "The unique name of the Stackdriver account that will host this project.\nCaller needs stackdriver.projects.edit permission on the host project.", - "required": true, - "type": "string", - "pattern": "^accounts/[^/]+$", - "location": "path" - } - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/monitoring", - "https://www.googleapis.com/auth/monitoring.write" - ], - "flatPath": "v2/accounts/{accountsId}/projects", - "path": "v2/{+parent}/projects", - "id": "stackdriver.accounts.projects.create", - "description": "Creates a new monitored project in a Stackdriver account.\nOperation\u003cresponse: MonitoredProject\u003e", - "request": { - "$ref": "MonitoredProject" - } - } - } - } - } - }, - "operations": { - "methods": { - "get": { - "httpMethod": "GET", - "response": { - "$ref": "Operation" - }, - "parameterOrder": [ - "name" - ], - "parameters": { - "name": { - "pattern": "^operations/.*$", - "location": "path", - "description": "The name of the operation resource.", - "required": true, - "type": "string" - } - }, - "scopes": [ - "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/monitoring", - "https://www.googleapis.com/auth/monitoring.read" - ], - "flatPath": "v2/operations/{operationsId}", - "id": "stackdriver.operations.get", - "path": "v2/{+name}", - "description": "Gets the latest state of a long-running operation. Clients can use this\nmethod to poll the operation result at intervals as recommended by the API\nservice." - } - } - } - } -} \ No newline at end of file From 8bad5239bd5adeb90f8d6706d31431f64fc09542 Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Mon, 4 Dec 2023 10:16:00 -0800 Subject: [PATCH 053/107] Update enrolled_teams.yml 12/1/23 (#9568) --- tools/issue-labeler/labeler/enrolled_teams.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/issue-labeler/labeler/enrolled_teams.yml b/tools/issue-labeler/labeler/enrolled_teams.yml index 112c8212a205..0fb80fd35430 100755 --- a/tools/issue-labeler/labeler/enrolled_teams.yml +++ b/tools/issue-labeler/labeler/enrolled_teams.yml @@ -35,6 +35,9 @@ service/apigateway: service/apigee: resources: - google_apigee_.* +service/apikeys: + resources: + - google_apikeys_key service/artifactregistry: resources: - google_artifact_registry_.* @@ -285,6 +288,9 @@ service/deploymentmanager: service/dialogflow: resources: - google_dialogflow_.* +service/discoveryengine: + resources: + - google_discoveryengine_.* service/dlp: resources: - google_data_loss_prevention_.* @@ -520,6 +526,9 @@ service/service-networking: service/servicedirectory: resources: - google_service_directory_.* +service/serviceusage: + resources: + - google_project_service service/serviceusage-quota: resources: - google_service_usage_consumer_quota_override From 9a32d4cb39052f3f49939325dc589f1302b95a1d Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Mon, 4 Dec 2023 19:24:42 +0100 Subject: [PATCH 054/107] Document `dns_name` and `psc_service_attachment_link` for Cloud SQL instances. (#9517) --- .../website/docs/r/sql_database_instance.html.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown index 027776ab0922..fc057586edbc 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown @@ -517,6 +517,8 @@ exported: * `connection_name` - The connection name of the instance to be used in connection strings. For example, when connecting with [Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/connect-admin-proxy). +* `dsn_name` - The DNS name of the instance. See [Connect to an instance using Private Service Connect](https://cloud.google.com/sql/docs/mysql/configure-private-service-connect#view-summary-information-cloud-sql-instances-psc-enabled) for more details. + * `service_account_email_address` - The service account email address assigned to the instance. @@ -549,6 +551,8 @@ a workaround for an [issue fixed in Terraform 0.12](https://github.com/hashicorp but also provides a convenient way to access an IP of a specific type without performing filtering in a Terraform config. +* `psc_service_attachment_link` - the URI that points to the service attachment of the instance. + * `instance_type` - The type of the instance. The supported values are `SQL_INSTANCE_TYPE_UNSPECIFIED`, `CLOUD_SQL_INSTANCE`, `ON_PREMISES_INSTANCE` and `READ_REPLICA_INSTANCE`. ~> **NOTE:** Users can upgrade a read replica instance to a stand-alone Cloud SQL instance with the help of `instance_type`. To promote, users have to set the `instance_type` property as `CLOUD_SQL_INSTANCE` and remove/unset `master_instance_name` and `replica_configuration` from instance configuration. This operation might cause your instance to restart. From 6d9fb147f6f82a4be6820e179a66e7f883885be6 Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Tue, 5 Dec 2023 01:00:46 +0530 Subject: [PATCH 055/107] Add Nsx credentials datasource to vmwareengine (#9533) * Add Network and PC bootstrap functions * Add NSX Credentials to Vmwareengine --- .../provider/provider_mmv1_resources.go.erb | 1 + ...rce_google_vmwareengine_nsx_credentials.go | 90 +++++++++++++++++++ ...esource_vmwareengine_private_cloud_test.go | 26 +++++- ...vmwareengine_nsx_credentials.html.markdown | 33 +++++++ 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_nsx_credentials.go create mode 100644 mmv1/third_party/terraform/website/docs/d/vmwareengine_nsx_credentials.html.markdown diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index d2a58b745435..f05ea5d6faba 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -205,6 +205,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_vmwareengine_network": vmwareengine.DataSourceVmwareengineNetwork(), "google_vmwareengine_network_peering": vmwareengine.DataSourceVmwareengineNetworkPeering(), "google_vmwareengine_network_policy": vmwareengine.DataSourceVmwareengineNetworkPolicy(), + "google_vmwareengine_nsx_credentials": vmwareengine.DataSourceVmwareengineNsxCredentials(), "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), // ####### END handwritten datasources ########### diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_nsx_credentials.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_nsx_credentials.go new file mode 100644 index 000000000000..2a22d6db7eb2 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_nsx_credentials.go @@ -0,0 +1,90 @@ +package vmwareengine + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceVmwareengineNsxCredentials() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVmwareengineNsxCredentialsRead, + Schema: map[string]*schema.Schema{ + "parent": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The resource name of the private cloud which contains NSX. +Resource names are schemeless URIs that follow the conventions in https://cloud.google.com/apis/design/resource_names. +For example: projects/my-project/locations/us-west1-a/privateClouds/my-cloud`, + }, + "username": { + Type: schema.TypeString, + Computed: true, + Description: `Initial username.`, + }, + "password": { + Type: schema.TypeString, + Computed: true, + Description: `Initial password.`, + }, + }, + } +} + +func dataSourceVmwareengineNsxCredentialsRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{VmwareengineBasePath}}{{parent}}:showNsxCredentials") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + ErrorAbortPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.Is429QuotaError}, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("VmwareengineNsxCredentials %q", d.Id())) + } + + if err := d.Set("username", flattenVmwareengineNsxCredentailsUsername(res["username"], d, config)); err != nil { + return fmt.Errorf("Error reading NsxCredentails: %s", err) + } + if err := d.Set("password", flattenVmwareengineNsxCredentailsPassword(res["password"], d, config)); err != nil { + return fmt.Errorf("Error reading NsxCredentails: %s", err) + } + + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}:nsx-credentials") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return nil +} + +func flattenVmwareengineNsxCredentailsUsername(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineNsxCredentailsPassword(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go index 563dfa8d3f86..54ede7d89284 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go @@ -30,6 +30,7 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T Config: testPrivateCloudUpdateConfig(context, "description1", 3), Check: resource.ComposeTestCheckFunc( acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_private_cloud.ds", "google_vmwareengine_private_cloud.vmw-engine-pc", map[string]struct{}{}), + testAccCheckGoogleVmwareengineNsxCredentialsMeta("data.google_vmwareengine_nsx_credentials.nsx-ds"), ), }, { @@ -90,7 +91,7 @@ resource "google_vmwareengine_private_cloud" "vmw-engine-pc" { } } -data "google_vmwareengine_private_cloud" ds { +data "google_vmwareengine_private_cloud" "ds" { location = "%{region}-a" name = "tf-test-sample-pc%{random_suffix}" depends_on = [ @@ -98,9 +99,32 @@ data "google_vmwareengine_private_cloud" ds { ] } +# NSX Credentials is a child datasource of PC and is included in the PC test due to the high deployment time involved in the Creation and deletion of a PC +data "google_vmwareengine_nsx_credentials" "nsx-ds" { + parent = google_vmwareengine_private_cloud.vmw-engine-pc +} + `, context) } +func testAccCheckGoogleVmwareengineNsxCredentialsMeta(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Can't find nsx credentials data source: %s", n) + } + _, ok = rs.Primary.Attributes["username"] + if !ok { + return fmt.Errorf("can't find 'username' attribute in data source: %s", n) + } + _, ok = rs.Primary.Attributes["password"] + if !ok { + return fmt.Errorf("can't find 'password' attribute in data source: %s", n) + } + return nil + } +} + func testAccCheckVmwareenginePrivateCloudDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_nsx_credentials.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_nsx_credentials.html.markdown new file mode 100644 index 000000000000..36001b3d5ca1 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_nsx_credentials.html.markdown @@ -0,0 +1,33 @@ +--- +subcategory: "Cloud VMware Engine" +description: |- + Get NSX Credentials of a Private Cloud. +--- + +# google\_vmwareengine\_nsx_credentials + +Use this data source to get NSX credentials for a Private Cloud. + +To get more information about private cloud NSX credentials, see: +* [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds/showNsxCredentials) + +## Example Usage + +```hcl +data "google_vmwareengine_nsx_credentials" "ds" { + parent = "projects/my-project/locations/us-west1-a/privateClouds/my-cloud" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `parent` - (Required) The resource name of the private cloud which contains the NSX. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `username` - The username of the NSX Credential. +* `password` - The password of the NSX Credential. \ No newline at end of file From 3f4a82e143a3eeaa41e74e7932f63359d741ae27 Mon Sep 17 00:00:00 2001 From: Raz Amir <88726761+ramir-savvy@users.noreply.github.com> Date: Mon, 4 Dec 2023 21:44:16 +0200 Subject: [PATCH 056/107] Retry on firestore index create 409 with 'underlying data changed' (#9570) --- mmv1/products/firestore/Index.yaml | 2 +- .../terraform/transport/error_retry_predicates.go | 10 +++++++--- .../transport/error_retry_predicates_test.go | 13 ++++++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/mmv1/products/firestore/Index.yaml b/mmv1/products/firestore/Index.yaml index 877cdca86cb3..4bf078f1b521 100644 --- a/mmv1/products/firestore/Index.yaml +++ b/mmv1/products/firestore/Index.yaml @@ -17,7 +17,7 @@ base_url: projects/{{project}}/databases/{{database}}/collectionGroups/{{collect self_link: '{{name}}' immutable: true error_retry_predicates: - ["transport_tpg.FirestoreIndex409CrossTransactionContetion"] + ["transport_tpg.FirestoreIndex409Retry"] description: | Cloud Firestore indexes enable simple and complex queries against documents in a database. This resource manages composite indexes and not single diff --git a/mmv1/third_party/terraform/transport/error_retry_predicates.go b/mmv1/third_party/terraform/transport/error_retry_predicates.go index c37cce72c484..d023c0b47b19 100644 --- a/mmv1/third_party/terraform/transport/error_retry_predicates.go +++ b/mmv1/third_party/terraform/transport/error_retry_predicates.go @@ -331,11 +331,15 @@ func FirestoreField409RetryUnderlyingDataChanged(err error) (bool, string) { } // relevant for firestore in datastore mode -func FirestoreIndex409CrossTransactionContetion(err error) (bool, string) { - if gerr, ok := err.(*googleapi.Error); ok { - if gerr.Code == 409 && strings.Contains(gerr.Body, "Aborted due to cross-transaction contention") { +func FirestoreIndex409Retry(err error) (bool, string) { + if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 409 { + if strings.Contains(gerr.Body, "Aborted due to cross-transaction contention") { return true, "aborted due to cross-transaction contention - retrying" } + + if strings.Contains(gerr.Body, "Please retry, underlying data changed") { + return true, "underlying data changed - retrying" + } } return false, "" } diff --git a/mmv1/third_party/terraform/transport/error_retry_predicates_test.go b/mmv1/third_party/terraform/transport/error_retry_predicates_test.go index 317a7b0da9e9..a097e8219e5b 100644 --- a/mmv1/third_party/terraform/transport/error_retry_predicates_test.go +++ b/mmv1/third_party/terraform/transport/error_retry_predicates_test.go @@ -187,7 +187,18 @@ func TestFirestoreIndex409_crossTransactionContetion(t *testing.T) { Code: 409, Body: "Aborted due to cross-transaction contention", } - isRetryable, _ := FirestoreIndex409CrossTransactionContetion(&err) + isRetryable, _ := FirestoreIndex409Retry(&err) + if !isRetryable { + t.Errorf("Error not detected as retryable") + } +} + +func TestFirestoreIndex409_retryUnderlyingDataChanged(t *testing.T) { + err := googleapi.Error{ + Code: 409, + Body: "Please retry, underlying data changed", + } + isRetryable, _ := FirestoreIndex409Retry(&err) if !isRetryable { t.Errorf("Error not detected as retryable") } From 3a85747d20f2e7f4be3cba8e428073f70fe7be2b Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Mon, 4 Dec 2023 13:44:29 -0600 Subject: [PATCH 057/107] Skip VCR test TestAccLoggingProjectSink_updatePreservesCustomWriter (#9576) --- .../services/logging/resource_logging_project_sink_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go index c8bdcbebddc7..d89af08acdd1 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go @@ -165,6 +165,8 @@ func TestAccLoggingProjectSink_updatePreservesUniqueWriter(t *testing.T) { } func TestAccLoggingProjectSink_updatePreservesCustomWriter(t *testing.T) { + // Investigating failure reason, skipping in VCR for now + acctest.SkipIfVcr(t) t.Parallel() sinkName := "tf-test-sink-" + acctest.RandString(t, 10) From 482b1ab5d76a240ab9777e03535276ee7cf0df19 Mon Sep 17 00:00:00 2001 From: Aaron Liberatore Date: Mon, 4 Dec 2023 12:47:13 -0800 Subject: [PATCH 058/107] [GKE Hub]: Add Fleet binary authorization config (#9545) --- mmv1/products/gkehub2/Fleet.yaml | 22 +++++++++++++- .../resource_gke_hub_fleet_test.go.erb | 30 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/mmv1/products/gkehub2/Fleet.yaml b/mmv1/products/gkehub2/Fleet.yaml index 0c9de65f03b6..88f2b389233c 100644 --- a/mmv1/products/gkehub2/Fleet.yaml +++ b/mmv1/products/gkehub2/Fleet.yaml @@ -99,6 +99,27 @@ properties: name: "defaultClusterConfig" description: The default cluster configurations to apply across the fleet. properties: + - !ruby/object:Api::Type::NestedObject + name: "binaryAuthorizationConfig" + description: Enable/Disable binary authorization features for the cluster. + properties: + - !ruby/object:Api::Type::Enum + name: "evaluationMode" + description: Mode of operation for binauthz policy evaluation. + values: + - DISABLED + - POLICY_BINDINGS + - !ruby/object:Api::Type::Array + name: "policyBindings" + description: Binauthz policies that apply to this cluster. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: "name" + description: | + The relative resource name of the binauthz platform policy to audit. GKE + platform policies have the following format: + `projects/{project_number}/platforms/gke/policies/{policy_id}`. - !ruby/object:Api::Type::NestedObject name: "securityPostureConfig" description: Enable/Disable Security Posture features for the cluster. @@ -109,7 +130,6 @@ properties: values: - DISABLED - BASIC - - ENTERPRISE - !ruby/object:Api::Type::Enum name: "vulnerabilityMode" description: Sets which mode to use for vulnerability scanning. diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb index d0f91aca472a..ca516876d0a7 100755 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_fleet_test.go.erb @@ -48,6 +48,14 @@ func TestAccGKEHub2Fleet_gkehubFleetBasicExample_update(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccGKEHub2Fleet_removedDefaultClusterConfig(context), + }, + { + ResourceName: "google_gke_hub_fleet.default", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -58,6 +66,9 @@ resource "google_gke_hub_fleet" "default" { project = google_project.project.project_id display_name = "my production fleet" default_cluster_config { + binary_authorization_config { + evaluation_mode = "DISABLED" + } security_posture_config { mode = "DISABLED" vulnerability_mode = "VULNERABILITY_DISABLED" @@ -72,8 +83,14 @@ func testAccGKEHub2Fleet_update(context map[string]interface{}) string { return gkeHubFleetProjectSetupForGA(context) + acctest.Nprintf(` resource "google_gke_hub_fleet" "default" { project = google_project.project.project_id - display_name = "my staging fleet" + display_name = "my updated fleet" default_cluster_config { + binary_authorization_config { + evaluation_mode = "POLICY_BINDINGS" + policy_bindings { + name = "projects/${google_project.project.project_id}/platforms/gke/policies/policy_id" + } + } security_posture_config { mode = "BASIC" vulnerability_mode = "VULNERABILITY_BASIC" @@ -84,6 +101,17 @@ resource "google_gke_hub_fleet" "default" { `, context) } +func testAccGKEHub2Fleet_removedDefaultClusterConfig(context map[string]interface{}) string { + return gkeHubFleetProjectSetupForGA(context) + acctest.Nprintf(` +resource "google_gke_hub_fleet" "default" { + project = google_project.project.project_id + display_name = "my updated fleet" + + depends_on = [time_sleep.wait_for_gkehub_enablement] +} +`, context) +} + func gkeHubFleetProjectSetupForGA(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_project" "project" { From 3005b4c8c20569581358b99ab7b77aefe485fcc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wiktor=20Niesiob=C4=99dzki?= Date: Mon, 4 Dec 2023 22:49:44 +0100 Subject: [PATCH 059/107] Cloud Run v2 limits examples and docs (#9563) * Cloud Run v2 limits examples and docs Improve documentation for limits and provide examples how they can be used in Cloud Run Service and Job. * Fix limits declaration * Remove primary_resource_name --- mmv1/products/cloudrunv2/Job.yaml | 7 +++++- mmv1/products/cloudrunv2/Service.yaml | 7 +++++- .../examples/cloudrunv2_job_limits.tf.erb | 24 +++++++++++++++++++ .../examples/cloudrunv2_service_limits.tf.erb | 17 +++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 mmv1/templates/terraform/examples/cloudrunv2_job_limits.tf.erb create mode 100644 mmv1/templates/terraform/examples/cloudrunv2_service_limits.tf.erb diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index fe8509b65791..176c056e5715 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -58,6 +58,11 @@ examples: ])" vars: cloud_run_job_name: 'cloudrun-job' + - !ruby/object:Provider::Terraform::Examples + name: 'cloudrunv2_job_limits' + primary_resource_id: 'default' + vars: + cloud_run_job_name: 'cloudrun-job' - !ruby/object:Provider::Terraform::Examples name: 'cloudrunv2_job_sql' primary_resource_id: 'default' @@ -337,7 +342,7 @@ properties: - !ruby/object:Api::Type::KeyValuePairs name: 'limits' description: |- - Only memory and CPU are supported. Note: The only supported values for CPU are '1', '2', '4', and '8'. Setting 4 CPU requires at least 2Gi of memory. The values of the map is string form of the 'quantity' k8s type: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go + Only memory and CPU are supported. Use key `cpu` for CPU limit and `memory` for memory limit. Note: The only supported values for CPU are '1', '2', '4', and '8'. Setting 4 CPU requires at least 2Gi of memory. The values of the map is string form of the 'quantity' k8s type: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go default_from_api: true - !ruby/object:Api::Type::Array name: 'ports' diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index a1cede779aad..07bdcba208f4 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -61,6 +61,11 @@ examples: random_suffix\"])" vars: cloud_run_service_name: 'cloudrun-service' + - !ruby/object:Provider::Terraform::Examples + name: 'cloudrunv2_service_limits' + primary_resource_id: 'default' + vars: + cloud_run_service_name: 'cloudrun-service' - !ruby/object:Provider::Terraform::Examples name: 'cloudrunv2_service_sql' primary_resource_id: 'default' @@ -421,7 +426,7 @@ properties: - !ruby/object:Api::Type::KeyValuePairs name: 'limits' description: |- - Only memory and CPU are supported. Note: The only supported values for CPU are '1', '2', '4', and '8'. Setting 4 CPU requires at least 2Gi of memory. The values of the map is string form of the 'quantity' k8s type: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go + Only memory and CPU are supported. Use key `cpu` for CPU limit and `memory` for memory limit. Note: The only supported values for CPU are '1', '2', '4', and '8'. Setting 4 CPU requires at least 2Gi of memory. The values of the map is string form of the 'quantity' k8s type: https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/api/resource/quantity.go default_from_api: true - !ruby/object:Api::Type::Boolean name: 'cpuIdle' diff --git a/mmv1/templates/terraform/examples/cloudrunv2_job_limits.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_job_limits.tf.erb new file mode 100644 index 000000000000..52c1523ac7d7 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudrunv2_job_limits.tf.erb @@ -0,0 +1,24 @@ +resource "google_cloud_run_v2_job" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['cloud_run_job_name'] %>" + location = "us-central1" + + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + resources { + limits = { + cpu = "2" + memory = "1024Mi" + } + } + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } +} diff --git a/mmv1/templates/terraform/examples/cloudrunv2_service_limits.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_service_limits.tf.erb new file mode 100644 index 000000000000..30476a53159e --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudrunv2_service_limits.tf.erb @@ -0,0 +1,17 @@ +resource "google_cloud_run_v2_service" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['cloud_run_service_name'] %>" + location = "us-central1" + ingress = "INGRESS_TRAFFIC_ALL" + + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + resources { + limits = { + cpu = "2" + memory = "1024Mi" + } + } + } + } +} From 9344002d0782ca87f6df9d79122d5d4882bd1cac Mon Sep 17 00:00:00 2001 From: Will Yardley Date: Mon, 4 Dec 2023 14:32:09 -0800 Subject: [PATCH 060/107] docs: remove app engine warning on `cloud_tasks_queue` (#8342) --- mmv1/products/cloudtasks/Queue.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/mmv1/products/cloudtasks/Queue.yaml b/mmv1/products/cloudtasks/Queue.yaml index 511130752b00..a6b985f8db48 100644 --- a/mmv1/products/cloudtasks/Queue.yaml +++ b/mmv1/products/cloudtasks/Queue.yaml @@ -27,12 +27,6 @@ iam_policy: !ruby/object:Api::Resource::IamPolicy id_format: 'projects/{{project}}/locations/{{location}}/queues/{{name}}' custom_code: !ruby/object:Provider::Terraform::CustomCode constants: 'templates/terraform/constants/cloud_tasks_retry_config_custom_diff.go' -docs: !ruby/object:Provider::Terraform::Docs - warning: | - This resource requires an App Engine application to be created on the - project you're provisioning it on. If you haven't already enabled it, you - can create a `google_app_engine_application` resource to do so. This - resource's location will be the same as the App Engine location specified. examples: - !ruby/object:Provider::Terraform::Examples name: 'queue_basic' From 2717aaf1a1716a081efbd63fd6d46fb8260e97d1 Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Tue, 5 Dec 2023 02:22:24 +0000 Subject: [PATCH 061/107] bigquery connection - spark connection type (#7498) Co-authored-by: Scott Suarez --- .../bigqueryconnection/Connection.yaml | 43 +++++++++++++++++++ .../examples/bigquery_connection_spark.tf.erb | 33 ++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 mmv1/templates/terraform/examples/bigquery_connection_spark.tf.erb diff --git a/mmv1/products/bigqueryconnection/Connection.yaml b/mmv1/products/bigqueryconnection/Connection.yaml index 253e6299b96e..5b5109303328 100644 --- a/mmv1/products/bigqueryconnection/Connection.yaml +++ b/mmv1/products/bigqueryconnection/Connection.yaml @@ -119,6 +119,12 @@ examples: vars: connection_id: 'my-connection' database: 'projects/project/instances/instance/databases/database' + - !ruby/object:Provider::Terraform::Examples + name: "bigquery_connection_spark" + region_override: "US" + primary_resource_id: "connection" + vars: + connection_id: "my-connection" properties: - !ruby/object:Api::Type::String name: name @@ -167,6 +173,7 @@ properties: - azure - cloud_spanner - cloud_resource + - spark properties: - !ruby/object:Api::Type::String name: 'instanceId' @@ -216,6 +223,7 @@ properties: - azure - cloud_spanner - cloud_resource + - spark update_mask_fields: - 'aws.access_role.iam_role_id' properties: @@ -248,6 +256,7 @@ properties: - azure - cloud_spanner - cloud_resource + - spark update_mask_fields: - 'azure.customer_tenant_id' - 'azure.federated_application_client_id' @@ -295,6 +304,7 @@ properties: - azure - cloud_spanner - cloud_resource + - spark properties: - !ruby/object:Api::Type::String name: 'database' @@ -352,6 +362,7 @@ properties: - azure - cloud_spanner - cloud_resource + - spark send_empty_value: true properties: - !ruby/object:Api::Type::String @@ -360,3 +371,35 @@ properties: The account ID of the service created for the purpose of this connection. output: true + - !ruby/object:Api::Type::NestedObject + name: spark + description: Container for connection properties to execute stored procedures for Apache Spark. + resources. + exactly_one_of: + - cloud_sql + - aws + - azure + - cloud_spanner + - cloud_resource + - spark + send_empty_value: true + properties: + - !ruby/object:Api::Type::String + name: 'serviceAccountId' + description: The account ID of the service created for the purpose of this + connection. + output: true + - !ruby/object:Api::Type::NestedObject + name: metastoreServiceConfig + description: Dataproc Metastore Service configuration for the connection. + properties: + - !ruby/object:Api::Type::String + name: metastoreService + description: Resource name of an existing Dataproc Metastore service in the form of projects/[projectId]/locations/[region]/services/[serviceId]. + - !ruby/object:Api::Type::NestedObject + name: sparkHistoryServerConfig + description: Spark History Server configuration for the connection. + properties: + - !ruby/object:Api::Type::String + name: dataprocCluster + description: Resource name of an existing Dataproc Cluster to act as a Spark History Server for the connection if the form of projects/[projectId]/regions/[region]/clusters/[cluster_name]. diff --git a/mmv1/templates/terraform/examples/bigquery_connection_spark.tf.erb b/mmv1/templates/terraform/examples/bigquery_connection_spark.tf.erb new file mode 100644 index 000000000000..18fcff706402 --- /dev/null +++ b/mmv1/templates/terraform/examples/bigquery_connection_spark.tf.erb @@ -0,0 +1,33 @@ +resource "google_bigquery_connection" "<%= ctx[:primary_resource_id] %>" { + connection_id = "<%= ctx[:vars]['connection_id'] %>" + location = "US" + friendly_name = "👋" + description = "a riveting description" + spark { + spark_history_server_config { + dataproc_cluster = google_dataproc_cluster.basic.id + } + } +} + +resource "google_dataproc_cluster" "basic" { + name = "<%= ctx[:vars]['connection_id'] %>" + region = "us-central1" + + cluster_config { + # Keep the costs down with smallest config we can get away with + software_config { + override_properties = { + "dataproc:dataproc.allow.zero.workers" = "true" + } + } + + master_config { + num_instances = 1 + machine_type = "e2-standard-2" + disk_config { + boot_disk_size_gb = 35 + } + } + } + } From 805f9afb5e5a4857aeac3d44c855818382b3dc21 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Tue, 5 Dec 2023 11:16:08 -0800 Subject: [PATCH 062/107] Recursively look for function calls in missing test detector (#9580) --- tools/missing-test-detector/reader.go | 76 +++++++++---------- tools/missing-test-detector/reader_test.go | 44 +++++++++-- .../testdata/service/function_call_test.go | 34 +++++++++ 3 files changed, 107 insertions(+), 47 deletions(-) create mode 100644 tools/missing-test-detector/testdata/service/function_call_test.go diff --git a/tools/missing-test-detector/reader.go b/tools/missing-test-detector/reader.go index 3ac95d54092d..651bb1d6875d 100644 --- a/tools/missing-test-detector/reader.go +++ b/tools/missing-test-detector/reader.go @@ -216,25 +216,23 @@ func readStepsCompLit(stepsCompLit *ast.CompositeLit, funcDecls map[string]*ast. for _, eltCompLitElt := range eltCompLit.Elts { if keyValueExpr, ok := eltCompLitElt.(*ast.KeyValueExpr); ok { if ident, ok := keyValueExpr.Key.(*ast.Ident); ok && ident.Name == "Config" { + var configStr string + var err error if configCallExpr, ok := keyValueExpr.Value.(*ast.CallExpr); ok { - step, err := readConfigCallExpr(configCallExpr, funcDecls, varDecls) - if err != nil { - errs = append(errs, err) - } - test.Steps = append(test.Steps, step) + configStr, err = readConfigCallExpr(configCallExpr, funcDecls, varDecls) } else if ident, ok := keyValueExpr.Value.(*ast.Ident); ok { if configVar, ok := varDecls[ident.Name]; ok { - configStr, err := strconv.Unquote(configVar.Value) - if err != nil { - errs = append(errs, err) - } - step, err := readConfigStr(configStr) - if err != nil { - errs = append(errs, err) - } - test.Steps = append(test.Steps, step) + configStr, err = strconv.Unquote(configVar.Value) } } + if err != nil { + errs = append(errs, err) + } + step, err := readConfigStr(configStr) + if err != nil { + errs = append(errs, err) + } + test.Steps = append(test.Steps, step) } } } @@ -247,46 +245,40 @@ func readStepsCompLit(stepsCompLit *ast.CompositeLit, funcDecls map[string]*ast. } // Read the call expression in the public test function that returns the config. -func readConfigCallExpr(configCallExpr *ast.CallExpr, funcDecls map[string]*ast.FuncDecl, varDecls map[string]*ast.BasicLit) (Step, error) { +func readConfigCallExpr(configCallExpr *ast.CallExpr, funcDecls map[string]*ast.FuncDecl, varDecls map[string]*ast.BasicLit) (string, error) { if ident, ok := configCallExpr.Fun.(*ast.Ident); ok { if configFunc, ok := funcDecls[ident.Name]; ok { - return readConfigFunc(configFunc) + return readConfigFunc(configFunc, funcDecls, varDecls) } - return nil, fmt.Errorf("failed to find function declaration %s", ident.Name) + return "", fmt.Errorf("failed to find function declaration %s", ident.Name) } - return nil, fmt.Errorf("failed to get ident for %v", configCallExpr.Fun) + return "", fmt.Errorf("failed to get ident for %v", configCallExpr.Fun) } -func readConfigFunc(configFunc *ast.FuncDecl) (Step, error) { +func readConfigFunc(configFunc *ast.FuncDecl, funcDecls map[string]*ast.FuncDecl, varDecls map[string]*ast.BasicLit) (string, error) { for _, stmt := range configFunc.Body.List { if returnStmt, ok := stmt.(*ast.ReturnStmt); ok { - for _, result := range returnStmt.Results { - configStr, err := readConfigFuncResult(result) - if err != nil { - return nil, err - } - if configStr != "" { - return readConfigStr(configStr) - } + if len(returnStmt.Results) > 0 { + return readConfigFuncResult(returnStmt.Results[0], funcDecls, varDecls) } - return nil, fmt.Errorf("failed to find a config string in results %v", returnStmt.Results) + return "", fmt.Errorf("failed to find a config string in results %v", returnStmt.Results) } } - return nil, fmt.Errorf("failed to find a return statement in %v", configFunc.Body.List) + return "", fmt.Errorf("failed to find a return statement in %v", configFunc.Body.List) } // Read the return result of a config func and return the config string. -func readConfigFuncResult(result ast.Expr) (string, error) { +func readConfigFuncResult(result ast.Expr, funcDecls map[string]*ast.FuncDecl, varDecls map[string]*ast.BasicLit) (string, error) { if basicLit, ok := result.(*ast.BasicLit); ok && basicLit.Kind == token.STRING { return strconv.Unquote(basicLit.Value) } else if callExpr, ok := result.(*ast.CallExpr); ok { - return readConfigFuncCallExpr(callExpr) + return readConfigFuncCallExpr(callExpr, funcDecls, varDecls) } else if binaryExpr, ok := result.(*ast.BinaryExpr); ok { - xConfigStr, err := readConfigFuncResult(binaryExpr.X) + xConfigStr, err := readConfigFuncResult(binaryExpr.X, funcDecls, varDecls) if err != nil { return "", err } - yConfigStr, err := readConfigFuncResult(binaryExpr.Y) + yConfigStr, err := readConfigFuncResult(binaryExpr.Y, funcDecls, varDecls) if err != nil { return "", err } @@ -298,16 +290,16 @@ func readConfigFuncResult(result ast.Expr) (string, error) { // Read the call expression in the config function that returns the config string. // The call expression can contain a nested call expression. // Return the config string. -func readConfigFuncCallExpr(configFuncCallExpr *ast.CallExpr) (string, error) { - if len(configFuncCallExpr.Args) == 0 { - return "", fmt.Errorf("no arguments found for call expression %v", configFuncCallExpr) - } - if basicLit, ok := configFuncCallExpr.Args[0].(*ast.BasicLit); ok && basicLit.Kind == token.STRING { - return strconv.Unquote(basicLit.Value) - } else if nestedCallExpr, ok := configFuncCallExpr.Args[0].(*ast.CallExpr); ok { - return readConfigFuncCallExpr(nestedCallExpr) +func readConfigFuncCallExpr(configFuncCallExpr *ast.CallExpr, funcDecls map[string]*ast.FuncDecl, varDecls map[string]*ast.BasicLit) (string, error) { + if len(configFuncCallExpr.Args) > 0 { + if basicLit, ok := configFuncCallExpr.Args[0].(*ast.BasicLit); ok && basicLit.Kind == token.STRING { + return strconv.Unquote(basicLit.Value) + } else if nestedCallExpr, ok := configFuncCallExpr.Args[0].(*ast.CallExpr); ok { + return readConfigFuncCallExpr(nestedCallExpr, funcDecls, varDecls) + } } - return "", fmt.Errorf("no string literal found in arguments to call expression %v", configFuncCallExpr) + // Config string not readable from args, attempt to read call expression as a helper function. + return readConfigCallExpr(configFuncCallExpr, funcDecls, varDecls) } // Read the config string and return a test step. diff --git a/tools/missing-test-detector/reader_test.go b/tools/missing-test-detector/reader_test.go index e42d3eff4137..cb70579f6b46 100644 --- a/tools/missing-test-detector/reader_test.go +++ b/tools/missing-test-detector/reader_test.go @@ -144,10 +144,8 @@ func TestReadCrossFileTests(t *testing.T) { if err != nil { t.Fatalf("error reading cross file tests: %v", err) } - if len(tests) != 2 { - t.Fatalf("unexpected number of tests: %d, expected 2", len(tests)) - } - if expectedTests := []*Test{ + + expectedTests := []*Test{ { Name: "testAccCrossFile1", Steps: []Step{ @@ -172,8 +170,44 @@ func TestReadCrossFileTests(t *testing.T) { }, }, }, - }; !reflect.DeepEqual(tests, expectedTests) { + } + + if len(tests) != len(expectedTests) { + t.Fatalf("unexpected number of tests: %d, expected %d", len(tests), len(expectedTests)) + } + + if !reflect.DeepEqual(tests, expectedTests) { t.Errorf("found unexpected cross file tests: %v, expected %v", tests, expectedTests) } } + +func TestReadHelperFunctionCall(t *testing.T) { + tests, err := readTestFiles([]string{"testdata/service/function_call_test.go"}) + if err != nil { + t.Fatalf("error reading function call test: %v", err) + } + if len(tests) != 1 { + t.Fatalf("unexpected number of tests: %d, expected 1", len(tests)) + } + expectedTest := &Test{ + Name: "TestAccFunctionCallResource", + Steps: []Step{ + Step{ + "helped_resource": Resources{ + "primary": Resource{ + "field_one": "\"value-one\"", + }, + }, + "helper_resource": Resources{ + "default": Resource{ + "field_one": "\"value-one\"", + }, + }, + }, + }, + } + if !reflect.DeepEqual(tests[0], expectedTest) { + t.Errorf("found unexpected tests using helper function: %v, expected %v", tests[0], expectedTest) + } +} diff --git a/tools/missing-test-detector/testdata/service/function_call_test.go b/tools/missing-test-detector/testdata/service/function_call_test.go new file mode 100644 index 000000000000..a430e8a796a9 --- /dev/null +++ b/tools/missing-test-detector/testdata/service/function_call_test.go @@ -0,0 +1,34 @@ +package service_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" +) + +func TestAccFunctionCallResource(t *testing.T) { + acctest.VcrTest(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: testAccFunctionCallResource(), + }, + }, + }) +} + +func helperFunction() string { + return ` +resource "helper_resource" "default" { + field_one = "value-one" +} +` +} + +func testAccFunctionCallResource() string { + return helperFunction() + acctest.Nprintf(` +resource "helped_resource" "primary" { + field_one = "value-one" +} +`) +} From 05c4410c0e599f33ab255e3820187855c82c7739 Mon Sep 17 00:00:00 2001 From: pratikgarg10 <33780624+pratikgarg10@users.noreply.github.com> Date: Tue, 5 Dec 2023 11:50:19 -0800 Subject: [PATCH 063/107] add support for IAM Group authentication to google_sql_user (#9578) --- .../services/sql/resource_sql_user.go | 6 ++++-- .../services/sql/resource_sql_user_test.go | 11 ++++++++++ .../website/docs/r/sql_user.html.markdown | 21 ++++++++++++++++++- 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user.go b/mmv1/third_party/terraform/services/sql/resource_sql_user.go index 599e55df39f7..15bf8061b05d 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user.go @@ -102,8 +102,10 @@ func ResourceSqlUser() *schema.Resource { ForceNew: true, DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("BUILT_IN"), Description: `The user type. It determines the method to authenticate the user during login. - The default is the database's built-in user type. Flags include "BUILT_IN", "CLOUD_IAM_USER", or "CLOUD_IAM_SERVICE_ACCOUNT".`, - ValidateFunc: validation.StringInSlice([]string{"BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", ""}, false), + The default is the database's built-in user type. Flags include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", + "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" or "CLOUD_IAM_GROUP_SERVICE_ACCOUNT".`, + ValidateFunc: validation.StringInSlice([]string{"BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", + "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER", "CLOUD_IAM_GROUP_SERVICE_ACCOUNT", ""}, false), }, "sql_server_user_details": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go index efcf0d5f5962..9091ef56a534 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go @@ -26,6 +26,7 @@ func TestAccSqlUser_mysql(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"), testAccCheckGoogleSqlUserExists(t, "google_sql_user.user2"), + testAccCheckGoogleSqlUserExists(t, "google_sql_user.user3"), ), }, { @@ -34,6 +35,7 @@ func TestAccSqlUser_mysql(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"), testAccCheckGoogleSqlUserExists(t, "google_sql_user.user2"), + testAccCheckGoogleSqlUserExists(t, "google_sql_user.user3"), ), }, { @@ -311,6 +313,15 @@ resource "google_sql_user" "user2" { instance = google_sql_database_instance.instance.name host = "gmail.com" password = "hunter2" + type = "CLOUD_IAM_USER" +} + +resource "google_sql_user" "user3" { + name = "admin" + instance = google_sql_database_instance.instance.name + host = "gmail.com" + password = "hunter3" + type = "CLOUD_IAM_GROUP" } `, instance, password) } diff --git a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown index 9b96d4463a22..0072e8aa762b 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown @@ -72,6 +72,24 @@ resource "google_sql_user" "iam_service_account_user" { instance = google_sql_database_instance.main.name type = "CLOUD_IAM_SERVICE_ACCOUNT" } + +resource "google_sql_user" "iam_group" { + name = "group1@example.com" + instance = google_sql_database_instance.main.name + type = "CLOUD_IAM_GROUP" +} + +resource "google_sql_user" "iam_group_user" { + name = "group_user1@example.com" + instance = google_sql_database_instance.main.name + type = "CLOUD_IAM_GROUP_USER" +} + +resource "google_sql_user" "iam_group_service_account_user" { + name = "my-service-account@example.iam.gserviceaccount.com" + instance = google_sql_database_instance.main.name + type = "CLOUD_IAM_GROUP_SERVICE_ACCOUNT" +} ``` ## Argument Reference @@ -91,7 +109,8 @@ The following arguments are supported: * `type` - (Optional) The user type. It determines the method to authenticate the user during login. The default is the database's built-in user type. Flags - include "BUILT_IN", "CLOUD_IAM_USER", or "CLOUD_IAM_SERVICE_ACCOUNT". + include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", + "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" or "CLOUD_IAM_GROUP_SERVICE_ACCOUNT". * `deletion_policy` - (Optional) The deletion policy for the user. Setting `ABANDON` allows the resource to be abandoned rather than deleted. This is useful From 99b5c55dd2b3f66b91a192e9a22a7ffe51a387b1 Mon Sep 17 00:00:00 2001 From: Gorlami96 <30335782+Gorlami96@users.noreply.github.com> Date: Wed, 6 Dec 2023 02:17:46 +0530 Subject: [PATCH 064/107] migrating router-bgp-peer to be a handwritten resource (#9559) * Making router-bgp-peer as a handwritten resource * Adding sweeper file, removing example suffix from test files and adding resource in the handwritten section in provider * Removing unused import statements * Removing unused import statements from router_peer * Fix indentation --------- Co-authored-by: Shivang Dixit Co-authored-by: Thomas Rodgers --- mmv1/products/compute/RouterBgpPeer.yaml | 315 ---- .../provider/provider_mmv1_resources.go.erb | 3 +- .../resource_compute_router_peer.go.erb | 1318 +++++++++++++++++ .../resource_compute_router_peer_sweeper.go | 122 ++ .../resource_compute_router_peer_test.go.erb | 188 +++ .../docs/r/compute_router_peer.html.markdown | 410 +++++ 6 files changed, 2040 insertions(+), 316 deletions(-) delete mode 100644 mmv1/products/compute/RouterBgpPeer.yaml create mode 100644 mmv1/third_party/terraform/services/compute/resource_compute_router_peer.go.erb create mode 100644 mmv1/third_party/terraform/services/compute/resource_compute_router_peer_sweeper.go create mode 100644 mmv1/third_party/terraform/services/compute/resource_compute_router_peer_test.go.erb create mode 100644 mmv1/third_party/terraform/website/docs/r/compute_router_peer.html.markdown diff --git a/mmv1/products/compute/RouterBgpPeer.yaml b/mmv1/products/compute/RouterBgpPeer.yaml deleted file mode 100644 index 7b83bb74dcba..000000000000 --- a/mmv1/products/compute/RouterBgpPeer.yaml +++ /dev/null @@ -1,315 +0,0 @@ -# Copyright 2023 Google Inc. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ---- !ruby/object:Api::Resource -name: 'RouterBgpPeer' -base_url: projects/{{project}}/regions/{{region}}/routers/{{router}} -self_link: projects/{{project}}/regions/{{region}}/routers/{{router}} -create_verb: :PATCH -update_verb: :PATCH -delete_verb: :PATCH -identity: - - name -nested_query: !ruby/object:Api::Resource::NestedQuery - modify_by_patch: true - keys: - - bgpPeers -description: | - BGP information that must be configured into the routing stack to - establish BGP peering. This information must specify the peer ASN - and either the interface name, IP address, or peer IP address. - Please refer to RFC4273. -references: !ruby/object:Api::Resource::ReferenceLinks - guides: - 'Google Cloud Router': 'https://cloud.google.com/router/docs/' - api: 'https://cloud.google.com/compute/docs/reference/rest/v1/routers' -async: !ruby/object:Api::OpAsync - operation: !ruby/object:Api::OpAsync::Operation - kind: 'compute#operation' - path: 'name' - base_url: 'projects/{{project}}/regions/{{regions}}/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' -legacy_name: 'google_compute_router_peer' -exclude_tgc: true -id_format: 'projects/{{project}}/regions/{{region}}/routers/{{router}}/{{name}}' -mutex: router/{{region}}/{{router}} -custom_code: !ruby/object:Provider::Terraform::CustomCode - constants: templates/terraform/constants/router_bgp_peer.erb -examples: - # These examples are not used to autogenerate tests, as fine-grained - # resources do not fit the normal test flow - we need to test deletion - # in a test step while parent resource still exists vs in CheckDestroy - # when all resources have been deleted. - - !ruby/object:Provider::Terraform::Examples - name: 'router_peer_basic' - primary_resource_id: 'peer' - skip_test: true - vars: - router_name: 'my-router' - peer_name: 'my-router-peer' - - !ruby/object:Provider::Terraform::Examples - name: 'router_peer_disabled' - primary_resource_id: 'peer' - skip_test: true - vars: - router_name: 'my-router' - peer_name: 'my-router-peer' - - !ruby/object:Provider::Terraform::Examples - name: 'router_peer_bfd' - primary_resource_id: 'peer' - skip_test: true - vars: - router_name: 'my-router' - peer_name: 'my-router-peer' - - !ruby/object:Provider::Terraform::Examples - name: 'router_peer_router_appliance' - primary_resource_id: 'peer' - vars: - router_name: 'my-router' - peer_name: 'my-router-peer' -parameters: - - !ruby/object:Api::Type::ResourceRef - name: 'router' - resource: 'Router' - imports: 'name' - description: | - The name of the Cloud Router in which this BgpPeer will be configured. - required: true - immutable: true - url_param_only: true - - !ruby/object:Api::Type::ResourceRef - name: region - resource: Region - imports: name - description: | - Region where the router and BgpPeer reside. - If it is not provided, the provider region is used. - immutable: true - required: false - url_param_only: true - default_from_api: true - custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' -properties: - - !ruby/object:Api::Type::String - name: 'name' - description: | - Name of this BGP peer. 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. - required: true - immutable: true - validation: !ruby/object:Provider::Terraform::Validation - function: 'verify.ValidateRFC1035Name(2, 63)' - - !ruby/object:Api::Type::String - name: 'interface' - api_name: 'interfaceName' - description: | - Name of the interface the BGP peer is associated with. - required: true - immutable: true - - !ruby/object:Api::Type::String - name: 'ipAddress' - description: | - IP address of the interface inside Google Cloud Platform. - Only IPv4 is supported. - default_from_api: true - - !ruby/object:Api::Type::String - name: 'peerIpAddress' - description: | - IP address of the BGP interface outside Google Cloud Platform. - Only IPv4 is supported. Required if `ip_address` is set. - default_from_api: true - - !ruby/object:Api::Type::Integer - name: 'peerAsn' - description: | - Peer BGP Autonomous System Number (ASN). - Each BGP interface may use a different value. - required: true - - !ruby/object:Api::Type::Integer - name: 'advertisedRoutePriority' - description: | - The priority of routes advertised to this BGP peer. - Where there is more than one matching route of maximum - length, the routes with the lowest priority value win. - send_empty_value: true - - !ruby/object:Api::Type::Enum - name: advertiseMode - description: | - User-specified flag to indicate which mode to use for advertisement. - Valid values of this enum field are: `DEFAULT`, `CUSTOM` - values: - - :DEFAULT - - :CUSTOM - default_value: :DEFAULT - custom_flatten: 'templates/terraform/custom_flatten/default_if_empty.erb' - - !ruby/object:Api::Type::Array - name: advertisedGroups - description: | - User-specified list of prefix groups to advertise in custom - mode, which currently supports the following option: - - * `ALL_SUBNETS`: Advertises all of the router's own VPC subnets. - This excludes any routes learned for subnets that use VPC Network - Peering. - - - Note that this field can only be populated if advertiseMode is `CUSTOM` - and overrides the list defined for the router (in the "bgp" message). - These groups are advertised in addition to any specified prefixes. - Leave this field blank to advertise no custom groups. - send_empty_value: true - item_type: Api::Type::String - - !ruby/object:Api::Type::Array - name: advertisedIpRanges - description: | - User-specified list of individual IP ranges to advertise in - custom mode. This field can only be populated if advertiseMode - is `CUSTOM` and is advertised to all peers of the router. These IP - ranges will be advertised in addition to any specified groups. - Leave this field blank to advertise no custom IP ranges. - send_empty_value: true - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: range - required: true - description: | - The IP range to advertise. The value must be a - CIDR-formatted string. - - !ruby/object:Api::Type::String - name: description - description: | - User-specified description for the IP range. - send_empty_value: true - - !ruby/object:Api::Type::String - name: 'managementType' - description: | - The resource that configures and manages this BGP peer. - - * `MANAGED_BY_USER` is the default value and can be managed by - you or other users - * `MANAGED_BY_ATTACHMENT` is a BGP peer that is configured and - managed by Cloud Interconnect, specifically by an - InterconnectAttachment of type PARTNER. Google automatically - creates, updates, and deletes this type of BGP peer when the - PARTNER InterconnectAttachment is created, updated, - or deleted. - output: true - - !ruby/object:Api::Type::NestedObject - name: bfd - description: | - BFD configuration for the BGP peering. - default_from_api: true - properties: - - !ruby/object:Api::Type::Enum - name: sessionInitializationMode - description: | - The BFD session initialization mode for this BGP peer. - If set to `ACTIVE`, the Cloud Router will initiate the BFD session - for this BGP peer. If set to `PASSIVE`, the Cloud Router will wait - for the peer router to initiate the BFD session for this BGP peer. - If set to `DISABLED`, BFD is disabled for this BGP peer. - values: - - :ACTIVE - - :DISABLED - - :PASSIVE - required: true - - !ruby/object:Api::Type::Integer - name: minTransmitInterval - description: | - The minimum interval, in milliseconds, between BFD control packets - transmitted to the peer router. The actual value is negotiated - between the two routers and is equal to the greater of this value - and the corresponding receive interval of the other router. If set, - this value must be between 1000 and 30000. - default_value: 1000 - - !ruby/object:Api::Type::Integer - name: minReceiveInterval - description: | - The minimum interval, in milliseconds, between BFD control packets - received from the peer router. The actual value is negotiated - between the two routers and is equal to the greater of this value - and the transmit interval of the other router. If set, this value - must be between 1000 and 30000. - default_value: 1000 - - !ruby/object:Api::Type::Integer - name: multiplier - description: | - The number of consecutive BFD packets that must be missed before - BFD declares that a peer is unavailable. If set, the value must - be a value between 5 and 16. - default_value: 5 - - !ruby/object:Api::Type::Boolean - name: 'enable' - description: | - The status of the BGP peer connection. If set to false, any active session - with the peer is terminated and all associated routing information is removed. - If set to true, the peer connection can be established with routing information. - The default is true. - default_value: true - custom_expand: 'templates/terraform/custom_expand/bool_to_upper_string.erb' - custom_flatten: 'templates/terraform/custom_flatten/string_to_bool_default_true.erb' - send_empty_value: true - - !ruby/object:Api::Type::ResourceRef - name: 'routerApplianceInstance' - resource: 'Instance' - imports: 'selfLink' - description: | - The URI of the VM instance that is used as third-party router appliances - such as Next Gen Firewalls, Virtual Routers, or Router Appliances. - The VM instance must be located in zones contained in the same region as - this Cloud Router. The VM instance is the peer side of the BGP session. - custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' - - !ruby/object:Api::Type::Boolean - name: 'enableIpv6' - description: | - Enable IPv6 traffic over BGP Peer. If not specified, it is disabled by default. - default_value: false - send_empty_value: true - - !ruby/object:Api::Type::String - name: 'ipv6NexthopAddress' - description: | - IPv6 address of the interface inside Google Cloud Platform. - The address must be in the range 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64. - If you do not specify the next hop addresses, Google Cloud automatically - assigns unused addresses from the 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64 range for you. - default_from_api: true - validation: !ruby/object:Provider::Terraform::Validation - function: 'verify.ValidateIpAddress' - diff_suppress_func: ipv6RepresentationDiffSuppress - - !ruby/object:Api::Type::String - name: 'peerIpv6NexthopAddress' - description: | - IPv6 address of the BGP interface outside Google Cloud Platform. - The address must be in the range 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64. - If you do not specify the next hop addresses, Google Cloud automatically - assigns unused addresses from the 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64 range for you. - default_from_api: true - validation: !ruby/object:Provider::Terraform::Validation - function: 'verify.ValidateIpAddress' - diff_suppress_func: ipv6RepresentationDiffSuppress diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index f05ea5d6faba..8f41adb2b48e 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -331,6 +331,7 @@ var handwrittenResources = map[string]*schema.Resource{ "google_compute_attached_disk": compute.ResourceComputeAttachedDisk(), "google_compute_instance": compute.ResourceComputeInstance(), "google_compute_disk_async_replication": compute.ResourceComputeDiskAsyncReplication(), + "google_compute_router_peer": compute.ResourceComputeRouterBgpPeer(), <% unless version == 'ga' -%> "google_compute_instance_from_machine_image": compute.ResourceComputeInstanceFromMachineImage(), <% end -%> @@ -472,4 +473,4 @@ var handwrittenIAMResources = map[string]*schema.Resource{ "google_service_account_iam_member": tpgiamresource.ResourceIamMember(resourcemanager.IamServiceAccountSchema, resourcemanager.NewServiceAccountIamUpdater, resourcemanager.ServiceAccountIdParseFunc), "google_service_account_iam_policy": tpgiamresource.ResourceIamPolicy(resourcemanager.IamServiceAccountSchema, resourcemanager.NewServiceAccountIamUpdater, resourcemanager.ServiceAccountIdParseFunc), // ####### END non-generated IAM resources ########### -} \ No newline at end of file +} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_router_peer.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_router_peer.go.erb new file mode 100644 index 000000000000..4a5729ccc513 --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/resource_compute_router_peer.go.erb @@ -0,0 +1,1318 @@ +<% autogen_exception -%> +package compute + +import ( + "fmt" + "log" + "net" + "reflect" + "strconv" + "strings" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-provider-google/google/verify" + +) + +func ipv6RepresentationDiffSuppress(_, old, new string, d *schema.ResourceData) bool { + //Diff suppress any equal IPV6 address in different representations + //An IPV6 address can have long or short representations + //E.g 2001:0cb0:0000:0000:0fc0:0000:0000:0abc, after compression: + //A) 2001:0cb0::0fc0:0000:0000:0abc (Omit groups of all zeros) + //B) 2001:cb0:0:0:fc0::abc (Omit leading zeros) + //C) 2001:cb0::fc0:0:0:abc (Combining A and B) + //The GCP API follows rule B) for normalzation + + oldIp := net.ParseIP(old) + newIp := net.ParseIP(new) + return oldIp.Equal(newIp) +} + +func ResourceComputeRouterBgpPeer() *schema.Resource { + return &schema.Resource{ + Create: resourceComputeRouterBgpPeerCreate, + Read: resourceComputeRouterBgpPeerRead, + Update: resourceComputeRouterBgpPeerUpdate, + Delete: resourceComputeRouterBgpPeerDelete, + + Importer: &schema.ResourceImporter{ + State: resourceComputeRouterBgpPeerImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + CustomizeDiff: customdiff.All( + tpgresource.DefaultProviderProject, + ), + + Schema: map[string]*schema.Schema{ + "interface": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Name of the interface the BGP peer is associated with.`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: verify.ValidateRFC1035Name(2, 63), + Description: `Name of this BGP peer. 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.`, + }, + "peer_asn": { + Type: schema.TypeInt, + Required: true, + Description: `Peer BGP Autonomous System Number (ASN). +Each BGP interface may use a different value.`, + }, + "router": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The name of the Cloud Router in which this BgpPeer will be configured.`, + }, + "advertise_mode": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"DEFAULT", "CUSTOM", ""}), + Description: `User-specified flag to indicate which mode to use for advertisement. +Valid values of this enum field are: 'DEFAULT', 'CUSTOM' Default value: "DEFAULT" Possible values: ["DEFAULT", "CUSTOM"]`, + Default: "DEFAULT", + }, + "advertised_groups": { + Type: schema.TypeList, + Optional: true, + Description: `User-specified list of prefix groups to advertise in custom +mode, which currently supports the following option: + +* 'ALL_SUBNETS': Advertises all of the router's own VPC subnets. +This excludes any routes learned for subnets that use VPC Network +Peering. + + +Note that this field can only be populated if advertiseMode is 'CUSTOM' +and overrides the list defined for the router (in the "bgp" message). +These groups are advertised in addition to any specified prefixes. +Leave this field blank to advertise no custom groups.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "advertised_ip_ranges": { + Type: schema.TypeList, + Optional: true, + Description: `User-specified list of individual IP ranges to advertise in +custom mode. This field can only be populated if advertiseMode +is 'CUSTOM' and is advertised to all peers of the router. These IP +ranges will be advertised in addition to any specified groups. +Leave this field blank to advertise no custom IP ranges.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "range": { + Type: schema.TypeString, + Required: true, + Description: `The IP range to advertise. The value must be a +CIDR-formatted string.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `User-specified description for the IP range.`, + }, + }, + }, + }, + "advertised_route_priority": { + Type: schema.TypeInt, + Optional: true, + Description: `The priority of routes advertised to this BGP peer. +Where there is more than one matching route of maximum +length, the routes with the lowest priority value win.`, + }, + "bfd": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `BFD configuration for the BGP peering.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "session_initialization_mode": { + Type: schema.TypeString, + Required: true, + ValidateFunc: verify.ValidateEnum([]string{"ACTIVE", "DISABLED", "PASSIVE"}), + Description: `The BFD session initialization mode for this BGP peer. +If set to 'ACTIVE', the Cloud Router will initiate the BFD session +for this BGP peer. If set to 'PASSIVE', the Cloud Router will wait +for the peer router to initiate the BFD session for this BGP peer. +If set to 'DISABLED', BFD is disabled for this BGP peer. Possible values: ["ACTIVE", "DISABLED", "PASSIVE"]`, + }, + "min_receive_interval": { + Type: schema.TypeInt, + Optional: true, + Description: `The minimum interval, in milliseconds, between BFD control packets +received from the peer router. The actual value is negotiated +between the two routers and is equal to the greater of this value +and the transmit interval of the other router. If set, this value +must be between 1000 and 30000.`, + Default: 1000, + }, + "min_transmit_interval": { + Type: schema.TypeInt, + Optional: true, + Description: `The minimum interval, in milliseconds, between BFD control packets +transmitted to the peer router. The actual value is negotiated +between the two routers and is equal to the greater of this value +and the corresponding receive interval of the other router. If set, +this value must be between 1000 and 30000.`, + Default: 1000, + }, + "multiplier": { + Type: schema.TypeInt, + Optional: true, + Description: `The number of consecutive BFD packets that must be missed before +BFD declares that a peer is unavailable. If set, the value must +be a value between 5 and 16.`, + Default: 5, + }, + }, + }, + }, + "enable": { + Type: schema.TypeBool, + Optional: true, + Description: `The status of the BGP peer connection. If set to false, any active session +with the peer is terminated and all associated routing information is removed. +If set to true, the peer connection can be established with routing information. +The default is true.`, + Default: true, + }, + "enable_ipv6": { + Type: schema.TypeBool, + Optional: true, + Description: `Enable IPv6 traffic over BGP Peer. If not specified, it is disabled by default.`, + Default: false, + }, + "ip_address": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `IP address of the interface inside Google Cloud Platform. +Only IPv4 is supported.`, + }, + "ipv6_nexthop_address": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ValidateFunc: verify.ValidateIpAddress, + DiffSuppressFunc: ipv6RepresentationDiffSuppress, + Description: `IPv6 address of the interface inside Google Cloud Platform. +The address must be in the range 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64. +If you do not specify the next hop addresses, Google Cloud automatically +assigns unused addresses from the 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64 range for you.`, + }, + "peer_ip_address": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `IP address of the BGP interface outside Google Cloud Platform. +Only IPv4 is supported. Required if 'ip_address' is set.`, + }, + "peer_ipv6_nexthop_address": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ValidateFunc: verify.ValidateIpAddress, + DiffSuppressFunc: ipv6RepresentationDiffSuppress, + Description: `IPv6 address of the BGP interface outside Google Cloud Platform. +The address must be in the range 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64. +If you do not specify the next hop addresses, Google Cloud automatically +assigns unused addresses from the 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64 range for you.`, + }, + "region": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `Region where the router and BgpPeer reside. +If it is not provided, the provider region is used.`, + }, + "router_appliance_instance": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + Description: `The URI of the VM instance that is used as third-party router appliances +such as Next Gen Firewalls, Virtual Routers, or Router Appliances. +The VM instance must be located in zones contained in the same region as +this Cloud Router. The VM instance is the peer side of the BGP session.`, + }, + "management_type": { + Type: schema.TypeString, + Computed: true, + Description: `The resource that configures and manages this BGP peer. + +* 'MANAGED_BY_USER' is the default value and can be managed by +you or other users +* 'MANAGED_BY_ATTACHMENT' is a BGP peer that is configured and +managed by Cloud Interconnect, specifically by an +InterconnectAttachment of type PARTNER. Google automatically +creates, updates, and deletes this type of BGP peer when the +PARTNER InterconnectAttachment is created, updated, +or deleted.`, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + UseJSONNumber: true, + } +} + +func resourceComputeRouterBgpPeerCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + nameProp, err := expandNestedComputeRouterBgpPeerName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !tpgresource.IsEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + interfaceNameProp, err := expandNestedComputeRouterBgpPeerInterface(d.Get("interface"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("interface"); !tpgresource.IsEmptyValue(reflect.ValueOf(interfaceNameProp)) && (ok || !reflect.DeepEqual(v, interfaceNameProp)) { + obj["interfaceName"] = interfaceNameProp + } + ipAddressProp, err := expandNestedComputeRouterBgpPeerIpAddress(d.Get("ip_address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ip_address"); !tpgresource.IsEmptyValue(reflect.ValueOf(ipAddressProp)) && (ok || !reflect.DeepEqual(v, ipAddressProp)) { + obj["ipAddress"] = ipAddressProp + } + peerIpAddressProp, err := expandNestedComputeRouterBgpPeerPeerIpAddress(d.Get("peer_ip_address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("peer_ip_address"); !tpgresource.IsEmptyValue(reflect.ValueOf(peerIpAddressProp)) && (ok || !reflect.DeepEqual(v, peerIpAddressProp)) { + obj["peerIpAddress"] = peerIpAddressProp + } + peerAsnProp, err := expandNestedComputeRouterBgpPeerPeerAsn(d.Get("peer_asn"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("peer_asn"); !tpgresource.IsEmptyValue(reflect.ValueOf(peerAsnProp)) && (ok || !reflect.DeepEqual(v, peerAsnProp)) { + obj["peerAsn"] = peerAsnProp + } + advertisedRoutePriorityProp, err := expandNestedComputeRouterBgpPeerAdvertisedRoutePriority(d.Get("advertised_route_priority"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("advertised_route_priority"); ok || !reflect.DeepEqual(v, advertisedRoutePriorityProp) { + obj["advertisedRoutePriority"] = advertisedRoutePriorityProp + } + advertiseModeProp, err := expandNestedComputeRouterBgpPeerAdvertiseMode(d.Get("advertise_mode"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("advertise_mode"); !tpgresource.IsEmptyValue(reflect.ValueOf(advertiseModeProp)) && (ok || !reflect.DeepEqual(v, advertiseModeProp)) { + obj["advertiseMode"] = advertiseModeProp + } + advertisedGroupsProp, err := expandNestedComputeRouterBgpPeerAdvertisedGroups(d.Get("advertised_groups"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("advertised_groups"); ok || !reflect.DeepEqual(v, advertisedGroupsProp) { + obj["advertisedGroups"] = advertisedGroupsProp + } + advertisedIpRangesProp, err := expandNestedComputeRouterBgpPeerAdvertisedIpRanges(d.Get("advertised_ip_ranges"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("advertised_ip_ranges"); ok || !reflect.DeepEqual(v, advertisedIpRangesProp) { + obj["advertisedIpRanges"] = advertisedIpRangesProp + } + bfdProp, err := expandNestedComputeRouterBgpPeerBfd(d.Get("bfd"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("bfd"); !tpgresource.IsEmptyValue(reflect.ValueOf(bfdProp)) && (ok || !reflect.DeepEqual(v, bfdProp)) { + obj["bfd"] = bfdProp + } + enableProp, err := expandNestedComputeRouterBgpPeerEnable(d.Get("enable"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable"); ok || !reflect.DeepEqual(v, enableProp) { + obj["enable"] = enableProp + } + routerApplianceInstanceProp, err := expandNestedComputeRouterBgpPeerRouterApplianceInstance(d.Get("router_appliance_instance"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("router_appliance_instance"); !tpgresource.IsEmptyValue(reflect.ValueOf(routerApplianceInstanceProp)) && (ok || !reflect.DeepEqual(v, routerApplianceInstanceProp)) { + obj["routerApplianceInstance"] = routerApplianceInstanceProp + } + enableIpv6Prop, err := expandNestedComputeRouterBgpPeerEnableIpv6(d.Get("enable_ipv6"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_ipv6"); ok || !reflect.DeepEqual(v, enableIpv6Prop) { + obj["enableIpv6"] = enableIpv6Prop + } + ipv6NexthopAddressProp, err := expandNestedComputeRouterBgpPeerIpv6NexthopAddress(d.Get("ipv6_nexthop_address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ipv6_nexthop_address"); !tpgresource.IsEmptyValue(reflect.ValueOf(ipv6NexthopAddressProp)) && (ok || !reflect.DeepEqual(v, ipv6NexthopAddressProp)) { + obj["ipv6NexthopAddress"] = ipv6NexthopAddressProp + } + peerIpv6NexthopAddressProp, err := expandNestedComputeRouterBgpPeerPeerIpv6NexthopAddress(d.Get("peer_ipv6_nexthop_address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("peer_ipv6_nexthop_address"); !tpgresource.IsEmptyValue(reflect.ValueOf(peerIpv6NexthopAddressProp)) && (ok || !reflect.DeepEqual(v, peerIpv6NexthopAddressProp)) { + obj["peerIpv6NexthopAddress"] = peerIpv6NexthopAddressProp + } + + lockName, err := tpgresource.ReplaceVars(d, config, "router/{{region}}/{{router}}") + if err != nil { + return err + } + transport_tpg.MutexStore.Lock(lockName) + defer transport_tpg.MutexStore.Unlock(lockName) + + url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/routers/{{router}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new RouterBgpPeer: %#v", obj) + + obj, err = resourceComputeRouterBgpPeerPatchCreateEncoder(d, meta, obj) + if err != nil { + return err + } + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RouterBgpPeer: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutCreate), + }) + if err != nil { + return fmt.Errorf("Error creating RouterBgpPeer: %s", err) + } + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/regions/{{region}}/routers/{{router}}/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + err = ComputeOperationWaitTime( + config, res, project, "Creating RouterBgpPeer", userAgent, + d.Timeout(schema.TimeoutCreate)) + + if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create RouterBgpPeer: %s", err) + } + + log.Printf("[DEBUG] Finished creating RouterBgpPeer %q: %#v", d.Id(), res) + + return resourceComputeRouterBgpPeerRead(d, meta) +} + +func resourceComputeRouterBgpPeerRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/routers/{{router}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RouterBgpPeer: %s", err) + } + billingProject = project + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("ComputeRouterBgpPeer %q", d.Id())) + } + + res, err = flattenNestedComputeRouterBgpPeer(d, meta, res) + if err != nil { + return err + } + + if res == nil { + // Object isn't there any more - remove it from the state. + log.Printf("[DEBUG] Removing ComputeRouterBgpPeer because it couldn't be matched.") + d.SetId("") + return nil + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + + if err := d.Set("name", flattenNestedComputeRouterBgpPeerName(res["name"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("interface", flattenNestedComputeRouterBgpPeerInterface(res["interfaceName"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("ip_address", flattenNestedComputeRouterBgpPeerIpAddress(res["ipAddress"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("peer_ip_address", flattenNestedComputeRouterBgpPeerPeerIpAddress(res["peerIpAddress"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("peer_asn", flattenNestedComputeRouterBgpPeerPeerAsn(res["peerAsn"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("advertised_route_priority", flattenNestedComputeRouterBgpPeerAdvertisedRoutePriority(res["advertisedRoutePriority"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("advertise_mode", flattenNestedComputeRouterBgpPeerAdvertiseMode(res["advertiseMode"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("advertised_groups", flattenNestedComputeRouterBgpPeerAdvertisedGroups(res["advertisedGroups"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("advertised_ip_ranges", flattenNestedComputeRouterBgpPeerAdvertisedIpRanges(res["advertisedIpRanges"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("management_type", flattenNestedComputeRouterBgpPeerManagementType(res["managementType"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("bfd", flattenNestedComputeRouterBgpPeerBfd(res["bfd"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("enable", flattenNestedComputeRouterBgpPeerEnable(res["enable"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("router_appliance_instance", flattenNestedComputeRouterBgpPeerRouterApplianceInstance(res["routerApplianceInstance"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("enable_ipv6", flattenNestedComputeRouterBgpPeerEnableIpv6(res["enableIpv6"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("ipv6_nexthop_address", flattenNestedComputeRouterBgpPeerIpv6NexthopAddress(res["ipv6NexthopAddress"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + if err := d.Set("peer_ipv6_nexthop_address", flattenNestedComputeRouterBgpPeerPeerIpv6NexthopAddress(res["peerIpv6NexthopAddress"], d, config)); err != nil { + return fmt.Errorf("Error reading RouterBgpPeer: %s", err) + } + + return nil +} + +func resourceComputeRouterBgpPeerUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RouterBgpPeer: %s", err) + } + billingProject = project + + obj := make(map[string]interface{}) + ipAddressProp, err := expandNestedComputeRouterBgpPeerIpAddress(d.Get("ip_address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ip_address"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, ipAddressProp)) { + obj["ipAddress"] = ipAddressProp + } + peerIpAddressProp, err := expandNestedComputeRouterBgpPeerPeerIpAddress(d.Get("peer_ip_address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("peer_ip_address"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, peerIpAddressProp)) { + obj["peerIpAddress"] = peerIpAddressProp + } + peerAsnProp, err := expandNestedComputeRouterBgpPeerPeerAsn(d.Get("peer_asn"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("peer_asn"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, peerAsnProp)) { + obj["peerAsn"] = peerAsnProp + } + advertisedRoutePriorityProp, err := expandNestedComputeRouterBgpPeerAdvertisedRoutePriority(d.Get("advertised_route_priority"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("advertised_route_priority"); ok || !reflect.DeepEqual(v, advertisedRoutePriorityProp) { + obj["advertisedRoutePriority"] = advertisedRoutePriorityProp + } + advertiseModeProp, err := expandNestedComputeRouterBgpPeerAdvertiseMode(d.Get("advertise_mode"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("advertise_mode"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, advertiseModeProp)) { + obj["advertiseMode"] = advertiseModeProp + } + advertisedGroupsProp, err := expandNestedComputeRouterBgpPeerAdvertisedGroups(d.Get("advertised_groups"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("advertised_groups"); ok || !reflect.DeepEqual(v, advertisedGroupsProp) { + obj["advertisedGroups"] = advertisedGroupsProp + } + advertisedIpRangesProp, err := expandNestedComputeRouterBgpPeerAdvertisedIpRanges(d.Get("advertised_ip_ranges"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("advertised_ip_ranges"); ok || !reflect.DeepEqual(v, advertisedIpRangesProp) { + obj["advertisedIpRanges"] = advertisedIpRangesProp + } + bfdProp, err := expandNestedComputeRouterBgpPeerBfd(d.Get("bfd"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("bfd"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, bfdProp)) { + obj["bfd"] = bfdProp + } + enableProp, err := expandNestedComputeRouterBgpPeerEnable(d.Get("enable"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable"); ok || !reflect.DeepEqual(v, enableProp) { + obj["enable"] = enableProp + } + routerApplianceInstanceProp, err := expandNestedComputeRouterBgpPeerRouterApplianceInstance(d.Get("router_appliance_instance"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("router_appliance_instance"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, routerApplianceInstanceProp)) { + obj["routerApplianceInstance"] = routerApplianceInstanceProp + } + enableIpv6Prop, err := expandNestedComputeRouterBgpPeerEnableIpv6(d.Get("enable_ipv6"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("enable_ipv6"); ok || !reflect.DeepEqual(v, enableIpv6Prop) { + obj["enableIpv6"] = enableIpv6Prop + } + ipv6NexthopAddressProp, err := expandNestedComputeRouterBgpPeerIpv6NexthopAddress(d.Get("ipv6_nexthop_address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("ipv6_nexthop_address"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, ipv6NexthopAddressProp)) { + obj["ipv6NexthopAddress"] = ipv6NexthopAddressProp + } + peerIpv6NexthopAddressProp, err := expandNestedComputeRouterBgpPeerPeerIpv6NexthopAddress(d.Get("peer_ipv6_nexthop_address"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("peer_ipv6_nexthop_address"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, peerIpv6NexthopAddressProp)) { + obj["peerIpv6NexthopAddress"] = peerIpv6NexthopAddressProp + } + + lockName, err := tpgresource.ReplaceVars(d, config, "router/{{region}}/{{router}}") + if err != nil { + return err + } + transport_tpg.MutexStore.Lock(lockName) + defer transport_tpg.MutexStore.Unlock(lockName) + + url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/routers/{{router}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating RouterBgpPeer %q: %#v", d.Id(), obj) + + obj, err = resourceComputeRouterBgpPeerPatchUpdateEncoder(d, meta, obj) + if err != nil { + return err + } + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + + if err != nil { + return fmt.Errorf("Error updating RouterBgpPeer %q: %s", d.Id(), err) + } else { + log.Printf("[DEBUG] Finished updating RouterBgpPeer %q: %#v", d.Id(), res) + } + + err = ComputeOperationWaitTime( + config, res, project, "Updating RouterBgpPeer", userAgent, + d.Timeout(schema.TimeoutUpdate)) + + if err != nil { + return err + } + + return resourceComputeRouterBgpPeerRead(d, meta) +} + +func resourceComputeRouterBgpPeerDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for RouterBgpPeer: %s", err) + } + billingProject = project + + lockName, err := tpgresource.ReplaceVars(d, config, "router/{{region}}/{{router}}") + if err != nil { + return err + } + transport_tpg.MutexStore.Lock(lockName) + defer transport_tpg.MutexStore.Unlock(lockName) + + url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/routers/{{router}}") + if err != nil { + return err + } + + var obj map[string]interface{} + + obj, err = resourceComputeRouterBgpPeerPatchDeleteEncoder(d, meta, obj) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "RouterBgpPeer") + } + log.Printf("[DEBUG] Deleting RouterBgpPeer %q", d.Id()) + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "PATCH", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "RouterBgpPeer") + } + + err = ComputeOperationWaitTime( + config, res, project, "Deleting RouterBgpPeer", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting RouterBgpPeer %q: %#v", d.Id(), res) + return nil +} + +func resourceComputeRouterBgpPeerImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*transport_tpg.Config) + if err := tpgresource.ParseImportId([]string{ + "^projects/(?P[^/]+)/regions/(?P[^/]+)/routers/(?P[^/]+)/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)/(?P[^/]+)$", + "^(?P[^/]+)/(?P[^/]+)$", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/regions/{{region}}/routers/{{router}}/{{name}}") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} + +func flattenNestedComputeRouterBgpPeerName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerInterface(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerIpAddress(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerPeerIpAddress(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerPeerAsn(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNestedComputeRouterBgpPeerAdvertisedRoutePriority(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNestedComputeRouterBgpPeerAdvertiseMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil || tpgresource.IsEmptyValue(reflect.ValueOf(v)) { + return "DEFAULT" + } + + return v +} + +func flattenNestedComputeRouterBgpPeerAdvertisedGroups(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "range": flattenNestedComputeRouterBgpPeerAdvertisedIpRangesRange(original["range"], d, config), + "description": flattenNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(original["description"], d, config), + }) + } + return transformed +} +func flattenNestedComputeRouterBgpPeerAdvertisedIpRangesRange(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerManagementType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerBfd(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["session_initialization_mode"] = + flattenNestedComputeRouterBgpPeerBfdSessionInitializationMode(original["sessionInitializationMode"], d, config) + transformed["min_transmit_interval"] = + flattenNestedComputeRouterBgpPeerBfdMinTransmitInterval(original["minTransmitInterval"], d, config) + transformed["min_receive_interval"] = + flattenNestedComputeRouterBgpPeerBfdMinReceiveInterval(original["minReceiveInterval"], d, config) + transformed["multiplier"] = + flattenNestedComputeRouterBgpPeerBfdMultiplier(original["multiplier"], d, config) + return []interface{}{transformed} +} +func flattenNestedComputeRouterBgpPeerBfdSessionInitializationMode(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerBfdMinTransmitInterval(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNestedComputeRouterBgpPeerBfdMinReceiveInterval(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNestedComputeRouterBgpPeerBfdMultiplier(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenNestedComputeRouterBgpPeerEnable(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return true + } + b, err := strconv.ParseBool(v.(string)) + if err != nil { + // If we can't convert it into a bool return value as is and let caller handle it + return v + } + return b +} + +func flattenNestedComputeRouterBgpPeerRouterApplianceInstance(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + return tpgresource.ConvertSelfLinkToV1(v.(string)) +} + +func flattenNestedComputeRouterBgpPeerEnableIpv6(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerIpv6NexthopAddress(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedComputeRouterBgpPeerPeerIpv6NexthopAddress(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func expandNestedComputeRouterBgpPeerName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerInterface(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerIpAddress(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerPeerIpAddress(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerPeerAsn(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerAdvertisedRoutePriority(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerAdvertiseMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerAdvertisedGroups(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerAdvertisedIpRanges(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedRange, err := expandNestedComputeRouterBgpPeerAdvertisedIpRangesRange(original["range"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRange); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["range"] = transformedRange + } + + transformedDescription, err := expandNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(original["description"], d, config) + if err != nil { + return nil, err + } else { + transformed["description"] = transformedDescription + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNestedComputeRouterBgpPeerAdvertisedIpRangesRange(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerAdvertisedIpRangesDescription(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerBfd(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedSessionInitializationMode, err := expandNestedComputeRouterBgpPeerBfdSessionInitializationMode(original["session_initialization_mode"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSessionInitializationMode); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sessionInitializationMode"] = transformedSessionInitializationMode + } + + transformedMinTransmitInterval, err := expandNestedComputeRouterBgpPeerBfdMinTransmitInterval(original["min_transmit_interval"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMinTransmitInterval); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["minTransmitInterval"] = transformedMinTransmitInterval + } + + transformedMinReceiveInterval, err := expandNestedComputeRouterBgpPeerBfdMinReceiveInterval(original["min_receive_interval"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMinReceiveInterval); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["minReceiveInterval"] = transformedMinReceiveInterval + } + + transformedMultiplier, err := expandNestedComputeRouterBgpPeerBfdMultiplier(original["multiplier"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMultiplier); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["multiplier"] = transformedMultiplier + } + + return transformed, nil +} + +func expandNestedComputeRouterBgpPeerBfdSessionInitializationMode(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerBfdMinTransmitInterval(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerBfdMinReceiveInterval(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerBfdMultiplier(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerEnable(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + if v == nil { + return nil, nil + } + + return strings.ToUpper(strconv.FormatBool(v.(bool))), nil +} + +func expandNestedComputeRouterBgpPeerRouterApplianceInstance(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + f, err := tpgresource.ParseZonalFieldValue("instances", v.(string), "project", "zone", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for router_appliance_instance: %s", err) + } + return f.RelativeLink(), nil +} + +func expandNestedComputeRouterBgpPeerEnableIpv6(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerIpv6NexthopAddress(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedComputeRouterBgpPeerPeerIpv6NexthopAddress(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func flattenNestedComputeRouterBgpPeer(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) { + var v interface{} + var ok bool + + v, ok = res["bgpPeers"] + if !ok || v == nil { + return nil, nil + } + + switch v.(type) { + case []interface{}: + break + case map[string]interface{}: + // Construct list out of single nested resource + v = []interface{}{v} + default: + return nil, fmt.Errorf("expected list or map for value bgpPeers. Actual value: %v", v) + } + + _, item, err := resourceComputeRouterBgpPeerFindNestedObjectInList(d, meta, v.([]interface{})) + if err != nil { + return nil, err + } + return item, nil +} + +func resourceComputeRouterBgpPeerFindNestedObjectInList(d *schema.ResourceData, meta interface{}, items []interface{}) (index int, item map[string]interface{}, err error) { + expectedName, err := expandNestedComputeRouterBgpPeerName(d.Get("name"), d, meta.(*transport_tpg.Config)) + if err != nil { + return -1, nil, err + } + expectedFlattenedName := flattenNestedComputeRouterBgpPeerName(expectedName, d, meta.(*transport_tpg.Config)) + + // Search list for this resource. + for idx, itemRaw := range items { + if itemRaw == nil { + continue + } + item := itemRaw.(map[string]interface{}) + + itemName := flattenNestedComputeRouterBgpPeerName(item["name"], d, meta.(*transport_tpg.Config)) + // IsEmptyValue check so that if one is nil and the other is "", that's considered a match + if !(tpgresource.IsEmptyValue(reflect.ValueOf(itemName)) && tpgresource.IsEmptyValue(reflect.ValueOf(expectedFlattenedName))) && !reflect.DeepEqual(itemName, expectedFlattenedName) { + log.Printf("[DEBUG] Skipping item with name= %#v, looking for %#v)", itemName, expectedFlattenedName) + continue + } + log.Printf("[DEBUG] Found item for resource %q: %#v)", d.Id(), item) + return idx, item, nil + } + return -1, nil, nil +} + +// PatchCreateEncoder handles creating request data to PATCH parent resource +// with list including new object. +func resourceComputeRouterBgpPeerPatchCreateEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + currItems, err := resourceComputeRouterBgpPeerListForPatch(d, meta) + if err != nil { + return nil, err + } + + _, found, err := resourceComputeRouterBgpPeerFindNestedObjectInList(d, meta, currItems) + if err != nil { + return nil, err + } + + // Return error if item already created. + if found != nil { + return nil, fmt.Errorf("Unable to create RouterBgpPeer, existing object already found: %+v", found) + } + + // Return list with the resource to create appended + res := map[string]interface{}{ + "bgpPeers": append(currItems, obj), + } + + return res, nil +} + +// PatchUpdateEncoder handles creating request data to PATCH parent resource +// with list including updated object. +func resourceComputeRouterBgpPeerPatchUpdateEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + items, err := resourceComputeRouterBgpPeerListForPatch(d, meta) + if err != nil { + return nil, err + } + + idx, item, err := resourceComputeRouterBgpPeerFindNestedObjectInList(d, meta, items) + if err != nil { + return nil, err + } + + // Return error if item to update does not exist. + if item == nil { + return nil, fmt.Errorf("Unable to update RouterBgpPeer %q - not found in list", d.Id()) + } + + // Merge new object into old. + for k, v := range obj { + item[k] = v + } + items[idx] = item + + // Return list with new item added + res := map[string]interface{}{ + "bgpPeers": items, + } + + return res, nil +} + +// PatchDeleteEncoder handles creating request data to PATCH parent resource +// with list excluding object to delete. +func resourceComputeRouterBgpPeerPatchDeleteEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + currItems, err := resourceComputeRouterBgpPeerListForPatch(d, meta) + if err != nil { + return nil, err + } + + idx, item, err := resourceComputeRouterBgpPeerFindNestedObjectInList(d, meta, currItems) + if err != nil { + return nil, err + } + if item == nil { + // Spoof 404 error for proper handling by Delete (i.e. no-op) + return nil, tpgresource.Fake404("nested", "ComputeRouterBgpPeer") + } + + updatedItems := append(currItems[:idx], currItems[idx+1:]...) + res := map[string]interface{}{ + "bgpPeers": updatedItems, + } + + return res, nil +} + +// ListForPatch handles making API request to get parent resource and +// extracting list of objects. +func resourceComputeRouterBgpPeerListForPatch(d *schema.ResourceData, meta interface{}) ([]interface{}, error) { + config := meta.(*transport_tpg.Config) + url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/routers/{{router}}") + if err != nil { + return nil, err + } + project, err := tpgresource.GetProject(d, config) + if err != nil { + return nil, err + } + + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return nil, err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: project, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return nil, err + } + + var v interface{} + var ok bool + + v, ok = res["bgpPeers"] + if ok && v != nil { + ls, lsOk := v.([]interface{}) + if !lsOk { + return nil, fmt.Errorf(`expected list for nested field "bgpPeers"`) + } + return ls, nil + } + return nil, nil +} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_router_peer_sweeper.go b/mmv1/third_party/terraform/services/compute/resource_compute_router_peer_sweeper.go new file mode 100644 index 000000000000..c174a55376d3 --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/resource_compute_router_peer_sweeper.go @@ -0,0 +1,122 @@ +package compute + +import ( + "context" + "log" + "strings" + "testing" + + "github.com/hashicorp/terraform-provider-google/google/envvar" + "github.com/hashicorp/terraform-provider-google/google/sweeper" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func init() { + sweeper.AddTestSweepers("ComputeRouterBgpPeer", testSweepComputeRouterBgpPeer) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepComputeRouterBgpPeer(region string) error { + resourceName := "ComputeRouterBgpPeer" + log.Printf("[INFO][SWEEPER_LOG] Starting sweeper for %s", resourceName) + + config, err := sweeper.SharedConfigForRegion(region) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error getting shared config for region: %s", err) + return err + } + + err = config.LoadAndValidate(context.Background()) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error loading: %s", err) + return err + } + + t := &testing.T{} + billingId := envvar.GetTestBillingAccountFromEnv(t) + + // Setup variables to replace in list template + d := &tpgresource.ResourceDataMock{ + FieldsInSchema: map[string]interface{}{ + "project": config.Project, + "region": region, + "location": region, + "zone": "-", + "billing_account": billingId, + }, + } + + listTemplate := strings.Split("https://compute.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/routers/{{router}}", "?")[0] + listUrl, err := tpgresource.ReplaceVars(d, config, listTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing sweeper list url: %s", err) + return nil + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: config.Project, + RawURL: listUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error in response from request %s: %s", listUrl, err) + return nil + } + + resourceList, ok := res["bgpPeers"] + if !ok { + log.Printf("[INFO][SWEEPER_LOG] Nothing found in response.") + return nil + } + + rl := resourceList.([]interface{}) + + log.Printf("[INFO][SWEEPER_LOG] Found %d items in %s list response.", len(rl), resourceName) + // Keep count of items that aren't sweepable for logging. + nonPrefixCount := 0 + for _, ri := range rl { + obj := ri.(map[string]interface{}) + if obj["name"] == nil { + log.Printf("[INFO][SWEEPER_LOG] %s resource name was nil", resourceName) + return nil + } + + name := tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://compute.googleapis.com/compute/v1/projects/{{project}}/regions/{{region}}/routers/{{router}}" + deleteUrl, err := tpgresource.ReplaceVars(d, config, deleteTemplate) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] error preparing delete url: %s", err) + return nil + } + deleteUrl = deleteUrl + name + + // Don't wait on operations as we may have a lot to delete + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: config.Project, + RawURL: deleteUrl, + UserAgent: config.UserAgent, + }) + if err != nil { + log.Printf("[INFO][SWEEPER_LOG] Error deleting for url %s : %s", deleteUrl, err) + } else { + log.Printf("[INFO][SWEEPER_LOG] Sent delete request for %s resource: %s", resourceName, name) + } + } + + if nonPrefixCount > 0 { + log.Printf("[INFO][SWEEPER_LOG] %d items were non-sweepable and skipped.", nonPrefixCount) + } + + return nil +} diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_router_peer_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_router_peer_test.go.erb new file mode 100644 index 000000000000..e9545df09dcc --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/resource_compute_router_peer_test.go.erb @@ -0,0 +1,188 @@ +<% autogen_exception -%> +package compute_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccComputeRouterBgpPeer_routerPeerRouterAppliance(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeRouterBgpPeerDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRouterBgpPeer_routerPeerRouterAppliance(context), + }, + { + ResourceName: "google_compute_router_peer.peer", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"router_appliance_instance", "router", "region"}, + }, + }, + }) +} + +func testAccComputeRouterBgpPeer_routerPeerRouterAppliance(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "network" { + name = "tf-test-my-router%{random_suffix}-net" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "subnetwork" { + name = "tf-test-my-router%{random_suffix}-sub" + network = google_compute_network.network.self_link + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" +} + +resource "google_compute_address" "addr_intf" { + name = "tf-test-my-router%{random_suffix}-addr-intf" + region = google_compute_subnetwork.subnetwork.region + subnetwork = google_compute_subnetwork.subnetwork.id + address_type = "INTERNAL" +} + +resource "google_compute_address" "addr_intf_redundant" { + name = "tf-test-my-router%{random_suffix}-addr-intf-red" + region = google_compute_subnetwork.subnetwork.region + subnetwork = google_compute_subnetwork.subnetwork.id + address_type = "INTERNAL" +} + +resource "google_compute_address" "addr_peer" { + name = "tf-test-my-router%{random_suffix}-addr-peer" + region = google_compute_subnetwork.subnetwork.region + subnetwork = google_compute_subnetwork.subnetwork.id + address_type = "INTERNAL" +} + +resource "google_compute_instance" "instance" { + name = "router-appliance" + zone = "us-central1-a" + machine_type = "e2-medium" + can_ip_forward = true + + boot_disk { + initialize_params { + image = "debian-cloud/debian-11" + } + } + + network_interface { + network_ip = google_compute_address.addr_peer.address + subnetwork = google_compute_subnetwork.subnetwork.self_link + } +} + +resource "google_network_connectivity_hub" "hub" { + name = "tf-test-my-router%{random_suffix}-hub" +} + +resource "google_network_connectivity_spoke" "spoke" { + name = "tf-test-my-router%{random_suffix}-spoke" + location = google_compute_subnetwork.subnetwork.region + hub = google_network_connectivity_hub.hub.id + + linked_router_appliance_instances { + instances { + virtual_machine = google_compute_instance.instance.self_link + ip_address = google_compute_address.addr_peer.address + } + site_to_site_data_transfer = false + } +} + +resource "google_compute_router" "router" { + name = "tf-test-my-router%{random_suffix}-router" + region = google_compute_subnetwork.subnetwork.region + network = google_compute_network.network.self_link + bgp { + asn = 64514 + } +} + +resource "google_compute_router_interface" "interface_redundant" { + name = "tf-test-my-router%{random_suffix}-intf-red" + region = google_compute_router.router.region + router = google_compute_router.router.name + subnetwork = google_compute_subnetwork.subnetwork.self_link + private_ip_address = google_compute_address.addr_intf_redundant.address +} + +resource "google_compute_router_interface" "interface" { + name = "tf-test-my-router%{random_suffix}-intf" + region = google_compute_router.router.region + router = google_compute_router.router.name + subnetwork = google_compute_subnetwork.subnetwork.self_link + private_ip_address = google_compute_address.addr_intf.address + redundant_interface = google_compute_router_interface.interface_redundant.name +} + +resource "google_compute_router_peer" "peer" { + name = "tf-test-my-router-peer%{random_suffix}" + router = google_compute_router.router.name + region = google_compute_router.router.region + interface = google_compute_router_interface.interface.name + router_appliance_instance = google_compute_instance.instance.self_link + peer_asn = 65513 + peer_ip_address = google_compute_address.addr_peer.address +} +`, context) +} + +func testAccCheckComputeRouterBgpPeerDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_router_peer" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/routers/{{router}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("ComputeRouterBgpPeer still exists at %s", url) + } + } + + return nil + } +} diff --git a/mmv1/third_party/terraform/website/docs/r/compute_router_peer.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_router_peer.html.markdown new file mode 100644 index 000000000000..b5d755cb8261 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/r/compute_router_peer.html.markdown @@ -0,0 +1,410 @@ +--- +subcategory: "Compute Engine" +description: |- + BGP information that must be configured into the routing stack to + establish BGP peering. +--- + +# google\_compute\_router\_peer + +BGP information that must be configured into the routing stack to +establish BGP peering. This information must specify the peer ASN +and either the interface name, IP address, or peer IP address. +Please refer to RFC4273. + + +To get more information about RouterBgpPeer, see: + +* [API documentation](https://cloud.google.com/compute/docs/reference/rest/v1/routers) +* How-to Guides + * [Google Cloud Router](https://cloud.google.com/router/docs/) + +## Example Usage - Router Peer Basic + + +```hcl +resource "google_compute_router_peer" "peer" { + name = "my-router-peer" + router = "my-router" + region = "us-central1" + peer_asn = 65513 + advertised_route_priority = 100 + interface = "interface-1" +} +``` +## Example Usage - Router Peer Disabled + + +```hcl +resource "google_compute_router_peer" "peer" { + name = "my-router-peer" + router = "my-router" + region = "us-central1" + peer_ip_address = "169.254.1.2" + peer_asn = 65513 + advertised_route_priority = 100 + interface = "interface-1" + enable = false +} +``` +## Example Usage - Router Peer Bfd + + +```hcl +resource "google_compute_router_peer" "peer" { + name = "my-router-peer" + router = "my-router" + region = "us-central1" + peer_ip_address = "169.254.1.2" + peer_asn = 65513 + advertised_route_priority = 100 + interface = "interface-1" + + bfd { + min_receive_interval = 1000 + min_transmit_interval = 1000 + multiplier = 5 + session_initialization_mode = "ACTIVE" + } +} +``` + +## Example Usage - Router Peer Router Appliance + + +```hcl +resource "google_compute_network" "network" { + name = "my-router-net" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "subnetwork" { + name = "my-router-sub" + network = google_compute_network.network.self_link + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" +} + +resource "google_compute_address" "addr_intf" { + name = "my-router-addr-intf" + region = google_compute_subnetwork.subnetwork.region + subnetwork = google_compute_subnetwork.subnetwork.id + address_type = "INTERNAL" +} + +resource "google_compute_address" "addr_intf_redundant" { + name = "my-router-addr-intf-red" + region = google_compute_subnetwork.subnetwork.region + subnetwork = google_compute_subnetwork.subnetwork.id + address_type = "INTERNAL" +} + +resource "google_compute_address" "addr_peer" { + name = "my-router-addr-peer" + region = google_compute_subnetwork.subnetwork.region + subnetwork = google_compute_subnetwork.subnetwork.id + address_type = "INTERNAL" +} + +resource "google_compute_instance" "instance" { + name = "router-appliance" + zone = "us-central1-a" + machine_type = "e2-medium" + can_ip_forward = true + + boot_disk { + initialize_params { + image = "debian-cloud/debian-11" + } + } + + network_interface { + network_ip = google_compute_address.addr_peer.address + subnetwork = google_compute_subnetwork.subnetwork.self_link + } +} + +resource "google_network_connectivity_hub" "hub" { + name = "my-router-hub" +} + +resource "google_network_connectivity_spoke" "spoke" { + name = "my-router-spoke" + location = google_compute_subnetwork.subnetwork.region + hub = google_network_connectivity_hub.hub.id + + linked_router_appliance_instances { + instances { + virtual_machine = google_compute_instance.instance.self_link + ip_address = google_compute_address.addr_peer.address + } + site_to_site_data_transfer = false + } +} + +resource "google_compute_router" "router" { + name = "my-router-router" + region = google_compute_subnetwork.subnetwork.region + network = google_compute_network.network.self_link + bgp { + asn = 64514 + } +} + +resource "google_compute_router_interface" "interface_redundant" { + name = "my-router-intf-red" + region = google_compute_router.router.region + router = google_compute_router.router.name + subnetwork = google_compute_subnetwork.subnetwork.self_link + private_ip_address = google_compute_address.addr_intf_redundant.address +} + +resource "google_compute_router_interface" "interface" { + name = "my-router-intf" + region = google_compute_router.router.region + router = google_compute_router.router.name + subnetwork = google_compute_subnetwork.subnetwork.self_link + private_ip_address = google_compute_address.addr_intf.address + redundant_interface = google_compute_router_interface.interface_redundant.name +} + +resource "google_compute_router_peer" "peer" { + name = "my-router-peer" + router = google_compute_router.router.name + region = google_compute_router.router.region + interface = google_compute_router_interface.interface.name + router_appliance_instance = google_compute_instance.instance.self_link + peer_asn = 65513 + peer_ip_address = google_compute_address.addr_peer.address +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `name` - + (Required) + Name of this BGP peer. 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. + +* `interface` - + (Required) + Name of the interface the BGP peer is associated with. + +* `peer_asn` - + (Required) + Peer BGP Autonomous System Number (ASN). + Each BGP interface may use a different value. + +* `router` - + (Required) + The name of the Cloud Router in which this BgpPeer will be configured. + + +- - - + + +* `ip_address` - + (Optional) + IP address of the interface inside Google Cloud Platform. + Only IPv4 is supported. + +* `peer_ip_address` - + (Optional) + IP address of the BGP interface outside Google Cloud Platform. + Only IPv4 is supported. Required if `ip_address` is set. + +* `advertised_route_priority` - + (Optional) + The priority of routes advertised to this BGP peer. + Where there is more than one matching route of maximum + length, the routes with the lowest priority value win. + +* `advertise_mode` - + (Optional) + User-specified flag to indicate which mode to use for advertisement. + Valid values of this enum field are: `DEFAULT`, `CUSTOM` + Default value is `DEFAULT`. + Possible values are: `DEFAULT`, `CUSTOM`. + +* `advertised_groups` - + (Optional) + User-specified list of prefix groups to advertise in custom + mode, which currently supports the following option: + * `ALL_SUBNETS`: Advertises all of the router's own VPC subnets. + This excludes any routes learned for subnets that use VPC Network + Peering. + + Note that this field can only be populated if advertiseMode is `CUSTOM` + and overrides the list defined for the router (in the "bgp" message). + These groups are advertised in addition to any specified prefixes. + Leave this field blank to advertise no custom groups. + +* `advertised_ip_ranges` - + (Optional) + User-specified list of individual IP ranges to advertise in + custom mode. This field can only be populated if advertiseMode + is `CUSTOM` and is advertised to all peers of the router. These IP + ranges will be advertised in addition to any specified groups. + Leave this field blank to advertise no custom IP ranges. + Structure is [documented below](#nested_advertised_ip_ranges). + +* `bfd` - + (Optional) + BFD configuration for the BGP peering. + Structure is [documented below](#nested_bfd). + +* `enable` - + (Optional) + The status of the BGP peer connection. If set to false, any active session + with the peer is terminated and all associated routing information is removed. + If set to true, the peer connection can be established with routing information. + The default is true. + +* `router_appliance_instance` - + (Optional) + The URI of the VM instance that is used as third-party router appliances + such as Next Gen Firewalls, Virtual Routers, or Router Appliances. + The VM instance must be located in zones contained in the same region as + this Cloud Router. The VM instance is the peer side of the BGP session. + +* `enable_ipv6` - + (Optional) + Enable IPv6 traffic over BGP Peer. If not specified, it is disabled by default. + +* `ipv6_nexthop_address` - + (Optional) + IPv6 address of the interface inside Google Cloud Platform. + The address must be in the range 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64. + If you do not specify the next hop addresses, Google Cloud automatically + assigns unused addresses from the 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64 range for you. + +* `peer_ipv6_nexthop_address` - + (Optional) + IPv6 address of the BGP interface outside Google Cloud Platform. + The address must be in the range 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64. + If you do not specify the next hop addresses, Google Cloud automatically + assigns unused addresses from the 2600:2d00:0:2::/64 or 2600:2d00:0:3::/64 range for you. + +* `region` - + (Optional) + Region where the router and BgpPeer reside. + If it is not provided, the provider region is used. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + + +The `advertised_ip_ranges` block supports: + +* `range` - + (Required) + The IP range to advertise. The value must be a + CIDR-formatted string. + +* `description` - + (Optional) + User-specified description for the IP range. + +The `bfd` block supports: + +* `session_initialization_mode` - + (Required) + The BFD session initialization mode for this BGP peer. + If set to `ACTIVE`, the Cloud Router will initiate the BFD session + for this BGP peer. If set to `PASSIVE`, the Cloud Router will wait + for the peer router to initiate the BFD session for this BGP peer. + If set to `DISABLED`, BFD is disabled for this BGP peer. + Possible values are: `ACTIVE`, `DISABLED`, `PASSIVE`. + +* `min_transmit_interval` - + (Optional) + The minimum interval, in milliseconds, between BFD control packets + transmitted to the peer router. The actual value is negotiated + between the two routers and is equal to the greater of this value + and the corresponding receive interval of the other router. If set, + this value must be between 1000 and 30000. + +* `min_receive_interval` - + (Optional) + The minimum interval, in milliseconds, between BFD control packets + received from the peer router. The actual value is negotiated + between the two routers and is equal to the greater of this value + and the transmit interval of the other router. If set, this value + must be between 1000 and 30000. + +* `multiplier` - + (Optional) + The number of consecutive BFD packets that must be missed before + BFD declares that a peer is unavailable. If set, the value must + be a value between 5 and 16. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/regions/{{region}}/routers/{{router}}/{{name}}` + +* `management_type` - + The resource that configures and manages this BGP peer. + * `MANAGED_BY_USER` is the default value and can be managed by + you or other users + * `MANAGED_BY_ATTACHMENT` is a BGP peer that is configured and + managed by Cloud Interconnect, specifically by an + InterconnectAttachment of type PARTNER. Google automatically + creates, updates, and deletes this type of BGP peer when the + PARTNER InterconnectAttachment is created, updated, + or deleted. + + +## Timeouts + +This resource provides the following +[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + + +RouterBgpPeer can be imported using any of these accepted formats: + +* `projects/{{project}}/regions/{{region}}/routers/{{router}}/{{name}}` +* `{{project}}/{{region}}/{{router}}/{{name}}` +* `{{region}}/{{router}}/{{name}}` +* `{{router}}/{{name}}` + + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import RouterBgpPeer using one of the formats above. For example: + +```tf +import { + id = "projects/{{project}}/regions/{{region}}/routers/{{router}}/{{name}}" + to = google_compute_router_peer.default +} +``` + +When using the [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import), RouterBgpPeer can be imported using one of the formats above. For example: + +``` +$ terraform import google_compute_router_peer.default projects/{{project}}/regions/{{region}}/routers/{{router}}/{{name}} +$ terraform import google_compute_router_peer.default {{project}}/{{region}}/{{router}}/{{name}} +$ terraform import google_compute_router_peer.default {{region}}/{{router}}/{{name}} +$ terraform import google_compute_router_peer.default {{router}}/{{name}} +``` + +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override). From cc5606ed9072cb2cea144c1769d601d71bdc8ed1 Mon Sep 17 00:00:00 2001 From: kautikdk <144651627+kautikdk@users.noreply.github.com> Date: Tue, 5 Dec 2023 21:27:55 +0000 Subject: [PATCH 065/107] Fix Adding Unexpected Conditions (#9547) * Fix Adding Unexpected Conditions * Adds no_age field * Modify no_age description and variables name. Adds relevant comments. * Fixes Build Failure * Fixes indent issues and removes unnecessary condition. * Modified condition to include case when no_age is not present in the file. --- .../storage/resource_storage_bucket.go.erb | 42 ++++-- .../resource_storage_bucket_test.go.erb | 126 ++++++++++++++++++ .../docs/r/storage_bucket.html.markdown | 2 + 3 files changed, 159 insertions(+), 11 deletions(-) diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb index 7703e96c17f2..ca2ca5749529 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb @@ -217,6 +217,11 @@ func ResourceStorageBucket() *schema.Resource { Optional: true, Description: `Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.`, }, + "no_age": { + Type: schema.TypeBool, + Optional: true, + Description: `While set true, age value will be omitted.Required to set true when age is unset in the config file.`, + }, "with_state": { Type: schema.TypeString, Computed: true, @@ -1206,7 +1211,7 @@ func flattenBucketAutoclass(bucketAutoclass *storage.BucketAutoclass) []map[stri return autoclassList } -func flattenBucketLifecycle(lifecycle *storage.BucketLifecycle) []map[string]interface{} { +func flattenBucketLifecycle(d *schema.ResourceData, lifecycle *storage.BucketLifecycle) []map[string]interface{} { if lifecycle == nil || lifecycle.Rule == nil { return []map[string]interface{}{} } @@ -1216,7 +1221,7 @@ func flattenBucketLifecycle(lifecycle *storage.BucketLifecycle) []map[string]int for _, rule := range lifecycle.Rule { rules = append(rules, map[string]interface{}{ "action": schema.NewSet(resourceGCSBucketLifecycleRuleActionHash, []interface{}{flattenBucketLifecycleRuleAction(rule.Action)}), - "condition": schema.NewSet(resourceGCSBucketLifecycleRuleConditionHash, []interface{}{flattenBucketLifecycleRuleCondition(rule.Condition)}), + "condition": schema.NewSet(resourceGCSBucketLifecycleRuleConditionHash, []interface{}{flattenBucketLifecycleRuleCondition(d, rule.Condition)}), }) } @@ -1230,7 +1235,7 @@ func flattenBucketLifecycleRuleAction(action *storage.BucketLifecycleRuleAction) } } -func flattenBucketLifecycleRuleCondition(condition *storage.BucketLifecycleRuleCondition) map[string]interface{} { +func flattenBucketLifecycleRuleCondition(d *schema.ResourceData, condition *storage.BucketLifecycleRuleCondition) map[string]interface{} { ruleCondition := map[string]interface{}{ "created_before": condition.CreatedBefore, "matches_storage_class": tpgresource.ConvertStringArrToInterface(condition.MatchesStorageClass), @@ -1254,6 +1259,12 @@ func flattenBucketLifecycleRuleCondition(condition *storage.BucketLifecycleRuleC ruleCondition["with_state"] = "ARCHIVED" } } + // setting no_age value from state config since it is terraform only variable and not getting value from backend. + if v, ok := d.GetOk("lifecycle_rule.0.condition"); ok{ + state_condition := v.(*schema.Set).List()[0].(map[string]interface{}) + ruleCondition["no_age"] = state_condition["no_age"].(bool) + } + return ruleCondition } @@ -1401,11 +1412,14 @@ func expandStorageBucketLifecycleRuleCondition(v interface{}) (*storage.BucketLi condition := conditions[0].(map[string]interface{}) transformed := &storage.BucketLifecycleRuleCondition{} - - if v, ok := condition["age"]; ok { - age := int64(v.(int)) - transformed.Age = &age - transformed.ForceSendFields = append(transformed.ForceSendFields, "Age") + // Setting high precedence of no_age over age when both used together. + // Only sets age value when no_age is not present or no_age is present and has false value + if v, ok := condition["no_age"]; !ok || !(v.(bool)) { + if v, ok := condition["age"]; ok { + age := int64(v.(int)) + transformed.Age = &age + transformed.ForceSendFields = append(transformed.ForceSendFields, "Age") + } } if v, ok := condition["created_before"]; ok { @@ -1506,8 +1520,12 @@ func resourceGCSBucketLifecycleRuleConditionHash(v interface{}) int { var buf bytes.Buffer m := v.(map[string]interface{}) - if v, ok := m["age"]; ok { - buf.WriteString(fmt.Sprintf("%d-", v.(int))) + if v, ok := m["no_age"]; ok && v.(bool){ + buf.WriteString(fmt.Sprintf("%t-", v.(bool))) + } else { + if v, ok := m["age"]; ok { + buf.WriteString(fmt.Sprintf("%d-", v.(int))) + } } if v, ok := m["days_since_custom_time"]; ok { @@ -1650,7 +1668,9 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res if err := d.Set("autoclass", flattenBucketAutoclass(res.Autoclass)); err != nil { return fmt.Errorf("Error setting autoclass: %s", err) } - if err := d.Set("lifecycle_rule", flattenBucketLifecycle(res.Lifecycle)); err != nil { + // lifecycle_rule contains terraform only variable no_age. + // Passing config("d") to flattener function to set no_age separately. + if err := d.Set("lifecycle_rule", flattenBucketLifecycle(d,res.Lifecycle)); err != nil { return fmt.Errorf("Error setting lifecycle_rule: %s", err) } if err := tpgresource.SetLabels(res.Labels, d, "labels"); err != nil { diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb index 9cbd43fe8aa7..09c92686525d 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb @@ -381,6 +381,74 @@ func TestAccStorageBucket_lifecycleRuleStateAny(t *testing.T) { }) } +func TestAccStorageBucket_lifecycleRulesNoAge(t *testing.T) { + t.Parallel() + var bucket storage.Bucket + bucketName := acctest.TestBucketName(t) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccStorageBucketDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccStorageBucket_customAttributes_withLifecycle1(bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_customAttributes_withLifecycleNoAge(bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + testAccCheckStorageBucketLifecycleConditionNoAge(nil, &bucket), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy","lifecycle_rule.0.condition.0.no_age"}, + }, + { + Config: testAccStorageBucket_customAttributes_withLifecycleNoAgeAndAge(bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + testAccCheckStorageBucketLifecycleConditionNoAge(nil, &bucket), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy","lifecycle_rule.0.condition.0.no_age"}, + }, + { + Config: testAccStorageBucket_customAttributes_withLifecycle1(bucketName), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + }, + }) +} + func TestAccStorageBucket_storageClass(t *testing.T) { t.Parallel() @@ -1315,6 +1383,25 @@ func testAccCheckStorageBucketLifecycleConditionState(expected *bool, b *storage } } +func testAccCheckStorageBucketLifecycleConditionNoAge(expected *int64, b *storage.Bucket) resource.TestCheckFunc { + return func(s *terraform.State) error { + actual := b.Lifecycle.Rule[0].Condition.Age + if expected == nil && b.Lifecycle.Rule[0].Condition.Age== nil { + return nil + } + if expected == nil { + return fmt.Errorf("expected condition Age to be unset, instead got %d", *actual) + } + if actual == nil { + return fmt.Errorf("expected condition Age to be %d, instead got nil (unset)", *expected) + } + if *expected != *actual { + return fmt.Errorf("expected condition Age to be %d, instead got %d", *expected, *actual) + } + return nil + } +} + func testAccStorageBucketDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { config := acctest.GoogleProviderConfig(t) @@ -1478,6 +1565,45 @@ resource "google_storage_bucket" "bucket" { `, bucketName) } +func testAccStorageBucket_customAttributes_withLifecycleNoAge(bucketName string) string { + return fmt.Sprintf(` +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "EU" + force_destroy = "true" + lifecycle_rule { + action { + type = "Delete" + } + condition { + num_newer_versions = 2 + no_age = true + } + } +} +`, bucketName) +} + +func testAccStorageBucket_customAttributes_withLifecycleNoAgeAndAge(bucketName string) string { + return fmt.Sprintf(` +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "EU" + force_destroy = "true" + lifecycle_rule { + action { + type = "Delete" + } + condition { + num_newer_versions = 2 + age = 10 + no_age = true + } + } +} +`, bucketName) +} + func testAccStorageBucket_storageClass(bucketName, storageClass, location 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 0c2123fa25bf..0131446fffa8 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 @@ -147,6 +147,8 @@ The following arguments are supported: * `age` - (Optional) Minimum age of an object in days to satisfy this condition. +* `no_age` - (Optional) While set `true`, `age` value will be omitted. **Note** Required to set `true` when `age` is unset in the config file. + * `created_before` - (Optional) A date in the RFC 3339 format YYYY-MM-DD. This condition is satisfied when an object is created before midnight of the specified date in UTC. * `with_state` - (Optional) Match to live and/or archived objects. Unversioned buckets have only live objects. Supported values include: `"LIVE"`, `"ARCHIVED"`, `"ANY"`. From 12b126f452170f62a25048f808d9cc6d1e11b526 Mon Sep 17 00:00:00 2001 From: Karol Date: Wed, 6 Dec 2023 18:37:49 +0100 Subject: [PATCH 066/107] Add GKE support for tier 1 networking in GKE (#6826) --- .../resource_container_node_pool.go.erb | 40 ++++++++++++++-- .../resource_container_node_pool_test.go.erb | 46 ++++++++++++++++--- .../docs/r/container_cluster.html.markdown | 6 +++ 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb index 4350958d6a64..3ae142f56f20 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb @@ -464,6 +464,21 @@ var schemaNodePool = map[string]*schema.Schema{ }, }, }, + "network_performance_config": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Network bandwidth tier configuration.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "total_egress_bandwidth_tier": { + Type: schema.TypeString, + Required: true, + Description: `Specifies the total network bandwidth tier for the NodePool.`, + }, + }, + }, + }, }, }, }, @@ -1216,6 +1231,7 @@ func flattenNodeNetworkConfig(c *container.NodeNetworkConfig, d *schema.Resource "pod_range": c.PodRange, "enable_private_nodes": c.EnablePrivateNodes, "pod_cidr_overprovision_config": flattenPodCidrOverprovisionConfig(c.PodCidrOverprovisionConfig), + "network_performance_config": flattenNodeNetworkPerformanceConfig(c.NetworkPerformanceConfig), <% unless version == 'ga' -%> "additional_node_network_configs": flattenAdditionalNodeNetworkConfig(c.AdditionalNodeNetworkConfigs), "additional_pod_network_configs": flattenAdditionalPodNetworkConfig(c.AdditionalPodNetworkConfigs), @@ -1225,6 +1241,16 @@ func flattenNodeNetworkConfig(c *container.NodeNetworkConfig, d *schema.Resource return result } +func flattenNodeNetworkPerformanceConfig(c *container.NetworkPerformanceConfig) []map[string]interface{} { + result := []map[string]interface{}{} + if c != nil { + result = append(result, map[string]interface{}{ + "total_egress_bandwidth_tier": c.TotalEgressBandwidthTier, + }) + } + return result +} + <% unless version == 'ga' -%> func flattenAdditionalNodeNetworkConfig(c []*container.AdditionalNodeNetworkConfig) []map[string]interface{} { if c == nil { @@ -1321,6 +1347,14 @@ func expandNodeNetworkConfig(v interface{}) *container.NodeNetworkConfig { nnc.PodCidrOverprovisionConfig = expandPodCidrOverprovisionConfig(networkNodeConfig["pod_cidr_overprovision_config"]) + if v, ok := networkNodeConfig["network_performance_config"]; ok && len(v.([]interface{})) > 0 { + nnc.NetworkPerformanceConfig = &container.NetworkPerformanceConfig{} + network_performance_config := v.([]interface{})[0].(map[string]interface{}) + if total_egress_bandwidth_tier, ok := network_performance_config["total_egress_bandwidth_tier"]; ok { + nnc.NetworkPerformanceConfig.TotalEgressBandwidthTier = total_egress_bandwidth_tier.(string) + } + } + return nnc } @@ -1978,7 +2012,7 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node } if d.HasChange(prefix + "network_config") { - if d.HasChange(prefix + "network_config.0.enable_private_nodes") { + if d.HasChange(prefix + "network_config.0.enable_private_nodes") || d.HasChange(prefix + "network_config.0.network_performance_config") { req := &container.UpdateNodePoolRequest{ NodePoolId: name, NodeNetworkConfig: expandNodeNetworkConfig(d.Get(prefix + "network_config")), @@ -1998,7 +2032,7 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node return ContainerOperationWait(config, op, nodePoolInfo.project, nodePoolInfo.location, - "updating GKE node pool workload_metadata_config", userAgent, + "updating GKE node pool network_config", userAgent, timeout) } @@ -2006,7 +2040,7 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node return err } - log.Printf("[INFO] Updated workload_metadata_config for node pool %s", name) + log.Printf("[INFO] Updated network_config for node pool %s", name) } } diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb index 7f2d7d7aeb31..f821b5a5a413 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb @@ -579,10 +579,12 @@ func TestAccContainerNodePool_withNetworkConfig(t *testing.T) { CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccContainerNodePool_withNetworkConfig(cluster, np, network), + Config: testAccContainerNodePool_withNetworkConfig(cluster, np, network, "TIER_1"), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr( "google_container_node_pool.with_pco_disabled", "network_config.0.pod_cidr_overprovision_config.0.disabled", "true"), + resource.TestCheckResourceAttr("google_container_node_pool.with_tier1_net", "network_config.0.network_performance_config.#", "1"), + resource.TestCheckResourceAttr("google_container_node_pool.with_tier1_net", "network_config.0.network_performance_config.0.total_egress_bandwidth_tier", "TIER_1"), ), }, { @@ -597,6 +599,14 @@ func TestAccContainerNodePool_withNetworkConfig(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{"network_config.0.create_pod_range"}, }, + // edit the updateable network config + { + Config: testAccContainerNodePool_withNetworkConfig(cluster, np, network, "TIER_UNSPECIFIED"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_container_node_pool.with_tier1_net", "network_config.0.network_performance_config.#", "1"), + resource.TestCheckResourceAttr("google_container_node_pool.with_tier1_net", "network_config.0.network_performance_config.0.total_egress_bandwidth_tier", "TIER_UNSPECIFIED"), + ), + }, }, }) } @@ -2998,7 +3008,7 @@ resource "google_container_node_pool" "np" { `, cluster, networkName, subnetworkName, np, mode) } -func testAccContainerNodePool_withNetworkConfig(cluster, np, network string) string { +func testAccContainerNodePool_withNetworkConfig(cluster, np, network, netTier string) string { return fmt.Sprintf(` resource "google_compute_network" "container_network" { name = "%s" @@ -3075,7 +3085,7 @@ resource "google_container_node_pool" "with_auto_pod_cidr" { node_count = 1 network_config { create_pod_range = true - pod_range = "auto-pod-range" + pod_range = "auto-pod-range" pod_ipv4_cidr_block = "10.2.0.0/20" } node_config { @@ -3091,7 +3101,7 @@ resource "google_container_node_pool" "with_pco_disabled" { cluster = google_container_cluster.cluster.name node_count = 1 network_config { - pod_cidr_overprovision_config { + pod_cidr_overprovision_config { disabled = true } } @@ -3102,7 +3112,31 @@ resource "google_container_node_pool" "with_pco_disabled" { } } -`, network, cluster, np, np, np) +resource "google_container_node_pool" "with_tier1_net" { + name = "%s-tier1" + location = "us-central1" + cluster = google_container_cluster.cluster.name + node_count = 1 + node_locations = [ + "us-central1-a", + ] + network_config { + network_performance_config { + total_egress_bandwidth_tier = "%s" + } + } + node_config { + machine_type = "n2-standard-32" + gvnic { + enabled = true + } + oauth_scopes = [ + "https://www.googleapis.com/auth/cloud-platform", + ] + } +} + +`, network, cluster, np, np, np, np, netTier) } <% unless version.nil? || version == 'ga' -%> @@ -4105,4 +4139,4 @@ resource "google_container_node_pool" "without_confidential_boot_disk" { } `, cluster, networkName, subnetworkName, np) } -<% end -%> \ No newline at end of file +<% end -%> diff --git a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown index 7ec0fb4e10f5..157bfb70f76e 100644 --- a/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/container_cluster.html.markdown @@ -957,6 +957,12 @@ sole_tenant_config { * `threads_per_core` - (Required) The number of threads per physical core. To disable simultaneous multithreading (SMT) set this to 1. If unset, the maximum number of threads supported per core by the underlying processor is assumed. +* `network_performance_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Network bandwidth tier configuration. + +The `network_performance_config` block supports: + +* `total_egress_bandwidth_tier` (Required) - Specifies the total network bandwidth tier for the NodePool. + The `ephemeral_storage_config` block supports: * `local_ssd_count` (Required) - Number of local SSDs to use to back ephemeral storage. Uses NVMe interfaces. Each local SSD is 375 GB in size. If zero, it means to disable using local SSDs as ephemeral storage. From cf700745b980492fa902f7d5a60c70bb11886ee3 Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Wed, 6 Dec 2023 23:19:25 +0530 Subject: [PATCH 067/107] doc(spanner): add example for using spanner with autoscaler config (#9591) * doc(spanner): add example for using spanner with autoscaler config * fix references * fix tests --- mmv1/products/spanner/Instance.yaml | 6 ++++++ .../spanner_instance_with_autoscaling.tf.erb | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index 7d2b8f595fc9..0a353ee85dd8 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -63,6 +63,12 @@ examples: 'example' # Randomness skip_vcr: true + - !ruby/object:Provider::Terraform::Examples + name: 'spanner_instance_with_autoscaling' + primary_resource_id: + 'example' + # Randomness + skip_vcr: true - !ruby/object:Provider::Terraform::Examples name: 'spanner_instance_multi_regional' primary_resource_id: diff --git a/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb b/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb new file mode 100644 index 000000000000..3830a71a70d8 --- /dev/null +++ b/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb @@ -0,0 +1,17 @@ +resource "google_spanner_instance" "example" { + config = "regional-us-central1" + display_name = "Test Spanner Instance" + autoscaling_config { + autoscaling_limits { + max_processing_units = 3000 + min_processing_units = 2000 + } + autoscaling_targets { + high_priority_cpu_utilization_percent = 75 + storage_utilization_percent = 90 + } + } + labels = { + "foo" = "bar" + } +} From b16a839ade68f8cbcbfa1071e089cd6b4e3af239 Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Thu, 7 Dec 2023 00:32:46 +0530 Subject: [PATCH 068/107] Add ExternalAddress resource to Vmwareengine (#9573) --- .../vmwareengine/ExternalAddress.yaml | 125 ++++++++++++++ ...mware_engine_external_address_basic.tf.erb | 41 +++++ .../provider/provider_mmv1_resources.go.erb | 1 + ...ce_google_vmwareengine_external_address.go | 39 +++++ ...urce_vmwareengine_external_address_test.go | 152 ++++++++++++++++++ .../transport/error_retry_predicates.go | 11 ++ .../transport/error_retry_predicates_test.go | 11 ++ ...mwareengine_external_address.html.markdown | 32 ++++ 8 files changed, 412 insertions(+) create mode 100644 mmv1/products/vmwareengine/ExternalAddress.yaml create mode 100644 mmv1/templates/terraform/examples/vmware_engine_external_address_basic.tf.erb create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_external_address.go create mode 100644 mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_external_address_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/vmwareengine_external_address.html.markdown diff --git a/mmv1/products/vmwareengine/ExternalAddress.yaml b/mmv1/products/vmwareengine/ExternalAddress.yaml new file mode 100644 index 000000000000..f6ba9cdc6bb9 --- /dev/null +++ b/mmv1/products/vmwareengine/ExternalAddress.yaml @@ -0,0 +1,125 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the License); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'ExternalAddress' +base_url: '{{parent}}/externalAddresses' +create_url: '{{parent}}/externalAddresses?externalAddressId={{name}}' +self_link: '{{parent}}/externalAddresses/{{name}}' +update_mask: true +update_verb: :PATCH +references: !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds.externalAddresses' +description: | + An allocated external IP address and its corresponding internal IP address in a private cloud. +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: "name" + base_url: "{{op_id}}" + wait_ms: 1000 + timeouts: !ruby/object:Api::Timeouts + insert_minutes: 40 + result: !ruby/object:Api::OpAsync::Result + path: "response" + status: !ruby/object:Api::OpAsync::Status + path: "done" + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: "error" + message: "message" + include_project: true + +import_format: ["{{%parent}}/externalAddresses/{{name}}"] +id_format: "{{parent}}/externalAddresses/{{name}}" +error_retry_predicates: ['transport_tpg.ExternalIpServiceNotActive'] +autogen_async: true + +examples: + - !ruby/object:Provider::Terraform::Examples + name: "vmware_engine_external_address_basic" + primary_resource_id: "vmw-engine-external-address" + skip_test: true # update tests will take care of all CRUD tests. Parent PC creation is expensive and node reservation is required. + vars: + name: "sample-external-address" + network_id: "pc-nw" + private_cloud_id: "sample-pc" + management_cluster_id: "sample-mgmt-cluster" + network_policy_id: "sample-np" + +parameters: + - !ruby/object:Api::Type::String + name: "parent" + immutable: true + required: true + url_param_only: true + description: | + The resource name of the private cloud to create a new external address in. + Resource names are schemeless URIs that follow the conventions in https://cloud.google.com/apis/design/resource_names. + For example: projects/my-project/locations/us-west1-a/privateClouds/my-cloud + + - !ruby/object:Api::Type::String + name: "name" + required: true + immutable: true + url_param_only: true + description: | + The ID of the external IP Address. + +properties: + - !ruby/object:Api::Type::Time + name: 'createTime' + output: true + description: | + Creation time of this resource. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and + up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + + - !ruby/object:Api::Type::Time + name: 'updateTime' + output: true + description: | + Last updated time of this resource. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine + fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + + - !ruby/object:Api::Type::String + name: 'internalIp' + required: true + description: | + The internal IP address of a workload VM. + + - !ruby/object:Api::Type::String + name: 'externalIp' + output: true + description: | + The external IP address of a workload VM. + + - !ruby/object:Api::Type::String + name: 'state' + description: | + State of the resource. + output: true + + - !ruby/object:Api::Type::String + name: 'uid' + output: true + description: | + System-generated unique identifier for the resource. + + - !ruby/object:Api::Type::String + name: 'description' + description: | + User-provided description for this resource. diff --git a/mmv1/templates/terraform/examples/vmware_engine_external_address_basic.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_external_address_basic.tf.erb new file mode 100644 index 000000000000..874fbe25b5cf --- /dev/null +++ b/mmv1/templates/terraform/examples/vmware_engine_external_address_basic.tf.erb @@ -0,0 +1,41 @@ +resource "google_vmwareengine_network" "external-address-nw" { + name = "<%= ctx[:vars]['network_id'] %>" + location = "global" + type = "STANDARD" + description = "PC network description." +} + +resource "google_vmwareengine_private_cloud" "external-address-pc" { + location = "<%= ctx[:test_env_vars]['region'] %>-a" + name = "<%= ctx[:vars]['private_cloud_id'] %>" + description = "Sample test PC." + network_config { + management_cidr = "192.168.50.0/24" + vmware_engine_network = google_vmwareengine_network.external-address-nw.id + } + + management_cluster { + cluster_id = "<%= ctx[:vars]['management_cluster_id'] %>" + node_type_configs { + node_type_id = "standard-72" + node_count = 3 + } + } +} + +resource "google_vmwareengine_network_policy" "external-address-np" { + location = "<%= ctx[:test_env_vars]['region'] %>" + name = "<%= ctx[:vars]['network_policy_id'] %>" + edge_services_cidr = "192.168.30.0/26" + vmware_engine_network = google_vmwareengine_network.external-address-nw.id +} + +resource "google_vmwareengine_external_address" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['name'] %>" + parent = google_vmwareengine_private_cloud.external-address-pc.id + internal_ip = "192.168.0.66" + description = "Sample description." + depends_on = [ + google_vmwareengine_network_policy.external-address-np, + ] +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 8f41adb2b48e..baa795cf7d38 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -202,6 +202,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ <% unless version == 'ga' -%> "google_vmwareengine_cluster": vmwareengine.DataSourceVmwareengineCluster(), <% end -%> + "google_vmwareengine_external_address": vmwareengine.DataSourceVmwareengineExternalAddress(), "google_vmwareengine_network": vmwareengine.DataSourceVmwareengineNetwork(), "google_vmwareengine_network_peering": vmwareengine.DataSourceVmwareengineNetworkPeering(), "google_vmwareengine_network_policy": vmwareengine.DataSourceVmwareengineNetworkPolicy(), diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_external_address.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_external_address.go new file mode 100644 index 000000000000..f7d4b1120124 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_external_address.go @@ -0,0 +1,39 @@ +package vmwareengine + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceVmwareengineExternalAddress() *schema.Resource { + + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceVmwareengineExternalAddress().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "parent", "name") + return &schema.Resource{ + Read: dataSourceVmwareengineExternalAddressRead, + Schema: dsSchema, + } +} + +func dataSourceVmwareengineExternalAddressRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/externalAddresses/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + err = resourceVmwareengineExternalAddressRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_external_address_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_external_address_test.go new file mode 100644 index 000000000000..48ede6c32f05 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_external_address_test.go @@ -0,0 +1,152 @@ +package vmwareengine_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func TestAccVmwareengineExternalAddress_vmwareEngineExternalAddressUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "region": "southamerica-east1", // using region with low node utilization. + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineExternalAddressDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testVmwareEngineExternalAddressConfig(context, "description1", "192.168.0.66"), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_external_address.ds", "google_vmwareengine_external_address.vmw-engine-external-address", map[string]struct{}{}), + ), + }, + { + ResourceName: "google_vmwareengine_external_address.vmw-engine-external-address", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "name"}, + }, + { + Config: testVmwareEngineExternalAddressConfig(context, "description2", "192.168.0.67"), + }, + { + ResourceName: "google_vmwareengine_external_address.vmw-engine-external-address", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "name"}, + }, + }, + }) +} + +func testVmwareEngineExternalAddressConfig(context map[string]interface{}, description string, internalIp string) string { + context["internal_ip"] = internalIp + context["description"] = description + return acctest.Nprintf(` +resource "google_vmwareengine_network" "external-address-nw" { + name = "tf-test-sample-external-address-nw%{random_suffix}" + location = "global" + type = "STANDARD" + description = "PC network description." +} + +resource "google_vmwareengine_private_cloud" "external-address-pc" { + location = "%{region}-a" + name = "tf-test-sample-external-address-pc%{random_suffix}" + description = "Sample test PC." + network_config { + management_cidr = "192.168.1.0/24" + vmware_engine_network = google_vmwareengine_network.external-address-nw.id + } + + management_cluster { + cluster_id = "tf-test-sample-external-address-cluster%{random_suffix}" + node_type_configs { + node_type_id = "standard-72" + node_count = 3 + } + } +} + +resource "google_vmwareengine_network_policy" "external-address-np" { + location = "%{region}" + name = "tf-test-sample-external-address-np%{random_suffix}" + edge_services_cidr = "192.168.0.0/26" + vmware_engine_network = google_vmwareengine_network.external-address-nw.id + internet_access { + enabled = true + } + external_ip { + enabled = true + } +} + +resource "google_vmwareengine_external_address" "vmw-engine-external-address" { + name = "tf-test-sample-external-address%{random_suffix}" + parent = google_vmwareengine_private_cloud.external-address-pc.id + internal_ip = "%{internal_ip}" + description = "%{description}" + depends_on = [ + google_vmwareengine_network_policy.external-address-np, + ] +} + +data "google_vmwareengine_external_address" "ds" { + name = google_vmwareengine_external_address.vmw-engine-external-address.name + parent = google_vmwareengine_private_cloud.external-address-pc.id + depends_on = [ + google_vmwareengine_external_address.vmw-engine-external-address, + ] +} +`, context) +} + +func testAccCheckVmwareengineExternalAddressDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "google_vmwareengine_external_address" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{VmwareengineBasePath}}{{parent}}/externalAddresses/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: config.UserAgent, + }) + if err == nil { + return fmt.Errorf("VmwareengineExternalAddress still exists at %s", url) + } + } + + return nil + } +} diff --git a/mmv1/third_party/terraform/transport/error_retry_predicates.go b/mmv1/third_party/terraform/transport/error_retry_predicates.go index d023c0b47b19..3f1c95ca2fe2 100644 --- a/mmv1/third_party/terraform/transport/error_retry_predicates.go +++ b/mmv1/third_party/terraform/transport/error_retry_predicates.go @@ -521,3 +521,14 @@ func IsForbiddenIamServiceAccountRetryableError(opType string) RetryErrorPredica return false, "" } } + +// Retry the creation of `google_vmwareengine_external_address` resource if the network policy's +// External IP field is not active yet. +func ExternalIpServiceNotActive(err error) (bool, string) { + if gerr, ok := err.(*googleapi.Error); ok { + if gerr.Code == 400 && strings.Contains(gerr.Body, "External IP address network service is not active in the provided network policy") { + return true, "Waiting for external ip service to be enabled" + } + } + return false, "" +} diff --git a/mmv1/third_party/terraform/transport/error_retry_predicates_test.go b/mmv1/third_party/terraform/transport/error_retry_predicates_test.go index a097e8219e5b..6df6978cca86 100644 --- a/mmv1/third_party/terraform/transport/error_retry_predicates_test.go +++ b/mmv1/third_party/terraform/transport/error_retry_predicates_test.go @@ -203,3 +203,14 @@ func TestFirestoreIndex409_retryUnderlyingDataChanged(t *testing.T) { t.Errorf("Error not detected as retryable") } } + +func TestExternalIpServiceNotActive(t *testing.T) { + err := googleapi.Error{ + Code: 400, + Body: "External IP address network service is not active in the provided network policy", + } + isRetryable, _ := ExternalIpServiceNotActive(&err) + if !isRetryable { + t.Errorf("Error not detected as retryable") + } +} diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_external_address.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_external_address.html.markdown new file mode 100644 index 000000000000..862467c92bc7 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_external_address.html.markdown @@ -0,0 +1,32 @@ +--- +subcategory: "Cloud VMware Engine" +description: |- + Get information about a external address. +--- + +# google\_vmwareengine\_external_address + +Use this data source to get details about a external address resource. + +To get more information about external address, see: +* [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds.externalAddresses) + +## Example Usage + +```hcl +data "google_vmwareengine_external_address" "my_external_address" { + name = "my-external-address" + parent = "project/my-project/locations/us-west1-a/privateClouds/my-cloud" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Name of the resource. +* `parent` - (Required) The resource name of the private cloud that this cluster belongs. + +## Attributes Reference + +See [google_vmwareengine_external_address](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/vmwareengine_external_address#attributes-reference) resource for details of all the available attributes. \ No newline at end of file From 3547ac8d589d09f0b66f4c1fe3e1dfd9783c87d0 Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Thu, 7 Dec 2023 00:45:18 +0530 Subject: [PATCH 069/107] Add Subnet resource to Vmwareengine (#9560) --- mmv1/products/vmwareengine/Subnet.yaml | 168 ++++++++++++++++++ .../vmware_engine_subnet_user_defined.tf.erb | 30 ++++ .../provider/provider_mmv1_resources.go.erb | 1 + .../data_source_google_vmwareengine_subnet.go | 38 ++++ .../resource_vmwareengine_subnet_test.go | 90 ++++++++++ .../docs/d/vmwareengine_subnet.html.markdown | 34 ++++ 6 files changed, 361 insertions(+) create mode 100644 mmv1/products/vmwareengine/Subnet.yaml create mode 100644 mmv1/templates/terraform/examples/vmware_engine_subnet_user_defined.tf.erb create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_subnet.go create mode 100644 mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_subnet_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/vmwareengine_subnet.html.markdown diff --git a/mmv1/products/vmwareengine/Subnet.yaml b/mmv1/products/vmwareengine/Subnet.yaml new file mode 100644 index 000000000000..41faa4dd8751 --- /dev/null +++ b/mmv1/products/vmwareengine/Subnet.yaml @@ -0,0 +1,168 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the License); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'Subnet' +base_url: '{{parent}}/subnets' +create_url: '{{parent}}/subnets/{{name}}?update_mask=ip_cidr_range' +self_link: '{{parent}}/subnets/{{name}}' +update_mask: true +create_verb: :PATCH +update_verb: :PATCH +skip_delete: true +references: !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds.subnets' +description: | + Subnet in a private cloud. A Private Cloud contains two types of subnets: `management` subnets (such as vMotion) that + are read-only,and `userDefined`, which can also be updated. This resource should be used to read and update `userDefined` + subnets. To read `management` subnets, please utilize the subnet data source. +async: !ruby/object:Api::OpAsync + actions: ['create', 'update'] + operation: !ruby/object:Api::OpAsync::Operation + path: "name" + base_url: "{{op_id}}" + wait_ms: 1000 + result: !ruby/object:Api::OpAsync::Result + path: "response" + status: !ruby/object:Api::OpAsync::Status + path: "done" + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: "error" + message: "message" + include_project: true + +import_format: ["{{%parent}}/subnets/{{name}}"] +id_format: "{{parent}}/subnets/{{name}}" +autogen_async: true + +examples: + - !ruby/object:Provider::Terraform::Examples + name: "vmware_engine_subnet_user_defined" + skip_test: true # update tests will take care of read and update. Parent PC creation is expensive and node reservation is required. + primary_resource_id: "vmw-engine-subnet" + vars: + private_cloud_id: "sample-pc" + management_cluster_id: "sample-mgmt-cluster" + network_id: "pc-nw" + subnet_id: "service-1" + test_env_vars: + region: :REGION + +parameters: + - !ruby/object:Api::Type::String + name: "parent" + immutable: true + required: true + url_param_only: true + description: | + The resource name of the private cloud to create a new subnet in. + Resource names are schemeless URIs that follow the conventions in https://cloud.google.com/apis/design/resource_names. + For example: projects/my-project/locations/us-west1-a/privateClouds/my-cloud + + - !ruby/object:Api::Type::String + name: "name" + required: true + immutable: true + url_param_only: true + description: | + The ID of the subnet. For userDefined subnets, this name should be in the format of "service-n", + where n ranges from 1 to 5. + +properties: + - !ruby/object:Api::Type::Time + name: 'createTime' + output: true + description: | + Creation time of this resource. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and + up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + + - !ruby/object:Api::Type::Time + name: 'updateTime' + output: true + description: | + Last updated time of this resource. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine + fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + + - !ruby/object:Api::Type::String + name: 'ipCidrRange' + required: true + send_empty_value: true + description: | + The IP address range of the subnet in CIDR format. + + - !ruby/object:Api::Type::String + name: 'gatewayIp' + output: true + description: | + The IP address of the gateway of this subnet. Must fall within the IP prefix defined above. + + - !ruby/object:Api::Type::String + name: 'gatewayId' + output: true + description: | + The canonical identifier of the logical router that this subnet is attached to. + + - !ruby/object:Api::Type::Array + name: 'dhcpAddressRanges' + output: true + description: | + DHCP address ranges. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'firstAddress' + output: true + description: | + The first IP address of the range. + - !ruby/object:Api::Type::String + name: 'lastAddress' + output: true + description: | + The last IP address of the range. + + - !ruby/object:Api::Type::String + name: 'type' + output: true + description: | + The type of the subnet. + + - !ruby/object:Api::Type::Boolean + name: standardConfig + output: true + description: | + Whether the NSX-T configuration in the backend follows the standard configuration supported by Google Cloud. + If false, the subnet cannot be modified through Google Cloud, only through NSX-T directly. + + - !ruby/object:Api::Type::String + name: 'state' + description: | + State of the subnet. + output: true + + - !ruby/object:Api::Type::String + name: 'uid' + output: true + description: | + System-generated unique identifier for the resource. + + - !ruby/object:Api::Type::Integer + name: 'vlanId' + output: true + description: | + VLAN ID of the VLAN on which the subnet is configured. diff --git a/mmv1/templates/terraform/examples/vmware_engine_subnet_user_defined.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_subnet_user_defined.tf.erb new file mode 100644 index 000000000000..aeedd117bac4 --- /dev/null +++ b/mmv1/templates/terraform/examples/vmware_engine_subnet_user_defined.tf.erb @@ -0,0 +1,30 @@ +resource "google_vmwareengine_network" "subnet-nw" { + name = "<%= ctx[:vars]['network_id'] %>" + location = "global" + type = "STANDARD" + description = "PC network description." +} + +resource "google_vmwareengine_private_cloud" "subnet-pc" { + location = "<%= ctx[:test_env_vars]['region'] %>-a" + name = "<%= ctx[:vars]['private_cloud_id'] %>" + description = "Sample test PC." + network_config { + management_cidr = "192.168.50.0/24" + vmware_engine_network = google_vmwareengine_network.subnet-nw.id + } + + management_cluster { + cluster_id = "<%= ctx[:vars]['management_cluster_id'] %>" + node_type_configs { + node_type_id = "standard-72" + node_count = 3 + } + } +} + +resource "google_vmwareengine_subnet" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['subnet_id'] %>" + parent = google_vmwareengine_private_cloud.subnet-pc.id + ip_cidr_range = "192.168.100.0/26" +} diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index baa795cf7d38..80aa24eae9d3 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -208,6 +208,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_vmwareengine_network_policy": vmwareengine.DataSourceVmwareengineNetworkPolicy(), "google_vmwareengine_nsx_credentials": vmwareengine.DataSourceVmwareengineNsxCredentials(), "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), + "google_vmwareengine_subnet": vmwareengine.DataSourceVmwareengineSubnet(), // ####### END handwritten datasources ########### } diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_subnet.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_subnet.go new file mode 100644 index 000000000000..eb6af6c08ab6 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_subnet.go @@ -0,0 +1,38 @@ +package vmwareengine + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceVmwareengineSubnet() *schema.Resource { + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceVmwareengineSubnet().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "parent", "name") + return &schema.Resource{ + Read: dataSourceVmwareengineSubnetRead, + Schema: dsSchema, + } +} + +func dataSourceVmwareengineSubnetRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + // Store the ID now + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}/subnets/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + err = resourceVmwareengineSubnetRead(d, meta) + if err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + return nil +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_subnet_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_subnet_test.go new file mode 100644 index 000000000000..bf233f1dfde2 --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_subnet_test.go @@ -0,0 +1,90 @@ +package vmwareengine_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccVmwareengineSubnet_vmwareEngineUserDefinedSubnetUpdate(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "region": "southamerica-west1", // using region with low node utilization. + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testVmwareEngineSubnetConfig(context, "192.168.1.0/26"), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_subnet.ds", "google_vmwareengine_subnet.vmw-engine-subnet", map[string]struct{}{}), + ), + }, + { + ResourceName: "google_vmwareengine_subnet.vmw-engine-subnet", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "name"}, + }, + { + Config: testVmwareEngineSubnetConfig(context, "192.168.2.0/26"), + }, + { + ResourceName: "google_vmwareengine_subnet.vmw-engine-subnet", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "name"}, + }, + }, + }) +} + +func testVmwareEngineSubnetConfig(context map[string]interface{}, ipCidrRange string) string { + context["ip_cidr_range"] = ipCidrRange + return acctest.Nprintf(` +resource "google_vmwareengine_network" "subnet-nw" { + name = "tf-test-subnet-nw%{random_suffix}" + location = "global" + type = "STANDARD" + description = "PC network description." +} + +resource "google_vmwareengine_private_cloud" "subnet-pc" { + location = "%{region}-a" + name = "tf-test-subnet-pc%{random_suffix}" + description = "Sample test PC." + network_config { + management_cidr = "192.168.0.0/24" + vmware_engine_network = google_vmwareengine_network.subnet-nw.id + } + + management_cluster { + cluster_id = "tf-test-mgmt-cluster%{random_suffix}" + node_type_configs { + node_type_id = "standard-72" + node_count = 3 + } + } +} + +resource "google_vmwareengine_subnet" "vmw-engine-subnet" { + name = "service-2" + parent = google_vmwareengine_private_cloud.subnet-pc.id + ip_cidr_range = "%{ip_cidr_range}" +} + +data "google_vmwareengine_subnet" ds { + name = "service-2" + parent = google_vmwareengine_private_cloud.subnet-pc.id + depends_on = [ + google_vmwareengine_subnet.vmw-engine-subnet, + ] +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_subnet.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_subnet.html.markdown new file mode 100644 index 000000000000..0c6c77db835d --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_subnet.html.markdown @@ -0,0 +1,34 @@ +--- +subcategory: "Cloud VMware Engine" +description: |- + Get info about a private cloud subnet. +--- + +# google\_vmwareengine\_subnet + +Use this data source to get details about a subnet. Management subnets support only read operations and should be configured through this data source. User defined subnets can be configured using the resource as well as the datasource. + +To get more information about private cloud subnet, see: +* [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds.subnets) + +## Example Usage + +```hcl +data "google_vmwareengine_subnet" "my_subnet" { + name = "service-1" + parent = "project/my-project/locations/us-west1-a/privateClouds/my-cloud" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Name of the resource. +UserDefined subnets are named in the format of "service-n", where n ranges from 1 to 5. +Management subnets have arbitary names including "vmotion", "vsan", "system-management" etc. More details about subnet names can be found on the cloud console. +* `parent` - (Required) The resource name of the private cloud that this subnet belongs. + +## Attributes Reference + +See [google_vmwareengine_subnet](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/vmwareengine_subnet#attributes-reference) resource for details of all the available attributes. \ No newline at end of file From 0ca113a42f07ec89a9d49394f69796243f9d9a8b Mon Sep 17 00:00:00 2001 From: Obada Alabbadi <76101898+obada-ab@users.noreply.github.com> Date: Wed, 6 Dec 2023 21:17:20 +0100 Subject: [PATCH 070/107] Add external dataset reference to bigquery dataset (#9440) * Add external dataset reference to bigquery dataset * Update external dataset test * Refactor external dataset reference --- mmv1/products/bigquery/Dataset.yaml | 34 +++++++++++++++++++ mmv1/products/bigquery/product.yaml | 3 ++ ...uery_dataset_external_reference_aws.tf.erb | 12 +++++++ ...dataset_external_reference_aws_docs.tf.erb | 12 +++++++ 4 files changed, 61 insertions(+) create mode 100644 mmv1/templates/terraform/examples/bigquery_dataset_external_reference_aws.tf.erb create mode 100644 mmv1/templates/terraform/examples/bigquery_dataset_external_reference_aws_docs.tf.erb diff --git a/mmv1/products/bigquery/Dataset.yaml b/mmv1/products/bigquery/Dataset.yaml index 4e8540977f17..c865bc242b68 100644 --- a/mmv1/products/bigquery/Dataset.yaml +++ b/mmv1/products/bigquery/Dataset.yaml @@ -78,6 +78,20 @@ examples: vars: dataset_id: 'example_dataset' account_name: 'bqowner' + - !ruby/object:Provider::Terraform::Examples + name: 'bigquery_dataset_external_reference_aws' + primary_resource_id: 'dataset' + min_version: beta + skip_docs: true + vars: + dataset_id: 'example_dataset' + - !ruby/object:Provider::Terraform::Examples + name: 'bigquery_dataset_external_reference_aws_docs' + primary_resource_id: 'dataset' + min_version: beta + skip_test: true + vars: + dataset_id: 'example_dataset' virtual_fields: - !ruby/object:Api::Type::Boolean name: 'delete_contents_on_destroy' @@ -291,6 +305,26 @@ properties: description: | A hash of the resource. output: true + - !ruby/object:Api::Type::NestedObject + name: 'externalDatasetReference' + description: | + Information about the external metadata storage where the dataset is defined. + min_version: beta + immutable: true + properties: + - !ruby/object:Api::Type::String + name: 'externalSource' + description: | + External source that backs this dataset. + required: true + immutable: true + - !ruby/object:Api::Type::String + name: 'connection' + description: | + The connection id that is used to access the externalSource. + Format: projects/{projectId}/locations/{locationId}/connections/{connectionId} + required: true + immutable: true - !ruby/object:Api::Type::String name: 'friendlyName' description: A descriptive name for the dataset diff --git a/mmv1/products/bigquery/product.yaml b/mmv1/products/bigquery/product.yaml index 4738d4232d24..f280ad33d2a1 100644 --- a/mmv1/products/bigquery/product.yaml +++ b/mmv1/products/bigquery/product.yaml @@ -19,5 +19,8 @@ versions: - !ruby/object:Api::Product::Version name: ga base_url: https://bigquery.googleapis.com/bigquery/v2/ + - !ruby/object:Api::Product::Version + name: beta + base_url: https://bigquery.googleapis.com/bigquery/v2/ scopes: - https://www.googleapis.com/auth/bigquery diff --git a/mmv1/templates/terraform/examples/bigquery_dataset_external_reference_aws.tf.erb b/mmv1/templates/terraform/examples/bigquery_dataset_external_reference_aws.tf.erb new file mode 100644 index 000000000000..9018a26c6a78 --- /dev/null +++ b/mmv1/templates/terraform/examples/bigquery_dataset_external_reference_aws.tf.erb @@ -0,0 +1,12 @@ +resource "google_bigquery_dataset" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + dataset_id = "<%= ctx[:vars]['dataset_id'] %>" + friendly_name = "test" + description = "This is a test description" + location = "aws-us-east-1" + + external_dataset_reference { + external_source = "aws-glue://arn:aws:glue:us-east-1:772042918353:database/db_other_formats_external" + connection = "projects/bigquerytestdefault/locations/aws-us-east-1/connections/external_test-connection" + } +} diff --git a/mmv1/templates/terraform/examples/bigquery_dataset_external_reference_aws_docs.tf.erb b/mmv1/templates/terraform/examples/bigquery_dataset_external_reference_aws_docs.tf.erb new file mode 100644 index 000000000000..a509fb47c6d1 --- /dev/null +++ b/mmv1/templates/terraform/examples/bigquery_dataset_external_reference_aws_docs.tf.erb @@ -0,0 +1,12 @@ +resource "google_bigquery_dataset" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + dataset_id = "<%= ctx[:vars]['dataset_id'] %>" + friendly_name = "test" + description = "This is a test description" + location = "aws-us-east-1" + + external_dataset_reference { + external_source = "aws-glue://arn:aws:glue:us-east-1:999999999999:database/database" + connection = "projects/project/locations/aws-us-east-1/connections/connection" + } +} From 9b9aa20fc8ac98a3fe9ac350b6c108822fb435d9 Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Thu, 7 Dec 2023 06:25:01 +0530 Subject: [PATCH 071/107] Add VCenter Credentials to Vmwareengine (#9572) --- .../provider/provider_mmv1_resources.go.erb | 3 +- ...google_vmwareengine_vcenter_credentials.go | 90 +++++++++++++++++++ ...esource_vmwareengine_private_cloud_test.go | 24 ++++- ...reengine_vcenter_credentials.html.markdown | 33 +++++++ 4 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_vcenter_credentials.go create mode 100644 mmv1/third_party/terraform/website/docs/d/vmwareengine_vcenter_credentials.html.markdown diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 80aa24eae9d3..38e02676b2ec 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -208,7 +208,8 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_vmwareengine_network_policy": vmwareengine.DataSourceVmwareengineNetworkPolicy(), "google_vmwareengine_nsx_credentials": vmwareengine.DataSourceVmwareengineNsxCredentials(), "google_vmwareengine_private_cloud": vmwareengine.DataSourceVmwareenginePrivateCloud(), - "google_vmwareengine_subnet": vmwareengine.DataSourceVmwareengineSubnet(), + "google_vmwareengine_subnet": vmwareengine.DataSourceVmwareengineSubnet(), + "google_vmwareengine_vcenter_credentials": vmwareengine.DataSourceVmwareengineVcenterCredentials(), // ####### END handwritten datasources ########### } diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_vcenter_credentials.go b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_vcenter_credentials.go new file mode 100644 index 000000000000..45fb9b71a6bd --- /dev/null +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_vcenter_credentials.go @@ -0,0 +1,90 @@ +package vmwareengine + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceVmwareengineVcenterCredentials() *schema.Resource { + return &schema.Resource{ + Read: dataSourceVmwareengineVcenterCredentialsRead, + Schema: map[string]*schema.Schema{ + "parent": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `The resource name of the private cloud which contains vcenter. +Resource names are schemeless URIs that follow the conventions in https://cloud.google.com/apis/design/resource_names. +For example: projects/my-project/locations/us-west1-a/privateClouds/my-cloud`, + }, + "username": { + Type: schema.TypeString, + Computed: true, + Description: `Initial username.`, + }, + "password": { + Type: schema.TypeString, + Computed: true, + Description: `Initial password.`, + }, + }, + } +} + +func dataSourceVmwareengineVcenterCredentialsRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{VmwareengineBasePath}}{{parent}}:showVcenterCredentials") + if err != nil { + return err + } + + billingProject := "" + + // err == nil indicates that the billing_project value was found + if bp, err := tpgresource.GetBillingProject(d, config); err == nil { + billingProject = bp + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + Project: billingProject, + RawURL: url, + UserAgent: userAgent, + ErrorAbortPredicates: []transport_tpg.RetryErrorPredicateFunc{transport_tpg.Is429QuotaError}, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("VmwareengineVcenterCredentials %q", d.Id())) + } + + if err := d.Set("username", flattenVmwareengineVcenterCredentailsUsername(res["username"], d, config)); err != nil { + return fmt.Errorf("Error reading VcenterCredentails: %s", err) + } + if err := d.Set("password", flattenVmwareengineVcenterCredentailsPassword(res["password"], d, config)); err != nil { + return fmt.Errorf("Error reading VcenterCredentails: %s", err) + } + + id, err := tpgresource.ReplaceVars(d, config, "{{parent}}:vcenter-credentials") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return nil +} + +func flattenVmwareengineVcenterCredentailsUsername(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenVmwareengineVcenterCredentailsPassword(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go index 54ede7d89284..9a189bd1c378 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go @@ -31,6 +31,7 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T Check: resource.ComposeTestCheckFunc( acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_private_cloud.ds", "google_vmwareengine_private_cloud.vmw-engine-pc", map[string]struct{}{}), testAccCheckGoogleVmwareengineNsxCredentialsMeta("data.google_vmwareengine_nsx_credentials.nsx-ds"), + testAccCheckGoogleVmwareengineVcenterCredentialsMeta("data.google_vmwareengine_vcenter_credentials.vcenter-ds"), ), }, { @@ -99,9 +100,12 @@ data "google_vmwareengine_private_cloud" "ds" { ] } -# NSX Credentials is a child datasource of PC and is included in the PC test due to the high deployment time involved in the Creation and deletion of a PC +# NSX and Vcenter Credentials are child datasources of PC and are included in the PC test due to the high deployment time involved in the Creation and deletion of a PC data "google_vmwareengine_nsx_credentials" "nsx-ds" { parent = google_vmwareengine_private_cloud.vmw-engine-pc + +data "google_vmwareengine_vcenter_credentials" "vcenter-ds" { + parent = google_vmwareengine_private_cloud.vmw-engine-pc.id } `, context) @@ -125,6 +129,24 @@ func testAccCheckGoogleVmwareengineNsxCredentialsMeta(n string) resource.TestChe } } +func testAccCheckGoogleVmwareengineVcenterCredentialsMeta(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Can't find vcenter credentials data source: %s", n) + } + _, ok = rs.Primary.Attributes["username"] + if !ok { + return fmt.Errorf("can't find 'username' attribute in data source: %s", n) + } + _, ok = rs.Primary.Attributes["password"] + if !ok { + return fmt.Errorf("can't find 'password' attribute in data source: %s", n) + } + return nil + } +} + func testAccCheckVmwareenginePrivateCloudDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_vcenter_credentials.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_vcenter_credentials.html.markdown new file mode 100644 index 000000000000..b2050d38c910 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_vcenter_credentials.html.markdown @@ -0,0 +1,33 @@ +--- +subcategory: "Cloud VMware Engine" +description: |- + Get Vcenter Credentials of a Private Cloud. +--- + +# google\_vmwareengine\_vcenter_credentials + +Use this data source to get Vcenter credentials for a Private Cloud. + +To get more information about private cloud Vcenter credentials, see: +* [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds/showVcenterCredentials) + +## Example Usage + +```hcl +data "google_vmwareengine_vcenter_credentials" "ds" { + parent = "projects/my-project/locations/us-west1-a/privateClouds/my-cloud" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `parent` - (Required) The resource name of the private cloud which contains the Vcenter. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `username` - The username of the Vcenter Credential. +* `password` - The password of the Vcenter Credential. \ No newline at end of file From 0782e1a9c6d73bbf636bef7e97e01e92cd99d226 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Wed, 6 Dec 2023 16:56:02 -0800 Subject: [PATCH 072/107] Add `saml` field to `google_iam_workload_identity_pool_provider` resource (#9061) * add saml block to workloadIdentityPoolProvider resource * add tf examples for saml tests * add newline in yaml * lintcheck * fix saml tests * add metadata.xml file for testing * apply to correct iam service * change iam beta endpoint from v1beta to v1 --- .../iambeta/WorkloadIdentityPoolProvider.yaml | 32 +++++++++++++++++-- mmv1/products/iambeta/product.yaml | 2 +- ...d_identity_pool_provider_saml_basic.tf.erb | 16 ++++++++++ ...ad_identity_pool_provider_saml_full.tf.erb | 19 +++++++++++ .../iambeta/test-fixtures/metadata.xml | 14 ++++++++ 5 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_saml_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_saml_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/iambeta/test-fixtures/metadata.xml diff --git a/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml b/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml index f5eea3482da5..808f8ab45efc 100644 --- a/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml +++ b/mmv1/products/iambeta/WorkloadIdentityPoolProvider.yaml @@ -53,6 +53,18 @@ examples: vars: workload_identity_pool_id: 'example-pool' workload_identity_pool_provider_id: 'example-prvdr' + - !ruby/object:Provider::Terraform::Examples + name: 'iam_workload_identity_pool_provider_saml_basic' + primary_resource_id: 'example' + vars: + workload_identity_pool_id: 'example-pool' + workload_identity_pool_provider_id: 'example-prvdr' + - !ruby/object:Provider::Terraform::Examples + name: 'iam_workload_identity_pool_provider_saml_full' + primary_resource_id: 'example' + vars: + workload_identity_pool_id: 'example-pool' + workload_identity_pool_provider_id: 'example-prvdr' - !ruby/object:Provider::Terraform::Examples name: 'iam_workload_identity_pool_provider_oidc_upload_key' primary_resource_id: 'example' @@ -205,10 +217,11 @@ properties: name: aws description: An Amazon Web Services identity provider. Not compatible with the property - oidc. + oidc or saml. exactly_one_of: - aws - oidc + - saml properties: - !ruby/object:Api::Type::String name: accountId @@ -218,10 +231,11 @@ properties: name: oidc description: An OpenId Connect 1.0 identity provider. Not compatible with the property - aws. + aws or saml. exactly_one_of: - aws - oidc + - saml update_mask_fields: - 'oidc.allowed_audiences' - 'oidc.issuer_uri' @@ -274,3 +288,17 @@ properties: } ``` required: false + - !ruby/object:Api::Type::NestedObject + name: saml + description: + An SAML 2.0 identity provider. Not compatible with the property + oidc or aws. + exactly_one_of: + - aws + - oidc + - saml + properties: + - !ruby/object:Api::Type::String + name: idpMetadataXml + description: SAML Identity provider configuration metadata xml doc. + required: true diff --git a/mmv1/products/iambeta/product.yaml b/mmv1/products/iambeta/product.yaml index 55786f97e1ec..5d92e8bd8737 100644 --- a/mmv1/products/iambeta/product.yaml +++ b/mmv1/products/iambeta/product.yaml @@ -18,7 +18,7 @@ legacy_name: iam versions: - !ruby/object:Api::Product::Version name: beta - base_url: https://iam.googleapis.com/v1beta/ + base_url: https://iam.googleapis.com/v1/ - !ruby/object:Api::Product::Version name: ga base_url: https://iam.googleapis.com/v1/ diff --git a/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_saml_basic.tf.erb b/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_saml_basic.tf.erb new file mode 100644 index 000000000000..6ec26e598c90 --- /dev/null +++ b/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_saml_basic.tf.erb @@ -0,0 +1,16 @@ +resource "google_iam_workload_identity_pool" "pool" { + workload_identity_pool_id = "<%= ctx[:vars]["workload_identity_pool_id"] %>" +} + +resource "google_iam_workload_identity_pool_provider" "<%= ctx[:primary_resource_id] %>" { + workload_identity_pool_id = google_iam_workload_identity_pool.pool.workload_identity_pool_id + workload_identity_pool_provider_id = "<%= ctx[:vars]["workload_identity_pool_provider_id"] %>" + attribute_mapping = { + "google.subject" = "assertion.arn" + "attribute.aws_account" = "assertion.account" + "attribute.environment" = "assertion.arn.contains(\":instance-profile/Production\") ? \"prod\" : \"test\"" + } + saml { + idp_metadata_xml = file("test-fixtures/metadata.xml") + } +} diff --git a/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_saml_full.tf.erb b/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_saml_full.tf.erb new file mode 100644 index 000000000000..7bfa6bea5054 --- /dev/null +++ b/mmv1/templates/terraform/examples/iam_workload_identity_pool_provider_saml_full.tf.erb @@ -0,0 +1,19 @@ +resource "google_iam_workload_identity_pool" "pool" { + workload_identity_pool_id = "<%= ctx[:vars]["workload_identity_pool_id"] %>" +} + +resource "google_iam_workload_identity_pool_provider" "<%= ctx[:primary_resource_id] %>" { + workload_identity_pool_id = google_iam_workload_identity_pool.pool.workload_identity_pool_id + workload_identity_pool_provider_id = "<%= ctx[:vars]["workload_identity_pool_provider_id"] %>" + display_name = "Name of provider" + description = "SAML 2.0 identity pool provider for automated test" + disabled = true + attribute_mapping = { + "google.subject" = "assertion.arn" + "attribute.aws_account" = "assertion.account" + "attribute.environment" = "assertion.arn.contains(\":instance-profile/Production\") ? \"prod\" : \"test\"" + } + saml { + idp_metadata_xml = file("test-fixtures/metadata.xml") + } +} diff --git a/mmv1/third_party/terraform/services/iambeta/test-fixtures/metadata.xml b/mmv1/third_party/terraform/services/iambeta/test-fixtures/metadata.xml new file mode 100644 index 000000000000..ce9acb1dbeb3 --- /dev/null +++ b/mmv1/third_party/terraform/services/iambeta/test-fixtures/metadata.xml @@ -0,0 +1,14 @@ + + + + + + + + MIIC3jCCAcagAwIBAgIBATANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDExNNeSBTZXJ2aWNlIFByb3ZpZGVyMB4XDTIzMTEzMDAwMzc1NVoXDTM4MTEyNjAwMzc1NVowHjEcMBoGA1UEAxMTTXkgU2VydmljZSBQcm92aWRlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM1W92rSmU8MbqNhIL6E0OEg3H0t65wqEMqg8r99yjZq/KW9ps6PoO4MZVIFLAMRtXvoTrVv6oPYCoc1T5u46Wl16qldGGRWk44Lr03L5xRqhKAVPfHMGL3HO0aaSnrVjKuFbGgjoMxJRSHHmU2Q6FU5AaRP2zodnkNhsZZt+x4dwKkow94uvTIQc1avdfCqKB5PeS2+2/oeFoNc78Pbnok+wUKZbhHwzYQdmSZ8NJnsIDpqf1IGcXyMMEqGkHmAa3O3sme4gYkl/0MbHcCSFwyaW+gUFy0uHz/amTiiZNoJ+0TPoNLz0XLXYv7ACxz5mTa/DaMvZ1zRsKi6wOzoSOUCAwEAAaMnMCUwDgYDVR0PAQH/BAQDAgKEMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQBFyfbJBaKuHSNd4Kx73ozSV2no96ctY3ZciUjCmUArLeqg0qQwkwXP6AoOd5bwIpKAmgHJgyv7T6GGHA+w9qNXuQxU86ph3gPRlYCB3+pnaiDq/iUECE09pleQJr//Am5x2Z1Bc8itMUPRuVsU873DASOFho3HZykmgS6x4JwAqCO2dBNoYHi+N9DsbQ9MatNdUOvrYgCTzbwRuwsDwLno/OSFQYTLqZVTW+NuEL/Axtx/yu9wKvuTzcD2MqPHaisy35PkPbJLsCauFJn8CAC4U5xKEkwsaumANeMZzzvAv8J2SIyjagLI+iF06AmCQNeytSvYxptxt7hhTg6uJVxS + + + + + + \ No newline at end of file From d6ce7020cd1e2a490a93c91ccc643531dba8bae7 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Thu, 7 Dec 2023 05:17:54 -0800 Subject: [PATCH 073/107] add `numeric_id` field into `google_compute_network` resource (#9473) * add numberic_id field * add flattener, encoders, and id field for numeric_id use * WIP: add numberId test * add value checks for id and numeric_id * add strconv * use decoder to store id into numericId after API request * remove network check and add suffix variable * add endlines * typo * Updated test to explicitly check numeric_id and id with ResourceAttr * update regex to be more strict on numeric_id check --- mmv1/products/compute/Network.yaml | 8 +++++ .../terraform/decoders/compute_network.go.erb | 2 ++ .../terraform/encoders/compute_network.go.erb | 2 ++ .../update_encoder/compute_network.go.erb | 2 ++ .../resource_compute_network_test.go.erb | 30 +++++++++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 mmv1/templates/terraform/decoders/compute_network.go.erb create mode 100644 mmv1/templates/terraform/encoders/compute_network.go.erb create mode 100644 mmv1/templates/terraform/update_encoder/compute_network.go.erb diff --git a/mmv1/products/compute/Network.yaml b/mmv1/products/compute/Network.yaml index 4c35f622d19a..895c5a5105df 100644 --- a/mmv1/products/compute/Network.yaml +++ b/mmv1/products/compute/Network.yaml @@ -70,6 +70,9 @@ virtual_fields: If set to `true`, default routes (`0.0.0.0/0`) will be deleted immediately after network creation. Defaults to `false`. custom_code: !ruby/object:Provider::Terraform::CustomCode + decoder: templates/terraform/decoders/compute_network.go.erb + encoder: templates/terraform/encoders/compute_network.go.erb + update_encoder: templates/terraform/update_encoder/compute_network.go.erb post_create: templates/terraform/post_create/compute_network_delete_default_route.erb properties: - !ruby/object:Api::Type::String @@ -100,6 +103,11 @@ properties: required: true validation: !ruby/object:Provider::Terraform::Validation function: 'verify.ValidateGCEName' + - !ruby/object:Api::Type::String + name: 'numericId' + description: | + The unique identifier for the resource. This identifier is defined by the server. + output: true - !ruby/object:Api::Type::Boolean name: 'autoCreateSubnetworks' description: | diff --git a/mmv1/templates/terraform/decoders/compute_network.go.erb b/mmv1/templates/terraform/decoders/compute_network.go.erb new file mode 100644 index 000000000000..d1dfb685ae0b --- /dev/null +++ b/mmv1/templates/terraform/decoders/compute_network.go.erb @@ -0,0 +1,2 @@ +res["numericId"] = res["id"] // stores unique id into numericId attribute before it's changed to path format +return res, nil diff --git a/mmv1/templates/terraform/encoders/compute_network.go.erb b/mmv1/templates/terraform/encoders/compute_network.go.erb new file mode 100644 index 000000000000..084107f2772e --- /dev/null +++ b/mmv1/templates/terraform/encoders/compute_network.go.erb @@ -0,0 +1,2 @@ +delete(obj, "numeric_id") // Field doesn't exist in the API +return obj, nil diff --git a/mmv1/templates/terraform/update_encoder/compute_network.go.erb b/mmv1/templates/terraform/update_encoder/compute_network.go.erb new file mode 100644 index 000000000000..084107f2772e --- /dev/null +++ b/mmv1/templates/terraform/update_encoder/compute_network.go.erb @@ -0,0 +1,2 @@ +delete(obj, "numeric_id") // Field doesn't exist in the API +return obj, nil diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_network_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_network_test.go.erb index 38f9ff58d49b..ce9d2f2406aa 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_network_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_network_test.go.erb @@ -3,8 +3,10 @@ package compute_test import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" @@ -106,6 +108,34 @@ func TestAccComputeNetwork_routingModeAndUpdate(t *testing.T) { }) } +func TestAccComputeNetwork_numericId(t *testing.T) { + t.Parallel() + suffixName := acctest.RandString(t, 10) + networkName := fmt.Sprintf("tf-test-network-basic-%s", suffixName) + projectId := envvar.GetTestProjectFromEnv() + networkId := fmt.Sprintf("projects/%v/global/networks/%v", projectId, networkName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeNetworkDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeNetwork_basic(suffixName), + Check: resource.ComposeTestCheckFunc( + resource.TestMatchResourceAttr("google_compute_network.bar", "numeric_id",regexp.MustCompile("^\\d{1,}$")), + resource.TestCheckResourceAttr("google_compute_network.bar", "id", networkId), + ), + }, + { + ResourceName: "google_compute_network.bar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccComputeNetwork_default_routing_mode(t *testing.T) { t.Parallel() From 7ebfe21ca18a66c8326218a496858b9f4a8aea28 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:25:48 +0000 Subject: [PATCH 074/107] Update regex in `TestAccContainerCluster_errorNoClusterCreated` acc test (#9594) --- .../services/container/resource_container_cluster_test.go.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index 2d04467b5c0f..c79ed5c9779a 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -3705,7 +3705,7 @@ func TestAccContainerCluster_errorNoClusterCreated(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccContainerCluster_withInvalidLocation("wonderland"), - ExpectError: regexp.MustCompile(`Location "wonderland" does not exist.`), + ExpectError: regexp.MustCompile(`(Location "wonderland" does not exist)|(Permission denied on 'locations\/wonderland' \(or it may not exist\))`), }, }, }) From 4ca0c3ca2e512950578ecc500cba7e82bc5a13e6 Mon Sep 17 00:00:00 2001 From: Akira Noda <61897166+tsugumi-sys@users.noreply.github.com> Date: Fri, 8 Dec 2023 00:49:00 +0900 Subject: [PATCH 075/107] Doc: Adding description of unique constraints on display_name argument (#9589) --- mmv1/products/datacatalog/Taxonomy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/datacatalog/Taxonomy.yaml b/mmv1/products/datacatalog/Taxonomy.yaml index e348865410aa..c7016b11cf8d 100644 --- a/mmv1/products/datacatalog/Taxonomy.yaml +++ b/mmv1/products/datacatalog/Taxonomy.yaml @@ -66,6 +66,7 @@ properties: name: 'displayName' description: | User defined name of this taxonomy. + The taxonomy display name must be unique within an organization. It must: contain only unicode letters, numbers, underscores, dashes and spaces; not start or end with spaces; and be at most 200 bytes long when encoded in UTF-8. From ac1397e126a49535fac419ede1524ef3eb464556 Mon Sep 17 00:00:00 2001 From: Sam Eiderman Date: Thu, 7 Dec 2023 19:01:03 +0200 Subject: [PATCH 076/107] Do not replace GKE's NodePool resource on machineType/diskType/diskSizeGb change (#9575) --- .../services/container/node_config.go.erb | 3 - .../resource_container_node_pool.go.erb | 33 +++++++++ .../resource_container_node_pool_test.go.erb | 68 +++++++++++++++++++ 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/services/container/node_config.go.erb b/mmv1/third_party/terraform/services/container/node_config.go.erb index b5ce9e2e29bc..af3492f29413 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.erb +++ b/mmv1/third_party/terraform/services/container/node_config.go.erb @@ -72,7 +72,6 @@ func schemaNodeConfig() *schema.Schema { Type: schema.TypeInt, Optional: true, Computed: true, - ForceNew: true, ValidateFunc: validation.IntAtLeast(10), Description: `Size of the disk attached to each node, specified in GB. The smallest allowed disk size is 10GB.`, }, @@ -81,7 +80,6 @@ func schemaNodeConfig() *schema.Schema { Type: schema.TypeString, Optional: true, Computed: true, - ForceNew: true, Description: `Type of the disk attached to each node. Such as pd-standard, pd-balanced or pd-ssd`, }, @@ -283,7 +281,6 @@ func schemaNodeConfig() *schema.Schema { Type: schema.TypeString, Optional: true, Computed: true, - ForceNew: true, Description: `The name of a Google Compute Engine machine type.`, }, diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb index 3ae142f56f20..a4208ccfd799 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool.go.erb @@ -1464,6 +1464,39 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node } } + if d.HasChange("node_config.0.disk_size_gb") || + d.HasChange("node_config.0.disk_type") || + d.HasChange("node_config.0.machine_type") { + req := &container.UpdateNodePoolRequest{ + Name: name, + DiskSizeGb: int64(d.Get("node_config.0.disk_size_gb").(int)), + DiskType: d.Get("node_config.0.disk_type").(string), + MachineType: d.Get("node_config.0.machine_type").(string), + } + updateF := func() error { + clusterNodePoolsUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.NodePools.Update(nodePoolInfo.fullyQualifiedName(name), req) + if config.UserProjectOverride { + clusterNodePoolsUpdateCall.Header().Add("X-Goog-User-Project", nodePoolInfo.project) + } + op, err := clusterNodePoolsUpdateCall.Do() + if err != nil { + return err + } + + // Wait until it's updated + return ContainerOperationWait(config, op, + nodePoolInfo.project, + nodePoolInfo.location, + "updating GKE node pool disk_size_gb/disk_type/machine_type", userAgent, + timeout) + } + + if err := retryWhileIncompatibleOperation(timeout, npLockKey, updateF); err != nil { + return err + } + log.Printf("[INFO] Updated disk disk_size_gb/disk_type/machine_type for Node Pool %s", d.Id()) + } + if d.HasChange(prefix + "node_config.0.taint") { req := &container.UpdateNodePoolRequest{ Name: name, diff --git a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb index f821b5a5a413..e06180e6c0e9 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_node_pool_test.go.erb @@ -280,6 +280,42 @@ func TestAccContainerNodePool_withTaintsUpdate(t *testing.T) { }) } +func TestAccContainerNodePool_withMachineAndDiskUpdate(t *testing.T) { + t.Parallel() + + cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + nodePool := fmt.Sprintf("tf-test-nodepool-%s", acctest.RandString(t, 10)) + networkName := acctest.BootstrapSharedTestNetwork(t, "gke-cluster") + subnetworkName := acctest.BootstrapSubnet(t, "gke-cluster", networkName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerNodePoolDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerNodePool_basic(cluster, nodePool, networkName, subnetworkName), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccContainerNodePool_withMachineAndDiskUpdate(cluster, nodePool, networkName, subnetworkName), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + // autoscaling.# = 0 is equivalent to no autoscaling at all, + // but will still cause an import diff + ImportStateVerifyIgnore: []string{"autoscaling.#", "node_config.0.taint"}, + }, + }, + }) +} + func TestAccContainerNodePool_withReservationAffinity(t *testing.T) { t.Parallel() @@ -2664,6 +2700,38 @@ resource "google_container_node_pool" "np" { `, cluster, networkName, subnetworkName, np) } +func testAccContainerNodePool_withMachineAndDiskUpdate(cluster, np, networkName, subnetworkName string) string { + return fmt.Sprintf(` +provider "google" { + alias = "user-project-override" + user_project_override = true +} +resource "google_container_cluster" "cluster" { + provider = google.user-project-override + name = "%s" + location = "us-central1-a" + initial_node_count = 3 + deletion_protection = false + network = "%s" + subnetwork = "%s" +} + +resource "google_container_node_pool" "np" { + provider = google.user-project-override + name = "%s" + location = "us-central1-a" + cluster = google_container_cluster.cluster.name + initial_node_count = 2 + + node_config { + machine_type = "n1-standard-1" // can't be e2 because of local-ssd + disk_size_gb = 15 + disk_type = "pd-ssd" + } +} +`, cluster, networkName, subnetworkName, np) +} + func testAccContainerNodePool_withReservationAffinity(cluster, np, networkName, subnetworkName string) string { return fmt.Sprintf(` data "google_container_engine_versions" "central1a" { From 8abd3028dea15486c2d78a52897cc5d617560dcb Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 7 Dec 2023 09:31:07 -0800 Subject: [PATCH 077/107] Remove activesupport (#9579) * Copy the ActiveSupport camelize code w/ slight modifications * Remove activesupport gem * Simplify camelize * Slightly simplify and also rubocop * Also remove the dependency in tests * Fix tgc --------- Co-authored-by: Riley Karson --- mmv1/Gemfile | 1 - mmv1/Gemfile.lock | 12 ------------ mmv1/api/type.rb | 2 +- mmv1/compiler.rb | 1 - mmv1/google/extensions.rb | 11 +++++++++++ mmv1/google/string_utils.rb | 18 ++++++++++++++++++ mmv1/provider/terraform_tgc.rb | 1 + mmv1/spec/compiler_spec.rb | 1 - .../terraform/datasource_iam.html.markdown.erb | 2 +- .../terraform/resource_iam.html.markdown.erb | 2 +- 10 files changed, 33 insertions(+), 18 deletions(-) diff --git a/mmv1/Gemfile b/mmv1/Gemfile index 9fbcb00be24e..b0b4949b38d6 100644 --- a/mmv1/Gemfile +++ b/mmv1/Gemfile @@ -1,6 +1,5 @@ source 'https://rubygems.org' -gem 'activesupport' gem 'binding_of_caller' gem 'openapi_parser', '~> 1.0.0' gem 'parallel' diff --git a/mmv1/Gemfile.lock b/mmv1/Gemfile.lock index 5c7e999f4191..f0bb3296cd4f 100644 --- a/mmv1/Gemfile.lock +++ b/mmv1/Gemfile.lock @@ -1,22 +1,13 @@ GEM remote: https://rubygems.org/ specs: - activesupport (7.0.4.2) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 1.6, < 2) - minitest (>= 5.1) - tzinfo (~> 2.0) ast (2.4.2) binding_of_caller (1.0.0) debug_inspector (>= 0.0.1) - concurrent-ruby (1.2.0) debug_inspector (1.1.0) diff-lcs (1.5.0) - i18n (1.12.0) - concurrent-ruby (~> 1.0) json (2.6.3) metaclass (0.0.4) - minitest (5.17.0) mocha (1.3.0) metaclass (~> 0.0.1) openapi_parser (1.0.0) @@ -53,15 +44,12 @@ GEM rubocop-ast (1.24.1) parser (>= 3.1.1.0) ruby-progressbar (1.11.0) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) unicode-display_width (2.4.2) PLATFORMS ruby DEPENDENCIES - activesupport binding_of_caller mocha (~> 1.3.0) openapi_parser (~> 1.0.0) diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index d9bac98786b2..90487dd8808d 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -425,7 +425,7 @@ def min_version end def exact_version - return nil if @exact_version.nil? || @exact_version.blank? + return nil if @exact_version.nil? || @exact_version.empty? @__resource.__product.version_obj(@exact_version) end diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index adfa9655034e..1f2cdc5f82c3 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -21,7 +21,6 @@ # generation. ENV['TZ'] = 'UTC' -require 'active_support/inflector' require 'api/compiler' require 'openapi_generate/parser' require 'google/logger' diff --git a/mmv1/google/extensions.rb b/mmv1/google/extensions.rb index 8ba95cb3b744..4cd9d0718ac7 100644 --- a/mmv1/google/extensions.rb +++ b/mmv1/google/extensions.rb @@ -37,4 +37,15 @@ def plural def title Google::StringUtils.title(self) end + + def camelize(first_letter = :upper) + case first_letter + when :upper + Google::StringUtils.camelize(self, true) + when :lower + Google::StringUtils.camelize(self, false) + else + raise ArgumentError, 'Invalid option, use either :upper or :lower.' + end + end end diff --git a/mmv1/google/string_utils.rb b/mmv1/google/string_utils.rb index 33575771fe99..0a3d25730c6d 100644 --- a/mmv1/google/string_utils.rb +++ b/mmv1/google/string_utils.rb @@ -74,5 +74,23 @@ def self.plural(source) "#{source}s" end + + # Slimmed down version of ActiveSupport::Inflector code + def self.camelize(term, uppercase_first_letter) + acronyms_camelize_regex = /^(?:(?=a)b(?=\b|[A-Z_])|\w)/ + + string = term.to_s + string = if uppercase_first_letter + string.sub(/^[a-z\d]*/) { |match| match.capitalize! || match } + else + string.sub(acronyms_camelize_regex) { |match| match.downcase! || match } + end + # handle snake case + string.gsub!(/(?:_)([a-z\d]*)/i) do + word = ::Regexp.last_match(1) + word.capitalize! || word + end + string + end end end diff --git a/mmv1/provider/terraform_tgc.rb b/mmv1/provider/terraform_tgc.rb index e8fad32fe852..9f28816857de 100644 --- a/mmv1/provider/terraform_tgc.rb +++ b/mmv1/provider/terraform_tgc.rb @@ -13,6 +13,7 @@ require 'provider/terraform_oics' require 'fileutils' +require 'set' module Provider # Code generator for a library converting terraform state to gcp objects. diff --git a/mmv1/spec/compiler_spec.rb b/mmv1/spec/compiler_spec.rb index bc57c6e6a9ae..e3a8627f0599 100644 --- a/mmv1/spec/compiler_spec.rb +++ b/mmv1/spec/compiler_spec.rb @@ -13,7 +13,6 @@ require 'spec_helper' require 'api/compiler' -require 'active_support/inflector' describe Api::Compiler do context 'should fail if file does not exist' do diff --git a/mmv1/templates/terraform/datasource_iam.html.markdown.erb b/mmv1/templates/terraform/datasource_iam.html.markdown.erb index 39fd93d86128..cd40438e57fe 100644 --- a/mmv1/templates/terraform/datasource_iam.html.markdown.erb +++ b/mmv1/templates/terraform/datasource_iam.html.markdown.erb @@ -99,7 +99,7 @@ The following arguments are supported: * `<%= param.name.underscore -%>` - (Required) <%= param.description -%> Used to find the parent resource to bind the IAM policy to <% end -%> <% end -%> -<% if object.iam_policy.base_url.present? -%> +<% if !object.iam_policy.base_url.nil? -%> <% if object.iam_policy.base_url.include?("{{project}}") -%> <%# The following new line allow for project to be bullet-formatted properly. -%> diff --git a/mmv1/templates/terraform/resource_iam.html.markdown.erb b/mmv1/templates/terraform/resource_iam.html.markdown.erb index 2663feb0ae0c..0d92349e0257 100644 --- a/mmv1/templates/terraform/resource_iam.html.markdown.erb +++ b/mmv1/templates/terraform/resource_iam.html.markdown.erb @@ -228,7 +228,7 @@ The following arguments are supported: * `<%= param.name.underscore -%>` - (Required) <%= param.description -%> Used to find the parent resource to bind the IAM policy to <% end -%> <% end -%> -<% if object.iam_policy.base_url.present? -%> +<% if !object.iam_policy.base_url.nil? -%> <% if object.iam_policy.base_url.include?("{{project}}") -%> <%# The following new line allow for project to be bullet-formatted properly. -%> From ec7eec622d9aefb7c3d490dc9c3df02209cd8ea0 Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Thu, 7 Dec 2023 10:14:28 -0800 Subject: [PATCH 078/107] Revert " add support for IAM Group authentication to google_sql_user (#9578)" (#9595) This reverts commit 05c4410c0e599f33ab255e3820187855c82c7739. --- .../services/sql/resource_sql_user.go | 6 ++---- .../services/sql/resource_sql_user_test.go | 11 ---------- .../website/docs/r/sql_user.html.markdown | 21 +------------------ 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user.go b/mmv1/third_party/terraform/services/sql/resource_sql_user.go index 15bf8061b05d..599e55df39f7 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user.go @@ -102,10 +102,8 @@ func ResourceSqlUser() *schema.Resource { ForceNew: true, DiffSuppressFunc: tpgresource.EmptyOrDefaultStringSuppress("BUILT_IN"), Description: `The user type. It determines the method to authenticate the user during login. - The default is the database's built-in user type. Flags include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", - "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" or "CLOUD_IAM_GROUP_SERVICE_ACCOUNT".`, - ValidateFunc: validation.StringInSlice([]string{"BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", - "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER", "CLOUD_IAM_GROUP_SERVICE_ACCOUNT", ""}, false), + The default is the database's built-in user type. Flags include "BUILT_IN", "CLOUD_IAM_USER", or "CLOUD_IAM_SERVICE_ACCOUNT".`, + ValidateFunc: validation.StringInSlice([]string{"BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", ""}, false), }, "sql_server_user_details": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go index 9091ef56a534..efcf0d5f5962 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_user_test.go @@ -26,7 +26,6 @@ func TestAccSqlUser_mysql(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"), testAccCheckGoogleSqlUserExists(t, "google_sql_user.user2"), - testAccCheckGoogleSqlUserExists(t, "google_sql_user.user3"), ), }, { @@ -35,7 +34,6 @@ func TestAccSqlUser_mysql(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckGoogleSqlUserExists(t, "google_sql_user.user1"), testAccCheckGoogleSqlUserExists(t, "google_sql_user.user2"), - testAccCheckGoogleSqlUserExists(t, "google_sql_user.user3"), ), }, { @@ -313,15 +311,6 @@ resource "google_sql_user" "user2" { instance = google_sql_database_instance.instance.name host = "gmail.com" password = "hunter2" - type = "CLOUD_IAM_USER" -} - -resource "google_sql_user" "user3" { - name = "admin" - instance = google_sql_database_instance.instance.name - host = "gmail.com" - password = "hunter3" - type = "CLOUD_IAM_GROUP" } `, instance, password) } diff --git a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown index 0072e8aa762b..9b96d4463a22 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown @@ -72,24 +72,6 @@ resource "google_sql_user" "iam_service_account_user" { instance = google_sql_database_instance.main.name type = "CLOUD_IAM_SERVICE_ACCOUNT" } - -resource "google_sql_user" "iam_group" { - name = "group1@example.com" - instance = google_sql_database_instance.main.name - type = "CLOUD_IAM_GROUP" -} - -resource "google_sql_user" "iam_group_user" { - name = "group_user1@example.com" - instance = google_sql_database_instance.main.name - type = "CLOUD_IAM_GROUP_USER" -} - -resource "google_sql_user" "iam_group_service_account_user" { - name = "my-service-account@example.iam.gserviceaccount.com" - instance = google_sql_database_instance.main.name - type = "CLOUD_IAM_GROUP_SERVICE_ACCOUNT" -} ``` ## Argument Reference @@ -109,8 +91,7 @@ The following arguments are supported: * `type` - (Optional) The user type. It determines the method to authenticate the user during login. The default is the database's built-in user type. Flags - include "BUILT_IN", "CLOUD_IAM_USER", "CLOUD_IAM_SERVICE_ACCOUNT", - "CLOUD_IAM_GROUP", "CLOUD_IAM_GROUP_USER" or "CLOUD_IAM_GROUP_SERVICE_ACCOUNT". + include "BUILT_IN", "CLOUD_IAM_USER", or "CLOUD_IAM_SERVICE_ACCOUNT". * `deletion_policy` - (Optional) The deletion policy for the user. Setting `ABANDON` allows the resource to be abandoned rather than deleted. This is useful From 4153866aaf018b769837b565a1088095fb25ae61 Mon Sep 17 00:00:00 2001 From: Alex Coomans Date: Thu, 7 Dec 2023 12:06:18 -0800 Subject: [PATCH 079/107] Add remove_instance_on_destroy option to per-compute instance config resources (#9588) It's a bit counterintuitive that creating a per-instance config in an IGM spins up an instance but destroying it leaves the instance behind. Also fixed a bug related to the operation to detach the disk from the instance failing due to the instance having been deleted. Other than the tests for the new per-instance config behavior, I was unable to devise an isolated test to trigger this issue. Fixes hashicorp/terraform-provider-google#9042 & hashicorp/terraform-provider-google#16621. --- mmv1/products/compute/PerInstanceConfig.yaml | 11 +- .../compute/RegionPerInstanceConfig.yaml | 11 +- .../custom_delete/per_instance_config.go.erb | 35 ++- .../region_per_instance_config.go.erb | 34 ++- .../compute_per_instance_config.go.erb | 3 - .../terraform/pre_delete/detach_disk.erb | 3 +- ...ce_compute_per_instance_config_test.go.erb | 222 +++++++++++++++++- ...ute_region_per_instance_config_test.go.erb | 181 ++++++++++++++ .../services/compute/stateful_mig_polling.go | 123 ++++++++++ .../terraform/tpgresource/common_operation.go | 2 +- 10 files changed, 598 insertions(+), 27 deletions(-) delete mode 100644 mmv1/templates/terraform/pre_delete/compute_per_instance_config.go.erb diff --git a/mmv1/products/compute/PerInstanceConfig.yaml b/mmv1/products/compute/PerInstanceConfig.yaml index 2c5d8e494298..fd37ee09d9fe 100644 --- a/mmv1/products/compute/PerInstanceConfig.yaml +++ b/mmv1/products/compute/PerInstanceConfig.yaml @@ -100,8 +100,18 @@ virtual_fields: - :REFRESH - :NONE default_value: :REPLACE + - !ruby/object:Api::Type::Boolean + name: 'remove_instance_on_destroy' + conflicts: + - remove_instance_state_on_destroy + description: | + When true, deleting this config will immediately remove the underlying instance. + When false, deleting this config will use the behavior as determined by remove_instance_on_destroy. + default_value: false - !ruby/object:Api::Type::Boolean name: 'remove_instance_state_on_destroy' + conflicts: + - remove_instance_on_destroy description: | When true, deleting this config will immediately remove any specified state from the underlying instance. When false, deleting this config will *not* immediately remove any state from the underlying instance. @@ -110,7 +120,6 @@ virtual_fields: custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/compute_per_instance_config.go.erb update_encoder: templates/terraform/update_encoder/compute_per_instance_config.go.erb - pre_delete: templates/terraform/pre_delete/compute_per_instance_config.go.erb post_update: templates/terraform/post_update/compute_per_instance_config.go.erb custom_delete: templates/terraform/custom_delete/per_instance_config.go.erb parameters: diff --git a/mmv1/products/compute/RegionPerInstanceConfig.yaml b/mmv1/products/compute/RegionPerInstanceConfig.yaml index 710864fcdaed..307756f20d38 100644 --- a/mmv1/products/compute/RegionPerInstanceConfig.yaml +++ b/mmv1/products/compute/RegionPerInstanceConfig.yaml @@ -101,8 +101,18 @@ virtual_fields: - :REFRESH - :NONE default_value: :REPLACE + - !ruby/object:Api::Type::Boolean + name: 'remove_instance_on_destroy' + conflicts: + - remove_instance_state_on_destroy + description: | + When true, deleting this config will immediately remove the underlying instance. + When false, deleting this config will use the behavior as determined by remove_instance_on_destroy. + default_value: false - !ruby/object:Api::Type::Boolean name: 'remove_instance_state_on_destroy' + conflicts: + - remove_instance_on_destroy description: | When true, deleting this config will immediately remove any specified state from the underlying instance. When false, deleting this config will *not* immediately remove any state from the underlying instance. @@ -111,7 +121,6 @@ virtual_fields: custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/compute_per_instance_config.go.erb update_encoder: templates/terraform/update_encoder/compute_per_instance_config.go.erb - pre_delete: templates/terraform/pre_delete/compute_per_instance_config.go.erb post_update: templates/terraform/post_update/compute_region_per_instance_config.go.erb custom_delete: templates/terraform/custom_delete/region_per_instance_config.go.erb parameters: diff --git a/mmv1/templates/terraform/custom_delete/per_instance_config.go.erb b/mmv1/templates/terraform/custom_delete/per_instance_config.go.erb index ce069c2ff827..71a62d09cd76 100644 --- a/mmv1/templates/terraform/custom_delete/per_instance_config.go.erb +++ b/mmv1/templates/terraform/custom_delete/per_instance_config.go.erb @@ -10,14 +10,31 @@ transport_tpg.MutexStore.Lock(lockName) defer transport_tpg.MutexStore.Unlock(lockName) - url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/instanceGroupManagers/{{instance_group_manager}}/deletePerInstanceConfigs") + var url string + if d.Get("remove_instance_on_destroy").(bool) { + url, err = tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/instanceGroupManagers/{{instance_group_manager}}/deleteInstances") + } else { + url, err = tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/instanceGroupManagers/{{instance_group_manager}}/deletePerInstanceConfigs") + } if err != nil { return err } var obj map[string]interface{} - obj = map[string]interface{}{ - "names": [1]string{d.Get("name").(string)}, + if d.Get("remove_instance_on_destroy").(bool) { + // Instance name in deleteInstances request must include zone + instanceName, err := tpgresource.ReplaceVars(d, config, "zones/{{zone}}/instances/{{name}}") + if err != nil { + return err + } + + obj = map[string]interface{}{ + "instances": [1]string{instanceName}, + } + } else { + obj = map[string]interface{}{ + "names": [1]string{d.Get("name").(string)}, + } } log.Printf("[DEBUG] Deleting PerInstanceConfig %q", d.Id()) @@ -42,8 +59,14 @@ return err } - // Potentially delete the state managed by this config - if d.Get("remove_instance_state_on_destroy").(bool) { + if d.Get("remove_instance_on_destroy").(bool) { + err = transport_tpg.PollingWaitTime(resourceComputePerInstanceConfigInstancePollRead(d, meta, d.Get("name").(string)), PollCheckInstanceConfigInstanceDeleted, "Deleting PerInstanceConfig", d.Timeout(schema.TimeoutDelete), 1) + if err != nil { + return fmt.Errorf("Error waiting for instance delete on PerInstanceConfig %q: %s", d.Id(), err) + } + } else if d.Get("remove_instance_state_on_destroy").(bool) { + // Potentially delete the state managed by this config + // Instance name in applyUpdatesToInstances request must include zone instanceName, err := tpgresource.ReplaceVars(d, config, "zones/{{zone}}/instances/{{name}}") if err != nil { @@ -85,7 +108,7 @@ err = transport_tpg.PollingWaitTime(resourceComputePerInstanceConfigPollRead(d, meta), PollCheckInstanceConfigDeleted, "Deleting PerInstanceConfig", d.Timeout(schema.TimeoutDelete), 1) if err != nil { return fmt.Errorf("Error waiting for delete on PerInstanceConfig %q: %s", d.Id(), err) - } + } } log.Printf("[DEBUG] Finished deleting PerInstanceConfig %q: %#v", d.Id(), res) diff --git a/mmv1/templates/terraform/custom_delete/region_per_instance_config.go.erb b/mmv1/templates/terraform/custom_delete/region_per_instance_config.go.erb index 72caafa23452..4df61c37649d 100644 --- a/mmv1/templates/terraform/custom_delete/region_per_instance_config.go.erb +++ b/mmv1/templates/terraform/custom_delete/region_per_instance_config.go.erb @@ -10,14 +10,31 @@ transport_tpg.MutexStore.Lock(lockName) defer transport_tpg.MutexStore.Unlock(lockName) - url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/instanceGroupManagers/{{region_instance_group_manager}}/deletePerInstanceConfigs") + var url string + if d.Get("remove_instance_on_destroy").(bool) { + url, err = tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/instanceGroupManagers/{{region_instance_group_manager}}/deleteInstances") + } else { + url, err = tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/instanceGroupManagers/{{region_instance_group_manager}}/deletePerInstanceConfigs") + } if err != nil { return err } var obj map[string]interface{} - obj = map[string]interface{}{ - "names": [1]string{d.Get("name").(string)}, + if d.Get("remove_instance_on_destroy").(bool) { + // Instance name in deleteInstances request must include zone + instanceName, err := findInstanceName(d, config) + if err != nil { + return err + } + + obj = map[string]interface{}{ + "instances": [1]string{instanceName}, + } + } else { + obj = map[string]interface{}{ + "names": [1]string{d.Get("name").(string)}, + } } log.Printf("[DEBUG] Deleting RegionPerInstanceConfig %q", d.Id()) @@ -42,8 +59,13 @@ return err } - // Potentially delete the state managed by this config - if d.Get("remove_instance_state_on_destroy").(bool) { + if d.Get("remove_instance_on_destroy").(bool) { + err = transport_tpg.PollingWaitTime(resourceComputeRegionPerInstanceConfigInstancePollRead(d, meta, d.Get("name").(string)), PollCheckInstanceConfigInstanceDeleted, "Deleting RegionPerInstanceConfig", d.Timeout(schema.TimeoutDelete), 1) + if err != nil { + return fmt.Errorf("Error waiting for instance delete on RegionPerInstanceConfig %q: %s", d.Id(), err) + } + } else if d.Get("remove_instance_state_on_destroy").(bool) { + // Potentially delete the state managed by this config // Instance name in applyUpdatesToInstances request must include zone instanceName, err := findInstanceName(d, config) if err != nil { @@ -86,7 +108,7 @@ err = transport_tpg.PollingWaitTime(resourceComputeRegionPerInstanceConfigPollRead(d, meta), PollCheckInstanceConfigDeleted, "Deleting RegionPerInstanceConfig", d.Timeout(schema.TimeoutDelete), 1) if err != nil { return fmt.Errorf("Error waiting for delete on RegionPerInstanceConfig %q: %s", d.Id(), err) - } + } } log.Printf("[DEBUG] Finished deleting RegionPerInstanceConfig %q: %#v", d.Id(), res) diff --git a/mmv1/templates/terraform/pre_delete/compute_per_instance_config.go.erb b/mmv1/templates/terraform/pre_delete/compute_per_instance_config.go.erb deleted file mode 100644 index 0fcf58a17620..000000000000 --- a/mmv1/templates/terraform/pre_delete/compute_per_instance_config.go.erb +++ /dev/null @@ -1,3 +0,0 @@ -obj = map[string]interface{}{ - "names": [1]string{d.Get("name").(string)}, -} \ No newline at end of file diff --git a/mmv1/templates/terraform/pre_delete/detach_disk.erb b/mmv1/templates/terraform/pre_delete/detach_disk.erb index 55c6eafa4905..cda955083ba3 100644 --- a/mmv1/templates/terraform/pre_delete/detach_disk.erb +++ b/mmv1/templates/terraform/pre_delete/detach_disk.erb @@ -56,7 +56,8 @@ if v, ok := readRes["users"].([]interface{}); ok { err = ComputeOperationWaitTime(config, op, call.project, fmt.Sprintf("Detaching disk from %s/%s/%s", call.project, call.zone, call.instance), userAgent, d.Timeout(schema.TimeoutDelete)) if err != nil { - if opErr, ok := err.(ComputeOperationError); ok && len(opErr.Errors) == 1 && opErr.Errors[0].Code == "RESOURCE_NOT_FOUND" { + var opErr ComputeOperationError + if errors.As(err, &opErr) && len(opErr.Errors) == 1 && opErr.Errors[0].Code == "RESOURCE_NOT_FOUND" { log.Printf("[WARN] instance %q was deleted while awaiting detach", call.instance) continue } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_per_instance_config_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_per_instance_config_test.go.erb index 0b947748e85d..a7a50f783525 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_per_instance_config_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_per_instance_config_test.go.erb @@ -170,6 +170,67 @@ func TestAccComputePerInstanceConfig_statefulIps(t *testing.T) { }) } +func TestAccComputePerInstanceConfig_removeInstanceOnDestroy(t *testing.T) { + t.Parallel() + + igmName := fmt.Sprintf("tf-test-igm-%s", acctest.RandString(t, 10)) + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "igm_name": igmName, + "config_name": fmt.Sprintf("instance-%s", acctest.RandString(t, 10)), + "config_name2": fmt.Sprintf("instance-%s", acctest.RandString(t, 10)), + "network": fmt.Sprintf("tf-test-igm-%s", acctest.RandString(t, 10)), + "subnetwork": fmt.Sprintf("tf-test-igm-%s", acctest.RandString(t, 10)), + "address1": fmt.Sprintf("tf-test-igm-address%s", acctest.RandString(t, 10)), + "address2": fmt.Sprintf("tf-test-igm-address%s", acctest.RandString(t, 10)), + } + igmId := fmt.Sprintf("projects/%s/zones/%s/instanceGroupManagers/%s", + envvar.GetTestProjectFromEnv(), envvar.GetTestZoneFromEnv(), igmName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccComputePerInstanceConfig_removeInstanceOnDestroyBefore(context), + }, + { + ResourceName: "google_compute_per_instance_config.config_one", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"remove_instance_on_destroy", "zone"}, + }, + { + ResourceName: "google_compute_per_instance_config.config_two", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"remove_instance_on_destroy", "zone"}, + }, + { + Config: testAccComputePerInstanceConfig_removeInstanceOnDestroyAfter(context), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputePerInstanceConfigDestroyed(t, igmId, context["config_name"].(string)), + testAccCheckComputePerInstanceConfigInstanceDestroyed(t, igmId, context["config_name"].(string)), + ), + }, + { + ResourceName: "google_compute_per_instance_config.config_two", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"remove_instance_on_destroy", "zone"}, + }, + { + // delete all configs + Config: testAccComputePerInstanceConfig_igm(context), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputePerInstanceConfigDestroyed(t, igmId, context["config_name2"].(string)), + testAccCheckComputePerInstanceConfigInstanceDestroyed(t, igmId, context["config_name2"].(string)), + ), + }, + }, + }) +} + func testAccComputePerInstanceConfig_statefulBasic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_compute_per_instance_config" "default" { @@ -340,6 +401,109 @@ resource "google_compute_instance_group_manager" "igm" { `, context) } +func testAccComputePerInstanceConfig_removeInstanceOnDestroyBefore(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + name = "%{network}" +} + +resource "google_compute_subnetwork" "default" { + name = "%{subnetwork}" + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" + network = google_compute_network.default.id +} + +resource "google_compute_address" "static_internal_ip" { + name = "%{address1}" + address_type = "INTERNAL" +} + +resource "google_compute_address" "static_external_ip" { + name = "%{address2}" + address_type = "EXTERNAL" +} + +resource "google_compute_per_instance_config" "config_one" { + instance_group_manager = google_compute_instance_group_manager.igm.name + name = "%{config_name}" + remove_instance_on_destroy = true + preserved_state { + metadata = { + asdf = "config-one" + } + disk { + device_name = "my-stateful-disk1" + source = google_compute_disk.disk.id + } + + disk { + device_name = "my-stateful-disk2" + source = google_compute_disk.disk1.id + } + internal_ip { + ip_address { + address = google_compute_address.static_internal_ip.self_link + } + auto_delete = "NEVER" + interface_name = "nic0" + } + external_ip { + ip_address { + address = google_compute_address.static_external_ip.self_link + } + auto_delete = "NEVER" + interface_name = "nic0" + } + } +} + +resource "google_compute_disk" "disk" { + name = "test-disk-%{random_suffix}" + type = "pd-ssd" + zone = google_compute_instance_group_manager.igm.zone + image = "debian-8-jessie-v20170523" + physical_block_size_bytes = 4096 +} + +resource "google_compute_disk" "disk1" { + name = "test-disk2-%{random_suffix}" + type = "pd-ssd" + zone = google_compute_instance_group_manager.igm.zone + image = "debian-cloud/debian-11" + physical_block_size_bytes = 4096 +} + +resource "google_compute_per_instance_config" "config_two" { + zone = google_compute_instance_group_manager.igm.zone + instance_group_manager = google_compute_instance_group_manager.igm.name + name = "%{config_name2}" + remove_instance_on_destroy = true + preserved_state { + metadata = { + asdf = "config-two" + } + } +} +`, context) + testAccComputePerInstanceConfig_igm(context) +} + +func testAccComputePerInstanceConfig_removeInstanceOnDestroyAfter(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_per_instance_config" "config_two" { + zone = google_compute_instance_group_manager.igm.zone + instance_group_manager = google_compute_instance_group_manager.igm.name + name = "%{config_name2}" + remove_instance_on_destroy = true + preserved_state { + metadata = { + asdf = "config-two" + } + } +} +`, context) + testAccComputePerInstanceConfig_igm(context) +} + func testAccComputePerInstanceConfig_statefulIpsBasic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_compute_network" "default" { @@ -352,17 +516,17 @@ resource "google_compute_subnetwork" "default" { region = "us-central1" network = google_compute_network.default.id } - + resource "google_compute_address" "static_internal_ip" { name = "%{address1}" address_type = "INTERNAL" } - + resource "google_compute_address" "static_external_ip" { name = "%{address2}" address_type = "EXTERNAL" } - + resource "google_compute_per_instance_config" "default" { instance_group_manager = google_compute_instance_group_manager.igm.name name = "%{config_name}" @@ -404,7 +568,7 @@ resource "google_compute_disk" "disk" { image = "debian-8-jessie-v20170523" physical_block_size_bytes = 4096 } - + resource "google_compute_disk" "disk1" { name = "test-disk2-%{random_suffix}" type = "pd-ssd" @@ -427,17 +591,17 @@ resource "google_compute_subnetwork" "default" { region = "us-central1" network = google_compute_network.default.id } - + resource "google_compute_address" "static_internal_ip" { name = "%{address1}" address_type = "INTERNAL" } - + resource "google_compute_address" "static_external_ip" { name = "%{address2}" address_type = "EXTERNAL" } - + resource "google_compute_per_instance_config" "default" { instance_group_manager = google_compute_instance_group_manager.igm.name name = "%{config_name}" @@ -479,7 +643,7 @@ resource "google_compute_disk" "disk" { image = "debian-8-jessie-v20170523" physical_block_size_bytes = 4096 } - + resource "google_compute_disk" "disk1" { name = "test-disk2-%{random_suffix}" type = "pd-ssd" @@ -505,6 +669,48 @@ func testAccCheckComputePerInstanceConfigDestroyed(t *testing.T, igmId, configNa } } +// Checks that the instance with the given name was destroyed. +func testAccCheckComputePerInstanceConfigInstanceDestroyed(t *testing.T, igmId, configName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + foundNames, err := testAccComputePerInstanceConfigListInstances(t, igmId) + if err != nil { + return fmt.Errorf("unable to confirm instance with name %s was destroyed: %v", configName, err) + } + if _, ok := foundNames[configName]; ok { + return fmt.Errorf("instance with name %s still exists", configName) + } + + return nil + } +} + +func testAccComputePerInstanceConfigListInstances(t *testing.T, igmId string) (map[string]struct{}, error) { + config := acctest.GoogleProviderConfig(t) + + url := fmt.Sprintf("%s%s/listManagedInstances", config.ComputeBasePath, igmId) + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + RawURL: url, + UserAgent: config.UserAgent, + }) + if err != nil { + return nil, err + } + + v, ok := res["managedInstances"] + if !ok || v == nil { + return nil, nil + } + items := v.([]interface{}) + instances := make(map[string]struct{}) + for _, item := range items { + instance := item.(map[string]interface{}) + instances[fmt.Sprintf("%v", instance["name"])] = struct{}{} + } + return instances, nil +} + func testAccComputePerInstanceConfigListNames(t *testing.T, igmId string) (map[string]struct{}, error) { config := acctest.GoogleProviderConfig(t) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_per_instance_config_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_per_instance_config_test.go.erb index e12d5291e6a7..c2191d46be8c 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_per_instance_config_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_per_instance_config_test.go.erb @@ -169,6 +169,67 @@ func TestAccComputeRegionPerInstanceConfig_statefulIps(t *testing.T) { }) } +func TestAccComputeRegionPerInstanceConfig_removeInstanceOnDestroy(t *testing.T) { + t.Parallel() + + rigmName := fmt.Sprintf("tf-test-rigm-%s", acctest.RandString(t, 10)) + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "rigm_name": rigmName, + "config_name": fmt.Sprintf("instance-%s", acctest.RandString(t, 10)), + "config_name2": fmt.Sprintf("instance-%s", acctest.RandString(t, 10)), + "network": fmt.Sprintf("tf-test-rigm-%s", acctest.RandString(t, 10)), + "subnetwork": fmt.Sprintf("tf-test-rigm-%s", acctest.RandString(t, 10)), + "address1": fmt.Sprintf("tf-test-rigm-address%s", acctest.RandString(t, 10)), + "address2": fmt.Sprintf("tf-test-rigm-address%s", acctest.RandString(t, 10)), + } + rigmId := fmt.Sprintf("projects/%s/regions/%s/instanceGroupManagers/%s", + envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), rigmName) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionPerInstanceConfig_removeInstanceOnDestroyBefore(context), + }, + { + ResourceName: "google_compute_region_per_instance_config.config_one", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"remove_instance_on_destroy", "zone"}, + }, + { + ResourceName: "google_compute_region_per_instance_config.config_two", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"remove_instance_on_destroy", "zone"}, + }, + { + Config: testAccComputeRegionPerInstanceConfig_removeInstanceOnDestroyAfter(context), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionPerInstanceConfigDestroyed(t, rigmId, context["config_name"].(string)), + testAccCheckComputeRegionPerInstanceConfigInstanceDestroyed(t, rigmId, context["config_name"].(string)), + ), + }, + { + ResourceName: "google_compute_region_per_instance_config.config_two", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"remove_instance_on_destroy", "zone"}, + }, + { + // delete all configs + Config: testAccComputeRegionPerInstanceConfig_rigm(context), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionPerInstanceConfigDestroyed(t, rigmId, context["config_name2"].(string)), + testAccCheckComputeRegionPerInstanceConfigInstanceDestroyed(t, rigmId, context["config_name2"].(string)), + ), + }, + }, + }) +} + func testAccComputeRegionPerInstanceConfig_statefulBasic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_compute_region_per_instance_config" "default" { @@ -347,6 +408,111 @@ resource "google_compute_region_instance_group_manager" "rigm" { `, context) } + +func testAccComputeRegionPerInstanceConfig_removeInstanceOnDestroyBefore(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + name = "%{network}" +} + +resource "google_compute_subnetwork" "default" { + name = "%{subnetwork}" + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" + network = google_compute_network.default.id +} + +resource "google_compute_address" "static_internal_ip" { + name = "%{address1}" + address_type = "INTERNAL" +} + +resource "google_compute_address" "static_external_ip" { + name = "%{address2}" + address_type = "EXTERNAL" +} + +resource "google_compute_region_per_instance_config" "config_one" { + region = google_compute_region_instance_group_manager.rigm.region + region_instance_group_manager = google_compute_region_instance_group_manager.rigm.name + name = "%{config_name}" + remove_instance_on_destroy = true + preserved_state { + metadata = { + asdf = "config-one" + } + disk { + device_name = "my-stateful-disk1" + source = google_compute_disk.disk.id + } + + disk { + device_name = "my-stateful-disk2" + source = google_compute_disk.disk1.id + } + internal_ip { + ip_address { + address = google_compute_address.static_internal_ip.self_link + } + auto_delete = "NEVER" + interface_name = "nic0" + } + external_ip { + ip_address { + address = google_compute_address.static_external_ip.self_link + } + auto_delete = "NEVER" + interface_name = "nic0" + } + } +} + +resource "google_compute_disk" "disk" { + name = "test-disk-%{random_suffix}" + type = "pd-ssd" + zone = "us-central1-c" + image = "debian-8-jessie-v20170523" + physical_block_size_bytes = 4096 +} + +resource "google_compute_disk" "disk1" { + name = "test-disk2-%{random_suffix}" + type = "pd-ssd" + zone = "us-central1-c" + image = "debian-cloud/debian-11" + physical_block_size_bytes = 4096 +} + +resource "google_compute_region_per_instance_config" "config_two" { + region = google_compute_region_instance_group_manager.rigm.region + region_instance_group_manager = google_compute_region_instance_group_manager.rigm.name + name = "%{config_name2}" + remove_instance_on_destroy = true + preserved_state { + metadata = { + asdf = "config-two" + } + } +} +`, context) + testAccComputeRegionPerInstanceConfig_rigm(context) +} + +func testAccComputeRegionPerInstanceConfig_removeInstanceOnDestroyAfter(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_region_per_instance_config" "config_two" { + region = google_compute_region_instance_group_manager.rigm.region + region_instance_group_manager = google_compute_region_instance_group_manager.rigm.name + name = "%{config_name2}" + remove_instance_on_destroy = true + preserved_state { + metadata = { + asdf = "config-two" + } + } +} +`, context) + testAccComputeRegionPerInstanceConfig_rigm(context) +} + func testAccComputeRegionPerInstanceConfig_statefulIpsBasic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_compute_network" "default" { @@ -513,3 +679,18 @@ func testAccCheckComputeRegionPerInstanceConfigDestroyed(t *testing.T, rigmId, c return nil } } + +// Checks that the instance with the given name was destroyed. +func testAccCheckComputeRegionPerInstanceConfigInstanceDestroyed(t *testing.T, rigmId, configName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + foundNames, err := testAccComputePerInstanceConfigListInstances(t, rigmId) + if err != nil { + return fmt.Errorf("unable to confirm instance with name %s was destroyed: %v", configName, err) + } + if _, ok := foundNames[configName]; ok { + return fmt.Errorf("instance with name %s still exists", configName) + } + + return nil + } +} diff --git a/mmv1/third_party/terraform/services/compute/stateful_mig_polling.go b/mmv1/third_party/terraform/services/compute/stateful_mig_polling.go index 57f96ff9fd62..fa22c2ec1d00 100644 --- a/mmv1/third_party/terraform/services/compute/stateful_mig_polling.go +++ b/mmv1/third_party/terraform/services/compute/stateful_mig_polling.go @@ -47,6 +47,58 @@ func resourceComputePerInstanceConfigPollRead(d *schema.ResourceData, meta inter } } +// Deleting a PerInstanceConfig & the underlying instance needs both regular operation polling AND custom polling for deletion which is why this is not generated +func resourceComputePerInstanceConfigInstancePollRead(d *schema.ResourceData, meta interface{}, instanceName string) transport_tpg.PollReadFunc { + return func() (map[string]interface{}, error) { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return nil, err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/zones/{{zone}}/instanceGroupManagers/{{instance_group_manager}}/listManagedInstances") + if err != nil { + return nil, err + } + + url, err = transport_tpg.AddQueryParams(url, map[string]string{"filter": fmt.Sprintf("name=%q", instanceName)}) + if err != nil { + return nil, err + } + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return nil, err + } + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return res, err + } + + value, ok := res["managedInstances"] + if !ok || value == nil { + return nil, nil + } + + managedInstances, ok := value.([]interface{}) + if !ok { + return nil, fmt.Errorf("expected list for value managedInstances. Actual value: %v", value) + } + + if len(managedInstances) == 1 { + return managedInstances[0].(map[string]interface{}), nil + } + + return nil, nil + } +} + // RegionPerInstanceConfig needs both regular operation polling AND custom polling for deletion which is why this is not generated func resourceComputeRegionPerInstanceConfigPollRead(d *schema.ResourceData, meta interface{}) transport_tpg.PollReadFunc { return func() (map[string]interface{}, error) { @@ -85,6 +137,58 @@ func resourceComputeRegionPerInstanceConfigPollRead(d *schema.ResourceData, meta } } +// Deleting a RegionPerInstanceConfig & the underlying instance needs both regular operation polling AND custom polling for deletion which is why this is not generated +func resourceComputeRegionPerInstanceConfigInstancePollRead(d *schema.ResourceData, meta interface{}, instanceName string) transport_tpg.PollReadFunc { + return func() (map[string]interface{}, error) { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return nil, err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/instanceGroupManagers/{{region_instance_group_manager}}/listManagedInstances") + if err != nil { + return nil, err + } + + url, err = transport_tpg.AddQueryParams(url, map[string]string{"filter": fmt.Sprintf("name=%q", instanceName)}) + if err != nil { + return nil, err + } + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return nil, err + } + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: project, + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return res, err + } + + value, ok := res["managedInstances"] + if !ok || value == nil { + return nil, nil + } + + managedInstances, ok := value.([]interface{}) + if !ok { + return nil, fmt.Errorf("expected list for value managedInstances. Actual value: %v", value) + } + + if len(managedInstances) == 1 { + return managedInstances[0].(map[string]interface{}), nil + } + + return nil, nil + } +} + // Returns an instance name in the form zones/{zone}/instances/{instance} for the managed // instance matching the name of a PerInstanceConfig func findInstanceName(d *schema.ResourceData, config *transport_tpg.Config) (string, error) { @@ -167,3 +271,22 @@ func PollCheckInstanceConfigDeleted(resp map[string]interface{}, respErr error) } return transport_tpg.ErrorPollResult(fmt.Errorf("Expected PerInstanceConfig to be deleting but status is: %s", status)) } + +func PollCheckInstanceConfigInstanceDeleted(resp map[string]interface{}, respErr error) transport_tpg.PollResult { + if respErr != nil { + return transport_tpg.ErrorPollResult(respErr) + } + + // Nested object 404 appears as nil response + if resp == nil { + // Instance no longer exists + return transport_tpg.SuccessPollResult() + } + + // Read status + status := resp["currentAction"].(string) + if status == "DELETING" { + return transport_tpg.PendingStatusPollResult("Still deleting") + } + return transport_tpg.ErrorPollResult(fmt.Errorf("Expected PerInstanceConfig instance to be deleting but status is: %s", status)) +} diff --git a/mmv1/third_party/terraform/tpgresource/common_operation.go b/mmv1/third_party/terraform/tpgresource/common_operation.go index 10b4de877879..cfe6880fde86 100644 --- a/mmv1/third_party/terraform/tpgresource/common_operation.go +++ b/mmv1/third_party/terraform/tpgresource/common_operation.go @@ -151,7 +151,7 @@ func OperationWait(w Waiter, activity string, timeout time.Duration, pollInterva } opRaw, err := c.WaitForState() if err != nil { - return fmt.Errorf("Error waiting for %s: %s", activity, err) + return fmt.Errorf("Error waiting for %s: %w", activity, err) } err = w.SetOp(opRaw) From d026cd2d4c705b31429b353b8ef1df25ee18048a Mon Sep 17 00:00:00 2001 From: Eric Pang Date: Thu, 7 Dec 2023 15:26:02 -0500 Subject: [PATCH 080/107] Add host_config, state_note, kms_key, private_config fields to Secure Source Manager Instance resource (#9583) --- .../securesourcemanager/Instance.yaml | 85 +++++++++++++++++++ ...secure_source_manager_instance_cmek.tf.erb | 26 ++++++ ...ure_source_manager_instance_private.tf.erb | 76 +++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb create mode 100644 mmv1/templates/terraform/examples/secure_source_manager_instance_private.tf.erb diff --git a/mmv1/products/securesourcemanager/Instance.yaml b/mmv1/products/securesourcemanager/Instance.yaml index a058f6a75064..f619fee4d56b 100644 --- a/mmv1/products/securesourcemanager/Instance.yaml +++ b/mmv1/products/securesourcemanager/Instance.yaml @@ -63,6 +63,27 @@ examples: ])" vars: instance_id: 'my-instance' + - !ruby/object:Provider::Terraform::Examples + name: 'secure_source_manager_instance_cmek' + primary_resource_id: 'default' + primary_resource_name: "fmt.Sprintf(\"tf-test-my-instance%s\", + context[\"random_suffix\"\ + ])" + vars: + instance_id: 'my-instance' + keyring_name: 'my-keyring' + key_name: 'my-key' + - !ruby/object:Provider::Terraform::Examples + name: 'secure_source_manager_instance_private' + pull_external: true + primary_resource_id: 'default' + primary_resource_name: "fmt.Sprintf(\"tf-test-my-instance%s\", + context[\"random_suffix\"\ + ])" + vars: + instance_id: 'my-instance' + ca_pool_id: 'ca-pool' + root_ca_id: 'root-ca' parameters: - !ruby/object:Api::Type::String name: 'location' @@ -110,3 +131,67 @@ properties: - :DELETING - :PAUSED - :UNKNOWN + - !ruby/object:Api::Type::NestedObject + name: 'hostConfig' + description: | + A list of hostnames for this instance. + output: true + properties: + - !ruby/object:Api::Type::String + name: 'html' + description: 'HTML hostname.' + output: true + - !ruby/object:Api::Type::String + name: 'api' + description: 'API hostname.' + output: true + - !ruby/object:Api::Type::String + name: 'gitHttp' + description: 'Git HTTP hostname.' + output: true + - !ruby/object:Api::Type::String + name: 'gitSsh' + description: 'Git SSH hostname.' + output: true + - !ruby/object:Api::Type::Enum + name: 'stateNote' + description: | + Provides information about the current instance state. + output: true + values: + - :STATE_NOTE_UNSPECIFIED + - :PAUSED_CMEK_UNAVAILABLE + - :INSTANCE_RESUMING + - !ruby/object:Api::Type::String + name: 'kmsKey' + description: | + Customer-managed encryption key name, in the format projects/*/locations/*/keyRings/*/cryptoKeys/*. + immutable: true + - !ruby/object:Api::Type::NestedObject + name: 'privateConfig' + description: | + Private settings for private instance. + immutable: true + properties: + - !ruby/object:Api::Type::Boolean + name: 'isPrivate' + description: | + 'Indicate if it's private instance.' + required: true + immutable: true + - !ruby/object:Api::Type::String + name: 'caPool' + description: | + CA pool resource, resource must in the format of `projects/{project}/locations/{location}/caPools/{ca_pool}`. + required: true + immutable: true + - !ruby/object:Api::Type::String + name: 'httpServiceAttachment' + description: | + Service Attachment for HTTP, resource is in the format of `projects/{project}/regions/{region}/serviceAttachments/{service_attachment}`. + output: true + - !ruby/object:Api::Type::String + name: 'sshServiceAttachment' + description: | + Service Attachment for SSH, resource is in the format of `projects/{project}/regions/{region}/serviceAttachments/{service_attachment}`. + output: true diff --git a/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb b/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb new file mode 100644 index 000000000000..abde1100aaa7 --- /dev/null +++ b/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb @@ -0,0 +1,26 @@ +resource "google_kms_key_ring" "key_ring" { + name = "<%= ctx[:vars]['keyring_name'] %>" + location = "us-central1" +} + +resource "google_kms_crypto_key" "crypto_key" { + name = "<%= ctx[:vars]['key_name'] %>" + key_ring = google_kms_key_ring.key_ring.id +} + +resource "google_kms_crypto_key_iam_binding" "crypto_key_binding" { + crypto_key_id = google_kms_crypto_key.crypto_key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com" + ] +} + +resource "google_secure_source_manager_instance" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + instance_id = "<%= ctx[:vars]['instance_id'] %>" + kms_key = google_kms_crypto_key.crypto_key.id +} + +data "google_project" "project" {} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/secure_source_manager_instance_private.tf.erb b/mmv1/templates/terraform/examples/secure_source_manager_instance_private.tf.erb new file mode 100644 index 000000000000..03a334e9bf97 --- /dev/null +++ b/mmv1/templates/terraform/examples/secure_source_manager_instance_private.tf.erb @@ -0,0 +1,76 @@ +resource "google_privateca_ca_pool" "ca_pool" { + name = "<%= ctx[:vars]['ca_pool_id'] %>" + location = "us-central1" + tier = "ENTERPRISE" + publishing_options { + publish_ca_cert = true + publish_crl = true + } +} + +resource "google_privateca_certificate_authority" "root_ca" { + pool = google_privateca_ca_pool.ca_pool.name + certificate_authority_id = "<%= ctx[:vars]['root_ca_id'] %>" + location = "us-central1" + config { + subject_config { + subject { + organization = "google" + common_name = "my-certificate-authority" + } + } + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = true + } + } + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } + + // Disable deletion protections for easier test cleanup purposes + deletion_protection = false + ignore_active_certificates_on_deletion = true + skip_grace_period = true +} + +resource "google_privateca_ca_pool_iam_binding" "ca_pool_binding" { + ca_pool = google_privateca_ca_pool.ca_pool.id + role = "roles/privateca.certificateRequester" + + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com" + ] +} + +resource "google_secure_source_manager_instance" "<%= ctx[:primary_resource_id] %>" { + instance_id = "<%= ctx[:vars]['instance_id'] %>" + location = "us-central1" + private_config { + is_private = true + ca_pool = google_privateca_ca_pool.ca_pool.id + } + depends_on = [ + google_privateca_certificate_authority.root_ca, + time_sleep.wait_60_seconds + ] +} + +# ca pool IAM permissions can take time to propagate +resource "time_sleep" "wait_60_seconds" { + depends_on = [google_privateca_ca_pool_iam_binding.ca_pool_binding] + + create_duration = "60s" +} + +data "google_project" "project" {} \ No newline at end of file From 65322ce7395a0a1e39dcfe357dae47c90b954c5a Mon Sep 17 00:00:00 2001 From: Esteban Bouza Date: Fri, 8 Dec 2023 05:26:14 +0800 Subject: [PATCH 081/107] Add data source for google_compute_region_disk (#9421) --- .../provider/provider_mmv1_resources.go.erb | 5 +- .../data_source_google_compute_region_disk.go | 46 +++++++++++++++++ ..._source_google_compute_region_disk_test.go | 49 ++++++++++++++++++ .../docs/d/compute_region_disk.html.markdown | 50 +++++++++++++++++++ 4 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 mmv1/third_party/terraform/services/compute/data_source_google_compute_region_disk.go create mode 100644 mmv1/third_party/terraform/services/compute/data_source_google_compute_region_disk_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/compute_region_disk.html.markdown diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index 38e02676b2ec..a43b78ba436c 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -73,7 +73,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_compute_backend_service": compute.DataSourceGoogleComputeBackendService(), "google_compute_backend_bucket": compute.DataSourceGoogleComputeBackendBucket(), "google_compute_default_service_account": compute.DataSourceGoogleComputeDefaultServiceAccount(), - "google_compute_disk": compute.DataSourceGoogleComputeDisk(), + "google_compute_disk": compute.DataSourceGoogleComputeDisk(), "google_compute_forwarding_rule": compute.DataSourceGoogleComputeForwardingRule(), "google_compute_global_address": compute.DataSourceGoogleComputeGlobalAddress(), "google_compute_global_forwarding_rule": compute.DataSourceGoogleComputeGlobalForwardingRule(), @@ -92,9 +92,10 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_compute_network_peering": compute.DataSourceComputeNetworkPeering(), "google_compute_node_types": compute.DataSourceGoogleComputeNodeTypes(), "google_compute_regions": compute.DataSourceGoogleComputeRegions(), - "google_compute_region_network_endpoint_group": compute.DataSourceGoogleComputeRegionNetworkEndpointGroup(), + "google_compute_region_disk": compute.DataSourceGoogleComputeRegionDisk(), "google_compute_region_instance_group": compute.DataSourceGoogleComputeRegionInstanceGroup(), "google_compute_region_instance_template": compute.DataSourceGoogleComputeRegionInstanceTemplate(), + "google_compute_region_network_endpoint_group": compute.DataSourceGoogleComputeRegionNetworkEndpointGroup(), "google_compute_region_ssl_certificate": compute.DataSourceGoogleRegionComputeSslCertificate(), "google_compute_resource_policy": compute.DataSourceGoogleComputeResourcePolicy(), "google_compute_router": compute.DataSourceGoogleComputeRouter(), diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_disk.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_disk.go new file mode 100644 index 000000000000..010c96f65f72 --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_disk.go @@ -0,0 +1,46 @@ +package compute + +import ( + "fmt" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +func DataSourceGoogleComputeRegionDisk() *schema.Resource { + + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceComputeRegionDisk().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "name") + tpgresource.AddOptionalFieldsToSchema(dsSchema, "project") + tpgresource.AddOptionalFieldsToSchema(dsSchema, "region") + + return &schema.Resource{ + Read: dataSourceGoogleComputeRegionDiskRead, + Schema: dsSchema, + } +} + +func dataSourceGoogleComputeRegionDiskRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/regions/{{region}}/disks/{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + err = resourceComputeRegionDiskRead(d, meta) + if err != nil { + return err + } + + if err := tpgresource.SetDataSourceLabels(d); err != nil { + return err + } + + if d.Id() == "" { + return fmt.Errorf("%s not found", id) + } + + return nil +} diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_disk_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_disk_test.go new file mode 100644 index 000000000000..d28025ef857b --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_region_disk_test.go @@ -0,0 +1,49 @@ +package compute_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccDataSourceGoogleComputeRegionDisk_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeDiskDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleComputeRegionDisk_basic(context), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceState("data.google_compute_region_disk.foo", "google_compute_region_disk.foo"), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleComputeRegionDisk_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_region_disk" "foo" { + name = "tf-test-compute-disk-%{random_suffix}" + type = "pd-standard" + replica_zones = ["us-central1-a", "us-central1-f"] + + labels = { + my-label = "my-label-value" + } +} + +data "google_compute_region_disk" "foo" { + name = google_compute_region_disk.foo.name + project = google_compute_region_disk.foo.project +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/compute_region_disk.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_region_disk.html.markdown new file mode 100644 index 000000000000..ca3b5443ee4c --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/compute_region_disk.html.markdown @@ -0,0 +1,50 @@ +--- +subcategory: "Compute Engine" +description: |- + Get information about a Google Compute Regional Persistent disks. +--- + +# google\_compute\_region\_disk + +Get information about a Google Compute Regional Persistent disks. + +[the official documentation](https://cloud.google.com/compute/docs/disks) and its [API](https://cloud.google.com/compute/docs/reference/rest/v1/regionDisks). + +## Example Usage + +```hcl +data "google_compute_region_disk" "disk" { + name = "persistent-regional-disk" + project = "example" + region = "us-central1" + type = "pd-ssd" + physical_block_size_bytes = 4096 + + replica_zones = ["us-central1-a", "us-central1-f"] +} + +resource "google_compute_instance" "default" { + # ... + + attached_disk { + source = data.google_compute_disk.disk.self_link + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of a specific disk. + +- - - + +* `region` - (Optional) A reference to the region where the disk resides. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + +## Attributes Reference + +See [google_compute_region_disk](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_region_disk) resource for details of the available attributes. \ No newline at end of file From a007c7ce0f9498648bb61de3e9151b0639ed181b Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Thu, 7 Dec 2023 21:35:15 +0000 Subject: [PATCH 082/107] dataform_repository - add missing args (#9173) --- mmv1/products/dataform/Repository.yaml | 11 +++++++++++ .../terraform/examples/dataform_repository.tf.erb | 6 ++++++ 2 files changed, 17 insertions(+) diff --git a/mmv1/products/dataform/Repository.yaml b/mmv1/products/dataform/Repository.yaml index 6c7b206f65a6..1d99d98c8fb7 100644 --- a/mmv1/products/dataform/Repository.yaml +++ b/mmv1/products/dataform/Repository.yaml @@ -123,3 +123,14 @@ properties: - !ruby/object:Api::Type::String name: 'serviceAccount' description: The service account to run workflow invocations under. + - !ruby/object:Api::Type::String + name: npmrcEnvironmentVariablesSecretVersion + description: Optional. The name of the Secret Manager secret version to be used to interpolate variables into the .npmrc file for package installation operations. Must be in the format projects/*/secrets/*/versions/*. The file itself must be in a JSON format. + - !ruby/object:Api::Type::String + name: displayName + description: Optional. The repository's user-friendly name. + - !ruby/object:Api::Type::KeyValueLabels + name: labels + description: | + Optional. Repository user labels. + An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. diff --git a/mmv1/templates/terraform/examples/dataform_repository.tf.erb b/mmv1/templates/terraform/examples/dataform_repository.tf.erb index 3a9e3232aa57..1e76e9133b1e 100644 --- a/mmv1/templates/terraform/examples/dataform_repository.tf.erb +++ b/mmv1/templates/terraform/examples/dataform_repository.tf.erb @@ -22,6 +22,12 @@ resource "google_secret_manager_secret_version" "secret_version" { resource "google_dataform_repository" "<%= ctx[:primary_resource_id] %>" { provider = google-beta name = "<%= ctx[:vars]['dataform_repository_name'] %>" + display_name = "<%= ctx[:vars]['dataform_repository_name'] %>" + npmrc_environment_variables_secret_version = google_secret_manager_secret_version.secret_version.id + + labels = { + label_foo1 = "label-bar1" + } git_remote_settings { url = google_sourcerepo_repository.git_repository.url From c3b3a420aa6290cb448cb232185fb9cff4bc04f7 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 7 Dec 2023 22:26:13 +0000 Subject: [PATCH 083/107] Add migrationcenter service to enabled APIs (#9603) --- .ci/infra/terraform/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index bed01ed1da2a..49ecc649a20d 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -261,6 +261,7 @@ module "project-services" { "managedidentities.googleapis.com", "memcache.googleapis.com", "metastore.googleapis.com", + "migrationcenter.googleapis.com", "ml.googleapis.com", "mobilecrashreporting.googleapis.com", "monitoring.googleapis.com", From d4a31b0b29bc5759eb10f1f29a9df1f67cbbd7b3 Mon Sep 17 00:00:00 2001 From: Eric Pang Date: Thu, 7 Dec 2023 18:00:28 -0500 Subject: [PATCH 084/107] Update documentation links in Secure Source Manager Instance (#9585) * Update links * Update mmv1/products/securesourcemanager/Instance.yaml Co-authored-by: Nick Elliot --------- Co-authored-by: Nick Elliot --- mmv1/products/securesourcemanager/Instance.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mmv1/products/securesourcemanager/Instance.yaml b/mmv1/products/securesourcemanager/Instance.yaml index f619fee4d56b..963c073e5ad0 100644 --- a/mmv1/products/securesourcemanager/Instance.yaml +++ b/mmv1/products/securesourcemanager/Instance.yaml @@ -20,7 +20,8 @@ immutable: true description: 'Instances are deployed to an available Google Cloud region and are accessible via their web interface.' references: !ruby/object:Api::Resource::ReferenceLinks guides: - 'Official Documentation': 'https://cloud.google.com/secure-source-manager/overview/overview' + 'Official Documentation': 'https://cloud.google.com/secure-source-manager/docs/create-instance' + api: 'https://cloud.google.com/secure-source-manager/docs/reference/rest/v1/projects.locations.instances' import_format: ['projects/{{project}}/locations/{{location}}/instances/{{instance_id}}', '{{instance_id}}'] autogen_async: true async: !ruby/object:Api::OpAsync From 67e40a4feff66c569577d0e25e4b0e49d564fbf2 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 8 Dec 2023 14:25:22 +0000 Subject: [PATCH 085/107] Ignore `update_time` in import test on `google_vmwareengine_network_policy` resource (#9601) --- .../resource_vmwareengine_private_cloud_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go index 9a189bd1c378..40b0cde0a558 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go @@ -38,7 +38,7 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T ResourceName: "google_vmwareengine_private_cloud.vmw-engine-pc", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "name"}, + ImportStateVerifyIgnore: []string{"location", "name", "update_time"}, }, { Config: testPrivateCloudUpdateConfig(context, "description2", 4), // Expand PC @@ -47,7 +47,7 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T ResourceName: "google_vmwareengine_private_cloud.vmw-engine-pc", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "name"}, + ImportStateVerifyIgnore: []string{"location", "name", "update_time"}, }, { Config: testPrivateCloudUpdateConfig(context, "description2", 3), // Shrink PC @@ -56,7 +56,7 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T ResourceName: "google_vmwareengine_private_cloud.vmw-engine-pc", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "name"}, + ImportStateVerifyIgnore: []string{"location", "name", "update_time"}, }, }, }) From 528ec5d02ef2a696e4c2887551eff5cf1bd535fe Mon Sep 17 00:00:00 2001 From: Amir Romashkin Date: Fri, 8 Dec 2023 18:35:02 +0100 Subject: [PATCH 086/107] Extract converter_factory and hcl_write from utils (#9607) --- mmv1/third_party/cai2hcl/common/converter.go | 4 -- .../cai2hcl/common/converter_factory.go | 21 +++++++ mmv1/third_party/cai2hcl/common/hcl_write.go | 55 +++++++++++++++++ mmv1/third_party/cai2hcl/common/utils.go | 60 ------------------- 4 files changed, 76 insertions(+), 64 deletions(-) create mode 100644 mmv1/third_party/cai2hcl/common/converter_factory.go create mode 100644 mmv1/third_party/cai2hcl/common/hcl_write.go diff --git a/mmv1/third_party/cai2hcl/common/converter.go b/mmv1/third_party/cai2hcl/common/converter.go index 17f6a652daac..b83af7b72568 100644 --- a/mmv1/third_party/cai2hcl/common/converter.go +++ b/mmv1/third_party/cai2hcl/common/converter.go @@ -2,7 +2,6 @@ package common import ( "github.com/GoogleCloudPlatform/terraform-google-conversion/v5/caiasset" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/zclconf/go-cty/cty" ) @@ -12,9 +11,6 @@ type Converter interface { Convert(asset []*caiasset.Asset) ([]*HCLResourceBlock, error) } -// Function initializing a converter from TF resource name and TF resource schema. -type ConverterFactory = func(name string, schema map[string]*schema.Schema) Converter - // HCLResourceBlock identifies the HCL block's labels and content. type HCLResourceBlock struct { Labels []string diff --git a/mmv1/third_party/cai2hcl/common/converter_factory.go b/mmv1/third_party/cai2hcl/common/converter_factory.go new file mode 100644 index 000000000000..e4bec63d3184 --- /dev/null +++ b/mmv1/third_party/cai2hcl/common/converter_factory.go @@ -0,0 +1,21 @@ +package common + +import ( + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/provider" +) + +// Function initializing a converter from TF resource name and TF resource schema. +type ConverterFactory = func(name string, schema map[string]*schema.Schema) Converter + +// Initializes map of converters. +func CreateConverterMap(converterFactories map[string]ConverterFactory) map[string]Converter { + tpgProvider := tpg.Provider() + + result := make(map[string]Converter, len(converterFactories)) + for name, factory := range converterFactories { + result[name] = factory(name, tpgProvider.ResourcesMap[name].Schema) + } + + return result +} diff --git a/mmv1/third_party/cai2hcl/common/hcl_write.go b/mmv1/third_party/cai2hcl/common/hcl_write.go new file mode 100644 index 000000000000..c14b67401f99 --- /dev/null +++ b/mmv1/third_party/cai2hcl/common/hcl_write.go @@ -0,0 +1,55 @@ +package common + +import ( + "fmt" + + "github.com/hashicorp/hcl/v2/hclwrite" + "github.com/zclconf/go-cty/cty" +) + +func hclWriteBlock(val cty.Value, body *hclwrite.Body) error { + if val.IsNull() { + return nil + } + if !val.Type().IsObjectType() { + return fmt.Errorf("expect object type only, but type = %s", val.Type().FriendlyName()) + } + it := val.ElementIterator() + for it.Next() { + objKey, objVal := it.Element() + if objVal.IsNull() { + continue + } + objValType := objVal.Type() + switch { + case objValType.IsObjectType(): + newBlock := body.AppendNewBlock(objKey.AsString(), nil) + if err := hclWriteBlock(objVal, newBlock.Body()); err != nil { + return err + } + case objValType.IsCollectionType(): + if objVal.LengthInt() == 0 { + continue + } + // Presumes map should not contain object type. + if !objValType.IsMapType() && objValType.ElementType().IsObjectType() { + listIterator := objVal.ElementIterator() + for listIterator.Next() { + _, listVal := listIterator.Element() + subBlock := body.AppendNewBlock(objKey.AsString(), nil) + if err := hclWriteBlock(listVal, subBlock.Body()); err != nil { + return err + } + } + continue + } + fallthrough + default: + if objValType.FriendlyName() == "string" && objVal.AsString() == "" { + continue + } + body.SetAttributeValue(objKey.AsString(), objVal) + } + } + return nil +} diff --git a/mmv1/third_party/cai2hcl/common/utils.go b/mmv1/third_party/cai2hcl/common/utils.go index 0325957d9b3e..cac4204eec2f 100644 --- a/mmv1/third_party/cai2hcl/common/utils.go +++ b/mmv1/third_party/cai2hcl/common/utils.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/hcl/hcl/printer" "github.com/hashicorp/hcl/v2/hclwrite" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/provider" "github.com/zclconf/go-cty/cty" ctyjson "github.com/zclconf/go-cty/cty/json" ) @@ -55,18 +54,6 @@ func MapToCtyValWithSchema(m map[string]interface{}, s map[string]*schema.Schema return ret, nil } -// Initializes map of converters. -func CreateConverterMap(converterFactories map[string]ConverterFactory) map[string]Converter { - tpgProvider := tpg.Provider() - - result := make(map[string]Converter, len(converterFactories)) - for name, factory := range converterFactories { - result[name] = factory(name, tpgProvider.ResourcesMap[name].Schema) - } - - return result -} - func Convert(assets []*caiasset.Asset, converterNames map[string]string, converterMap map[string]Converter) ([]byte, error) { // Group resources from the same tf resource type for convert. // tf -> cai has 1:N mappings occasionally @@ -105,53 +92,6 @@ func Convert(assets []*caiasset.Asset, converterNames map[string]string, convert return printer.Format(f.Bytes()) } -func hclWriteBlock(val cty.Value, body *hclwrite.Body) error { - if val.IsNull() { - return nil - } - if !val.Type().IsObjectType() { - return fmt.Errorf("expect object type only, but type = %s", val.Type().FriendlyName()) - } - it := val.ElementIterator() - for it.Next() { - objKey, objVal := it.Element() - if objVal.IsNull() { - continue - } - objValType := objVal.Type() - switch { - case objValType.IsObjectType(): - newBlock := body.AppendNewBlock(objKey.AsString(), nil) - if err := hclWriteBlock(objVal, newBlock.Body()); err != nil { - return err - } - case objValType.IsCollectionType(): - if objVal.LengthInt() == 0 { - continue - } - // Presumes map should not contain object type. - if !objValType.IsMapType() && objValType.ElementType().IsObjectType() { - listIterator := objVal.ElementIterator() - for listIterator.Next() { - _, listVal := listIterator.Element() - subBlock := body.AppendNewBlock(objKey.AsString(), nil) - if err := hclWriteBlock(listVal, subBlock.Body()); err != nil { - return err - } - } - continue - } - fallthrough - default: - if objValType.FriendlyName() == "string" && objVal.AsString() == "" { - continue - } - body.SetAttributeValue(objKey.AsString(), objVal) - } - } - return nil -} - func hashicorpCtyTypeToZclconfCtyType(t hashicorpcty.Type) (cty.Type, error) { b, err := json.Marshal(t) if err != nil { From a691e0379079f0fd3f65f054b4d73456f314dbe8 Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Fri, 8 Dec 2023 11:28:47 -0800 Subject: [PATCH 087/107] =?UTF-8?q?add=20optional=20input=20ParentService?= =?UTF-8?q?=20to=20BootstrapSharedServiceNetworkingC=E2=80=A6=20(#9598)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mmv1/products/looker/Instance.yaml | 2 +- .../terraform/acctest/bootstrap_test_utils.go | 36 +++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/mmv1/products/looker/Instance.yaml b/mmv1/products/looker/Instance.yaml index 5af50943cc3b..38b871deb18e 100644 --- a/mmv1/products/looker/Instance.yaml +++ b/mmv1/products/looker/Instance.yaml @@ -71,7 +71,7 @@ examples: test_vars_overrides: address_name: 'acctest.BootstrapSharedTestGlobalAddress(t, "looker-vpc-network-1", acctest.AddressWithPrefixLength(20))' kms_key_name: 'acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' - network_name: 'acctest.BootstrapSharedServiceNetworkingConnection(t, "looker-vpc-network-1", acctest.AddressWithPrefixLength(20))' + network_name: 'acctest.BootstrapSharedServiceNetworkingConnection(t, "looker-vpc-network-1", acctest.ServiceNetworkWithPrefixLength(20))' skip_docs: true parameters: - !ruby/object:Api::Type::String diff --git a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go index 213db73ecbd3..d0bb61468ad6 100644 --- a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go +++ b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go @@ -443,6 +443,35 @@ func BootstrapSharedTestGlobalAddress(t *testing.T, testId string, params ...fun return address.Name } +type ServiceNetworkSettings struct { + PrefixLength int + ParentService string +} + +func ServiceNetworkWithPrefixLength(prefixLength int) func(*ServiceNetworkSettings) { + return func(settings *ServiceNetworkSettings) { + settings.PrefixLength = prefixLength + } +} + +func ServiceNetworkWithParentService(parentService string) func(*ServiceNetworkSettings) { + return func(settings *ServiceNetworkSettings) { + settings.ParentService = parentService + } +} + +func NewServiceNetworkSettings(options ...func(*ServiceNetworkSettings)) *ServiceNetworkSettings { + settings := &ServiceNetworkSettings{ + PrefixLength: 16, // default prefix length + ParentService: "servicenetworking.googleapis.com", // default parent service + } + + for _, o := range options { + o(settings) + } + return settings +} + // BootstrapSharedServiceNetworkingConnection will create a shared network // if it hasn't been created in the test project, a global address // if it hasn't been created in the test project, and a service networking connection @@ -461,8 +490,9 @@ func BootstrapSharedTestGlobalAddress(t *testing.T, testId string, params ...fun // https://cloud.google.com/vpc/docs/configure-private-services-access#removing-connection // // testId specifies the test for which a shared network and a gobal address are used/initialized. -func BootstrapSharedServiceNetworkingConnection(t *testing.T, testId string, params ...func(*AddressSettings)) string { - parentService := "services/servicenetworking.googleapis.com" +func BootstrapSharedServiceNetworkingConnection(t *testing.T, testId string, params ...func(*ServiceNetworkSettings)) string { + settings := NewServiceNetworkSettings(params...) + parentService := "services/" + settings.ParentService projectId := envvar.GetTestProjectFromEnv() config := BootstrapConfig(t) @@ -479,7 +509,7 @@ func BootstrapSharedServiceNetworkingConnection(t *testing.T, testId string, par networkName := SharedTestNetworkPrefix + testId networkId := fmt.Sprintf("projects/%v/global/networks/%v", project.ProjectNumber, networkName) - globalAddressName := BootstrapSharedTestGlobalAddress(t, testId, params...) + globalAddressName := BootstrapSharedTestGlobalAddress(t, testId, AddressWithPrefixLength(settings.PrefixLength)) readCall := config.NewServiceNetworkingClient(config.UserAgent).Services.Connections.List(parentService).Network(networkId) if config.UserProjectOverride { From fd83cc81557bcab5680ef473a4f892ff9f39f106 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 8 Dec 2023 11:46:38 -0800 Subject: [PATCH 088/107] Refactor magician structs (#9605) * Refactored github interfaces Fixed bug in overriding breaking changes * gofmt * Removed GetPullRequestLabelIDs --- .ci/magician/cloudbuild/build_trigger.go | 8 +- .ci/magician/cloudbuild/community.go | 14 ++-- .ci/magician/cloudbuild/init.go | 12 +-- .ci/magician/cmd/community_checker.go | 20 ++--- .ci/magician/cmd/community_checker_test.go | 18 ++++- .ci/magician/cmd/generate_comment.go | 78 +++++++++---------- .ci/magician/cmd/interfaces.go | 34 ++++++++ .ci/magician/cmd/membership_checker.go | 28 ++----- .ci/magician/cmd/membership_checker_test.go | 24 +++++- .ci/magician/cmd/mock_github_test.go | 13 +--- .ci/magician/cmd/test_tgc.go | 2 +- .ci/magician/cmd/test_tpg.go | 2 +- .ci/magician/exec/runner.go | 35 +++------ .ci/magician/github/get.go | 52 +++++-------- .ci/magician/github/init.go | 22 +----- .ci/magician/github/membership.go | 2 +- .ci/magician/github/reviewer_assignment.go | 2 +- .../github/reviewer_assignment_test.go | 4 +- .ci/magician/github/set.go | 12 +-- .ci/magician/main.go | 1 - 20 files changed, 182 insertions(+), 201 deletions(-) create mode 100644 .ci/magician/cmd/interfaces.go diff --git a/.ci/magician/cloudbuild/build_trigger.go b/.ci/magician/cloudbuild/build_trigger.go index 04ecaf80c748..676e5a5b64a6 100644 --- a/.ci/magician/cloudbuild/build_trigger.go +++ b/.ci/magician/cloudbuild/build_trigger.go @@ -5,10 +5,10 @@ import ( "fmt" "os" - "google.golang.org/api/cloudbuild/v1" + cloudbuildv1 "google.golang.org/api/cloudbuild/v1" ) -func (cb cloudBuild) TriggerMMPresubmitRuns(commitSha string, substitutions map[string]string) error { +func (cb *Client) TriggerMMPresubmitRuns(commitSha string, substitutions map[string]string) error { presubmitTriggerId, ok := os.LookupEnv("GENERATE_DIFFS_TRIGGER") if !ok { return fmt.Errorf("did not provide GENERATE_DIFFS_TRIGGER environment variable") @@ -24,12 +24,12 @@ func (cb cloudBuild) TriggerMMPresubmitRuns(commitSha string, substitutions map[ func triggerCloudBuildRun(projectId, triggerId, repoName, commitSha string, substitutions map[string]string) error { ctx := context.Background() - c, err := cloudbuild.NewService(ctx) + c, err := cloudbuildv1.NewService(ctx) if err != nil { return fmt.Errorf("failed to create Cloud Build service client: %s", err) } - repoSource := &cloudbuild.RepoSource{ + repoSource := &cloudbuildv1.RepoSource{ ProjectId: projectId, RepoName: repoName, CommitSha: commitSha, diff --git a/.ci/magician/cloudbuild/community.go b/.ci/magician/cloudbuild/community.go index ff7634b82d7d..09b8d2d6345a 100644 --- a/.ci/magician/cloudbuild/community.go +++ b/.ci/magician/cloudbuild/community.go @@ -5,10 +5,10 @@ import ( "fmt" "os" - "google.golang.org/api/cloudbuild/v1" + cloudbuildv1 "google.golang.org/api/cloudbuild/v1" ) -func (cb cloudBuild) ApproveCommunityChecker(prNumber, commitSha string) error { +func (cb *Client) ApproveCommunityChecker(prNumber, commitSha string) error { buildId, err := getPendingBuildId(PROJECT_ID, commitSha) if err != nil { return err @@ -26,7 +26,7 @@ func (cb cloudBuild) ApproveCommunityChecker(prNumber, commitSha string) error { return nil } -func (cb cloudBuild) GetAwaitingApprovalBuildLink(prNumber, commitSha string) (string, error) { +func (cb *Client) GetAwaitingApprovalBuildLink(prNumber, commitSha string) (string, error) { buildId, err := getPendingBuildId(PROJECT_ID, commitSha) if err != nil { return "", err @@ -49,7 +49,7 @@ func getPendingBuildId(projectId, commitSha string) (string, error) { ctx := context.Background() - c, err := cloudbuild.NewService(ctx) + c, err := cloudbuildv1.NewService(ctx) if err != nil { return "", err } @@ -76,15 +76,15 @@ func getPendingBuildId(projectId, commitSha string) (string, error) { func approveBuild(projectId, buildId string) error { ctx := context.Background() - c, err := cloudbuild.NewService(ctx) + c, err := cloudbuildv1.NewService(ctx) if err != nil { return err } name := fmt.Sprintf("projects/%s/builds/%s", projectId, buildId) - approveBuildRequest := &cloudbuild.ApproveBuildRequest{ - ApprovalResult: &cloudbuild.ApprovalResult{ + approveBuildRequest := &cloudbuildv1.ApproveBuildRequest{ + ApprovalResult: &cloudbuildv1.ApprovalResult{ Decision: "APPROVED", }, } diff --git a/.ci/magician/cloudbuild/init.go b/.ci/magician/cloudbuild/init.go index e2d29face5a2..52f65318aa0c 100644 --- a/.ci/magician/cloudbuild/init.go +++ b/.ci/magician/cloudbuild/init.go @@ -1,14 +1,8 @@ package cloudbuild -type cloudBuild bool - -type CloudBuild interface { - ApproveCommunityChecker(prNumber, commitSha string) error - GetAwaitingApprovalBuildLink(prNumber, commitSha string) (string, error) - TriggerMMPresubmitRuns(commitSha string, substitutions map[string]string) error +type Client struct { } -func NewCloudBuildService() CloudBuild { - var x cloudBuild = true - return x +func NewClient() *Client { + return &Client{} } diff --git a/.ci/magician/cmd/community_checker.go b/.ci/magician/cmd/community_checker.go index f1b8a943d08e..3630bbb323f1 100644 --- a/.ci/magician/cmd/community_checker.go +++ b/.ci/magician/cmd/community_checker.go @@ -12,17 +12,6 @@ import ( "github.com/spf13/cobra" ) -type ccGithub interface { - GetPullRequestAuthor(prNumber string) (string, error) - GetUserType(user string) github.UserType - RemoveLabel(prNumber string, label string) error - PostBuildStatus(prNumber string, title string, state string, targetUrl string, commitSha string) error -} - -type ccCloudbuild interface { - TriggerMMPresubmitRuns(commitSha string, substitutions map[string]string) error -} - // communityApprovalCmd represents the communityApproval command var communityApprovalCmd = &cobra.Command{ Use: "community-checker", @@ -63,13 +52,13 @@ var communityApprovalCmd = &cobra.Command{ baseBranch := args[5] fmt.Println("Base Branch: ", baseBranch) - gh := github.NewGithubService() - cb := cloudbuild.NewCloudBuildService() + gh := github.NewClient() + cb := cloudbuild.NewClient() execCommunityChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch, gh, cb) }, } -func execCommunityChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch string, gh ccGithub, cb ccCloudbuild) { +func execCommunityChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch string, gh GithubClient, cb CloudbuildClient) { substitutions := map[string]string{ "BRANCH_NAME": branchName, "_PR_NUMBER": prNumber, @@ -78,12 +67,13 @@ func execCommunityChecker(prNumber, commitSha, branchName, headRepoUrl, headBran "_BASE_BRANCH": baseBranch, } - author, err := gh.GetPullRequestAuthor(prNumber) + pullRequest, err := gh.GetPullRequest(prNumber) if err != nil { fmt.Println(err) os.Exit(1) } + author := pullRequest.User.Login authorUserType := gh.GetUserType(author) trusted := authorUserType == github.CoreContributorUserType || authorUserType == github.GooglerUserType diff --git a/.ci/magician/cmd/community_checker_test.go b/.ci/magician/cmd/community_checker_test.go index dec9682e50a2..f429a7910cb1 100644 --- a/.ci/magician/cmd/community_checker_test.go +++ b/.ci/magician/cmd/community_checker_test.go @@ -8,7 +8,11 @@ import ( func TestExecCommunityChecker_CoreContributorFlow(t *testing.T) { gh := &mockGithub{ - author: "core_author", + pullRequest: github.PullRequest{ + User: github.User{ + Login: "core_author", + }, + }, userType: github.CoreContributorUserType, calledMethods: make(map[string][][]any), } @@ -34,7 +38,11 @@ func TestExecCommunityChecker_CoreContributorFlow(t *testing.T) { func TestExecCommunityChecker_GooglerFlow(t *testing.T) { gh := &mockGithub{ - author: "googler_author", + pullRequest: github.PullRequest{ + User: github.User{ + Login: "googler_author", + }, + }, userType: github.GooglerUserType, calledMethods: make(map[string][][]any), firstReviewer: "reviewer1", @@ -61,7 +69,11 @@ func TestExecCommunityChecker_GooglerFlow(t *testing.T) { func TestExecCommunityChecker_AmbiguousUserFlow(t *testing.T) { gh := &mockGithub{ - author: "ambiguous_author", + pullRequest: github.PullRequest{ + User: github.User{ + Login: "ambiguous_author", + }, + }, userType: github.CommunityUserType, calledMethods: make(map[string][][]any), firstReviewer: github.GetRandomReviewer(), diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index c38b68009189..2d2aa39f3b73 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -12,23 +12,7 @@ import ( "github.com/spf13/cobra" ) -const allowBreakingChangesLabel = 4598495472 - -type gcGithub interface { - GetPullRequestLabelIDs(prNumber string) (map[int]struct{}, error) - PostBuildStatus(prNumber, title, state, targetURL, commitSha string) error - PostComment(prNumber, comment string) error -} - -type gcRunner interface { - GetCWD() string - Copy(src, dest string) error - RemoveAll(path string) error - PushDir(path string) error - PopDir() error - Run(name string, args, env []string) (string, error) - MustRun(name string, args, env []string) string -} +const allowBreakingChangesLabel = "override-breaking-change" type ProviderVersion string @@ -74,8 +58,8 @@ var generateCommentCmd = &cobra.Command{ commit := os.Getenv("COMMIT_SHA") fmt.Println("Commit SHA: ", commit) - pr := os.Getenv("PR_NUMBER") - fmt.Println("PR Number: ", pr) + prNumber := os.Getenv("PR_NUMBER") + fmt.Println("PR Number: ", prNumber) githubToken, ok := os.LookupEnv("GITHUB_TOKEN") if !ok { @@ -83,19 +67,19 @@ var generateCommentCmd = &cobra.Command{ os.Exit(1) } - gh := github.NewGithubService() + gh := github.NewClient() rnr, err := exec.NewRunner() if err != nil { fmt.Println("Error creating a runner: ", err) os.Exit(1) } - execGenerateComment(buildID, projectID, buildStep, commit, pr, githubToken, gh, rnr) + execGenerateComment(buildID, projectID, buildStep, commit, prNumber, githubToken, gh, rnr) }, } -func execGenerateComment(buildID, projectID, buildStep, commit, pr, githubToken string, gh gcGithub, r gcRunner) { - newBranch := "auto-pr-" + pr - oldBranch := "auto-pr-" + pr + "-old" +func execGenerateComment(buildID, projectID, buildStep, commit, prNumber, githubToken string, gh GithubClient, r ExecRunner) { + newBranch := "auto-pr-" + prNumber + oldBranch := "auto-pr-" + prNumber + "-old" wd := r.GetCWD() mmLocalPath := filepath.Join(wd, "..", "..") tpgRepoName := "terraform-provider-google" @@ -173,7 +157,7 @@ func execGenerateComment(buildID, projectID, buildStep, commit, pr, githubToken showBreakingChangesFailed = true } versionedBreakingChanges[repo.Version] = output - err = addLabels(diffProcessorPath, githubToken, pr, r) + err = addLabels(diffProcessorPath, githubToken, prNumber, r) if err != nil { fmt.Println("Error adding TPG labels to PR: ", err) } @@ -204,12 +188,20 @@ The breaking change detector crashed during execution. This is usually due to th if breakingChanges != "" { message += breakingChanges + "\n\n" - labels, err := gh.GetPullRequestLabelIDs(pr) + pullRequest, err := gh.GetPullRequest(prNumber) if err != nil { - fmt.Printf("Error getting pull request labels: %v\n", err) + fmt.Printf("Error getting pull request: %v\n", err) os.Exit(1) } - if _, ok := labels[allowBreakingChangesLabel]; !ok { + + breakingChangesAllowed := false + for _, label := range pullRequest.Labels { + if label.Name == allowBreakingChangesLabel { + breakingChangesAllowed = true + break + } + } + if !breakingChangesAllowed { breakingState = "failure" } } @@ -223,13 +215,13 @@ The breaking change detector crashed during execution. This is usually due to th } } - if err := gh.PostComment(pr, message); err != nil { - fmt.Printf("Error posting comment to PR %s: %v\n", pr, err) + if err := gh.PostComment(prNumber, message); err != nil { + fmt.Printf("Error posting comment to PR %s: %v\n", prNumber, err) } targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", buildID, buildStep, projectID) - if err := gh.PostBuildStatus(pr, "terraform-provider-breaking-change-test", breakingState, targetURL, commit); err != nil { - fmt.Printf("Error posting build status for pr %s commit %s: %v\n", pr, commit, err) + if err := gh.PostBuildStatus(prNumber, "terraform-provider-breaking-change-test", breakingState, targetURL, commit); err != nil { + fmt.Printf("Error posting build status for pr %s commit %s: %v\n", prNumber, commit, err) os.Exit(1) } @@ -239,7 +231,7 @@ The breaking change detector crashed during execution. This is usually due to th } if diffs := r.MustRun("git", []string{"diff", "HEAD", "origin/main", "tools/missing-test-detector"}, nil); diffs != "" { fmt.Printf("Found diffs in missing test detector:\n%s\nRunning tests.\n", diffs) - if err := testTools(mmLocalPath, tpgbLocalPath, pr, commit, buildID, buildStep, projectID, gh, r); err != nil { + if err := testTools(mmLocalPath, tpgbLocalPath, prNumber, commit, buildID, buildStep, projectID, gh, r); err != nil { fmt.Printf("Error testing tools in %s: %v\n", mmLocalPath, err) os.Exit(1) } @@ -250,7 +242,7 @@ The breaking change detector crashed during execution. This is usually due to th } } -func cloneAndDiff(repo Repository, oldBranch, newBranch, githubToken string, r gcRunner) (string, error) { +func cloneAndDiff(repo Repository, oldBranch, newBranch, githubToken string, r ExecRunner) (string, error) { // Clone the repo to the desired repo.Path. url := fmt.Sprintf("https://modular-magician:%s@github.com/modular-magician/%s", githubToken, repo.Name) if _, err := r.Run("git", []string{"clone", "-b", newBranch, url, repo.Path}, nil); err != nil { @@ -276,7 +268,7 @@ func cloneAndDiff(repo Repository, oldBranch, newBranch, githubToken string, r g } // Build the diff processor for tpg or tpgb -func buildDiffProcessor(diffProcessorPath, providerLocalPath, oldBranch, newBranch string, r gcRunner) error { +func buildDiffProcessor(diffProcessorPath, providerLocalPath, oldBranch, newBranch string, r ExecRunner) error { if err := r.PushDir(diffProcessorPath); err != nil { return err } @@ -291,7 +283,7 @@ func buildDiffProcessor(diffProcessorPath, providerLocalPath, oldBranch, newBran return r.PopDir() } -func computeBreakingChanges(diffProcessorPath string, r gcRunner) (string, error) { +func computeBreakingChanges(diffProcessorPath string, r ExecRunner) (string, error) { if err := r.PushDir(diffProcessorPath); err != nil { return "", err } @@ -302,11 +294,11 @@ func computeBreakingChanges(diffProcessorPath string, r gcRunner) (string, error return breakingChanges, r.PopDir() } -func addLabels(diffProcessorPath, githubToken, pr string, r gcRunner) error { +func addLabels(diffProcessorPath, githubToken, prNumber string, r ExecRunner) error { if err := r.PushDir(diffProcessorPath); err != nil { return err } - output, err := r.Run("bin/diff-processor", []string{"add-labels", pr}, []string{fmt.Sprintf("GITHUB_TOKEN=%s", githubToken)}) + output, err := r.Run("bin/diff-processor", []string{"add-labels", prNumber}, []string{fmt.Sprintf("GITHUB_TOKEN=%s", githubToken)}) fmt.Println(output) if err != nil { return err @@ -314,7 +306,7 @@ func addLabels(diffProcessorPath, githubToken, pr string, r gcRunner) error { return r.PopDir() } -func cleanDiffProcessor(diffProcessorPath string, r gcRunner) error { +func cleanDiffProcessor(diffProcessorPath string, r ExecRunner) error { for _, path := range []string{"old", "new", "bin"} { if err := r.RemoveAll(filepath.Join(diffProcessorPath, path)); err != nil { return err @@ -368,7 +360,7 @@ An ` + "`override-breaking-change`" + `label can be added to allow merging. // Run the missing test detector and return the results. // Returns an empty string unless there are missing tests. // Error will be nil unless an error occurs during setup. -func detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch string, r gcRunner) (string, error) { +func detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch string, r ExecRunner) (string, error) { tpgbLocalPathOld := tpgbLocalPath + "old" if err := r.Copy(tpgbLocalPath, tpgbLocalPathOld); err != nil { @@ -417,7 +409,7 @@ func detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch string, r gcRunner // Update the provider package name to the given name in the given path. // name should be either "old" or "new". -func updatePackageName(name, path string, r gcRunner) error { +func updatePackageName(name, path string, r ExecRunner) error { oldPackageName := "github.com/hashicorp/terraform-provider-google-beta" newPackageName := "google/provider/" + name fmt.Printf("Updating package name in %s from %s to %s\n", path, oldPackageName, newPackageName) @@ -438,7 +430,7 @@ func updatePackageName(name, path string, r gcRunner) error { // Run unit tests for the missing test detector and diff processor. // Report results using Github API. -func testTools(mmLocalPath, tpgbLocalPath, pr, commit, buildID, buildStep, projectID string, gh gcGithub, r gcRunner) error { +func testTools(mmLocalPath, tpgbLocalPath, prNumber, commit, buildID, buildStep, projectID string, gh GithubClient, r ExecRunner) error { missingTestDetectorPath := filepath.Join(mmLocalPath, "tools", "missing-test-detector") r.PushDir(missingTestDetectorPath) if _, err := r.Run("go", []string{"mod", "tidy"}, nil); err != nil { @@ -451,7 +443,7 @@ func testTools(mmLocalPath, tpgbLocalPath, pr, commit, buildID, buildStep, proje state = "failure" } targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", buildID, buildStep, projectID) - if err := gh.PostBuildStatus(pr, "unit-tests-missing-test-detector", state, targetURL, commit); err != nil { + if err := gh.PostBuildStatus(prNumber, "unit-tests-missing-test-detector", state, targetURL, commit); err != nil { return err } return r.PopDir() diff --git a/.ci/magician/cmd/interfaces.go b/.ci/magician/cmd/interfaces.go new file mode 100644 index 000000000000..ef99df1723bd --- /dev/null +++ b/.ci/magician/cmd/interfaces.go @@ -0,0 +1,34 @@ +package cmd + +import ( + "magician/github" +) + +type GithubClient interface { + GetPullRequest(prNumber string) (github.PullRequest, error) + GetPullRequestRequestedReviewer(prNumber string) (string, error) + GetPullRequestPreviousAssignedReviewers(prNumber string) ([]string, error) + GetUserType(user string) github.UserType + PostBuildStatus(prNumber, title, state, targetURL, commitSha string) error + PostComment(prNumber, comment string) error + RequestPullRequestReviewer(prNumber, assignee string) error + AddLabel(prNumber, label string) error + RemoveLabel(prNumber, label string) error + CreateWorkflowDispatchEvent(workflowFileName string, inputs map[string]any) error +} + +type CloudbuildClient interface { + ApproveCommunityChecker(prNumber, commitSha string) error + GetAwaitingApprovalBuildLink(prNumber, commitSha string) (string, error) + TriggerMMPresubmitRuns(commitSha string, substitutions map[string]string) error +} + +type ExecRunner interface { + GetCWD() string + Copy(src, dest string) error + RemoveAll(path string) error + PushDir(path string) error + PopDir() error + Run(name string, args, env []string) (string, error) + MustRun(name string, args, env []string) string +} diff --git a/.ci/magician/cmd/membership_checker.go b/.ci/magician/cmd/membership_checker.go index df837ff81e33..b5fcd8b85160 100644 --- a/.ci/magician/cmd/membership_checker.go +++ b/.ci/magician/cmd/membership_checker.go @@ -12,23 +12,6 @@ import ( "github.com/spf13/cobra" ) -type mcGithub interface { - GetPullRequestAuthor(prNumber string) (string, error) - GetUserType(user string) github.UserType - GetPullRequestRequestedReviewer(prNumber string) (string, error) - GetPullRequestPreviousAssignedReviewers(prNumber string) ([]string, error) - RequestPullRequestReviewer(prNumber string, reviewer string) error - PostComment(prNumber string, comment string) error - AddLabel(prNumber string, label string) error - PostBuildStatus(prNumber string, title string, state string, targetUrl string, commitSha string) error -} - -type mcCloudbuild interface { - ApproveCommunityChecker(prNumber, commitSha string) error - GetAwaitingApprovalBuildLink(prNumber, commitSha string) (string, error) - TriggerMMPresubmitRuns(commitSha string, substitutions map[string]string) error -} - // membershipCheckerCmd represents the membershipChecker command var membershipCheckerCmd = &cobra.Command{ Use: "membership-checker", @@ -77,13 +60,13 @@ var membershipCheckerCmd = &cobra.Command{ baseBranch := args[5] fmt.Println("Base Branch: ", baseBranch) - gh := github.NewGithubService() - cb := cloudbuild.NewCloudBuildService() + gh := github.NewClient() + cb := cloudbuild.NewClient() execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch, gh, cb) }, } -func execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch string, gh mcGithub, cb mcCloudbuild) { +func execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch string, gh GithubClient, cb CloudbuildClient) { substitutions := map[string]string{ "BRANCH_NAME": branchName, "_PR_NUMBER": prNumber, @@ -92,12 +75,13 @@ func execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBra "_BASE_BRANCH": baseBranch, } - author, err := gh.GetPullRequestAuthor(prNumber) + pullRequest, err := gh.GetPullRequest(prNumber) if err != nil { fmt.Println(err) os.Exit(1) } + author := pullRequest.User.Login authorUserType := gh.GetUserType(author) trusted := authorUserType == github.CoreContributorUserType || authorUserType == github.GooglerUserType @@ -116,7 +100,7 @@ func execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBra os.Exit(1) } - reviewersToRequest, newPrimaryReviewer := github.ChooseReviewers(firstRequestedReviewer, previouslyInvolvedReviewers) + reviewersToRequest, newPrimaryReviewer := github.ChooseCoreReviewers(firstRequestedReviewer, previouslyInvolvedReviewers) for _, reviewer := range reviewersToRequest { err = gh.RequestPullRequestReviewer(prNumber, reviewer) diff --git a/.ci/magician/cmd/membership_checker_test.go b/.ci/magician/cmd/membership_checker_test.go index b79f3fd13699..184c9ec5d8eb 100644 --- a/.ci/magician/cmd/membership_checker_test.go +++ b/.ci/magician/cmd/membership_checker_test.go @@ -9,7 +9,11 @@ import ( func TestExecMembershipChecker_CoreContributorFlow(t *testing.T) { gh := &mockGithub{ - author: "core_author", + pullRequest: github.PullRequest{ + User: github.User{ + Login: "core_author", + }, + }, userType: github.CoreContributorUserType, calledMethods: make(map[string][][]any), } @@ -43,7 +47,11 @@ func TestExecMembershipChecker_CoreContributorFlow(t *testing.T) { func TestExecMembershipChecker_GooglerFlow(t *testing.T) { gh := &mockGithub{ - author: "googler_author", + pullRequest: github.PullRequest{ + User: github.User{ + Login: "googler_author", + }, + }, userType: github.GooglerUserType, calledMethods: make(map[string][][]any), firstReviewer: "reviewer1", @@ -87,7 +95,11 @@ func TestExecMembershipChecker_GooglerFlow(t *testing.T) { func TestExecMembershipChecker_AmbiguousUserFlow(t *testing.T) { gh := &mockGithub{ - author: "ambiguous_author", + pullRequest: github.PullRequest{ + User: github.User{ + Login: "ambiguous_author", + }, + }, userType: github.CommunityUserType, calledMethods: make(map[string][][]any), firstReviewer: github.GetRandomReviewer(), @@ -139,7 +151,11 @@ func TestExecMembershipChecker_AmbiguousUserFlow(t *testing.T) { func TestExecMembershipChecker_CommentForNewPrimaryReviewer(t *testing.T) { gh := &mockGithub{ - author: "googler_author", + pullRequest: github.PullRequest{ + User: github.User{ + Login: "googler_author", + }, + }, userType: github.GooglerUserType, calledMethods: make(map[string][][]any), firstReviewer: "", diff --git a/.ci/magician/cmd/mock_github_test.go b/.ci/magician/cmd/mock_github_test.go index dbd20f582a32..49bd98b624bb 100644 --- a/.ci/magician/cmd/mock_github_test.go +++ b/.ci/magician/cmd/mock_github_test.go @@ -3,16 +3,16 @@ package cmd import "magician/github" type mockGithub struct { - author string + pullRequest github.PullRequest userType github.UserType firstReviewer string previousReviewers []string calledMethods map[string][][]any } -func (m *mockGithub) GetPullRequestAuthor(prNumber string) (string, error) { - m.calledMethods["GetPullRequestAuthor"] = append(m.calledMethods["GetPullRequestAuthor"], []any{prNumber}) - return m.author, nil +func (m *mockGithub) GetPullRequest(prNumber string) (github.PullRequest, error) { + m.calledMethods["GetPullRequest"] = append(m.calledMethods["GetPullRequest"], []any{prNumber}) + return m.pullRequest, nil } func (m *mockGithub) GetUserType(user string) github.UserType { @@ -59,8 +59,3 @@ func (m *mockGithub) CreateWorkflowDispatchEvent(workflowFileName string, inputs m.calledMethods["CreateWorkflowDispatchEvent"] = append(m.calledMethods["CreateWorkflowDispatchEvent"], []any{workflowFileName, inputs}) return nil } - -func (m *mockGithub) GetPullRequestLabelIDs(prNumber string) (map[int]struct{}, error) { - m.calledMethods["GetPullRequestLabelIDs"] = append(m.calledMethods["GetPullRequestLabelIDs"], []any{prNumber}) - return nil, nil -} diff --git a/.ci/magician/cmd/test_tgc.go b/.ci/magician/cmd/test_tgc.go index 109cd1fea32b..a5610daaedb9 100644 --- a/.ci/magician/cmd/test_tgc.go +++ b/.ci/magician/cmd/test_tgc.go @@ -21,7 +21,7 @@ var testTGCCmd = &cobra.Command{ commit := os.Getenv("COMMIT_SHA") pr := os.Getenv("PR_NUMBER") - gh := github.NewGithubService() + gh := github.NewClient() execTestTGC(commit, pr, gh) }, diff --git a/.ci/magician/cmd/test_tpg.go b/.ci/magician/cmd/test_tpg.go index b5543d18899a..75398c7a4281 100644 --- a/.ci/magician/cmd/test_tpg.go +++ b/.ci/magician/cmd/test_tpg.go @@ -27,7 +27,7 @@ var testTPGCmd = &cobra.Command{ commit := os.Getenv("COMMIT_SHA") pr := os.Getenv("PR_NUMBER") - gh := github.NewGithubService() + gh := github.NewClient() execTestTPG(version, commit, pr, gh) }, diff --git a/.ci/magician/exec/runner.go b/.ci/magician/exec/runner.go index c9423237b285..3bc21e23116d 100644 --- a/.ci/magician/exec/runner.go +++ b/.ci/magician/exec/runner.go @@ -12,47 +12,36 @@ import ( cp "github.com/otiai10/copy" ) -type actualRunner struct { +type Runner struct { cwd string dirStack *list.List } -type Runner interface { - GetCWD() string - Copy(src, dest string) error - RemoveAll(path string) error - PushDir(path string) error - PopDir() error - WriteFile(name, data string) error - Run(name string, args, env []string) (string, error) - MustRun(name string, args, env []string) string -} - -func NewRunner() (Runner, error) { +func NewRunner() (*Runner, error) { wd, err := os.Getwd() if err != nil { return nil, err } - return &actualRunner{ + return &Runner{ cwd: wd, dirStack: list.New(), }, nil } -func (ar *actualRunner) GetCWD() string { +func (ar *Runner) GetCWD() string { return ar.cwd } -func (ar *actualRunner) Copy(src, dest string) error { +func (ar *Runner) Copy(src, dest string) error { return cp.Copy(ar.abs(src), ar.abs(dest)) } -func (ar *actualRunner) RemoveAll(path string) error { +func (ar *Runner) RemoveAll(path string) error { return os.RemoveAll(ar.abs(path)) } // PushDir changes the directory for the runner to the desired path and saves the previous directory in the stack. -func (ar *actualRunner) PushDir(path string) error { +func (ar *Runner) PushDir(path string) error { if ar.dirStack == nil { return errors.New("attempted to push dir, but stack was nil") } @@ -62,7 +51,7 @@ func (ar *actualRunner) PushDir(path string) error { } // PopDir removes the most recently added directory from the stack and changes front to it. -func (ar *actualRunner) PopDir() error { +func (ar *Runner) PopDir() error { if ar.dirStack == nil || ar.dirStack.Len() == 0 { return errors.New("attempted to pop dir, but stack was nil or empty") } @@ -75,11 +64,11 @@ func (ar *actualRunner) PopDir() error { return nil } -func (ar *actualRunner) WriteFile(name, data string) error { +func (ar *Runner) WriteFile(name, data string) error { return os.WriteFile(ar.abs(name), []byte(data), 0644) } -func (ar *actualRunner) Run(name string, args, env []string) (string, error) { +func (ar *Runner) Run(name string, args, env []string) (string, error) { cmd := exec.Command(name, args...) cmd.Dir = ar.cwd cmd.Env = append(os.Environ(), env...) @@ -91,7 +80,7 @@ func (ar *actualRunner) Run(name string, args, env []string) (string, error) { return string(out), nil } -func (ar *actualRunner) MustRun(name string, args, env []string) string { +func (ar *Runner) MustRun(name string, args, env []string) string { out, err := ar.Run(name, args, env) if err != nil { log.Fatal(err) @@ -99,7 +88,7 @@ func (ar *actualRunner) MustRun(name string, args, env []string) string { return out } -func (ar *actualRunner) abs(path string) string { +func (ar *Runner) abs(path string) string { if !filepath.IsAbs(path) { return filepath.Join(ar.cwd, path) } diff --git a/.ci/magician/github/get.go b/.ci/magician/github/get.go index 48f3cdab1a3e..30df68d4db4a 100644 --- a/.ci/magician/github/get.go +++ b/.ci/magician/github/get.go @@ -5,24 +5,35 @@ import ( utils "magician/utility" ) -func (gh *github) GetPullRequestAuthor(prNumber string) (string, error) { +type User struct { + Login string `json:"login"` +} + +type Label struct { + Name string `json:"name"` +} + +type PullRequest struct { + User struct { + Login string `json:"login"` + } `json:"user"` + Labels []Label `json:"labels"` +} + +func (gh *Client) GetPullRequest(prNumber string) (PullRequest, error) { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/%s", prNumber) - var pullRequest struct { - User struct { - Login string `json:"login"` - } `json:"user"` - } + var pullRequest PullRequest _, err := utils.RequestCall(url, "GET", gh.token, &pullRequest, nil) if err != nil { - return "", err + return pullRequest, err } - return pullRequest.User.Login, nil + return pullRequest, nil } -func (gh *github) GetPullRequestRequestedReviewer(prNumber string) (string, error) { +func (gh *Client) GetPullRequestRequestedReviewer(prNumber string) (string, error) { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/%s/requested_reviewers", prNumber) var requestedReviewers struct { @@ -43,7 +54,7 @@ func (gh *github) GetPullRequestRequestedReviewer(prNumber string) (string, erro return requestedReviewers.Users[0].Login, nil } -func (gh *github) GetPullRequestPreviousAssignedReviewers(prNumber string) ([]string, error) { +func (gh *Client) GetPullRequestPreviousAssignedReviewers(prNumber string) ([]string, error) { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/%s/reviews", prNumber) var reviews []struct { @@ -69,24 +80,3 @@ func (gh *github) GetPullRequestPreviousAssignedReviewers(prNumber string) ([]st return result, nil } - -func (gh *github) GetPullRequestLabelIDs(prNumber string) (map[int]struct{}, error) { - url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/%s/reviews", prNumber) - - var labels []struct { - Label struct { - ID int `json:"id"` - } `json:"label"` - } - - if _, err := utils.RequestCall(url, "GET", gh.token, &labels, nil); err != nil { - return nil, err - } - - var result map[int]struct{} - for _, label := range labels { - result[label.Label.ID] = struct{}{} - } - - return result, nil -} diff --git a/.ci/magician/github/init.go b/.ci/magician/github/init.go index 3822a0274c5f..ff63ae2c1ef5 100644 --- a/.ci/magician/github/init.go +++ b/.ci/magician/github/init.go @@ -5,31 +5,17 @@ import ( "os" ) -// GithubService represents the service for GitHub interactions. -type github struct { +// Client for GitHub interactions. +type Client struct { token string } -type GithubService interface { - GetPullRequestAuthor(prNumber string) (string, error) - GetPullRequestRequestedReviewer(prNumber string) (string, error) - GetPullRequestPreviousAssignedReviewers(prNumber string) ([]string, error) - GetPullRequestLabelIDs(prNumber string) (map[int]struct{}, error) - GetUserType(user string) UserType - PostBuildStatus(prNumber, title, state, targetURL, commitSha string) error - PostComment(prNumber, comment string) error - RequestPullRequestReviewer(prNumber, assignee string) error - AddLabel(prNumber, label string) error - RemoveLabel(prNumber, label string) error - CreateWorkflowDispatchEvent(workflowFileName string, inputs map[string]any) error -} - -func NewGithubService() GithubService { +func NewClient() *Client { githubToken, ok := os.LookupEnv("GITHUB_TOKEN") if !ok { fmt.Println("Did not provide GITHUB_TOKEN environment variable") os.Exit(1) } - return &github{token: githubToken} + return &Client{token: githubToken} } diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index 98af81827746..adac576f2f68 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -56,7 +56,7 @@ func (ut UserType) String() string { } } -func (gh *github) GetUserType(user string) UserType { +func (gh *Client) GetUserType(user string) UserType { if isTeamMember(user, gh.token) { fmt.Println("User is a team member") return CoreContributorUserType diff --git a/.ci/magician/github/reviewer_assignment.go b/.ci/magician/github/reviewer_assignment.go index b3e968145d9f..820bb76a4f81 100644 --- a/.ci/magician/github/reviewer_assignment.go +++ b/.ci/magician/github/reviewer_assignment.go @@ -14,7 +14,7 @@ var ( ) // Returns a list of users to request review from, as well as a new primary reviewer if this is the first run. -func ChooseReviewers(firstRequestedReviewer string, previouslyInvolvedReviewers []string) (reviewersToRequest []string, newPrimaryReviewer string) { +func ChooseCoreReviewers(firstRequestedReviewer string, previouslyInvolvedReviewers []string) (reviewersToRequest []string, newPrimaryReviewer string) { hasPrimaryReviewer := false newPrimaryReviewer = "" diff --git a/.ci/magician/github/reviewer_assignment_test.go b/.ci/magician/github/reviewer_assignment_test.go index b96ac59a7389..779d308cfb22 100644 --- a/.ci/magician/github/reviewer_assignment_test.go +++ b/.ci/magician/github/reviewer_assignment_test.go @@ -9,7 +9,7 @@ import ( "golang.org/x/exp/slices" ) -func TestChooseReviewers(t *testing.T) { +func TestChooseCoreReviewers(t *testing.T) { cases := map[string]struct { FirstRequestedReviewer string PreviouslyInvolvedReviewers []string @@ -57,7 +57,7 @@ func TestChooseReviewers(t *testing.T) { tc := tc t.Run(tn, func(t *testing.T) { t.Parallel() - reviewers, primaryReviewer := ChooseReviewers(tc.FirstRequestedReviewer, tc.PreviouslyInvolvedReviewers) + reviewers, primaryReviewer := ChooseCoreReviewers(tc.FirstRequestedReviewer, tc.PreviouslyInvolvedReviewers) if tc.ExpectPrimaryReviewer && primaryReviewer == "" { t.Error("wanted primary reviewer to be returned; got none") } diff --git a/.ci/magician/github/set.go b/.ci/magician/github/set.go index 90f116f673fb..e1575a4e505c 100644 --- a/.ci/magician/github/set.go +++ b/.ci/magician/github/set.go @@ -6,7 +6,7 @@ import ( "net/http" ) -func (gh *github) PostBuildStatus(prNumber, title, state, targetURL, commitSha string) error { +func (gh *Client) PostBuildStatus(prNumber, title, state, targetURL, commitSha string) error { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/%s", commitSha) postBody := map[string]string{ @@ -25,7 +25,7 @@ func (gh *github) PostBuildStatus(prNumber, title, state, targetURL, commitSha s return nil } -func (gh *github) PostComment(prNumber, comment string) error { +func (gh *Client) PostComment(prNumber, comment string) error { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/%s/comments", prNumber) body := map[string]string{ @@ -46,7 +46,7 @@ func (gh *github) PostComment(prNumber, comment string) error { return nil } -func (gh *github) RequestPullRequestReviewer(prNumber, assignee string) error { +func (gh *Client) RequestPullRequestReviewer(prNumber, assignee string) error { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/%s/requested_reviewers", prNumber) body := map[string][]string{ @@ -68,7 +68,7 @@ func (gh *github) RequestPullRequestReviewer(prNumber, assignee string) error { return nil } -func (gh *github) AddLabel(prNumber, label string) error { +func (gh *Client) AddLabel(prNumber, label string) error { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/%s/labels", prNumber) body := map[string][]string{ @@ -84,7 +84,7 @@ func (gh *github) AddLabel(prNumber, label string) error { } -func (gh *github) RemoveLabel(prNumber, label string) error { +func (gh *Client) RemoveLabel(prNumber, label string) error { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/%s/labels/%s", prNumber, label) _, err := utils.RequestCall(url, "DELETE", gh.token, nil, nil) @@ -95,7 +95,7 @@ func (gh *github) RemoveLabel(prNumber, label string) error { return nil } -func (gh *github) CreateWorkflowDispatchEvent(workflowFileName string, inputs map[string]any) error { +func (gh *Client) CreateWorkflowDispatchEvent(workflowFileName string, inputs map[string]any) error { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/actions/workflows/%s/dispatches", workflowFileName) resp, err := utils.RequestCall(url, "POST", gh.token, nil, map[string]any{ "ref": "main", diff --git a/.ci/magician/main.go b/.ci/magician/main.go index 7cf107ae4fbc..41c664080c04 100644 --- a/.ci/magician/main.go +++ b/.ci/magician/main.go @@ -1,6 +1,5 @@ /* Copyright © 2023 NAME HERE - */ package main From dadb91b07109f0cc2ac9e08822424bac8f8e8f92 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Fri, 8 Dec 2023 13:50:56 -0600 Subject: [PATCH 089/107] Upgrade DCL to v1.59.0 (#9565) --- mmv1/third_party/terraform/go.mod.erb | 2 +- mmv1/third_party/terraform/go.sum | 2 ++ .../recaptchaenterprise/samples/waf.key.json | 21 ++++++++++++++ .../recaptchaenterprise/samples/waf_key.yaml | 22 ++++++++++++++ tpgtools/go.mod | 2 +- tpgtools/go.sum | 4 +++ .../samples/nodepool/basic.tf.tmpl | 4 +++ .../samples/nodepool/basic_update.tf.tmpl | 4 +++ .../samples/nodepool/beta_basic.tf.tmpl | 4 +++ .../nodepool/beta_basic_update.tf.tmpl | 4 +++ tpgtools/overrides/orgpolicy/beta/policy.yaml | 8 +++-- .../samples/policy/dry_run_spec.tf.tmpl | 29 +++++++++++++++++++ .../samples/policy/dry_run_spec.yaml | 3 ++ 13 files changed, 105 insertions(+), 4 deletions(-) create mode 100755 tpgtools/api/recaptchaenterprise/samples/waf.key.json create mode 100755 tpgtools/api/recaptchaenterprise/samples/waf_key.yaml create mode 100644 tpgtools/overrides/orgpolicy/samples/policy/dry_run_spec.tf.tmpl create mode 100644 tpgtools/overrides/orgpolicy/samples/policy/dry_run_spec.yaml diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index e887f11fecab..4a7de9491de0 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -4,7 +4,7 @@ go 1.20 require ( cloud.google.com/go/bigtable v1.19.0 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.59.0 github.com/apparentlymart/go-cidr v1.1.0 github.com/davecgh/go-spew v1.1.1 github.com/dnaeon/go-vcr v1.0.1 diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 1644657b191a..62430b733c77 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -17,6 +17,8 @@ cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0 h1:Rz/Jlnt195m9B8CJPQejuTbXaPCoB1w1QYQjD4oKHMk= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.59.0 h1:jL4ac+IUrVftmfduFslaMXWj9ENuiXEiwZFw3U5ikUA= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.59.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= diff --git a/tpgtools/api/recaptchaenterprise/samples/waf.key.json b/tpgtools/api/recaptchaenterprise/samples/waf.key.json new file mode 100755 index 000000000000..1e9f5c12750f --- /dev/null +++ b/tpgtools/api/recaptchaenterprise/samples/waf.key.json @@ -0,0 +1,21 @@ +{ + "displayName": "display-name-one", + "project": "{{project}}", + "webSettings": { + "allowAllDomains": true, + "allowedDomains": [], + "integrationType": "INVISIBLE", + "challengeSecurityPreference": "USABILITY" + }, + "wafSettings": { + "wafFeature": "CHALLENGE_PAGE", + "wafService": "CA" + }, + "testingOptions": { + "testingScore": 0.5, + "testingChallenge": "NOCAPTCHA" + }, + "labels": { + "label-one": "value-one" + } +} diff --git a/tpgtools/api/recaptchaenterprise/samples/waf_key.yaml b/tpgtools/api/recaptchaenterprise/samples/waf_key.yaml new file mode 100755 index 000000000000..db726a20f886 --- /dev/null +++ b/tpgtools/api/recaptchaenterprise/samples/waf_key.yaml @@ -0,0 +1,22 @@ +# Copyright 2023 Google LLC. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +name: waf_key +description: A basic test of recaptcha enterprise key that includes WAF settings +type: key +versions: +- ga +resource: samples/waf.key.json +variables: +- name: project + type: project diff --git a/tpgtools/go.mod b/tpgtools/go.mod index b8256b7777fc..f983fe37b2ff 100644 --- a/tpgtools/go.mod +++ b/tpgtools/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( bitbucket.org/creachadair/stringset v0.0.11 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.59.0 github.com/golang/glog v1.1.2 github.com/hashicorp/hcl v1.0.0 github.com/kylelemons/godebug v1.1.0 diff --git a/tpgtools/go.sum b/tpgtools/go.sum index c38592fc1e81..3fa5dd2136d1 100644 --- a/tpgtools/go.sum +++ b/tpgtools/go.sum @@ -8,6 +8,10 @@ cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2Aawl github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0 h1:Rz/Jlnt195m9B8CJPQejuTbXaPCoB1w1QYQjD4oKHMk= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.57.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.58.0 h1:BePRfJS3N4ZNUzn+Z5vKMthuoitcvmD7Yw14X8BM60c= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.58.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.59.0 h1:jL4ac+IUrVftmfduFslaMXWj9ENuiXEiwZFw3U5ikUA= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.59.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= diff --git a/tpgtools/overrides/containerazure/samples/nodepool/basic.tf.tmpl b/tpgtools/overrides/containerazure/samples/nodepool/basic.tf.tmpl index 8ea45ee3f996..90b33a363a31 100644 --- a/tpgtools/overrides/containerazure/samples/nodepool/basic.tf.tmpl +++ b/tpgtools/overrides/containerazure/samples/nodepool/basic.tf.tmpl @@ -73,6 +73,10 @@ resource "google_container_azure_node_pool" "primary" { owner = "mmv2" } + labels = { + key_one = "label_one" + } + vm_size = "Standard_DS2_v2" } diff --git a/tpgtools/overrides/containerazure/samples/nodepool/basic_update.tf.tmpl b/tpgtools/overrides/containerazure/samples/nodepool/basic_update.tf.tmpl index 2786c74963b7..267a053c5b45 100644 --- a/tpgtools/overrides/containerazure/samples/nodepool/basic_update.tf.tmpl +++ b/tpgtools/overrides/containerazure/samples/nodepool/basic_update.tf.tmpl @@ -74,6 +74,10 @@ resource "google_container_azure_node_pool" "primary" { owner = "mmv2" } + labels = { + key_two = "label_two" + } + vm_size = "Standard_DS2_v2" } diff --git a/tpgtools/overrides/containerazure/samples/nodepool/beta_basic.tf.tmpl b/tpgtools/overrides/containerazure/samples/nodepool/beta_basic.tf.tmpl index 4967311d5107..8dc605998b2c 100644 --- a/tpgtools/overrides/containerazure/samples/nodepool/beta_basic.tf.tmpl +++ b/tpgtools/overrides/containerazure/samples/nodepool/beta_basic.tf.tmpl @@ -77,6 +77,10 @@ resource "google_container_azure_node_pool" "primary" { owner = "mmv2" } + labels = { + key_one = "label_one" + } + vm_size = "Standard_DS2_v2" image_type = "ubuntu" diff --git a/tpgtools/overrides/containerazure/samples/nodepool/beta_basic_update.tf.tmpl b/tpgtools/overrides/containerazure/samples/nodepool/beta_basic_update.tf.tmpl index 2156af0dc662..bce21faa8001 100644 --- a/tpgtools/overrides/containerazure/samples/nodepool/beta_basic_update.tf.tmpl +++ b/tpgtools/overrides/containerazure/samples/nodepool/beta_basic_update.tf.tmpl @@ -78,6 +78,10 @@ resource "google_container_azure_node_pool" "primary" { owner = "mmv2" } + labels = { + key_two = "label_two" + } + vm_size = "Standard_DS2_v2" image_type = "ubuntu" diff --git a/tpgtools/overrides/orgpolicy/beta/policy.yaml b/tpgtools/overrides/orgpolicy/beta/policy.yaml index e31fa2fc2c0a..08ff9e6b371f 100644 --- a/tpgtools/overrides/orgpolicy/beta/policy.yaml +++ b/tpgtools/overrides/orgpolicy/beta/policy.yaml @@ -7,5 +7,9 @@ field: spec.rules.deny_all - type: ENUM_BOOL field: spec.rules.enforce -- type: EXCLUDE - field: dry_run_spec +- type: ENUM_BOOL + field: dry_run_spec.rules.allow_all +- type: ENUM_BOOL + field: dry_run_spec.rules.deny_all +- type: ENUM_BOOL + field: dry_run_spec.rules.enforce \ No newline at end of file diff --git a/tpgtools/overrides/orgpolicy/samples/policy/dry_run_spec.tf.tmpl b/tpgtools/overrides/orgpolicy/samples/policy/dry_run_spec.tf.tmpl new file mode 100644 index 000000000000..1c66f04c389b --- /dev/null +++ b/tpgtools/overrides/orgpolicy/samples/policy/dry_run_spec.tf.tmpl @@ -0,0 +1,29 @@ +resource "google_org_policy_custom_constraint" "constraint" { + name = "custom.disableGkeAutoUpgrade%{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"] + resource_types = ["container.googleapis.com/NodePool"] +} + +resource "google_org_policy_policy" "primary" { + name = "organizations/{{org_id}}/policies/${google_org_policy_custom_constraint.constraint.name}" + parent = "organizations/{{org_id}}" + + spec { + rules { + enforce = "FALSE" + } + } + dry_run_spec { + inherit_from_parent = false + reset = false + rules { + enforce = "FALSE" + } + } +} diff --git a/tpgtools/overrides/orgpolicy/samples/policy/dry_run_spec.yaml b/tpgtools/overrides/orgpolicy/samples/policy/dry_run_spec.yaml new file mode 100644 index 000000000000..48afc1aedb93 --- /dev/null +++ b/tpgtools/overrides/orgpolicy/samples/policy/dry_run_spec.yaml @@ -0,0 +1,3 @@ +variables: + - name: "org_id" + type: "org_id" \ No newline at end of file From 1c04820a4aa5b0cdae510ddeb546528c61ff18ea Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 8 Dec 2023 19:54:37 +0000 Subject: [PATCH 090/107] Add missing attribute reference and closing bracket to test (#9600) --- .../vmwareengine/resource_vmwareengine_private_cloud_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go index 40b0cde0a558..05195787f1a2 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go @@ -102,8 +102,8 @@ data "google_vmwareengine_private_cloud" "ds" { # NSX and Vcenter Credentials are child datasources of PC and are included in the PC test due to the high deployment time involved in the Creation and deletion of a PC data "google_vmwareengine_nsx_credentials" "nsx-ds" { - parent = google_vmwareengine_private_cloud.vmw-engine-pc - + parent = google_vmwareengine_private_cloud.vmw-engine-pc.id +} data "google_vmwareengine_vcenter_credentials" "vcenter-ds" { parent = google_vmwareengine_private_cloud.vmw-engine-pc.id } From 680968fde8a58272df843d8c2dc6867ac8a176b7 Mon Sep 17 00:00:00 2001 From: kautikdk <144651627+kautikdk@users.noreply.github.com> Date: Fri, 8 Dec 2023 20:10:42 +0000 Subject: [PATCH 091/107] Add rpo attribute to 'google_storage_bucket' resource (#9574) * Add rpo attribute for 'google_storage_bucket' resource * Modifies test-case, markdown and Fixes indent issues * Modifies rpo markdown and dualLocation_rpo testcase. --- .../storage/resource_storage_bucket.go.erb | 26 +++- .../resource_storage_bucket_test.go.erb | 117 ++++++++++++++++++ .../docs/r/storage_bucket.html.markdown | 2 + 3 files changed, 144 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb index ca2ca5749529..8ea3385195cb 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket.go.erb @@ -470,6 +470,12 @@ func ResourceStorageBucket() *schema.Resource { }, 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.`, }, + "rpo": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Specifies the RPO setting of bucket. If set 'ASYNC_TURBO', The Turbo Replication will be enabled for the dual-region bucket. Value 'DEFAULT' will set RPO setting to default. Turbo Replication is only for buckets in dual-regions.See the docs for more details.`, + }, "public_access_prevention": { Type: schema.TypeString, Optional: true, @@ -602,6 +608,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error sb.CustomPlacementConfig = expandBucketCustomPlacementConfig(v.([]interface{})) } + if v, ok := d.GetOk("rpo"); ok{ + sb.Rpo = v.(string) + } + var res *storage.Bucket err = transport_tpg.Retry(transport_tpg.RetryOptions{ @@ -765,6 +775,14 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error sb.IamConfiguration = expandIamConfiguration(d) } + if d.HasChange("rpo") { + if v,ok := d.GetOk("rpo"); ok{ + sb.Rpo = v.(string) + } else { + sb.NullFields = append(sb.NullFields, "Rpo") + } + } + res, err := config.NewStorageClient(userAgent).Buckets.Patch(d.Get("name").(string), sb).Do() if err != nil { return err @@ -1691,7 +1709,13 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res if err := d.Set("custom_placement_config", flattenBucketCustomPlacementConfig(res.CustomPlacementConfig)); err != nil { return fmt.Errorf("Error setting custom_placement_config: %s", err) } - + // Needs to hide rpo field for single-region buckets. + // Check the Rpo field from API response to determine whether bucket is in single region config or not. + if res.Rpo != "" { + if err := d.Set("rpo", res.Rpo); err != nil { + return fmt.Errorf("Error setting RPO setting : %s", err) + } + } if res.IamConfiguration != nil && res.IamConfiguration.UniformBucketLevelAccess != nil { if err := d.Set("uniform_bucket_level_access", res.IamConfiguration.UniformBucketLevelAccess.Enabled); err != nil { return fmt.Errorf("Error setting uniform_bucket_level_access: %s", err) diff --git a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb index 09c92686525d..7c686a2878cd 100644 --- a/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb +++ b/mmv1/third_party/terraform/services/storage/resource_storage_bucket_test.go.erb @@ -178,6 +178,98 @@ func TestAccStorageBucket_dualLocation(t *testing.T) { }) } +func TestAccStorageBucket_dualLocation_rpo(t *testing.T) { + t.Parallel() + bucketName := acctest.TestBucketName(t) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccStorageBucketDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccStorageBucket_dualLocation(bucketName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "rpo", "DEFAULT"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_dualLocation_rpo(bucketName,"ASYNC_TURBO"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "rpo", "ASYNC_TURBO"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_dualLocation_rpo(bucketName,"DEFAULT"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "rpo", "DEFAULT"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + }, + }) +} + +func TestAccStorageBucket_multiLocation_rpo(t *testing.T) { + t.Parallel() + + bucketName := acctest.TestBucketName(t) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccStorageBucketDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccStorageBucket_basic(bucketName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "rpo", "DEFAULT"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_multiLocation_rpo(bucketName,"DEFAULT"), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "rpo", "DEFAULT"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + }, + }) +} + func TestAccStorageBucket_customAttributes(t *testing.T) { t.Parallel() @@ -1491,6 +1583,31 @@ resource "google_storage_bucket" "bucket" { `, bucketName) } +func testAccStorageBucket_dualLocation_rpo(bucketName string,rpo 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"] + } + rpo = "%s" +} +`, bucketName,rpo) +} + +func testAccStorageBucket_multiLocation_rpo(bucketName string,rpo string) string { + return fmt.Sprintf(` +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "ASIA" + force_destroy = true + rpo = "%s" +} +`, bucketName,rpo) +} + 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 0131446fffa8..2389ac04bf55 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 @@ -125,6 +125,8 @@ The following arguments are supported: * `requester_pays` - (Optional, Default: false) Enables [Requester Pays](https://cloud.google.com/storage/docs/requester-pays) on a storage bucket. +* `rpo` - (Optional) The recovery point objective for cross-region replication of the bucket. Applicable only for dual and multi-region buckets. `"DEFAULT"` sets default replication. `"ASYNC_TURBO"` value enables turbo replication, valid for dual-region buckets only. See [Turbo Replication](https://cloud.google.com/storage/docs/managing-turbo-replication) for more information. If rpo is not specified at bucket creation, it defaults to `"DEFAULT"` for dual and multi-region buckets. **NOTE** If used with single-region bucket, It will throw an error. + * `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. * `public_access_prevention` - (Optional) Prevents public access to a bucket. Acceptable values are "inherited" or "enforced". If "inherited", the bucket uses [public access prevention](https://cloud.google.com/storage/docs/public-access-prevention). only if the bucket is subject to the public access prevention organization policy constraint. Defaults to "inherited". From a1b033aaea49e933ea13528e03b9ab2a46342770 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 8 Dec 2023 12:46:21 -0800 Subject: [PATCH 092/107] Remove the code related to api.yaml (#9596) --- mmv1/compiler.rb | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 1f2cdc5f82c3..c7c73c5d91e2 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -152,31 +152,16 @@ product_override_path = File.join(override_dir, product_name, 'product.yaml') if override_dir product_yaml_path = File.join(product_name, 'product.yaml') - api_override_path = '' - api_override_path = File.join(override_dir, product_name, 'api.yaml') if override_dir - api_yaml_path = File.join(product_name, 'api.yaml') - provider_override_path = '' provider_override_path = File.join(override_dir, product_name, "#{provider_name}.yaml") \ if override_dir provider_yaml_path = File.join(product_name, "#{provider_name}.yaml") - unless File.exist?(product_yaml_path) || File.exist?(product_override_path) \ - || File.exist?(api_yaml_path) || File.exist?(api_override_path) + unless File.exist?(product_yaml_path) || File.exist?(product_override_path) raise "#{product_name} does not contain an api.yaml or product.yaml file" end - if File.exist?(api_override_path) - result = if File.exist?(api_yaml_path) - YAML.load_file(api_yaml_path, permitted_classes: allowed_classes) \ - .merge(YAML.load_file(api_override_path, permitted_classes: allowed_classes)) - else - YAML.load_file(api_override_path, permitted_classes: allowed_classes) - end - product_yaml = result.to_yaml - elsif File.exist?(api_yaml_path) - product_yaml = File.read(api_yaml_path) - elsif File.exist?(product_override_path) + if File.exist?(product_override_path) result = if File.exist?(product_yaml_path) YAML.load_file(product_yaml_path, permitted_classes: allowed_classes) \ .merge(YAML.load_file(product_override_path, permitted_classes: allowed_classes)) From 2b5c4b2cdc0ac1764e38b5b985e4aec17d9d6401 Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Sat, 9 Dec 2023 03:56:20 +0530 Subject: [PATCH 093/107] Promote Cluster to GA (#9550) --- mmv1/products/vmwareengine/Cluster.yaml | 3 - .../vmware_engine_cluster_basic.tf.erb | 9 +- .../vmware_engine_cluster_full.tf.erb | 9 +- .../provider/provider_mmv1_resources.go.erb | 2 - ...ata_source_google_vmwareengine_cluster.go} | 4 +- ... => resource_vmwareengine_cluster_test.go} | 85 +++++++------------ .../docs/d/vmwareengine_cluster.html.markdown | 4 - 7 files changed, 40 insertions(+), 76 deletions(-) rename mmv1/third_party/terraform/services/vmwareengine/{data_source_google_vmwareengine_cluster.go.erb => data_source_google_vmwareengine_cluster.go} (94%) rename mmv1/third_party/terraform/services/vmwareengine/{resource_vmwareengine_cluster_test.go.erb => resource_vmwareengine_cluster_test.go} (71%) diff --git a/mmv1/products/vmwareengine/Cluster.yaml b/mmv1/products/vmwareengine/Cluster.yaml index 06fc5d2e8a1b..e2fa5c8053c3 100644 --- a/mmv1/products/vmwareengine/Cluster.yaml +++ b/mmv1/products/vmwareengine/Cluster.yaml @@ -14,7 +14,6 @@ --- !ruby/object:Api::Resource name: "Cluster" -min_version: beta base_url: "{{parent}}/clusters" create_url: "{{parent}}/clusters?clusterId={{name}}" self_link: "{{parent}}/clusters/{{name}}" @@ -53,7 +52,6 @@ autogen_async: true examples: - !ruby/object:Provider::Terraform::Examples name: "vmware_engine_cluster_basic" - min_version: beta primary_resource_id: "vmw-engine-ext-cluster" skip_test: true # update tests will take care of create and update. PC and cluster creation is expensive and node reservation is required. vars: @@ -65,7 +63,6 @@ examples: region: :REGION - !ruby/object:Provider::Terraform::Examples name: "vmware_engine_cluster_full" - min_version: beta primary_resource_id: "vmw-ext-cluster" skip_test: true # update tests will take care of create and update. PC and cluster creation is expensive and node reservation is required. vars: diff --git a/mmv1/templates/terraform/examples/vmware_engine_cluster_basic.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_cluster_basic.tf.erb index 05fc4467dc02..ef7152569e08 100644 --- a/mmv1/templates/terraform/examples/vmware_engine_cluster_basic.tf.erb +++ b/mmv1/templates/terraform/examples/vmware_engine_cluster_basic.tf.erb @@ -1,5 +1,4 @@ resource "google_vmwareengine_cluster" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta name = "<%= ctx[:vars]['name'] %>" parent = google_vmwareengine_private_cloud.cluster-pc.id node_type_configs { @@ -9,7 +8,6 @@ resource "google_vmwareengine_cluster" "<%= ctx[:primary_resource_id] %>" { } resource "google_vmwareengine_private_cloud" "cluster-pc" { - provider = google-beta location = "<%= ctx[:test_env_vars]['region'] %>-a" name = "<%= ctx[:vars]['private_cloud_id'] %>" description = "Sample test PC." @@ -28,9 +26,8 @@ resource "google_vmwareengine_private_cloud" "cluster-pc" { } resource "google_vmwareengine_network" "cluster-nw" { - provider = google-beta - name = "<%= ctx[:test_env_vars]['region'] %>-default" - location = "<%= ctx[:test_env_vars]['region'] %>" - type = "LEGACY" + name = "<%= ctx[:vars]['network_id'] %>" + type = "STANDARD" + location = "global" description = "PC network description." } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/vmware_engine_cluster_full.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_cluster_full.tf.erb index 43ec853462c1..ce2584a72549 100644 --- a/mmv1/templates/terraform/examples/vmware_engine_cluster_full.tf.erb +++ b/mmv1/templates/terraform/examples/vmware_engine_cluster_full.tf.erb @@ -1,5 +1,4 @@ resource "google_vmwareengine_cluster" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta name = "<%= ctx[:vars]['name'] %>" parent = google_vmwareengine_private_cloud.cluster-pc.id node_type_configs { @@ -10,7 +9,6 @@ resource "google_vmwareengine_cluster" "<%= ctx[:primary_resource_id] %>" { } resource "google_vmwareengine_private_cloud" "cluster-pc" { - provider = google-beta location = "<%= ctx[:test_env_vars]['region'] %>-a" name = "<%= ctx[:vars]['private_cloud_id'] %>" description = "Sample test PC." @@ -30,9 +28,8 @@ resource "google_vmwareengine_private_cloud" "cluster-pc" { } resource "google_vmwareengine_network" "cluster-nw" { - provider = google-beta - name = "<%= ctx[:test_env_vars]['region'] %>-default" - location = "<%= ctx[:test_env_vars]['region'] %>" - type = "LEGACY" + name = "<%= ctx[:vars]['network_id'] %>" + type = "STANDARD" + location = "global" description = "PC network description." } \ No newline at end of file diff --git a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb index a43b78ba436c..d0bfb7e99f0d 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -200,9 +200,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_vpc_access_connector": vpcaccess.DataSourceVPCAccessConnector(), "google_redis_instance": redis.DataSourceGoogleRedisInstance(), "google_vertex_ai_index": vertexai.DataSourceVertexAIIndex(), - <% unless version == 'ga' -%> "google_vmwareengine_cluster": vmwareengine.DataSourceVmwareengineCluster(), - <% end -%> "google_vmwareengine_external_address": vmwareengine.DataSourceVmwareengineExternalAddress(), "google_vmwareengine_network": vmwareengine.DataSourceVmwareengineNetwork(), "google_vmwareengine_network_peering": vmwareengine.DataSourceVmwareengineNetworkPeering(), diff --git a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go similarity index 94% rename from mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb rename to mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go index cdeff513d0e0..fe11f1b7b67e 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/data_source_google_vmwareengine_cluster.go @@ -1,6 +1,5 @@ -<% autogen_exception -%> package vmwareengine -<% unless version == 'ga' -%> + import ( "fmt" @@ -38,4 +37,3 @@ func dataSourceVmwareengineClusterRead(d *schema.ResourceData, meta interface{}) } return nil } -<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_cluster_test.go.erb b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_cluster_test.go similarity index 71% rename from mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_cluster_test.go.erb rename to mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_cluster_test.go index c128ec1ce24d..af97dbf89768 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_cluster_test.go @@ -1,11 +1,9 @@ -<% autogen_exception -%> package vmwareengine_test -<% unless version == 'ga' -%> import ( "fmt" - "testing" "strings" + "testing" "github.com/hashicorp/terraform-provider-google/google/acctest" "github.com/hashicorp/terraform-provider-google/google/envvar" @@ -17,10 +15,11 @@ import ( ) func TestAccVmwareengineCluster_vmwareEngineClusterUpdate(t *testing.T) { + acctest.SkipIfVcr(t) t.Parallel() context := map[string]interface{}{ - "region": "southamerica-west1", // using region with low node utilization. + "region": "southamerica-west1", // using region with low node utilization. "org_id": envvar.GetTestOrgFromEnv(t), "billing_account": envvar.GetTestBillingAccountFromEnv(t), "random_suffix": acctest.RandString(t, 10), @@ -28,14 +27,13 @@ func TestAccVmwareengineCluster_vmwareEngineClusterUpdate(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), - CheckDestroy: testAccCheckVmwareengineClusterDestroyProducer(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckVmwareengineClusterDestroyProducer(t), Steps: []resource.TestStep{ { Config: testVmwareEngineClusterConfig(context, 3), Check: resource.ComposeTestCheckFunc( acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_cluster.ds", "google_vmwareengine_cluster.vmw-engine-ext-cluster", map[string]struct{}{}), - acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_private_cloud.ds", "google_vmwareengine_private_cloud.cluster-pc", map[string]struct{}{}), ), }, { @@ -44,19 +42,19 @@ func TestAccVmwareengineCluster_vmwareEngineClusterUpdate(t *testing.T) { ImportStateVerify: true, ImportStateVerifyIgnore: []string{"parent", "name"}, }, - { - Config: testVmwareEngineClusterConfig(context, 4), // expand the cluster - }, - { + { + Config: testVmwareEngineClusterConfig(context, 4), // expand the cluster + }, + { ResourceName: "google_vmwareengine_cluster.vmw-engine-ext-cluster", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"parent", "name"}, }, { - Config: testVmwareEngineClusterConfig(context, 3), // shrink the cluster. - }, - { + Config: testVmwareEngineClusterConfig(context, 3), // shrink the cluster. + }, + { ResourceName: "google_vmwareengine_cluster.vmw-engine-ext-cluster", ImportState: true, ImportStateVerify: true, @@ -67,66 +65,51 @@ func TestAccVmwareengineCluster_vmwareEngineClusterUpdate(t *testing.T) { } func testVmwareEngineClusterConfig(context map[string]interface{}, nodeCount int) string { - context["node_count"] = nodeCount; + context["node_count"] = nodeCount return acctest.Nprintf(` -resource "google_vmwareengine_cluster" "vmw-engine-ext-cluster" { - provider = google-beta - name = "tf-test-ext-cluster%{random_suffix}" - parent = google_vmwareengine_private_cloud.cluster-pc.id - node_type_configs { - node_type_id = "standard-72" - node_count = %{node_count} - custom_core_count = 32 - } +resource "google_vmwareengine_network" "cluster-nw" { + name = "tf-test-cluster-nw%{random_suffix}" + location = "global" + type = "STANDARD" + description = "PC network description." } resource "google_vmwareengine_private_cloud" "cluster-pc" { - provider = google-beta - location = "%{region}-a" - name = "tf-test-sample-pc%{random_suffix}" + location = "%{region}-a" + name = "tf-test-cluster-pc%{random_suffix}" description = "Sample test PC." network_config { - management_cidr = "192.168.30.0/24" + management_cidr = "192.168.10.0/24" vmware_engine_network = google_vmwareengine_network.cluster-nw.id } management_cluster { - cluster_id = "tf-test-sample-mgmt-cluster%{random_suffix}" + cluster_id = "tf-test-mgmt-cluster%{random_suffix}" node_type_configs { node_type_id = "standard-72" node_count = 3 - custom_core_count = 32 } } } -resource "google_vmwareengine_network" "cluster-nw" { - provider = google-beta - name = "%{region}-default" - location = "%{region}" - type = "LEGACY" - description = "PC network description." +resource "google_vmwareengine_cluster" "vmw-engine-ext-cluster" { + name = "tf-test-ext-cluster%{random_suffix}" + parent = google_vmwareengine_private_cloud.cluster-pc.id + node_type_configs { + node_type_id = "standard-72" + node_count = %{node_count} + custom_core_count = 32 + } } data "google_vmwareengine_cluster" ds { name = "tf-test-ext-cluster%{random_suffix}" - provider = google-beta - parent = google_vmwareengine_private_cloud.cluster-pc.id - depends_on = [ - google_vmwareengine_cluster.vmw-engine-ext-cluster, + parent = google_vmwareengine_private_cloud.cluster-pc.id + depends_on = [ + google_vmwareengine_cluster.vmw-engine-ext-cluster, ] } - -data "google_vmwareengine_private_cloud" ds { - location = "%{region}-a" - provider = google-beta - name = "tf-test-sample-pc%{random_suffix}" - depends_on = [ - google_vmwareengine_private_cloud.cluster-pc, - ] -} - `, context) } @@ -168,5 +151,3 @@ func testAccCheckVmwareengineClusterDestroyProducer(t *testing.T) func(s *terraf return nil } } - -<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/website/docs/d/vmwareengine_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/d/vmwareengine_cluster.html.markdown index 6da3627be83e..4d591081edf1 100644 --- a/mmv1/third_party/terraform/website/docs/d/vmwareengine_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/vmwareengine_cluster.html.markdown @@ -8,9 +8,6 @@ description: |- Use this data source to get details about a cluster resource. -~> **Warning:** This data source is in beta, and should be used with the terraform-provider-google-beta provider. -See [Provider Versions](https://terraform.io/docs/providers/google/guides/provider_versions.html) for more details on beta resources. - To get more information about private cloud cluster, see: * [API documentation](https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds.clusters) @@ -18,7 +15,6 @@ To get more information about private cloud cluster, see: ```hcl data "google_vmwareengine_cluster" "my_cluster" { - provider = google-beta name = "my-cluster" parent = "project/locations/us-west1-a/privateClouds/my-cloud" } From 42281d39a26971a0bef4a8c495e22f6564a99bdf Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 8 Dec 2023 15:08:56 -0800 Subject: [PATCH 094/107] Fixed TestAccLoggingProjectSink_updatePreservesCustomWriter (#9604) * Re-enabled test * Added sleep to allow IAM propagation * Added time provider to external providers * gofmt --- .../resource_logging_project_sink_test.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go index d89af08acdd1..ea6c1e83348b 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink_test.go @@ -165,8 +165,6 @@ func TestAccLoggingProjectSink_updatePreservesUniqueWriter(t *testing.T) { } func TestAccLoggingProjectSink_updatePreservesCustomWriter(t *testing.T) { - // Investigating failure reason, skipping in VCR for now - acctest.SkipIfVcr(t) t.Parallel() sinkName := "tf-test-sink-" + acctest.RandString(t, 10) @@ -186,7 +184,10 @@ func TestAccLoggingProjectSink_updatePreservesCustomWriter(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckLoggingProjectSinkDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckLoggingProjectSinkDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccLoggingProjectSink_customWriter(org, billingId, project, sinkName, account), @@ -529,6 +530,11 @@ resource "google_service_account_iam_member" "loggingsa-customsa-binding" { member = "serviceAccount:service-${local.project_number}@gcp-sa-logging.iam.gserviceaccount.com" } +resource "time_sleep" "wait_60_seconds" { + depends_on = [google_service_account_iam_member.loggingsa-customsa-binding] + create_duration = "60s" +} + resource "google_logging_project_sink" "custom_writer" { name = "%s" destination = "logging.googleapis.com/projects/${google_project.destination-project.project_id}/locations/us-central1/buckets/shared-bucket" @@ -538,8 +544,8 @@ resource "google_logging_project_sink" "custom_writer" { custom_writer_identity = "serviceAccount:${google_service_account.test-account1.email}" depends_on = [ - google_logging_project_bucket_config.destination-bucket, - google_service_account_iam_member.loggingsa-customsa-binding, + google_logging_project_bucket_config.destination-bucket, + time_sleep.wait_60_seconds, ] } `, project, project, org, billingId, serviceAccount, envvar.GetTestProjectFromEnv(), name, envvar.GetTestProjectFromEnv()) From 0d4f118b2a15029d7099b469a4c6da514df4e7c9 Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Fri, 8 Dec 2023 16:01:50 -0800 Subject: [PATCH 095/107] Build and test provider off main/feature (#9566) --- .github/workflows/build-downstream.yml | 2 +- .github/workflows/downstreams.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-downstream.yml b/.github/workflows/build-downstream.yml index 32fe3e526d37..f8446388ee65 100644 --- a/.github/workflows/build-downstream.yml +++ b/.github/workflows/build-downstream.yml @@ -17,7 +17,7 @@ jobs: generate-repository: runs-on: ubuntu-22.04 env: - BASE_BRANCH: ${{ github.event.pull_request.base.ref || github.ref }} + BASE_BRANCH: ${{ github.event.pull_request.base.ref || github.ref_name }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout Repository diff --git a/.github/workflows/downstreams.yml b/.github/workflows/downstreams.yml index 1c0114fbe324..98273ca7e18e 100644 --- a/.github/workflows/downstreams.yml +++ b/.github/workflows/downstreams.yml @@ -4,7 +4,8 @@ permissions: read-all on: push: branches: - - scott-test-* + - main + - 'FEATURE-BRANCH-*' concurrency: group: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('commit-{0}', github.sha) }} From 9e772a85d6c113ae38b6e5439d7ae72380481bec Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:48:50 +0000 Subject: [PATCH 096/107] Remove use of `google_kms_crypto_key_iam_binding` resources in acceptance tests to reduce test failures related to missing permissions (#9590) * Replace use of `google_kms_crypto_key_iam_binding` with `_member` equivalent * Replace use of `google_kms_crypto_key_iam_binding` with `_member` equivalent in examples files * Split `google_kms_crypto_key_iam_binding` with 2 members into two `_member` IAM resources in example file * Replace `google_kms_crypto_key_iam_binding` with 5 members into `_member` IAM resources created via for_each loop When this example is used to generate a test the crypto key used is a bootstrapped resource. By using an authoritative `_binding` IAM resource we allow conflict between tests using the same bootstrapped cypto key * Fix mistyped argument name * Remove use of for_each in acceptance test, create separate example files for test vs docs * SKip `TestAccCloudfunctions2function_cloudfunctions2CmekExample` in VCR * Skip `TestAccDataprocMetastoreService_dataprocMetastoreServiceCmekTestExample` in VCR --- mmv1/products/cloudfunctions2/Function.yaml | 16 +++ mmv1/products/metastore/Service.yaml | 1 + .../apigee_environment_type_test.tf.erb | 8 +- .../examples/apigee_instance_full.tf.erb | 8 +- .../examples/apigee_instance_full_test.tf.erb | 8 +- .../examples/apigee_nat_address_basic.tf.erb | 8 +- .../apigee_organization_cloud_full.tf.erb | 8 +- ...tion_cloud_full_disable_vpc_peering.tf.erb | 8 +- ...cloud_full_disable_vpc_peering_test.tf.erb | 8 +- ...apigee_organization_cloud_full_test.tf.erb | 8 +- .../apigee_organization_retention_test.tf.erb | 8 +- .../examples/cloudfunctions2_cmek.tf.erb | 68 ++++++++--- .../examples/cloudfunctions2_cmek_docs.tf.erb | 113 ++++++++++++++++++ .../examples/data_fusion_instance_cmek.tf.erb | 8 +- ...ataproc_metastore_service_cmek_test.tf.erb | 19 ++- ...ateca_certificate_authority_byo_key.tf.erb | 16 +-- .../examples/sql_instance_cmek.tf.erb | 6 +- .../alloydb/resource_alloydb_backup_test.go | 6 +- .../alloydb/resource_alloydb_cluster_test.go | 74 +++++------- ...resource_alloydb_secondary_cluster_test.go | 8 +- ...urce_compute_instance_template_test.go.erb | 4 + .../resource_logging_bucket_config_test.go | 16 +-- .../resource_sql_database_instance_test.go | 18 +-- 23 files changed, 281 insertions(+), 164 deletions(-) create mode 100644 mmv1/templates/terraform/examples/cloudfunctions2_cmek_docs.tf.erb diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index 0618283b0381..b0c34b5429dd 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -218,6 +218,8 @@ examples: - 'build_config.0.source.0.storage_source.0.bucket' - !ruby/object:Provider::Terraform::Examples name: 'cloudfunctions2_cmek' + skip_docs: true # the example file is written in a repetitive way to help acc tests, so exclude + skip_vcr: true primary_resource_id: 'function' min_version: beta vars: @@ -239,6 +241,20 @@ examples: ignore_read_extra: - 'build_config.0.source.0.storage_source.0.object' - 'build_config.0.source.0.storage_source.0.bucket' + - !ruby/object:Provider::Terraform::Examples + name: 'cloudfunctions2_cmek_docs' + skip_test: true # this example file will cause IAM conflicts between tests if used to make a test + primary_resource_id: 'function' + min_version: beta + vars: + function: 'function-cmek' + bucket_name: 'gcf-source' + zip_path: 'function-source.zip' + kms_service_name: 'cloudkms.googleapis.com' + cmek-repo: 'cmek-repo' + unencoded-ar-repo: 'ar-repo' + kms_key_name: 'cmek-key' + project: 'my-project-name' iam_policy: !ruby/object:Api::Resource::IamPolicy parent_resource_attribute: 'cloud_function' method_name_separator: ':' diff --git a/mmv1/products/metastore/Service.yaml b/mmv1/products/metastore/Service.yaml index e1ae22ed13e2..7d72c683b7f5 100644 --- a/mmv1/products/metastore/Service.yaml +++ b/mmv1/products/metastore/Service.yaml @@ -66,6 +66,7 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'dataproc_metastore_service_cmek_test' skip_docs: true + skip_vcr: true primary_resource_id: 'default' vars: metastore_service_name: 'example-service' diff --git a/mmv1/templates/terraform/examples/apigee_environment_type_test.tf.erb b/mmv1/templates/terraform/examples/apigee_environment_type_test.tf.erb index 1286cc5ec1dd..d0baa2ab5fe2 100644 --- a/mmv1/templates/terraform/examples/apigee_environment_type_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_environment_type_test.tf.erb @@ -86,15 +86,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "apigee_org" { @@ -109,7 +107,7 @@ resource "google_apigee_organization" "apigee_org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, google_project_service.apigee, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_instance_full.tf.erb b/mmv1/templates/terraform/examples/apigee_instance_full.tf.erb index 2cd5f3282265..26445ef11b85 100644 --- a/mmv1/templates/terraform/examples/apigee_instance_full.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_instance_full.tf.erb @@ -38,13 +38,11 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "apigee_org" { @@ -57,7 +55,7 @@ resource "google_apigee_organization" "apigee_org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_instance_full_test.tf.erb b/mmv1/templates/terraform/examples/apigee_instance_full_test.tf.erb index 08a5e3ab1558..8690e4320f25 100644 --- a/mmv1/templates/terraform/examples/apigee_instance_full_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_instance_full_test.tf.erb @@ -86,15 +86,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "apigee_org" { @@ -109,7 +107,7 @@ resource "google_apigee_organization" "apigee_org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_nat_address_basic.tf.erb b/mmv1/templates/terraform/examples/apigee_nat_address_basic.tf.erb index 3114e517815b..cbcbc32c10dc 100644 --- a/mmv1/templates/terraform/examples/apigee_nat_address_basic.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_nat_address_basic.tf.erb @@ -38,13 +38,11 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "apigee_org" { @@ -57,7 +55,7 @@ resource "google_apigee_organization" "apigee_org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_cloud_full.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_cloud_full.tf.erb index 891fb47422a9..6d37ffa69dbc 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_cloud_full.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_cloud_full.tf.erb @@ -38,13 +38,11 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "org" { @@ -57,6 +55,6 @@ resource "google_apigee_organization" "org" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering.tf.erb index d393b02985f3..42f797ce28c4 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering.tf.erb @@ -20,13 +20,11 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "org" { @@ -38,6 +36,6 @@ resource "google_apigee_organization" "org" { runtime_database_encryption_key_name = google_kms_crypto_key.apigee_key.id depends_on = [ - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering_test.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering_test.tf.erb index e1857349148b..f39d3fd4e9ef 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_disable_vpc_peering_test.tf.erb @@ -51,15 +51,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { @@ -84,6 +82,6 @@ resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { } depends_on = [ - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_test.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_test.tf.erb index a58a60fe4e2a..5a859ec6b7e6 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_cloud_full_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_cloud_full_test.tf.erb @@ -86,15 +86,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { @@ -120,6 +118,6 @@ resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/apigee_organization_retention_test.tf.erb b/mmv1/templates/terraform/examples/apigee_organization_retention_test.tf.erb index 365ba939e5a0..0de08ec9eb4b 100644 --- a/mmv1/templates/terraform/examples/apigee_organization_retention_test.tf.erb +++ b/mmv1/templates/terraform/examples/apigee_organization_retention_test.tf.erb @@ -86,15 +86,13 @@ resource "google_project_service_identity" "apigee_sa" { service = google_project_service.apigee.service } -resource "google_kms_crypto_key_iam_binding" "apigee_sa_keyuser" { +resource "google_kms_crypto_key_iam_member" "apigee_sa_keyuser" { provider = google-beta crypto_key_id = google_kms_crypto_key.apigee_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.apigee_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.apigee_sa.email}" } resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { @@ -110,7 +108,7 @@ resource "google_apigee_organization" "<%= ctx[:primary_resource_id] %>" { depends_on = [ google_service_networking_connection.apigee_vpc_connection, google_project_service.apigee, - google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + google_kms_crypto_key_iam_member.apigee_sa_keyuser, ] } diff --git a/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb b/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb index 9ad4af6978f4..0db9b17ad3de 100644 --- a/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb @@ -37,34 +37,58 @@ resource "google_artifact_registry_repository" "unencoded-ar-repo" { format = "DOCKER" } -resource "google_artifact_registry_repository_iam_binding" "binding" { +resource "google_artifact_registry_repository_iam_member" "member" { provider = google-beta location = google_artifact_registry_repository.encoded-ar-repo.location repository = google_artifact_registry_repository.encoded-ar-repo.name role = "roles/artifactregistry.admin" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com" } -resource "google_kms_crypto_key_iam_binding" "gcf_cmek_keyuser" { +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_1" { provider = google-beta crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@serverless-robot-prod.iam.gserviceaccount.com", - "serviceAccount:${google_project_service_identity.ea_sa.email}", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com" +} - depends_on = [ - google_project_service_identity.ea_sa - ] +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_2" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_3" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_4" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@serverless-robot-prod.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_5" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:${google_project_service_identity.ea_sa.email}" } resource "google_artifact_registry_repository" "encoded-ar-repo" { @@ -74,8 +98,13 @@ resource "google_artifact_registry_repository" "encoded-ar-repo" { repository_id = "<%= ctx[:vars]['cmek-repo'] %>" format = "DOCKER" kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" + depends_on = [ - google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_1, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_2, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_3, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_4, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_5, ] } @@ -107,7 +136,10 @@ resource "google_cloudfunctions2_function" "<%= ctx[:primary_resource_id] %>" { } depends_on = [ - google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_1, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_2, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_3, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_4, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_5, ] - } diff --git a/mmv1/templates/terraform/examples/cloudfunctions2_cmek_docs.tf.erb b/mmv1/templates/terraform/examples/cloudfunctions2_cmek_docs.tf.erb new file mode 100644 index 000000000000..8d719665a418 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudfunctions2_cmek_docs.tf.erb @@ -0,0 +1,113 @@ +locals { + project = "<%= ctx[:vars]['project'] %>" # Google Cloud Platform Project ID +} + +data "google_project" "project" { + provider = google-beta +} + +resource "google_storage_bucket" "bucket" { + provider = google-beta + + name = "${local.project}-<%= ctx[:vars]['bucket_name'] %>" # Every bucket name must be globally unique + location = "US" + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "object" { + provider = google-beta + + name = "function-source.zip" + bucket = google_storage_bucket.bucket.name + source = "<%= ctx[:vars]['zip_path'] %>" # Add path to the zipped function source code +} + +resource "google_project_service_identity" "ea_sa" { + provider = google-beta + + project = data.google_project.project.project_id + service = "eventarc.googleapis.com" +} + +resource "google_artifact_registry_repository" "unencoded-ar-repo" { + provider = google-beta + + repository_id = "<%= ctx[:vars]['unencoded-ar-repo'] %>" + location = "us-central1" + format = "DOCKER" +} + +resource "google_artifact_registry_repository_iam_binding" "binding" { + provider = google-beta + + location = google_artifact_registry_repository.encoded-ar-repo.location + repository = google_artifact_registry_repository.encoded-ar-repo.name + role = "roles/artifactregistry.admin" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", + ] +} + +resource "google_kms_crypto_key_iam_binding" "gcf_cmek_keyuser" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@serverless-robot-prod.iam.gserviceaccount.com", + "serviceAccount:${google_project_service_identity.ea_sa.email}", + ] + + depends_on = [ + google_project_service_identity.ea_sa + ] +} + +resource "google_artifact_registry_repository" "encoded-ar-repo" { + provider = google-beta + + location = "us-central1" + repository_id = "<%= ctx[:vars]['cmek-repo'] %>" + format = "DOCKER" + kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" + depends_on = [ + google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + ] +} + +resource "google_cloudfunctions2_function" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + + name = "<%= ctx[:vars]['function'] %>" + location = "us-central1" + description = "CMEK function" + kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" + + build_config { + runtime = "nodejs16" + entry_point = "helloHttp" # Set the entry point + docker_repository = google_artifact_registry_repository.encoded-ar-repo.id + + source { + storage_source { + bucket = google_storage_bucket.bucket.name + object = google_storage_bucket_object.object.name + } + } + } + + service_config { + max_instance_count = 1 + available_memory = "256M" + timeout_seconds = 60 + } + + depends_on = [ + google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + ] + +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/data_fusion_instance_cmek.tf.erb b/mmv1/templates/terraform/examples/data_fusion_instance_cmek.tf.erb index a72007725613..1bb61692283a 100644 --- a/mmv1/templates/terraform/examples/data_fusion_instance_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/data_fusion_instance_cmek.tf.erb @@ -7,7 +7,7 @@ resource "google_data_fusion_instance" "<%= ctx[:primary_resource_id] %>" { key_reference = google_kms_crypto_key.crypto_key.id } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding] + depends_on = [google_kms_crypto_key_iam_member.crypto_key_member] } resource "google_kms_crypto_key" "crypto_key" { @@ -20,13 +20,11 @@ resource "google_kms_key_ring" "key_ring" { location = "us-central1" } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding" { +resource "google_kms_crypto_key_iam_member" "crypto_key_member" { crypto_key_id = google_kms_crypto_key.crypto_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-datafusion.iam.gserviceaccount.com" - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-datafusion.iam.gserviceaccount.com" } data "google_project" "project" {} diff --git a/mmv1/templates/terraform/examples/dataproc_metastore_service_cmek_test.tf.erb b/mmv1/templates/terraform/examples/dataproc_metastore_service_cmek_test.tf.erb index f821af8a37c6..731960437dd5 100644 --- a/mmv1/templates/terraform/examples/dataproc_metastore_service_cmek_test.tf.erb +++ b/mmv1/templates/terraform/examples/dataproc_metastore_service_cmek_test.tf.erb @@ -15,7 +15,10 @@ resource "google_dataproc_metastore_service" "<%= ctx[:primary_resource_id] %>" version = "3.1.2" } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding] + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key_member_1, + google_kms_crypto_key_iam_member.crypto_key_member_2, + ] } resource "google_kms_crypto_key" "crypto_key" { @@ -30,12 +33,16 @@ resource "google_kms_key_ring" "key_ring" { location = "us-central1" } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding" { +resource "google_kms_crypto_key_iam_member" "crypto_key_member_1" { crypto_key_id = google_kms_crypto_key.crypto_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-metastore.iam.gserviceaccount.com", - "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}" - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-metastore.iam.gserviceaccount.com" } + +resource "google_kms_crypto_key_iam_member" "crypto_key_member_2" { + crypto_key_id = google_kms_crypto_key.crypto_key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.erb index 1db78f99f431..392e848712f3 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.erb +++ b/mmv1/templates/terraform/examples/privateca_certificate_authority_byo_key.tf.erb @@ -3,21 +3,17 @@ resource "google_project_service_identity" "privateca_sa" { service = "privateca.googleapis.com" } -resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_signerverifier" { +resource "google_kms_crypto_key_iam_member" "privateca_sa_keyuser_signerverifier" { crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" role = "roles/cloudkms.signerVerifier" - members = [ - "serviceAccount:${google_project_service_identity.privateca_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.privateca_sa.email}" } -resource "google_kms_crypto_key_iam_binding" "privateca_sa_keyuser_viewer" { +resource "google_kms_crypto_key_iam_member" "privateca_sa_keyuser_viewer" { crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" role = "roles/viewer" - members = [ - "serviceAccount:${google_project_service_identity.privateca_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.privateca_sa.email}" } resource "google_privateca_certificate_authority" "<%= ctx[:primary_resource_id] %>" { @@ -69,8 +65,8 @@ resource "google_privateca_certificate_authority" "<%= ctx[:primary_resource_id] } depends_on = [ - google_kms_crypto_key_iam_binding.privateca_sa_keyuser_signerverifier, - google_kms_crypto_key_iam_binding.privateca_sa_keyuser_viewer, + google_kms_crypto_key_iam_member.privateca_sa_keyuser_signerverifier, + google_kms_crypto_key_iam_member.privateca_sa_keyuser_viewer, ] } # [END privateca_create_ca_byo_key] \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/sql_instance_cmek.tf.erb b/mmv1/templates/terraform/examples/sql_instance_cmek.tf.erb index 3b352c0e574a..e0134a2caa28 100644 --- a/mmv1/templates/terraform/examples/sql_instance_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/sql_instance_cmek.tf.erb @@ -23,14 +23,12 @@ resource "google_kms_crypto_key" "key" { # [END cloud_sql_instance_key] # [START cloud_sql_instance_crypto_key] -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { provider = google-beta crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.gcp_sa_cloud_sql.email}", - ] + member = "serviceAccount:${google_project_service_identity.gcp_sa_cloud_sql.email}" } # [END cloud_sql_instance_crypto_key] diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go index 6f5c9c6c8616..259b207c672c 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_backup_test.go @@ -230,12 +230,10 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go index 21ba1948a2ff..bf1255bc788e 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_cluster_test.go @@ -491,7 +491,7 @@ resource "google_alloydb_cluster" "default" { encryption_config { kms_key_name = google_kms_crypto_key.key.id } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { name = "tf-test-alloydb-cluster%{random_suffix}" @@ -505,12 +505,10 @@ resource "google_kms_crypto_key" "key" { name = "%{key_name}" key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -582,7 +580,7 @@ resource "google_alloydb_cluster" "default" { lifecycle { prevent_destroy = true } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -601,12 +599,10 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -632,9 +628,9 @@ resource "google_alloydb_cluster" "default" { } } lifecycle { - prevent_destroy = true + prevent_destroy = true } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -654,24 +650,20 @@ resource "google_kms_crypto_key" "key" { } resource "google_kms_crypto_key" "key2" { - name = "%{key_name}-2" - key_ring = google_kms_key_ring.keyring.id + name = "%{key_name}-2" + key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } -resource "google_kms_crypto_key_iam_binding" "crypto_key2" { - crypto_key_id = google_kms_crypto_key.key2.id - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] +resource "google_kms_crypto_key_iam_member" "crypto_key2" { + crypto_key_id = google_kms_crypto_key.key2.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -696,7 +688,7 @@ resource "google_alloydb_cluster" "default" { retention_period = "510s" } } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -720,20 +712,16 @@ resource "google_kms_crypto_key" "key2" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } -resource "google_kms_crypto_key_iam_binding" "crypto_key2" { - crypto_key_id = google_kms_crypto_key.key2.id - role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] +resource "google_kms_crypto_key_iam_member" "crypto_key2" { + crypto_key_id = google_kms_crypto_key.key2.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -1042,7 +1030,7 @@ resource "google_alloydb_cluster" "default" { lifecycle { prevent_destroy = true } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -1051,12 +1039,10 @@ resource "google_compute_network" "default" { data "google_project" "project" {} -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = "%{key_name}" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } @@ -1074,7 +1060,7 @@ resource "google_alloydb_cluster" "default" { kms_key_name = "%{key_name}" } } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } resource "google_compute_network" "default" { @@ -1083,12 +1069,10 @@ resource "google_compute_network" "default" { data "google_project" "project" {} -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = "%{key_name}" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } diff --git a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_secondary_cluster_test.go b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_secondary_cluster_test.go index 55e01d0a2c54..3c98505bbd53 100644 --- a/mmv1/third_party/terraform/services/alloydb/resource_alloydb_secondary_cluster_test.go +++ b/mmv1/third_party/terraform/services/alloydb/resource_alloydb_secondary_cluster_test.go @@ -519,7 +519,7 @@ resource "google_alloydb_cluster" "secondary" { kms_key_name = google_kms_crypto_key.key.id } - depends_on = [google_alloydb_instance.primary, google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_alloydb_instance.primary, google_kms_crypto_key_iam_member.crypto_key] } data "google_project" "project" {} @@ -538,12 +538,10 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com" } `, context) } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb index 7518d6b70131..01b6f1c19767 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb @@ -3650,6 +3650,10 @@ resource "google_compute_image" "image" { kms_key_self_link = data.google_kms_crypto_key.key.id kms_key_service_account = google_service_account.test.email } + + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key + ] } diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config_test.go b/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config_test.go index b4556484a999..ab5b0313d09e 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config_test.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_bucket_config_test.go @@ -343,22 +343,18 @@ resource "google_kms_crypto_key" "key2" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding1" { +resource "google_kms_crypto_key_iam_member" "crypto_key_member1" { crypto_key_id = google_kms_crypto_key.key1.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${data.google_logging_project_cmek_settings.cmek_settings.service_account_id}", - ] + member = "serviceAccount:${data.google_logging_project_cmek_settings.cmek_settings.service_account_id}" } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding2" { +resource "google_kms_crypto_key_iam_member" "crypto_key_member2" { crypto_key_id = google_kms_crypto_key.key2.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${data.google_logging_project_cmek_settings.cmek_settings.service_account_id}", - ] + member = "serviceAccount:${data.google_logging_project_cmek_settings.cmek_settings.service_account_id}" } `, context), keyRingName, cryptoKeyName, cryptoKeyNameUpdate) } @@ -378,7 +374,7 @@ resource "google_logging_project_bucket_config" "basic" { kms_key_name = google_kms_crypto_key.key1.id } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding1] + depends_on = [google_kms_crypto_key_iam_member.crypto_key_member1] } `, testAccLoggingBucketConfigProject_preCmekSettings(context, keyRingName, cryptoKeyName, cryptoKeyNameUpdate), bucketId) } @@ -398,7 +394,7 @@ resource "google_logging_project_bucket_config" "basic" { kms_key_name = google_kms_crypto_key.key2.id } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key_binding2] + depends_on = [google_kms_crypto_key_iam_member.crypto_key_member2] } `, testAccLoggingBucketConfigProject_preCmekSettings(context, keyRingName, cryptoKeyName, cryptoKeyNameUpdate), bucketId) } diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go index af63bbd48ee1..74ca85b1fee6 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance_test.go @@ -3714,13 +3714,11 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com" } resource "google_sql_database_instance" "master" { @@ -3773,13 +3771,11 @@ resource "google_kms_crypto_key" "key" { key_ring = google_kms_key_ring.keyring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = google_kms_crypto_key.key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com" } resource "google_sql_database_instance" "master" { @@ -3812,13 +3808,11 @@ resource "google_kms_crypto_key" "key-rep" { key_ring = google_kms_key_ring.keyring-rep.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key_rep" { +resource "google_kms_crypto_key_iam_member" "crypto_key_rep" { crypto_key_id = google_kms_crypto_key.key-rep.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-cloud-sql.iam.gserviceaccount.com" } resource "google_sql_database_instance" "replica" { From cba7bf3076d97ae01b9857e82653149eadc9e4d5 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Mon, 11 Dec 2023 09:36:45 -0800 Subject: [PATCH 097/107] Add additional check to dangling cluster test (#9335) * Add additional check to dangling cluster test Also remove unused code which was needed for failed creation test * Avoid empty timeout field * Skip in VCR --- .../terraform/acctest/bootstrap_test_utils.go | 59 -------------- .../resource_container_cluster_test.go.erb | 76 +++++++++++++++++-- 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go index d0bb61468ad6..bb8e89626a59 100644 --- a/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go +++ b/mmv1/third_party/terraform/acctest/bootstrap_test_utils.go @@ -611,65 +611,6 @@ func BootstrapServicePerimeterProjects(t *testing.T, desiredProjects int) []*clo return projects } -func RemoveContainerServiceAgentRoleFromContainerEngineRobot(t *testing.T, project *cloudresourcemanager.Project) { - config := BootstrapConfig(t) - if config == nil { - return - } - - client := config.NewResourceManagerClient(config.UserAgent) - containerEngineRobot := fmt.Sprintf("serviceAccount:service-%d@container-engine-robot.iam.gserviceaccount.com", project.ProjectNumber) - getPolicyRequest := &cloudresourcemanager.GetIamPolicyRequest{} - policy, err := client.Projects.GetIamPolicy(project.ProjectId, getPolicyRequest).Do() - if err != nil { - t.Fatalf("error getting project iam policy: %v", err) - } - roleFound := false - changed := false - for _, binding := range policy.Bindings { - if binding.Role == "roles/container.serviceAgent" { - memberFound := false - for i, member := range binding.Members { - if member == containerEngineRobot { - binding.Members[i] = binding.Members[len(binding.Members)-1] - memberFound = true - } - } - if memberFound { - binding.Members = binding.Members[:len(binding.Members)-1] - changed = true - } - } else if binding.Role == "roles/editor" { - memberFound := false - for _, member := range binding.Members { - if member == containerEngineRobot { - memberFound = true - break - } - } - if !memberFound { - binding.Members = append(binding.Members, containerEngineRobot) - changed = true - } - roleFound = true - } - } - if !roleFound { - policy.Bindings = append(policy.Bindings, &cloudresourcemanager.Binding{ - Members: []string{containerEngineRobot}, - Role: "roles/editor", - }) - changed = true - } - if changed { - setPolicyRequest := &cloudresourcemanager.SetIamPolicyRequest{Policy: policy} - policy, err = client.Projects.SetIamPolicy(project.ProjectId, setPolicyRequest).Do() - if err != nil { - t.Fatalf("error setting project iam policy: %v", err) - } - } -} - // BootstrapProject will create or get a project named // "" that will persist across test runs, // where projectIDSuffix is based off of getTestProjectFromEnv(). The reason diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb index c79ed5c9779a..2428c885beef 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_test.go.erb @@ -3657,15 +3657,35 @@ func TestAccContainerCluster_autoprovisioningDefaultsManagement(t *testing.T) { // taints it, having Terraform clean it up during the next apply. This test // name is now inexact, but is being preserved to maintain the test history. func TestAccContainerCluster_errorCleanDanglingCluster(t *testing.T) { + acctest.SkipIfVcr(t) // skipped because the timeout step doesn't record operation GET interactions t.Parallel() - prefix := acctest.RandString(t, 10) - clusterName := fmt.Sprintf("tf-test-cluster-%s", prefix) - clusterNameError := fmt.Sprintf("tf-test-cluster-err-%s", prefix) + suffix := acctest.RandString(t, 10) + clusterName := fmt.Sprintf("tf-test-cluster-%s", suffix) + clusterNameError := fmt.Sprintf("tf-test-cluster-err-%s", suffix) + clusterNameErrorWithTimeout := fmt.Sprintf("tf-test-cluster-timeout-%s", suffix) containerNetName := fmt.Sprintf("tf-test-container-net-%s", acctest.RandString(t, 10)) initConfig := testAccContainerCluster_withInitialCIDR(containerNetName, clusterName) overlapConfig := testAccContainerCluster_withCIDROverlap(initConfig, clusterNameError) + overlapConfigWithTimeout := testAccContainerCluster_withCIDROverlapWithTimeout(initConfig, clusterNameErrorWithTimeout, "40s") + + checkTaintApplied := func(st *terraform.State) error { + // Return an error if there is no tainted (i.e. marked for deletion) cluster. + ms := st.RootModule() + errCluster, ok := ms.Resources["google_container_cluster.cidr_error_overlap"] + if !ok { + var resourceNames []string + for rn := range ms.Resources { + resourceNames = append(resourceNames, rn) + } + return fmt.Errorf("could not find google_container_cluster.cidr_error_overlap in resources: %v", resourceNames) + } + if !errCluster.Primary.Tainted { + return fmt.Errorf("cluster with ID %s should be tainted, but is not", errCluster.Primary.ID) + } + return nil + } acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -3682,14 +3702,28 @@ func TestAccContainerCluster_errorCleanDanglingCluster(t *testing.T) { ImportStateVerifyIgnore: []string{"deletion_protection"}, }, { + // First attempt to create the overlapping cluster with no timeout, this should fail and taint the resource. Config: overlapConfig, ExpectError: regexp.MustCompile("Error waiting for creating GKE cluster"), }, - // If tainted cluster won't be deleted, this step will return an error { - Config: overlapConfig, - PlanOnly: true, + // Check that the tainted resource is in the config. + Config: overlapConfig, + PlanOnly: true, + ExpectNonEmptyPlan: true, + Check: checkTaintApplied, + }, + { + // Next attempt to create the overlapping cluster with a 40s timeout. This will fail with a different error. + Config: overlapConfigWithTimeout, + ExpectError: regexp.MustCompile("timeout while waiting for state to become 'DONE'"), + }, + { + // Check that the tainted resource is in the config. + Config: overlapConfig, + PlanOnly: true, ExpectNonEmptyPlan: true, + Check: checkTaintApplied, }, }, }) @@ -5467,7 +5501,6 @@ func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { } func testAccContainerCluster_withEnablePrivateEndpoint(clusterName, flag, networkName, subnetworkName string) string { - return fmt.Sprintf(` data "google_container_engine_versions" "uscentral1a" { location = "us-central1-a" @@ -7981,7 +8014,7 @@ resource "google_container_cluster" "cidr_error_preempt" { func testAccContainerCluster_withCIDROverlap(initConfig, secondCluster string) string { return fmt.Sprintf(` - %s +%s resource "google_container_cluster" "cidr_error_overlap" { name = "%s" @@ -8002,6 +8035,33 @@ resource "google_container_cluster" "cidr_error_overlap" { `, initConfig, secondCluster) } + +func testAccContainerCluster_withCIDROverlapWithTimeout(initConfig, secondCluster, createTimeout string) string { + return fmt.Sprintf(` +%s + +resource "google_container_cluster" "cidr_error_overlap" { + name = "%s" + location = "us-central1-a" + + network = google_compute_network.container_network.name + subnetwork = google_compute_subnetwork.container_subnetwork.name + + initial_node_count = 1 + + networking_mode = "VPC_NATIVE" + ip_allocation_policy { + cluster_ipv4_cidr_block = "10.0.0.0/16" + services_ipv4_cidr_block = "10.1.0.0/16" + } + deletion_protection = false + timeouts { + create = "%s" + } +} +`, initConfig, secondCluster, createTimeout) +} + func testAccContainerCluster_withInvalidLocation(location string) string { return fmt.Sprintf(` resource "google_container_cluster" "with_resource_labels" { From c2f6cc6bfdc7c160de0eb36c9b9c9e6f151d8bba Mon Sep 17 00:00:00 2001 From: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Date: Mon, 11 Dec 2023 23:41:52 +0530 Subject: [PATCH 098/107] Terraform support for Workbench instances (#9368) * Workbench Instances * fix yaml to run tests * fix yaml to run tests * fix basic test * diff suppress for tags * add custom flattens * Add labels example * fix tags diff * custom_flatten with ignore_read * removed ignore_read * remove ignore_read on disks * Add kms key in full test * read_ignore for examples * clean up extra flattens * add update test * fix indent lint * fix wbi lint * fix lint issues * fix whitespace * change names in full test to vars * change tests to use variable names instead of hard coded values * stop wbi before updating machine_type * all tests passing * fix terraformgoogleconversion-codegen compiler error * make service account immutable * addressed issues with immutable fields * add disable_proxy_access into full example * Add disable_proxy_access in full test * remove returns in pre and post updates * test false values in secure vm config * fix empty shielded instance config * fixed update on non stop needing fields failing * create custom update mask * make disks sub fields completely immutable * update tests for shielded config and gpu driver * Removed scopes block from product * removed apis required * break shielded_instance_config update msk into submasks * revert update mask for shieldedInstanceConfig * Make vm image immutable * Remove gpu driver config * remove shielded instance config field * removed unspecified values in enums * reupload * removed max_items in serviceAccounts --- mmv1/products/workbench/Instance.yaml | 472 ++++++++++++++++++ mmv1/products/workbench/product.yaml | 39 ++ .../terraform/constants/workbench_instance.go | 142 ++++++ ...stance_boot_disk_encryption_flatten.go.erb | 17 + ...ench_instance_boot_disk_kms_flatten.go.erb | 17 + ...nch_instance_boot_disk_type_flatten.go.erb | 17 + ...stance_data_disk_encryption_flatten.go.erb | 17 + ...ench_instance_data_disk_kms_flatten.go.erb | 17 + ...nch_instance_data_disk_type_flatten.go.erb | 17 + ...workbench_instance_vm_image_flatten.go.erb | 17 + .../examples/workbench_instance_basic.tf.erb | 4 + .../workbench_instance_basic_gpu.tf.erb | 15 + .../examples/workbench_instance_full.tf.erb | 78 +++ .../examples/workbench_instance_labels.tf.erb | 24 + .../post_create/workbench_instance.go.erb | 3 + .../post_update/workbench_instance.go.erb | 35 ++ .../pre_update/workbench_instance.go.erb | 61 +++ ...esource_workbench_instance_gpu_test.go.erb | 272 ++++++++++ 18 files changed, 1264 insertions(+) create mode 100644 mmv1/products/workbench/Instance.yaml create mode 100644 mmv1/products/workbench/product.yaml create mode 100644 mmv1/templates/terraform/constants/workbench_instance.go create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb create mode 100644 mmv1/templates/terraform/examples/workbench_instance_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/workbench_instance_basic_gpu.tf.erb create mode 100644 mmv1/templates/terraform/examples/workbench_instance_full.tf.erb create mode 100644 mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb create mode 100644 mmv1/templates/terraform/post_create/workbench_instance.go.erb create mode 100644 mmv1/templates/terraform/post_update/workbench_instance.go.erb create mode 100644 mmv1/templates/terraform/pre_update/workbench_instance.go.erb create mode 100644 mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb diff --git a/mmv1/products/workbench/Instance.yaml b/mmv1/products/workbench/Instance.yaml new file mode 100644 index 000000000000..c5e77ee1abee --- /dev/null +++ b/mmv1/products/workbench/Instance.yaml @@ -0,0 +1,472 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +base_url: "projects/{{project}}/locations/{{location}}/instances" +create_url: "projects/{{project}}/locations/{{location}}/instances?instanceId={{name}}" +self_link: "projects/{{project}}/locations/{{location}}/instances/{{name}}" +id_format: "projects/{{project}}/locations/{{location}}/instances/{{name}}" +import_format: + - "projects/{{project}}/locations/{{location}}/instances/{{name}}" +name: Instance +description: A Workbench instance. +update_verb: :PATCH +update_mask: true +iam_policy: !ruby/object:Api::Resource::IamPolicy + method_name_separator: ":" + fetch_iam_policy_verb: :GET + parent_resource_attribute: "name" + import_format: + [ + 'projects/{{project}}/locations/{{location}}/instances/{{name}}', + '{{name}}', + ] + base_url: projects/{{project}}/locations/{{location}}/instances/{{name}} +autogen_async: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'workbench_instance_basic' + primary_resource_id: 'instance' + primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", + context[\"\ + random_suffix\"])" + region_override: 'us-west1-a' + vars: + instance_name: 'workbench-instance' + - !ruby/object:Provider::Terraform::Examples + name: 'workbench_instance_basic_gpu' + primary_resource_id: 'instance' + primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", + context[\"\ + random_suffix\"])" + region_override: 'us-west1-a' + vars: + instance_name: 'workbench-instance' + ignore_read_extra: + - 'gce_setup.0.vm_image' + - !ruby/object:Provider::Terraform::Examples + name: 'workbench_instance_labels' + primary_resource_id: 'instance' + primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", + context[\"\ + random_suffix\"])" + region_override: 'us-west1-a' + vars: + instance_name: 'workbench-instance' + network_name: 'wbi-test-default' + test_env_vars: + service_account: :SERVICE_ACCT + - !ruby/object:Provider::Terraform::Examples + name: 'workbench_instance_full' + primary_resource_id: 'instance' + primary_resource_name: "fmt.Sprintf(\"tf-test-workbench-instance%s\", + context[\"\ + random_suffix\"])" + region_override: 'us-west1-a' + vars: + instance_name: 'workbench-instance' + network_name: 'wbi-test-default' + keyring_name: 'tftest-shared-keyring-1' + key_name: 'tftest-shared-key-1' + test_env_vars: + service_account: :SERVICE_ACCT + ignore_read_extra: + - 'gce_setup.0.vm_image' + - 'gce_setup.0.boot_disk.0.disk_encryption' + - 'gce_setup.0.boot_disk.0.disk_type' + - 'gce_setup.0.boot_disk.0.kms_key' + - 'gce_setup.0.data_disks.0.disk_encryption' + - 'gce_setup.0.data_disks.0.disk_type' + - 'gce_setup.0.data_disks.0.kms_key' +timeouts: !ruby/object:Api::Timeouts + insert_minutes: 10 + update_minutes: 20 +custom_code: !ruby/object:Provider::Terraform::CustomCode + constants: templates/terraform/constants/workbench_instance.go + post_create: templates/terraform/post_create/workbench_instance.go.erb + pre_update: templates/terraform/pre_update/workbench_instance.go.erb + post_update: templates/terraform/post_update/workbench_instance.go.erb +properties: + - !ruby/object:Api::Type::String + name: name + description: 'The name of this workbench instance. Format: `projects/{project_id}/locations/{location}/instances/{instance_id}`' + required: true + immutable: true + url_param_only: true + pattern: v2/projects/{{project}}/locations/{{location}}/instances/{{name}} + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + - !ruby/object:Api::Type::NestedObject + name: gceSetup + default_from_api: true + description: The definition of how to configure a VM instance outside of Resources and Identity. + properties: + - !ruby/object:Api::Type::String + name: machineType + default_from_api: true + description: | + Optional. The machine type of the VM instance. https://cloud.google.com/compute/docs/machine-resource + pattern: projects/{{project}}/zones/{{location}}/machineTypes/{{name}} + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb + - !ruby/object:Api::Type::Array + name: acceleratorConfigs + description: | + The hardware accelerators used on this instance. If you use accelerators, make sure that your configuration has + [enough vCPUs and memory to support the `machine_type` you have selected](https://cloud.google.com/compute/docs/gpus/#gpus-list). + Currently supports only one accelerator configuration. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Enum + name: type + values: + - NVIDIA_TESLA_P100 + - NVIDIA_TESLA_V100 + - NVIDIA_TESLA_P4 + - NVIDIA_TESLA_T4 + - NVIDIA_TESLA_A100 + - NVIDIA_A100_80GB + - NVIDIA_L4 + - NVIDIA_TESLA_T4_VWS + - NVIDIA_TESLA_P100_VWS + - NVIDIA_TESLA_P4_VWS + description: Optional. Type of this accelerator. + - !ruby/object:Api::Type::String + name: coreCount + description: Optional. Count of cores of this accelerator. + description: | + Optional. The hardware accelerators used on this instance. If you + use accelerators, make sure that your configuration has [enough vCPUs and memory + to support the `machine_type` you have selected](https://cloud.google.com/compute/docs/gpus/#gpus-list). + Currently supports only one accelerator configuration. + - !ruby/object:Api::Type::Array + name: serviceAccounts + description: | + The service account that serves as an identity for the VM instance. Currently supports only one service account. + default_from_api: true + immutable: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: email + immutable: true + default_from_api: true + description: Optional. Email address of the service account. + - !ruby/object:Api::Type::Array + name: scopes + item_type: Api::Type::String + description: | + Output only. The list of scopes to be made available for this + service account. Set by the CLH to https://www.googleapis.com/auth/cloud-platform + output: true + description: | + Optional. The service account that serves as an identity for the + VM instance. Currently supports only one service account. + - !ruby/object:Api::Type::NestedObject + name: vmImage + custom_flatten: templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb + default_from_api: true + immutable: true + description: | + Definition of a custom Compute Engine virtual machine image for starting + a workbench instance with the environment installed directly on the VM. + properties: + - !ruby/object:Api::Type::String + name: project + immutable: true + description: | + The name of the Google Cloud project that this VM image belongs to. + Format: {project_id} + - !ruby/object:Api::Type::String + name: name + immutable: true + description: Optional. Use VM image name to find the image. + exactly_one_of: + - vm_image.0.name + - vm_image.0.family + - !ruby/object:Api::Type::String + name: family + immutable: true + description: | + Optional. Use this VM image family to find the image; the newest + image in this family will be used. + exactly_one_of: + - vm_image.0.name + - vm_image.0.family + - !ruby/object:Api::Type::NestedObject + name: bootDisk + default_from_api: true + description: The definition of a boot disk. + immutable: true + properties: + - !ruby/object:Api::Type::String + name: diskSizeGb + default_from_api: true + immutable: true + description: | + Optional. The size of the boot disk in GB attached to this instance, + up to a maximum of 64000 GB (64 TB). If not specified, this defaults to the + recommended value of 150GB. + - !ruby/object:Api::Type::Enum + name: diskType + default_from_api: true + immutable: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb + values: + - PD_STANDARD + - PD_SSD + - PD_BALANCED + - PD_EXTREME + description: Optional. Indicates the type of the disk. + - !ruby/object:Api::Type::Enum + name: diskEncryption + default_from_api: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb + values: + - GMEK + - CMEK + description: | + Optional. Input only. Disk encryption method used on the boot and + data disks, defaults to GMEK. + immutable: true + - !ruby/object:Api::Type::String + name: kmsKey + description: | + 'Optional. Input only. The KMS key used to encrypt the disks, only + applicable if disk_encryption is CMEK. Format: `projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}` + Learn more about using your own encryption keys.' + immutable: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb + - !ruby/object:Api::Type::Array + name: dataDisks + description: Data disks attached to the VM instance. Currently supports only one data disk. + max_size: 1 + default_from_api: true + immutable: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: diskSizeGb + default_from_api: true + immutable: true + description: | + Optional. The size of the disk in GB attached to this VM instance, + up to a maximum of 64000 GB (64 TB). If not specified, this defaults to + 100. + - !ruby/object:Api::Type::Enum + name: diskType + custom_flatten: templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb + values: + - PD_STANDARD + - PD_SSD + - PD_BALANCED + - PD_EXTREME + description: Optional. Input only. Indicates the type of the disk. + immutable: true + - !ruby/object:Api::Type::Enum + name: diskEncryption + default_from_api: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb + values: + - GMEK + - CMEK + description: | + Optional. Input only. Disk encryption method used on the boot + and data disks, defaults to GMEK. + immutable: true + - !ruby/object:Api::Type::String + name: kmsKey + description: | + 'Optional. Input only. The KMS key used to encrypt the disks, + only applicable if disk_encryption is CMEK. Format: `projects/{project_id}/locations/{location}/keyRings/{key_ring_id}/cryptoKeys/{key_id}` + Learn more about using your own encryption keys.' + immutable: true + custom_flatten: templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb + description: | + Optional. Data disks attached to the VM instance. Currently supports + only one data disk. + - !ruby/object:Api::Type::Array + name: networkInterfaces + description: The network interfaces for the VM. Supports only one interface. + default_from_api: true + immutable: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: network + description: 'Optional. The name of the VPC that this VM instance is in.' + immutable: true + custom_expand: templates/terraform/custom_expand/network_full_url.erb + diff_suppress_func: tpgresource.CompareSelfLinkRelativePaths + default_from_api: true + - !ruby/object:Api::Type::String + name: subnet + immutable: true + description: 'Optional. The name of the subnet that this VM instance is in.' + diff_suppress_func: tpgresource.CompareSelfLinkRelativePaths + default_from_api: true + - !ruby/object:Api::Type::Enum + name: nicType + immutable: true + description: | + Optional. The type of vNIC to be used on this interface. This + may be gVNIC or VirtioNet. + values: + - VIRTIO_NET + - GVNIC + description: Optional. The network interfaces for the VM. Supports only one interface. + - !ruby/object:Api::Type::Boolean + name: disablePublicIp + default_from_api: true + immutable: true + description: Optional. If true, no external IP will be assigned to this VM instance. + - !ruby/object:Api::Type::Array + name: tags + item_type: Api::Type::String + default_from_api: true + diff_suppress_func: WorkbenchInstanceTagsDiffSuppress + immutable: true + description: | + Optional. The Compute Engine tags to add to instance (see [Tagging + instances](https://cloud.google.com/compute/docs/label-or-tag-resources#tags)). + - !ruby/object:Api::Type::KeyValuePairs + name: metadata + default_from_api: true + diff_suppress_func: WorkbenchInstanceMetadataDiffSuppress + description: Optional. Custom metadata to apply to this instance. + - !ruby/object:Api::Type::Boolean + name: enableIpForwarding + immutable: true + description: | + Optional. Flag to enable ip forwarding or not, default false/off. + https://cloud.google.com/vpc/docs/using-routes#canipforward + - !ruby/object:Api::Type::String + name: proxyUri + description: Output only. The proxy endpoint that is used to access the Jupyter notebook. + output: true + - !ruby/object:Api::Type::Array + name: instanceOwners + item_type: Api::Type::String + description: | + 'Optional. Input only. The owner of this instance after creation. Format: + `alias@example.com` Currently supports one owner only. If not specified, all of + the service account users of your VM instance''s service account can use the instance.' + ignore_read: true + immutable: true + - !ruby/object:Api::Type::String + name: creator + description: Output only. Email address of entity that sent original CreateInstance request. + output: true + - !ruby/object:Api::Type::String + name: state + description: Output only. The state of this instance. + output: true + - !ruby/object:Api::Type::Array + name: upgradeHistory + description: Output only. The upgrade history of this instance. + output: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: snapshot + description: Optional. The snapshot of the boot disk of this workbench instance before upgrade. + - !ruby/object:Api::Type::String + name: vmImage + description: Optional. The VM image before this instance upgrade. + - !ruby/object:Api::Type::String + name: containerImage + description: Optional. The container image before this instance upgrade. + - !ruby/object:Api::Type::String + name: framework + description: Optional. The framework of this workbench instance. + - !ruby/object:Api::Type::String + name: version + description: Optional. The version of the workbench instance before this upgrade. + - !ruby/object:Api::Type::String + name: state + description: Output only. The state of this instance upgrade history entry. + output: true + - !ruby/object:Api::Type::String + name: createTime + description: | + An RFC3339 timestamp in UTC time. This in the format of yyyy-MM-ddTHH:mm:ss.SSSZ. + The milliseconds portion (".SSS") is optional. + - !ruby/object:Api::Type::String + name: action + description: Optional. Action. Rolloback or Upgrade. + - !ruby/object:Api::Type::String + name: targetVersion + description: Optional. Target VM Version, like m63. + - !ruby/object:Api::Type::String + name: healthState + description: Output only. Instance health_state. + output: true + - !ruby/object:Api::Type::NestedObject + properties: [] + name: healthInfo + description: | + 'Output only. Additional information about instance health. Example: + healthInfo": { "docker_proxy_agent_status": "1", "docker_status": "1", "jupyterlab_api_status": + "-1", "jupyterlab_status": "-1", "updated": "2020-10-18 09:40:03.573409" }' + output: true + - !ruby/object:Api::Type::String + name: createTime + description: | + An RFC3339 timestamp in UTC time. This in the format of yyyy-MM-ddTHH:mm:ss.SSSZ. + The milliseconds portion (".SSS") is optional. + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: | + An RFC3339 timestamp in UTC time. This in the format of yyyy-MM-ddTHH:mm:ss.SSSZ. + The milliseconds portion (".SSS") is optional. + output: true + - !ruby/object:Api::Type::Boolean + name: disableProxyAccess + immutable: true + description: Optional. If true, the workbench instance will not register with the proxy. + - !ruby/object:Api::Type::KeyValueLabels + name: labels + description: | + Optional. Labels to apply to this instance. These can be later modified + by the UpdateInstance method. + diff_suppress_func: WorkbenchInstanceLabelsDiffSuppress +parameters: + - !ruby/object:Api::Type::String + name: location + description: Part of `parent`. See documentation of `projectsId`. + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: instanceId + description: Required. User-defined unique ID of this instance. + url_param_only: true + immutable: true +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: name + base_url: "{{op_id}}" + wait_ms: 1000 + timeouts: + 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 diff --git a/mmv1/products/workbench/product.yaml b/mmv1/products/workbench/product.yaml new file mode 100644 index 000000000000..cbfc6ec431f1 --- /dev/null +++ b/mmv1/products/workbench/product.yaml @@ -0,0 +1,39 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +name: Workbench +display_name: Vertex AI Workbench +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://notebooks.googleapis.com/v2/ +scopes: + - https://www.googleapis.com/auth/cloud-platform +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + base_url: '{{op_id}}' + path: 'name' + 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' diff --git a/mmv1/templates/terraform/constants/workbench_instance.go b/mmv1/templates/terraform/constants/workbench_instance.go new file mode 100644 index 000000000000..6ae6d20dca67 --- /dev/null +++ b/mmv1/templates/terraform/constants/workbench_instance.go @@ -0,0 +1,142 @@ +var WorkbenchInstanceProvidedLabels = []string{ + "consumer-project-id", + "consumer-project-number", + "notebooks-product", + "resource-name", +} + +func WorkbenchInstanceLabelsDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the labels + for _, label := range WorkbenchInstanceProvidedLabels { + if strings.Contains(k, label) && new == "" { + return true + } + } + + // Let diff be determined by labels (above) + if strings.Contains(k, "labels.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + + +var WorkbenchInstanceProvidedMetadata = []string{ + "disable-swap-binaries", + "enable-guest-attributes", + "proxy-backend-id", + "proxy-registration-url", + "agent-health-check-interval-seconds", + "agent-health-check-path", + "container", + "data-disk-uri", + "dataproc-allow-custom-clusters", + "dataproc-cluster-name", + "dataproc-configs", + "dataproc-default-subnet", + "dataproc-locations-list", + "dataproc-machine-types-list", + "dataproc-notebooks-url", + "dataproc-region", + "dataproc-service-account", + "disable-check-xsrf", + "framework", + "gcs-data-bucket", + "generate-diagnostics-bucket", + "generate-diagnostics-file", + "generate-diagnostics-options", + "image-url", + "install-monitoring-agent", + "install-nvidia-driver", + "installed-extensions", + "notebooks-api", + "notebooks-api-version", + "notebooks-examples-location", + "notebooks-location", + "nvidia-driver-gcs-path", + "proxy-mode", + "proxy-status", + "proxy-url", + "proxy-user-mail", + "report-container-health", + "report-notebook-metrics", + "report-system-health", + "report-system-status", + "restriction", + "serial-port-logging-enable", + "shutdown-script", + "title", + "use-collaborative", + "version", + "enable-oslogin", +} + +func WorkbenchInstanceMetadataDiffSuppress(k, old, new string, d *schema.ResourceData) bool { + // Suppress diffs for the Metadata + for _, metadata := range WorkbenchInstanceProvidedMetadata { + if strings.Contains(k, metadata) && new == "" { + return true + } + } + + // Let diff be determined by metadata + if strings.Contains(k, "gce_setup.0.metadata.%") { + return true + } + + // For other keys, don't suppress diff. + return false +} + + +var WorkbenchInstanceProvidedTags = []string{ + "deeplearning-vm", + "notebook-instance", +} + +func WorkbenchInstanceTagsDiffSuppress(_, _, _ string, d *schema.ResourceData) bool { + old, new := d.GetChange("gce_setup.0.tags") + oldValue := old.([]interface{}) + newValue := new.([]interface{}) + oldValueList := []string{} + newValueList := []string{} + + for _, item := range oldValue { + oldValueList = append(oldValueList,item.(string)) + } + + for _, item := range newValue { + newValueList = append(newValueList,item.(string)) + } + newValueList= append(newValueList,WorkbenchInstanceProvidedTags...) + + sort.Strings(oldValueList) + sort.Strings(newValueList) + if reflect.DeepEqual(oldValueList, newValueList) { + return true + } + return false +} + +<% unless compiler == "terraformgoogleconversion-codegen" -%> +// waitForWorkbenchInstanceActive waits for an workbench instance to become "ACTIVE" +func waitForWorkbenchInstanceActive(d *schema.ResourceData, config *transport_tpg.Config, timeout time.Duration) error { + return resource.Retry(timeout, func() *resource.RetryError { + if err := resourceWorkbenchInstanceRead(d, config); err != nil { + return resource.NonRetryableError(err) + } + + name := d.Get("name").(string) + state := d.Get("state").(string) + if state == "ACTIVE" { + log.Printf("[DEBUG] Workbench Instance %q has state %q.", name, state) + return nil + } else { + return resource.RetryableError(fmt.Errorf("Workbench Instance %q has state %q. Waiting for ACTIVE state", name, state)) + } + + }) +} +<% end -%> diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb new file mode 100644 index 000000000000..eb44d9657f33 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_encryption_flatten.go.erb @@ -0,0 +1,17 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.boot_disk.0.disk_encryption") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb new file mode 100644 index 000000000000..70c27a7661e2 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_kms_flatten.go.erb @@ -0,0 +1,17 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.boot_disk.0.kms_key") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb new file mode 100644 index 000000000000..05092c33d46c --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_boot_disk_type_flatten.go.erb @@ -0,0 +1,17 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.boot_disk.0.disk_type") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb new file mode 100644 index 000000000000..d93558a3db76 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_encryption_flatten.go.erb @@ -0,0 +1,17 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.data_disks.0.disk_encryption") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb new file mode 100644 index 000000000000..b6a7b9649db0 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_kms_flatten.go.erb @@ -0,0 +1,17 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.data_disks.0.kms_key") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb new file mode 100644 index 000000000000..b23aa34b41e3 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_data_disk_type_flatten.go.erb @@ -0,0 +1,17 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.data_disks.0.disk_type") +} diff --git a/mmv1/templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb b/mmv1/templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb new file mode 100644 index 000000000000..24a7978041e5 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/workbench_instance_vm_image_flatten.go.erb @@ -0,0 +1,17 @@ +<%# The license inside this block applies to this file. + # Copyright 2023 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return d.Get("gce_setup.0.vm_image") +} diff --git a/mmv1/templates/terraform/examples/workbench_instance_basic.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_basic.tf.erb new file mode 100644 index 000000000000..3a2cac94277d --- /dev/null +++ b/mmv1/templates/terraform/examples/workbench_instance_basic.tf.erb @@ -0,0 +1,4 @@ +resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['instance_name'] %>" + location = "us-west1-a" +} diff --git a/mmv1/templates/terraform/examples/workbench_instance_basic_gpu.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_basic_gpu.tf.erb new file mode 100644 index 000000000000..41c682cf1936 --- /dev/null +++ b/mmv1/templates/terraform/examples/workbench_instance_basic_gpu.tf.erb @@ -0,0 +1,15 @@ +resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['instance_name'] %>" + location = "us-central1-a" + gce_setup { + machine_type = "n1-standard-1" // cant be e2 because of accelerator + accelerator_configs { + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + vm_image { + project = "deeplearning-platform-release" + family = "tf-latest-gpu" + } + } +} diff --git a/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb new file mode 100644 index 000000000000..f9f603ab483d --- /dev/null +++ b/mmv1/templates/terraform/examples/workbench_instance_full.tf.erb @@ -0,0 +1,78 @@ +resource "google_compute_network" "my_network" { + name = "<%= ctx[:vars]['network_name'] %>" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "my_subnetwork" { + name = "<%= ctx[:vars]['network_name'] %>" + network = google_compute_network.my_network.id + region = "us-central1" + ip_cidr_range = "10.0.1.0/24" +} + +resource "google_kms_key_ring" "keyring" { + name = "<%= ctx[:vars]['keyring_name'] %>" + location = "global" +} + +resource "google_kms_crypto_key" "crypto-key" { + name = "<%= ctx[:vars]['key_name'] %>" + key_ring = google_kms_key_ring.keyring.id +} + +resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['instance_name'] %>" + location = "us-central1-a" + + gce_setup { + machine_type = "n1-standard-4" // cant be e2 because of accelerator + accelerator_configs { + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + + disable_public_ip = false + + service_accounts { + email = "<%= ctx[:test_env_vars]["service_account"] %>" + } + + boot_disk { + disk_size_gb = 310 + disk_type = "PD_SSD" + disk_encryption = "GMEK" + kms_key = google_kms_crypto_key.crypto-key.id + } + + data_disks { + disk_size_gb = 330 + disk_type = "PD_SSD" + disk_encryption = "GMEK" + kms_key = google_kms_crypto_key.crypto-key.id + } + + network_interfaces { + network = google_compute_network.my_network.id + subnet = google_compute_subnetwork.my_subnetwork.id + nic_type = "GVNIC" + } + + metadata = { + terraform = "true" + } + + enable_ip_forwarding = true + + tags = ["abc", "def"] + + } + + disable_proxy_access = "true" + + instance_owners = [ "<%= ctx[:test_env_vars]["service_account"] %>"] + + labels = { + k = "val" + } + +} diff --git a/mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb b/mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb new file mode 100644 index 000000000000..3a0d9afda853 --- /dev/null +++ b/mmv1/templates/terraform/examples/workbench_instance_labels.tf.erb @@ -0,0 +1,24 @@ +resource "google_workbench_instance" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['instance_name'] %>" + location = "us-central1-a" + + gce_setup { + machine_type = "e2-standard-4" + + service_accounts { + email = "<%= ctx[:test_env_vars]["service_account"] %>" + } + + metadata = { + terraform = "true" + } + + } + + instance_owners = [ "<%= ctx[:test_env_vars]["service_account"] %>"] + + labels = { + k = "val" + } + +} diff --git a/mmv1/templates/terraform/post_create/workbench_instance.go.erb b/mmv1/templates/terraform/post_create/workbench_instance.go.erb new file mode 100644 index 000000000000..e3a968e4a6b2 --- /dev/null +++ b/mmv1/templates/terraform/post_create/workbench_instance.go.erb @@ -0,0 +1,3 @@ +if err := waitForWorkbenchInstanceActive(d, config, d.Timeout(schema.TimeoutCreate) - time.Minute); err != nil { + return fmt.Errorf("Workbench instance %q did not reach ACTIVE state: %q", d.Get("name").(string), err) +} diff --git a/mmv1/templates/terraform/post_update/workbench_instance.go.erb b/mmv1/templates/terraform/post_update/workbench_instance.go.erb new file mode 100644 index 000000000000..fa994a3aacb4 --- /dev/null +++ b/mmv1/templates/terraform/post_update/workbench_instance.go.erb @@ -0,0 +1,35 @@ +state := d.Get("state").(string) + +if state != "ACTIVE" { + startURL, err := tpgresource.ReplaceVars(d, config, "{{WorkbenchBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}:start") + if err != nil { + return err + } + + log.Printf("[DEBUG] Starting Workbench Instance: %q", name) + + emptyReqBody := make(map[string]interface{}) + + pRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: startURL, + UserAgent: userAgent, + Body: emptyReqBody, + }) + if err != nil { + return fmt.Errorf("Error Starting Workbench Instance: %s", err) + } + + var opResp map[string]interface{} + err = WorkbenchOperationWaitTimeWithResponse( + config, pRes, &opResp, project, "Starting Workbench Instance", userAgent, + d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("Error waiting to start Workbench Instance: %s", err) + } + +} else { + log.Printf("[DEBUG] Workbench Instance %q has state %q.", name, state) +} diff --git a/mmv1/templates/terraform/pre_update/workbench_instance.go.erb b/mmv1/templates/terraform/pre_update/workbench_instance.go.erb new file mode 100644 index 000000000000..2b33205942a7 --- /dev/null +++ b/mmv1/templates/terraform/pre_update/workbench_instance.go.erb @@ -0,0 +1,61 @@ +name := d.Get("name").(string) +if d.HasChange("gce_setup.0.machine_type") || d.HasChange("gce_setup.0.accelerator_configs") { + state := d.Get("state").(string) + if state != "STOPPED" { + stopURL, err := tpgresource.ReplaceVars(d, config, "{{WorkbenchBasePath}}projects/{{project}}/locations/{{location}}/instances/{{name}}:stop") + if err != nil { + return err + } + + log.Printf("[DEBUG] Stopping Workbench Instance: %q", name) + + emptyReqBody := make(map[string]interface{}) + + dRes, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: stopURL, + UserAgent: userAgent, + Body: emptyReqBody, + }) + if err != nil { + return fmt.Errorf("Error Stopping Workbench Instance: %s", err) + } + + var opRes map[string]interface{} + err = WorkbenchOperationWaitTimeWithResponse( + config, dRes, &opRes, project, "Stopping Workbench Instance", userAgent, + d.Timeout(schema.TimeoutUpdate)) + if err != nil { + return fmt.Errorf("Error waiting to stop Workbench Instance: %s", err) + } + + } else { + log.Printf("[DEBUG] Workbench Instance %q has state %q.", name, state) + } + +} else { + log.Printf("[DEBUG] Workbench Instance %q need not be stopped for the update.", name) +} + +// Build custom mask since the notebooks API does not support gce_setup as a valid mask +newUpdateMask := []string{} +if d.HasChange("gce_setup.0.machine_type") { + newUpdateMask = append(newUpdateMask, "gce_setup.machine_type") +} +if d.HasChange("gce_setup.0.accelerator_configs") { + newUpdateMask = append(newUpdateMask, "gce_setup.accelerator_configs") +} +if d.HasChange("gce_setup.0.metadata") { + newUpdateMask = append(newUpdateMask, "gceSetup.metadata") +} +if d.HasChange("effective_labels") { + newUpdateMask = append(newUpdateMask, "labels") +} + +// Overwrite the previously set mask. +url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(newUpdateMask, ",")}) +if err != nil { + return err +} diff --git a/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb b/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb new file mode 100644 index 000000000000..c1914881b2a6 --- /dev/null +++ b/mmv1/third_party/terraform/services/workbench/resource_workbench_instance_gpu_test.go.erb @@ -0,0 +1,272 @@ +<% autogen_exception -%> +package workbench_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccWorkbenchInstance_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_basic(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + { + Config: testAccWorkbenchInstance_update(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" +} +`, context) +} + +func testAccWorkbenchInstance_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + gce_setup { + machine_type = "n1-standard-16" + + accelerator_configs{ + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + + metadata = { + terraform = "true" + } + + } + + labels = { + k = "val" + } + +} +`, context) +} + +func TestAccWorkbenchInstance_updateGpu(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_basicGpu(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + { + Config: testAccWorkbenchInstance_updateGpu(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_basicGpu(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + gce_setup { + machine_type = "n1-standard-1" // cant be e2 because of accelerator + accelerator_configs { + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + + } +} +`, context) +} + +func testAccWorkbenchInstance_updateGpu(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + gce_setup { + machine_type = "n1-standard-16" + + accelerator_configs{ + type = "NVIDIA_TESLA_P4" + core_count = 1 + } + + } + + labels = { + k = "val" + } + +} +`, context) +} + +func TestAccWorkbenchInstance_removeGpu(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_Gpu(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + { + Config: testAccWorkbenchInstance_updateGpu(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_Gpu(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + gce_setup { + machine_type = "n1-standard-1" // cant be e2 because of accelerator + accelerator_configs { + type = "NVIDIA_TESLA_T4" + core_count = 1 + } + + } +} +`, context) +} + +func testAccWorkbenchInstance_removeGpu(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + gce_setup { + machine_type = "n1-standard-16" + + } + +} +`, context) +} + +func TestAccWorkbenchInstance_updateMetadata(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkbenchInstance_basic(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + { + Config: testAccWorkbenchInstance_updateMetadata(context), + }, + { + ResourceName: "google_workbench_instance.instance", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "instance_owners", "location", "instance_id", "request_id", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkbenchInstance_updateMetadata(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_workbench_instance" "instance" { + name = "tf-test-workbench-instance%{random_suffix}" + location = "us-central1-a" + + gce_setup { + metadata = { + terraform = "true" + } + } + + labels = { + k = "val" + } + +} +`, context) +} From 42bac036dc8ec30910c69ca6e6703fd6654ba7d1 Mon Sep 17 00:00:00 2001 From: James Edouard Date: Mon, 11 Dec 2023 17:24:56 -0500 Subject: [PATCH 099/107] Add support for severity options in AlertPolicy (#9544) * Add support for severity options in AlertPolicy * Update description for severity options * Add update test for severity options * Format go changes --------- Co-authored-by: James Edouard --- mmv1/products/monitoring/AlertPolicy.yaml | 10 +++++++++ .../resource_monitoring_alert_policy_test.go | 22 ++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/mmv1/products/monitoring/AlertPolicy.yaml b/mmv1/products/monitoring/AlertPolicy.yaml index 92aa4f110ad8..d968e2d4ea1c 100644 --- a/mmv1/products/monitoring/AlertPolicy.yaml +++ b/mmv1/products/monitoring/AlertPolicy.yaml @@ -957,6 +957,16 @@ properties: to 63 Unicode characters or 128 bytes, whichever is smaller. Labels and values can contain only lowercase letters, numerals, underscores, and dashes. Keys must begin with a letter. + - !ruby/object:Api::Type::Enum + name: severity + description: | + The severity of an alert policy indicates how important incidents generated + by that policy are. The severity level will be displayed on the Incident + detail page and in notifications. + values: + - :CRITICAL + - :ERROR + - :WARNING - !ruby/object:Api::Type::NestedObject name: documentation description: | diff --git a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_alert_policy_test.go b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_alert_policy_test.go index 857d40c00b24..c21ebca4a15d 100644 --- a/mmv1/third_party/terraform/services/monitoring/resource_monitoring_alert_policy_test.go +++ b/mmv1/third_party/terraform/services/monitoring/resource_monitoring_alert_policy_test.go @@ -48,7 +48,7 @@ func testAccMonitoringAlertPolicy_basic(t *testing.T) { CheckDestroy: testAccCheckAlertPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, "ALIGN_RATE", filter), + Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, "ALIGN_RATE", filter, "WARNING"), }, { ResourceName: "google_monitoring_alert_policy.basic", @@ -65,8 +65,10 @@ func testAccMonitoringAlertPolicy_update(t *testing.T) { conditionName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) filter1 := `metric.type=\"compute.googleapis.com/instance/disk/write_bytes_count\" AND resource.type=\"gce_instance\"` aligner1 := "ALIGN_RATE" + severity1 := "WARNING" filter2 := `metric.type=\"compute.googleapis.com/instance/cpu/utilization\" AND resource.type=\"gce_instance\"` aligner2 := "ALIGN_MAX" + severity2 := "ERROR" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -74,7 +76,7 @@ func testAccMonitoringAlertPolicy_update(t *testing.T) { CheckDestroy: testAccCheckAlertPolicyDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner1, filter1), + Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner1, filter1, severity1), }, { ResourceName: "google_monitoring_alert_policy.basic", @@ -82,7 +84,7 @@ func testAccMonitoringAlertPolicy_update(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner2, filter2), + Config: testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner2, filter2, severity2), }, { ResourceName: "google_monitoring_alert_policy.basic", @@ -233,7 +235,7 @@ func testAccMonitoringAlertPolicy_promql(t *testing.T) { }) } -func testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner, filter string) string { +func testAccMonitoringAlertPolicy_basicCfg(alertName, conditionName, aligner, filter, severity string) string { return fmt.Sprintf(` resource "google_monitoring_alert_policy" "basic" { display_name = "%s" @@ -255,8 +257,10 @@ resource "google_monitoring_alert_policy" "basic" { threshold_value = "0.5" } } + + severity = "%s" } -`, alertName, conditionName, aligner, filter) +`, alertName, conditionName, aligner, filter, severity) } func testAccMonitoringAlertPolicy_fullCfg(alertName, conditionName1, conditionName2 string) string { @@ -319,6 +323,8 @@ resource "google_monitoring_alert_policy" "full" { } } + severity = "WARNING" + documentation { content = "test content" mime_type = "text/markdown" @@ -348,6 +354,8 @@ resource "google_monitoring_alert_policy" "mql" { } } + severity = "WARNING" + documentation { content = "test content" mime_type = "text/markdown" @@ -382,6 +390,8 @@ resource "google_monitoring_alert_policy" "log" { auto_close = "2000s" } + severity = "WARNING" + documentation { content = "test content" mime_type = "text/markdown" @@ -441,6 +451,8 @@ resource "google_monitoring_alert_policy" "promql" { } } + severity = "WARNING" + documentation { content = "test content" mime_type = "text/markdown" From 135dfa3e51199e0bb43be5e9e782c2edfd4f88fd Mon Sep 17 00:00:00 2001 From: Edward Sun <42220489+edwardmedia@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:42:16 -0800 Subject: [PATCH 100/107] taint writer_identity (#9561) * taint writer_identity * update error handling --------- Co-authored-by: Edward Sun --- .../logging/resource_logging_project_sink.go | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go index 86f28c26d76f..9a2ecf70d7d6 100644 --- a/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go +++ b/mmv1/third_party/terraform/services/logging/resource_logging_project_sink.go @@ -94,10 +94,19 @@ func resourceLoggingProjectSinkAcquireOrCreate(d *schema.ResourceData, meta inte return resourceLoggingProjectSinkUpdate(d, meta) } -// if bigquery_options is set unique_writer_identity must be true +// 1) if bigquery_options is set unique_writer_identity must be true +// 2) taint the value of writer_identity when unique_writer_identity is updating from false -> true func resourceLoggingProjectSinkCustomizeDiff(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error { // separate func to allow unit testing - return resourceLoggingProjectSinkCustomizeDiffFunc(d) + err := resourceLoggingProjectSinkCustomizeDiffFunc(d) + if err != nil { + return err + } + err = resourceLoggingProjectSinkUniqueWriterIdentityCustomizeDiffFunc(d) + if err != nil { + return err + } + return nil } func resourceLoggingProjectSinkCustomizeDiffFunc(diff tpgresource.TerraformResourceDiff) error { @@ -115,6 +124,20 @@ func resourceLoggingProjectSinkCustomizeDiffFunc(diff tpgresource.TerraformResou return nil } +func resourceLoggingProjectSinkUniqueWriterIdentityCustomizeDiffFunc(diff *schema.ResourceDiff) error { + if !diff.HasChange("unique_writer_identity") { + return nil + } + // taint the value of writer_identity when unique_writer_identity is updating from false -> true + if diff.Get("unique_writer_identity").(bool) { + err := diff.SetNewComputed("writer_identity") + if err != nil { + return fmt.Errorf("Error re-setting writer_identity: %s", err) + } + } + return nil +} + func resourceLoggingProjectSinkRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) From 0124464a2158773138682030d38e0a454c998238 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Mon, 11 Dec 2023 23:56:51 +0000 Subject: [PATCH 101/107] Update Cloud Run v2 tests to make service account with sweepable name (#9620) --- .../data_source_google_cloud_run_v2_job_test.go | 14 ++++++-------- ...data_source_google_cloud_run_v2_service_test.go | 14 ++++++-------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_job_test.go b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_job_test.go index 5e2044eb37f1..482e4a196d18 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_job_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_job_test.go @@ -75,7 +75,7 @@ func TestAccDataSourceGoogleCloudRunV2Job_bindIAMPermission(t *testing.T) { project := envvar.GetTestProjectFromEnv() - name := fmt.Sprintf("tf-test-cloud-run-v2-job-%d", acctest.RandInt(t)) + name := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) location := "us-central1" id := fmt.Sprintf("projects/%s/locations/%s/jobs/%s", project, location, name) @@ -122,18 +122,16 @@ data "google_cloud_run_v2_job" "hello" { } resource "google_service_account" "foo" { - account_id = "foo-service-account" - display_name = "foo-service-account" + account_id = "%s" + display_name = "Service account for google_cloud_run_v2_job data source acceptance test " } -resource "google_cloud_run_v2_job_iam_binding" "foo_run_invoker" { +resource "google_cloud_run_v2_job_iam_member" "foo_run_invoker" { name = data.google_cloud_run_v2_job.hello.name location = data.google_cloud_run_v2_job.hello.location role = "roles/run.invoker" - members = [ - "serviceAccount:${google_service_account.foo.email}", - ] + member = "serviceAccount:${google_service_account.foo.email}" } -`, name, location) +`, name, location, name) } diff --git a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go index 7f7a4d5129c9..64de401e1e0e 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/data_source_google_cloud_run_v2_service_test.go @@ -68,7 +68,7 @@ func TestAccDataSourceGoogleCloudRunV2Service_bindIAMPermission(t *testing.T) { project := envvar.GetTestProjectFromEnv() - name := fmt.Sprintf("tf-test-cloud-run-v2-service-%d", acctest.RandInt(t)) + name := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) location := "us-central1" id := fmt.Sprintf("projects/%s/locations/%s/services/%s", project, location, name) @@ -108,18 +108,16 @@ data "google_cloud_run_v2_service" "hello" { } resource "google_service_account" "foo" { - account_id = "foo-service-account" - display_name = "foo-service-account" + account_id = "%s" + display_name = "Service account for google_cloud_run_v2_service data source acceptance test " } -resource "google_cloud_run_v2_service_iam_binding" "foo_run_invoker" { +resource "google_cloud_run_v2_service_iam_member" "foo_run_invoker" { name = data.google_cloud_run_v2_service.hello.name location = data.google_cloud_run_v2_service.hello.location role = "roles/run.invoker" - members = [ - "serviceAccount:${google_service_account.foo.email}", - ] + member = "serviceAccount:${google_service_account.foo.email}" } -`, name, location) +`, name, location, name) } From e87ca382d9e0e077426c1061920f1c69c63f3eee Mon Sep 17 00:00:00 2001 From: Swamita Gupta <55314843+swamitagupta@users.noreply.github.com> Date: Tue, 12 Dec 2023 22:09:52 +0530 Subject: [PATCH 102/107] Add type field to PrivateCloud in Vmwareengine (#9608) --- mmv1/products/vmwareengine/PrivateCloud.yaml | 13 ++++++++++++- .../vmware_engine_private_cloud_full.tf.erb | 6 ++++-- .../resource_vmwareengine_private_cloud_test.go | 4 +++- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/mmv1/products/vmwareengine/PrivateCloud.yaml b/mmv1/products/vmwareengine/PrivateCloud.yaml index 662dbe755cdb..33eac4d383f4 100644 --- a/mmv1/products/vmwareengine/PrivateCloud.yaml +++ b/mmv1/products/vmwareengine/PrivateCloud.yaml @@ -20,7 +20,7 @@ create_url: 'projects/{{project}}/locations/{{location}}/privateClouds?privateCl update_verb: :PATCH references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/vmware-engine/docs/reference/rest/v1/projects.locations.privateClouds' -description: / Represents a private cloud resource. Private clouds are zonal resources. +description: Represents a private cloud resource. Private clouds are zonal resources. error_abort_predicates: ['transport_tpg.Is429QuotaError'] async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation @@ -285,3 +285,14 @@ properties: name: 'fqdn' description: |- Fully qualified domain name of the appliance. + + - !ruby/object:Api::Type::Enum + name: 'type' + description: | + Initial type of the private cloud. + immutable: true + ignore_read: true + values: + - :STANDARD + - :TIME_LIMITED + default_value: :STANDARD diff --git a/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb b/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb index d246a3576538..ee12d6bfdd24 100644 --- a/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb +++ b/mmv1/templates/terraform/examples/vmware_engine_private_cloud_full.tf.erb @@ -2,6 +2,7 @@ resource "google_vmwareengine_private_cloud" "<%= ctx[:primary_resource_id] %>" location = "<%= ctx[:test_env_vars]['region'] %>-a" name = "<%= ctx[:vars]['private_cloud_id'] %>" description = "Sample test PC." + type = "TIME_LIMITED" network_config { management_cidr = "192.168.30.0/24" vmware_engine_network = google_vmwareengine_network.pc-nw.id @@ -11,7 +12,7 @@ resource "google_vmwareengine_private_cloud" "<%= ctx[:primary_resource_id] %>" cluster_id = "<%= ctx[:vars]['management_cluster_id'] %>" node_type_configs { node_type_id = "standard-72" - node_count = 3 + node_count = 1 custom_core_count = 32 } } @@ -21,4 +22,5 @@ resource "google_vmwareengine_network" "pc-nw" { name = "<%= ctx[:vars]['network_id'] %>" location = "global" type = "STANDARD" - description = "PC network description." \ No newline at end of file + description = "PC network description." +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go index 05195787f1a2..b486ff495db4 100644 --- a/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go +++ b/mmv1/third_party/terraform/services/vmwareengine/resource_vmwareengine_private_cloud_test.go @@ -27,7 +27,7 @@ func TestAccVmwareenginePrivateCloud_vmwareEnginePrivateCloudUpdate(t *testing.T CheckDestroy: testAccCheckVmwareenginePrivateCloudDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testPrivateCloudUpdateConfig(context, "description1", 3), + Config: testPrivateCloudUpdateConfig(context, "description1", 1), Check: resource.ComposeTestCheckFunc( acctest.CheckDataSourceStateMatchesResourceStateWithIgnores("data.google_vmwareengine_private_cloud.ds", "google_vmwareengine_private_cloud.vmw-engine-pc", map[string]struct{}{}), testAccCheckGoogleVmwareengineNsxCredentialsMeta("data.google_vmwareengine_nsx_credentials.nsx-ds"), @@ -78,6 +78,7 @@ resource "google_vmwareengine_private_cloud" "vmw-engine-pc" { location = "%{region}-a" name = "tf-test-sample-pc%{random_suffix}" description = "%{description}" + type = "TIME_LIMITED" network_config { management_cidr = "192.168.30.0/24" vmware_engine_network = google_vmwareengine_network.default-nw.id @@ -104,6 +105,7 @@ data "google_vmwareengine_private_cloud" "ds" { data "google_vmwareengine_nsx_credentials" "nsx-ds" { parent = google_vmwareengine_private_cloud.vmw-engine-pc.id } + data "google_vmwareengine_vcenter_credentials" "vcenter-ds" { parent = google_vmwareengine_private_cloud.vmw-engine-pc.id } From b4195a644bc0aaba2197195d3b8d472969c6a469 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:58:23 +0000 Subject: [PATCH 103/107] Remove use of `google_kms_crypto_key_iam_binding` resource in tests, to make tests stable in overnight testing (#9621) * Remove `google_kms_crypto_key_iam_binding` resources that affect shared crypto keys * Remove unnecessary use of `google_kms_crypto_key_iam_binding` (no shared crypto key affected) By removing this usage of `google_kms_crypto_key_iam_binding` I intend to make it easier to identify when acc tests affect shared resources that aren't provisioned by the test * Remove unnecessary use of `google_kms_crypto_key_iam_binding` (no shared crypto key affected) * Fix call to config function in acc test * Update mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb * Skip `TestAccCloudFunctionsFunction_cmek` in VCR --- ...secure_source_manager_instance_cmek.tf.erb | 6 ++-- ...source_cloudfunctions_function_test.go.erb | 31 ++++++++++++++----- .../resource_compute_instance_test.go.erb | 8 ++--- .../resource_spanner_database_test.go.erb | 8 ++--- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb b/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb index abde1100aaa7..c7fd6f9312d3 100644 --- a/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb +++ b/mmv1/templates/terraform/examples/secure_source_manager_instance_cmek.tf.erb @@ -8,13 +8,11 @@ resource "google_kms_crypto_key" "crypto_key" { key_ring = google_kms_key_ring.key_ring.id } -resource "google_kms_crypto_key_iam_binding" "crypto_key_binding" { +resource "google_kms_crypto_key_iam_member" "crypto_key_binding" { crypto_key_id = google_kms_crypto_key.crypto_key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com" - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-sourcemanager.iam.gserviceaccount.com" } resource "google_secure_source_manager_instance" "<%= ctx[:primary_resource_id] %>" { diff --git a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb index 9bf727547801..0c2be3a3a1a3 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function_test.go.erb @@ -295,7 +295,9 @@ func TestAccCloudFunctionsFunction_dockerRepository(t *testing.T) { <% unless version == "ga" -%> func TestAccCloudFunctionsFunction_cmek(t *testing.T) { + acctest.SkipIfVcr(t) t.Parallel() + kmsKey := acctest.BootstrapKMSKeyInLocation(t, "us-central1") funcResourceName := "google_cloudfunctions_function.function" arRepoName := fmt.Sprintf("tf-cmek-test-docker-repository-%s", acctest.RandString(t, 10)) @@ -1078,24 +1080,37 @@ resource "google_artifact_registry_repository_iam_binding" "binding" { ] } -resource "google_kms_crypto_key_iam_binding" "gcf_cmek_keyuser" { +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_1" { crypto_key_id = "%s" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com", - "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com", - ] + member = "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com" } +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_2" { + crypto_key_id = "%s" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com" +} + +resource "google_kms_crypto_key_iam_member" "gcf_cmek_keyuser_3" { + crypto_key_id = "%s" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + member = "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com" +} + + resource "google_artifact_registry_repository" "encoded-ar-repo" { repository_id = "%s" kms_key_name = "%s" location = "us-central1" format = "DOCKER" depends_on = [ - google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_1, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_2, + google_kms_crypto_key_iam_member.gcf_cmek_keyuser_3, ] } @@ -1123,7 +1138,7 @@ resource "google_cloudfunctions_function" "function" { timeout = 61 entry_point = "helloGET" } -`, kmsKey, arRepoName, kmsKey, bucketName, zipFilePath, functionName, kmsKey) +`, kmsKey, kmsKey, kmsKey, arRepoName, kmsKey, bucketName, zipFilePath, functionName, kmsKey) } <% end -%> diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb index 6d747946cef6..f52854d8a441 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_test.go.erb @@ -6905,12 +6905,10 @@ data "google_compute_image" "my_image" { data "google_project" "project" {} -resource "google_kms_crypto_key_iam_binding" "crypto_key" { +resource "google_kms_crypto_key_iam_member" "crypto_key" { crypto_key_id = "%{key_name}" role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com", - ] + member = "serviceAccount:${data.google_project.project.number}-compute@developer.gserviceaccount.com" } resource "google_compute_instance" "foobar" { @@ -6932,7 +6930,7 @@ resource "google_compute_instance" "foobar" { network_interface { network = "default" } - depends_on = [google_kms_crypto_key_iam_binding.crypto_key] + depends_on = [google_kms_crypto_key_iam_member.crypto_key] } `, context) diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb index 5488cdf31c35..3eb94e373be8 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_database_test.go.erb @@ -642,7 +642,7 @@ resource "google_spanner_database" "database" { deletion_protection = false - depends_on = [google_kms_crypto_key_iam_binding.crypto-key-binding] + depends_on = [google_kms_crypto_key_iam_member.crypto-key-binding] } resource "google_kms_key_ring" "keyring" { @@ -658,14 +658,12 @@ resource "google_kms_crypto_key" "example-key" { rotation_period = "100000s" } -resource "google_kms_crypto_key_iam_binding" "crypto-key-binding" { +resource "google_kms_crypto_key_iam_member" "crypto-key-binding" { provider = google-beta crypto_key_id = google_kms_crypto_key.example-key.id role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" - members = [ - "serviceAccount:${google_project_service_identity.ck_sa.email}", - ] + member = "serviceAccount:${google_project_service_identity.ck_sa.email}" } data "google_project" "project" { From 414d6bee6501a5d143222e5412dcfef100e9cd61 Mon Sep 17 00:00:00 2001 From: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Date: Tue, 12 Dec 2023 22:54:59 +0530 Subject: [PATCH 104/107] Label support for Google Managed Notebooks (#9625) --- mmv1/products/notebooks/Runtime.yaml | 9 +++++++++ .../terraform/examples/notebook_runtime_kernels.tf.erb | 3 +++ .../terraform/examples/notebook_runtime_script.tf.erb | 3 +++ 3 files changed, 15 insertions(+) diff --git a/mmv1/products/notebooks/Runtime.yaml b/mmv1/products/notebooks/Runtime.yaml index 721822b3e8e1..7657f51a0c95 100644 --- a/mmv1/products/notebooks/Runtime.yaml +++ b/mmv1/products/notebooks/Runtime.yaml @@ -569,3 +569,12 @@ properties: sessions stats. output: true output: true + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' + description: | + The labels to associate with this runtime. Label **keys** must + contain 1 to 63 characters, and must conform to [RFC 1035] + (https://www.ietf.org/rfc/rfc1035.txt). Label **values** may be + empty, but, if present, must contain 1 to 63 characters, and must + conform to [RFC 1035](https://www.ietf.org/rfc/rfc1035.txt). No + more than 32 labels can be associated with a cluster. diff --git a/mmv1/templates/terraform/examples/notebook_runtime_kernels.tf.erb b/mmv1/templates/terraform/examples/notebook_runtime_kernels.tf.erb index d97313a6bbff..1db5a97fe1b8 100644 --- a/mmv1/templates/terraform/examples/notebook_runtime_kernels.tf.erb +++ b/mmv1/templates/terraform/examples/notebook_runtime_kernels.tf.erb @@ -22,4 +22,7 @@ resource "google_notebooks_runtime" "<%= ctx[:primary_resource_id] %>" { } } } + labels = { + k = "val" + } } diff --git a/mmv1/templates/terraform/examples/notebook_runtime_script.tf.erb b/mmv1/templates/terraform/examples/notebook_runtime_script.tf.erb index d9320d924dbd..5dcb7e218896 100644 --- a/mmv1/templates/terraform/examples/notebook_runtime_script.tf.erb +++ b/mmv1/templates/terraform/examples/notebook_runtime_script.tf.erb @@ -19,4 +19,7 @@ resource "google_notebooks_runtime" "<%= ctx[:primary_resource_id] %>" { } } } + labels = { + k = "val" + } } From 1d1d8ed2a19c751c8fc14ef6e36b9bee54906568 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 12 Dec 2023 18:57:36 +0000 Subject: [PATCH 105/107] Add missing `depends_on` meta arguments to acceptance test config (#9623) --- .../resource_compute_instance_template_test.go.erb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb index 01b6f1c19767..b7ce7bb72af7 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template_test.go.erb @@ -3592,6 +3592,10 @@ resource "google_compute_snapshot" "snapshot" { kms_key_self_link = data.google_kms_crypto_key.key.id kms_key_service_account = google_service_account.test.email } + + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key + ] } resource "google_compute_instance_template" "template" { @@ -3611,6 +3615,10 @@ resource "google_compute_instance_template" "template" { network_interface { network = "default" } + + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key + ] } `, context) } @@ -3674,6 +3682,10 @@ resource "google_compute_instance_template" "template" { network_interface { network = "default" } + + depends_on = [ + google_kms_crypto_key_iam_member.crypto_key + ] } `, context) } From 6afde3f9effd7c1c7298108a856395f220421201 Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Wed, 13 Dec 2023 00:58:29 +0530 Subject: [PATCH 106/107] feat(spanner): support defining autoscaling limit as nodes (#9606) --- mmv1/products/spanner/Instance.yaml | 32 +++++- .../encoders/spanner_instance_update.go.erb | 6 ++ .../spanner_instance_with_autoscaling.tf.erb | 7 +- .../spanner/resource_spanner_instance_test.go | 101 ++++++++++++++++++ 4 files changed, 143 insertions(+), 3 deletions(-) diff --git a/mmv1/products/spanner/Instance.yaml b/mmv1/products/spanner/Instance.yaml index 0a353ee85dd8..251e3ee20d17 100644 --- a/mmv1/products/spanner/Instance.yaml +++ b/mmv1/products/spanner/Instance.yaml @@ -180,19 +180,49 @@ properties: name: 'autoscalingLimits' description: | Defines scale in controls to reduce the risk of response latency - and outages due to abrupt scale-in events + and outages due to abrupt scale-in events. Users can define the minimum and + maximum compute capacity allocated to the instance, and the autoscaler will + only scale within that range. Users can either use nodes or processing + units to specify the limits, but should use the same unit to set both the + min_limit and max_limit. properties: - !ruby/object:Api::Type::Integer name: 'minProcessingUnits' description: | Specifies minimum number of processing units allocated to the instance. If set, this number should be multiples of 1000. + exactly_one_of: + - min_processing_units + - min_nodes - !ruby/object:Api::Type::Integer name: 'maxProcessingUnits' description: | Specifies maximum number of processing units allocated to the instance. If set, this number should be multiples of 1000 and be greater than or equal to min_processing_units. + exactly_one_of: + - max_processing_units + - max_nodes + - !ruby/object:Api::Type::Integer + name: 'minNodes' + description: | + Specifies number of nodes allocated to the instance. If set, this number + should be greater than or equal to 1. + exactly_one_of: + - min_processing_units + - min_nodes + required_with: + - max_nodes + - !ruby/object:Api::Type::Integer + name: 'maxNodes' + description: | + Specifies maximum number of nodes allocated to the instance. If set, this number + should be greater than or equal to min_nodes. + exactly_one_of: + - max_processing_units + - max_nodes + required_with: + - min_nodes - !ruby/object:Api::Type::NestedObject name: 'autoscalingTargets' description: | diff --git a/mmv1/templates/terraform/encoders/spanner_instance_update.go.erb b/mmv1/templates/terraform/encoders/spanner_instance_update.go.erb index 6c9cc875a3b9..bb917b112ad1 100644 --- a/mmv1/templates/terraform/encoders/spanner_instance_update.go.erb +++ b/mmv1/templates/terraform/encoders/spanner_instance_update.go.erb @@ -24,6 +24,12 @@ if d.HasChange("autoscaling_config.0.autoscaling_limits.0.max_processing_units") if d.HasChange("autoscaling_config.0.autoscaling_limits.0.min_processing_units") { updateMask = append(updateMask, "autoscalingConfig.autoscalingLimits.minProcessingUnits") } +if d.HasChange("autoscaling_config.0.autoscaling_limits.0.max_nodes") { + updateMask = append(updateMask, "autoscalingConfig.autoscalingLimits.maxNodes") +} +if d.HasChange("autoscaling_config.0.autoscaling_limits.0.min_nodes") { + updateMask = append(updateMask, "autoscalingConfig.autoscalingLimits.minNodes") +} if d.HasChange("autoscaling_config.0.autoscaling_targets.0.high_priority_cpu_utilization_percent") { updateMask = append(updateMask, "autoscalingConfig.autoscalingTargets.highPriorityCpuUtilizationPercent") } diff --git a/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb b/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb index 3830a71a70d8..aa541cff768d 100644 --- a/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb +++ b/mmv1/templates/terraform/examples/spanner_instance_with_autoscaling.tf.erb @@ -3,8 +3,11 @@ resource "google_spanner_instance" "example" { display_name = "Test Spanner Instance" autoscaling_config { autoscaling_limits { - max_processing_units = 3000 - min_processing_units = 2000 + // Define the minimum and maximum compute capacity allocated to the instance + // Either use nodes or processing units to specify the limits, + // but should use the same unit to set both the min_limit and max_limit. + max_processing_units = 3000 // OR max_nodes = 3 + min_processing_units = 2000 // OR min_nodes = 2 } autoscaling_targets { high_priority_cpu_utilization_percent = 75 diff --git a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go index 07d2e067bd19..562721abe6c7 100644 --- a/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go +++ b/mmv1/third_party/terraform/services/spanner/resource_spanner_instance_test.go @@ -203,6 +203,67 @@ func TestAccSpannerInstance_basicWithAutoscalingUsingProcessingUnitConfigUpdate( }) } +func TestAccSpannerInstance_basicWithAutoscalingUsingNodeConfig(t *testing.T) { + t.Parallel() + + displayName := fmt.Sprintf("spanner-test-%s-dname", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSpannerInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigs(displayName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "state"), + ), + }, + { + ResourceName: "google_spanner_instance.basic", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSpannerInstance_basicWithAutoscalingUsingNodeConfigUpdate(t *testing.T) { + t.Parallel() + + displayName := fmt.Sprintf("spanner-test-%s-dname", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckSpannerInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigsUpdate(displayName, 1, 2, 65, 95), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "state"), + ), + }, + { + ResourceName: "google_spanner_instance.basic", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigsUpdate(displayName, 2, 3, 75, 90), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "state"), + ), + }, + { + ResourceName: "google_spanner_instance.basic", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + func testAccSpannerInstance_basic(name string) string { return fmt.Sprintf(` resource "google_spanner_instance" "basic" { @@ -304,3 +365,43 @@ resource "google_spanner_instance" "basic" { } `, name, name, maxProcessingUnits, minProcessingUnits, cupUtilizationPercent, storageUtilizationPercent) } + +func testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigs(name string) string { + return fmt.Sprintf(` +resource "google_spanner_instance" "basic" { + name = "%s" + config = "regional-us-central1" + display_name = "%s" + autoscaling_config { + autoscaling_limits { + max_nodes = 2 + min_nodes = 1 + } + autoscaling_targets { + high_priority_cpu_utilization_percent = 65 + storage_utilization_percent = 95 + } + } +} +`, name, name) +} + +func testAccSpannerInstance_basicWithAutoscalerConfigUsingNodesAsConfigsUpdate(name string, minNodes, maxNodes, cupUtilizationPercent, storageUtilizationPercent int) string { + return fmt.Sprintf(` +resource "google_spanner_instance" "basic" { + name = "%s" + config = "regional-us-central1" + display_name = "%s" + autoscaling_config { + autoscaling_limits { + max_nodes = %v + min_nodes = %v + } + autoscaling_targets { + high_priority_cpu_utilization_percent = %v + storage_utilization_percent = %v + } + } +} +`, name, name, maxNodes, minNodes, cupUtilizationPercent, storageUtilizationPercent) +} From de7d39b50c5d9894e25770a457eb9ab2c2f96eaf Mon Sep 17 00:00:00 2001 From: sahsagar-google <126025352+sahsagar-google@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:45:21 -0800 Subject: [PATCH 107/107] The version field should be under configmanagement instead of under oci (#9587) * Adding Terraform resources for Tenancy APIs in GKEHub * Segregating MembershipBinding and MembershipRBACRoleBinding to keep things simpler in the review * Fixing the docu URIs * Adding TF support for Tenancy API for Membership Binding * Adding dependent membership binding to the same commit chain * Making Scope un-updatable and replacing hard coded project number with the one from test env * Making Scope RRBAC updatable * Making Namespace immutable * Adding update test cases * Removing all memberships field from Scope since it is no longer supported * Removing all_memberships field for Scope from all test cases * Making naming in examples consistent across Tenancy APIs documentation * Update mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Update mmv1/templates/terraform/examples/gkehub_membership_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Update mmv1/templates/terraform/examples/gkehub_membership_rbac_role_binding_basic.tf.erb Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Fixing typo in the resource name * Adding state migrations for Membership * Updating the feature_membership documentation with the current resource state. Adding membership_location field to the doc * Fixing the version field to be directly under configmanagement instead of under the oci field * Adding tests for the field version * Changing version fields value to test upgradation --------- Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> --- mmv1/products/gkehub2/Feature.yaml | 6 +++--- .../services/gkehub2/resource_gke_hub_feature_test.go.erb | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mmv1/products/gkehub2/Feature.yaml b/mmv1/products/gkehub2/Feature.yaml index 67be3b1efc02..b3968b337586 100644 --- a/mmv1/products/gkehub2/Feature.yaml +++ b/mmv1/products/gkehub2/Feature.yaml @@ -215,6 +215,9 @@ properties: name: configmanagement description: Config Management spec properties: + - !ruby/object:Api::Type::String + name: version + description: 'Version of ACM installed' - !ruby/object:Api::Type::NestedObject name: configSync description: 'ConfigSync configuration for the cluster' @@ -271,9 +274,6 @@ properties: - !ruby/object:Api::Type::String name: syncWaitSecs description: 'Period in seconds between consecutive syncs. Default: 15' - - !ruby/object:Api::Type::String - name: version - description: 'Version of ACM installed' - !ruby/object:Api::Type::NestedObject name: policycontroller description: Policy Controller spec diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb index f2c14b2d223f..5af1d572cfd7 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_feature_test.go.erb @@ -460,6 +460,7 @@ resource "google_gke_hub_feature" "feature" { location = "global" fleet_default_member_config { configmanagement { + version = "1.16.0" config_sync { source_format = "hierarchy" git { @@ -486,6 +487,7 @@ resource "google_gke_hub_feature" "feature" { location = "global" fleet_default_member_config { configmanagement { + version = "1.16.1" config_sync { source_format = "unstructured" oci {