From 02e719917fd193513b3e580493a2df4e051cafc9 Mon Sep 17 00:00:00 2001 From: Deepak Kumar <21131061+kumadee@users.noreply.github.com> Date: Tue, 20 Feb 2024 20:53:34 +0100 Subject: [PATCH 001/200] fixes: permadiff issue if event trigger region is not specified (#9989) * fixes: permadiff issue if event trigger region is not specified - fixes https://github.com/hashicorp/terraform-provider-google/issues/17161 * chore: Updated cloudfunction2 test with no explicit trigger_region --- mmv1/products/cloudfunctions2/Function.yaml | 1 + .../terraform/examples/cloudfunctions2_basic_gcs.tf.erb | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index a094196586fc..71fd0ef07e87 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -594,6 +594,7 @@ properties: events originating in this region. It can be the same region as the function, a different region or multi-region, or the global region. If not provided, defaults to the same region as the function. + default_from_api: true - !ruby/object:Api::Type::String name: 'eventType' description: 'Required. The type of event to observe.' diff --git a/mmv1/templates/terraform/examples/cloudfunctions2_basic_gcs.tf.erb b/mmv1/templates/terraform/examples/cloudfunctions2_basic_gcs.tf.erb index 8dd602fc4c5f..00a11528241d 100644 --- a/mmv1/templates/terraform/examples/cloudfunctions2_basic_gcs.tf.erb +++ b/mmv1/templates/terraform/examples/cloudfunctions2_basic_gcs.tf.erb @@ -91,7 +91,6 @@ resource "google_cloudfunctions2_function" "<%= ctx[:primary_resource_id] %>" { } event_trigger { - trigger_region = "us-central1" # The trigger must be in the same location as the bucket event_type = "google.cloud.storage.object.v1.finalized" retry_policy = "RETRY_POLICY_RETRY" service_account_email = google_service_account.account.email From f25a214012dc398a6c1a07531a7ae85e049aa538 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Tue, 20 Feb 2024 15:38:56 -0800 Subject: [PATCH 002/200] Fix GKE front matter, bad field docs (#10018) * Fix GKE front matter, bad field docs * Update container_cluster.html.markdown --- .../docs/r/container_cluster.html.markdown | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) 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 46fafb9df471..b7713ba6d51c 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 @@ -6,22 +6,21 @@ description: |- # google\_container\_cluster --> Visit the [Provision a GKE Cluster (Google Cloud)](https://learn.hashicorp.com/tutorials/terraform/gke?in=terraform/kubernetes&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) Learn tutorial to learn how to provision and interact -with a GKE cluster. +Manages a Google Kubernetes Engine (GKE) cluster. --> See the [Using GKE with Terraform](/docs/providers/google/guides/using_gke_with_terraform.html) -guide for more information about using GKE with Terraform. +To get more information about GKE clusters, see: + * [The API reference](https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1beta1/projects.locations.clusters) + * How-to guides + * [GKE overview](https://cloud.google.com/kubernetes-engine/docs/concepts/kubernetes-engine-overview) + * [About cluster configuration choices](https://cloud.google.com/kubernetes-engine/docs/concepts/types-of-clusters) + * Terraform guidance + * [Using GKE with Terraform](/docs/providers/google/guides/using_gke_with_terraform.html) + * [Provision a GKE Cluster (Google Cloud) Learn tutorial](https://learn.hashicorp.com/tutorials/terraform/gke?in=terraform/kubernetes&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) -Manages a Google Kubernetes Engine (GKE) cluster. For more information see -[the official documentation](https://cloud.google.com/container-engine/docs/clusters) -and [the API reference](https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1beta1/projects.locations.clusters). +-> On version 5.0.0+ of the provider, you must explicitly set `deletion_protection = false` +and run `terraform apply` to write the field to state in order to destroy a cluster. --> **Note**: On version 5.0.0+ of the provider, you must explicitly set `deletion_protection=false` -(and run `terraform apply` to write the field to state) in order to destroy a cluster. -It is recommended to not set this field (or set it to true) until you're ready to destroy. - -~> **Warning:** All arguments and attributes, including basic auth username and -passwords as well as certificate outputs will be stored in the raw state as +~> All arguments and attributes (including certificate outputs) will be stored in the raw state as plaintext. [Read more about sensitive data in state](https://www.terraform.io/language/state/sensitive-data). ## Example Usage - with a separately managed node pool (recommended) @@ -1111,6 +1110,8 @@ subnet. See [Private Cluster Limitations](https://cloud.google.com/kubernetes-en for more details. This field only applies to private clusters, when `enable_private_nodes` is `true`. +* `private_endpoint_subnetwork` - (Optional) Subnetwork in cluster's network where master's endpoint will be provisioned. + * `master_global_access_config` (Optional) - Controls cluster master global access settings. If unset, Terraform will no longer manage this field and will not modify the previously-set value. Structure is [documented below](#nested_master_global_access_config). @@ -1121,8 +1122,6 @@ In addition, the `private_cluster_config` allows access to the following read-on * `private_endpoint` - The internal IP address of this cluster's master endpoint. -* `private_endpoint_subnetwork` - Subnetwork in cluster's network where master's endpoint will be provisioned. - * `public_endpoint` - The external IP address of this cluster's master endpoint. !> The Google provider is unable to validate certain configurations of From 3e85823b9bda72a1910ef6eabdf0b64ca6211de5 Mon Sep 17 00:00:00 2001 From: Max Portocarrero CI&T <105444618+maxi-cit@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:21:15 -0500 Subject: [PATCH 003/200] added default value for minPortsPerVM field at "google_compute_router_nat" (#9712) * added default value for statis allocation * setting the default from API --- mmv1/products/compute/RouterNat.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mmv1/products/compute/RouterNat.yaml b/mmv1/products/compute/RouterNat.yaml index 9b0d414391a1..fef5eb3398c2 100644 --- a/mmv1/products/compute/RouterNat.yaml +++ b/mmv1/products/compute/RouterNat.yaml @@ -236,7 +236,8 @@ properties: - !ruby/object:Api::Type::Integer name: minPortsPerVm description: | - Minimum number of ports allocated to a VM from this NAT. + Minimum number of ports allocated to a VM from this NAT. Defaults to 64 for static port allocation and 32 dynamic port allocation if not set. + default_from_api: true - !ruby/object:Api::Type::Integer name: maxPortsPerVm description: | From 7369959626ffc0ecea935a3210fdf46a90517bfb Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Wed, 21 Feb 2024 08:34:41 -0800 Subject: [PATCH 004/200] add newline removal bash command in guidelines (#9734) --- .../terraform/website/docs/guides/getting_started.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/website/docs/guides/getting_started.html.markdown b/mmv1/third_party/terraform/website/docs/guides/getting_started.html.markdown index 4559a54f224a..a329a71258e7 100644 --- a/mmv1/third_party/terraform/website/docs/guides/getting_started.html.markdown +++ b/mmv1/third_party/terraform/website/docs/guides/getting_started.html.markdown @@ -182,7 +182,7 @@ quota or billing issues which don't seem to apply to you, you may want to set ### Using Terraform Cloud as the Backend You need to use a different [environment variable](https://www.terraform.io/docs/cloud/workspaces/variables.html) name to store your credentials in Terraform Cloud. 1. Create an environment variable called `GOOGLE_CREDENTIALS` in your Terraform Cloud workspace. -2. Remove the newline characters from your JSON key file and then paste the credentials into the environment variable value field. +2. Remove the newline characters from your JSON key file and then paste the credentials into the environment variable value field. (Running `cat CREDENTIALS.json | tr -s '\n' ' '` will remove newline characters from your JSON key file) 3. Mark the variable as **Sensitive** and click **Save variable**. All runs within the workspace will use the `GOOGLE_CREDENTIALS` variable to authenticate with Google Cloud Platform. From 6675072e699fd4f3f445d83ae3469d091116c224 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:55:56 +0000 Subject: [PATCH 005/200] Update hashicorp/terraform-plugin-framework, hashicorp/terraform-plugin-mux, hashicorp/terraform-plugin-sdk/v2 (#10009) --- mmv1/third_party/terraform/go.mod.erb | 40 ++--- mmv1/third_party/terraform/go.sum | 202 ++++++++++---------------- 2 files changed, 100 insertions(+), 142 deletions(-) diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index b75cb3b55059..0d5943fb44fc 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -1,5 +1,6 @@ <% autogen_exception -%> module github.com/hashicorp/terraform-provider-google + go 1.20 require ( @@ -15,12 +16,12 @@ require ( github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-version v1.6.0 - github.com/hashicorp/terraform-plugin-framework v1.1.1 + github.com/hashicorp/terraform-plugin-framework v1.5.0 github.com/hashicorp/terraform-plugin-framework-validators v0.9.0 - github.com/hashicorp/terraform-plugin-go v0.14.3 - github.com/hashicorp/terraform-plugin-log v0.7.0 - github.com/hashicorp/terraform-plugin-mux v0.8.0 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 + github.com/hashicorp/terraform-plugin-go v0.20.0 + github.com/hashicorp/terraform-plugin-log v0.9.0 + github.com/hashicorp/terraform-plugin-mux v0.13.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/hashstructure v1.1.0 github.com/sirupsen/logrus v1.8.1 @@ -39,11 +40,13 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.5 // indirect cloud.google.com/go/longrunning v0.5.4 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/agext/levenshtein v1.2.2 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/apparentlymart/go-textseg/v15 v15.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/cloudflare/circl v1.3.3 // 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/envoyproxy/go-control-plane v0.11.1 // indirect @@ -63,17 +66,17 @@ require ( 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 - github.com/hashicorp/go-plugin v1.4.8 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-plugin v1.6.0 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/hc-install v0.4.0 // indirect - github.com/hashicorp/hcl/v2 v2.14.1 // indirect + github.com/hashicorp/hc-install v0.6.2 // indirect + github.com/hashicorp/hcl/v2 v2.19.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-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/hashicorp/terraform-exec v0.19.0 // indirect + github.com/hashicorp/terraform-json v0.18.0 // indirect + github.com/hashicorp/terraform-registry-address v0.2.3 // indirect + github.com/hashicorp/terraform-svchost v0.1.1 // indirect + github.com/hashicorp/yamux v0.1.1 // 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 @@ -84,9 +87,9 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.0.0 // 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 + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/zclconf/go-cty v1.14.1 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect @@ -94,6 +97,7 @@ require ( go.opentelemetry.io/otel/metric v1.21.0 // indirect go.opentelemetry.io/otel/trace v1.21.0 // indirect golang.org/x/crypto v0.18.0 // indirect + golang.org/x/mod v0.14.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index ab792bb42cf6..b265f1fc3590 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -1,7 +1,6 @@ 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.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= cloud.google.com/go/bigtable v1.19.0 h1:wiq9LT0kukfInzvy1joMDijCw/OD1UChpSbORXYn0LI= @@ -14,27 +13,22 @@ 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= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0 h1:s4Y6r6RrYLBnqosGXLwR0h1Gqr0VT3wgd6rqvHsD9OE= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.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/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= 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-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -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/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= 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= @@ -43,6 +37,8 @@ github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91 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/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= 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= @@ -50,14 +46,13 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH 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/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= 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/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= 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= @@ -70,20 +65,13 @@ github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -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/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= -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-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-git/v5 v5.10.1 h1:tu8/D8i+TWxgKpzQ3Vc43e+kkhXqtsZCKI/egajKnxk= 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-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -104,10 +92,8 @@ github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4er 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= @@ -127,8 +113,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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= @@ -149,75 +133,63 @@ github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv 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-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/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-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= 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/hc-install v0.6.2 h1:V1k+Vraqz4olgZ9UzKiAcbman9i9scg9GgSt/U3mw/M= +github.com/hashicorp/hc-install v0.6.2/go.mod h1:2JBpd+NCFKiHiu/yYCGaPyPHhZLxXTpz8oreHa/a3Ps= +github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI= +github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= 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-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM= +github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg= +github.com/hashicorp/terraform-json v0.18.0 h1:pCjgJEqqDESv4y0Tzdqfxr/edOIGkjs8keY42xfNBwU= +github.com/hashicorp/terraform-json v0.18.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= +github.com/hashicorp/terraform-plugin-framework v1.5.0 h1:8kcvqJs/x6QyOFSdeAyEgsenVOUeC/IyKpi2ul4fjTg= +github.com/hashicorp/terraform-plugin-framework v1.5.0/go.mod h1:6waavirukIlFpVpthbGd2PUNYaFedB0RwW3MDzJ/rtc= 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-mux v0.8.0/go.mod h1:vdW0daEi8Kd4RFJmet5Ot+SIVB/B8SwQVJiYKQwdCy8= -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-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/hashicorp/terraform-plugin-go v0.20.0 h1:oqvoUlL+2EUbKNsJbIt3zqqZ7wi6lzn4ufkn/UA51xQ= +github.com/hashicorp/terraform-plugin-go v0.20.0/go.mod h1:Rr8LBdMlY53a3Z/HpP+ZU3/xCDqtKNCkeI9qOyT10QE= +github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= +github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= +github.com/hashicorp/terraform-plugin-mux v0.13.0 h1:79U401/3nd8CWwDGtTHc8F3miSCAS9XGtVarxSTDgwA= +github.com/hashicorp/terraform-plugin-mux v0.13.0/go.mod h1:Ndv0FtwDG2ogzH59y64f2NYimFJ6I0smRgFUKfm6dyQ= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 h1:Bl3e2ei2j/Z3Hc2HIS15Gal2KMKyLAZ2om1HCEvK6es= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0/go.mod h1:i2C41tszDjiWfziPQDL5R/f3Zp0gahXe5No/MIO9rCE= +github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= +github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= +github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= +github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= 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/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= 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 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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= @@ -238,30 +210,25 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua 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/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= 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/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= 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= @@ -270,22 +237,16 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU 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/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -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= +github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA= +github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= @@ -302,14 +263,12 @@ go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+ 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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -319,72 +278,72 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl 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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= 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.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= 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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.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= 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.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= 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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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= @@ -398,6 +357,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn 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/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= 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= @@ -406,7 +367,6 @@ google.golang.org/api v0.156.0 h1:yloYcGbBtVYjLKQe4enCunxvwn3s2w/XPrrhVf6MsvQ= google.golang.org/api v0.156.0/go.mod h1:bUSmn4KFO0Q+69zo9CNIDp4Psi6BqM0np0CbzKRSiSY= 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.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -441,16 +401,10 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= 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.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From b7e1e25a635c74eb6c5f6b13828ddcefa67eecd7 Mon Sep 17 00:00:00 2001 From: Jesse Liddle Date: Wed, 21 Feb 2024 14:03:16 -0500 Subject: [PATCH 006/200] Adding Data Source Forwarding Rules (#10004) --- .../provider/provider_mmv1_resources.go.erb | 1 + ..._source_google_compute_forwarding_rules.go | 102 ++++++++++++++++++ ...ce_google_compute_forwarding_rules_test.go | 53 +++++++++ .../d/compute_forwarding_rules.html.markdown | 42 ++++++++ 4 files changed, 198 insertions(+) create mode 100644 mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rules.go create mode 100644 mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rules_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/compute_forwarding_rules.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 e37501f6d8bd..33109889347c 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -60,6 +60,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_compute_default_service_account": compute.DataSourceGoogleComputeDefaultServiceAccount(), "google_compute_disk": compute.DataSourceGoogleComputeDisk(), "google_compute_forwarding_rule": compute.DataSourceGoogleComputeForwardingRule(), + "google_compute_forwarding_rules": compute.DataSourceGoogleComputeForwardingRules(), "google_compute_global_address": compute.DataSourceGoogleComputeGlobalAddress(), "google_compute_global_forwarding_rule": compute.DataSourceGoogleComputeGlobalForwardingRule(), "google_compute_ha_vpn_gateway": compute.DataSourceGoogleComputeHaVpnGateway(), diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rules.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rules.go new file mode 100644 index 000000000000..80f467829735 --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rules.go @@ -0,0 +1,102 @@ +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 DataSourceGoogleComputeForwardingRules() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleComputeForwardingRulesRead, + + Schema: map[string]*schema.Schema{ + + "project": { + Type: schema.TypeString, + Optional: true, + }, + + "region": { + Type: schema.TypeString, + Optional: true, + }, + + "rules": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: tpgresource.DatasourceSchemaFromResourceSchema(ResourceComputeForwardingRule().Schema), + }, + }, + }, + } +} + +func dataSourceGoogleComputeForwardingRulesRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return err + } + + region, err := tpgresource.GetRegion(d, config) + if err != nil { + return err + } + + id := fmt.Sprintf("projects/%s/regions/%s/forwardingRules", project, region) + d.SetId(id) + + forwardingRulesAggregatedList, err := config.NewComputeClient(userAgent).ForwardingRules.List(project, region).Do() + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("Forwarding Rules Not Found : %s", project)) + } + + forwardingRules := make([]map[string]interface{}, 0, len(forwardingRulesAggregatedList.Items)) + + for i := 0; i < len(forwardingRulesAggregatedList.Items); i++ { + rule := forwardingRulesAggregatedList.Items[i] + mappedData := map[string]interface{}{ + "name": rule.Name, + "network": rule.Network, + "subnetwork": rule.Subnetwork, + "backend_service": rule.BackendService, + "ip_address": rule.IPAddress, + "service_name": rule.ServiceName, + "service_label": rule.ServiceLabel, + "description": rule.Description, + "self_link": rule.SelfLink, + "labels": rule.Labels, + "ports": rule.Ports, + "region": rule.Region, + "target": rule.Target, + "ip_version": rule.IpVersion, + "network_tier": rule.NetworkTier, + "base_forwarding_rule": rule.BaseForwardingRule, + "port_range": rule.PortRange, + } + forwardingRules = append(forwardingRules, mappedData) + } + + if err := d.Set("rules", forwardingRules); err != nil { + return fmt.Errorf("Error setting the forwarding rules names: %s", err) + } + + if err := d.Set("project", project); err != nil { + return fmt.Errorf("Error setting the network names: %s", err) + } + + if err := d.Set("region", region); err != nil { + return fmt.Errorf("Error setting the region: %s", err) + } + + return nil +} diff --git a/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rules_test.go b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rules_test.go new file mode 100644 index 000000000000..c0bc3e9004f9 --- /dev/null +++ b/mmv1/third_party/terraform/services/compute/data_source_google_compute_forwarding_rules_test.go @@ -0,0 +1,53 @@ +package compute_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccDataSourceGoogleForwardingRules(t *testing.T) { + t.Parallel() + + poolName := fmt.Sprintf("tf-%s", acctest.RandString(t, 10)) + ruleName := fmt.Sprintf("tf-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleForwardingRuleConfig(poolName, ruleName), + Check: acctest.CheckDataSourceStateMatchesResourceState("data.google_compute_forwarding_rule.my_forwarding_rule", "google_compute_forwarding_rule.foobar-fr"), + }, + }, + }) +} + +func testAccDataSourceGoogleForwardingRulesConfig(poolName, ruleName string) string { + return fmt.Sprintf(` +resource "google_compute_target_pool" "foobar-tp" { + description = "Resource created for Terraform acceptance testing" + instances = ["us-central1-a/foo", "us-central1-b/bar"] + name = "%s" +} + +resource "google_compute_forwarding_rule" "foobar-fr" { + description = "Resource created for Terraform acceptance testing" + ip_protocol = "UDP" + name = "%s" + port_range = "80-81" + target = google_compute_target_pool.foobar-tp.self_link + labels = { + my-label = "my-label-value" + } +} + +data "google_compute_forwarding_rules" "my_forwarding_rule" { + project = google_compute_forwarding_rule.foobar-fr.project + region = google_compute_forwarding_rule.foobar-fr.region +} +`, poolName, ruleName) +} diff --git a/mmv1/third_party/terraform/website/docs/d/compute_forwarding_rules.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_forwarding_rules.html.markdown new file mode 100644 index 000000000000..7c930a68a15d --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/compute_forwarding_rules.html.markdown @@ -0,0 +1,42 @@ +--- +subcategory: "Compute Engine" +description: |- + List forwarding rules in a region of a Google Cloud project. +--- + +# google\_compute\_forwarding\_rules + +List all networks in a specified Google Cloud project. + +## Example Usage + +```tf +data "google_compute_forwarding_rules" "my-forwarding-rules" { + project = "my-cloud-project" + region = "us-central1" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `project` - (Optional) The name of the project. + +* `region` - (Optional) The region you want to get the forwarding rules from. + +These arguments must be set in either the provider or the resouce in order for the information to be queried. + +## Attributes Reference + +In addition to the arguments listed above, the following attributes are exported: + +* `id` - an identifier for the resource with format projects/{{project}}/region/{{region}}/forwardingRules + +* `project` - The project name being queried. + +* `region` - The region being queried. + +* `rules` - This is a list of the forwarding rules in the project. Each forwarding rule will list the backend, description, ip address. name, network, self link, service label, service name, and subnet. + +* `self_link` - The URI of the resource. From 41c5863df55c2efc1d821e869aa8ef8c56df8852 Mon Sep 17 00:00:00 2001 From: Wessel Blokzijl Date: Wed, 21 Feb 2024 20:03:52 +0100 Subject: [PATCH 007/200] Fix broken terraform datasource google_compute_machine_types example (#10020) --- .../website/docs/d/compute_machine_types.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/website/docs/d/compute_machine_types.html.markdown b/mmv1/third_party/terraform/website/docs/d/compute_machine_types.html.markdown index b0cc4784099c..eb42c5054471 100644 --- a/mmv1/third_party/terraform/website/docs/d/compute_machine_types.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/compute_machine_types.html.markdown @@ -20,7 +20,7 @@ Configure a Google Kubernetes Engine (GKE) cluster with node auto-provisioning, ```hcl data "google_compute_machine_types" "example" { - filter = "name = 'n1-standard-1'" + filter = "name = \"n1-standard-1\"" zone = "us-central1-a" } From 6aba2a9bda474112d1d59bf0b8e7b627afb2ee7a Mon Sep 17 00:00:00 2001 From: Jack McCluskey <34928439+jrmccluskey@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:05:08 -0500 Subject: [PATCH 008/200] Add check for Environment proto field before accessing in Dataflow provider (#10016) --- .../terraform/services/dataflow/resource_dataflow_job.go.erb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job.go.erb index 9ecdbd2443ff..e2a0bb2f1b95 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job.go.erb @@ -371,6 +371,9 @@ func resourceDataflowJobRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("effective_labels", job.Labels); err != nil { return fmt.Errorf("Error setting effective_labels: %s", err) } + if job.Environment == nil { + return fmt.Errorf("Error accessing Environment proto: proto is nil") + } if err := d.Set("kms_key_name", job.Environment.ServiceKmsKeyName); err != nil { return fmt.Errorf("Error setting kms_key_name: %s", err) } From f56992625c9b27c1d828e81f87b42f5f2de426f9 Mon Sep 17 00:00:00 2001 From: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:09:39 -0800 Subject: [PATCH 009/200] Add comments to skipped sweeper (#10023) --- mmv1/products/alloydb/User.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/alloydb/User.yaml b/mmv1/products/alloydb/User.yaml index 1f3ad0f76698..895f7557d924 100644 --- a/mmv1/products/alloydb/User.yaml +++ b/mmv1/products/alloydb/User.yaml @@ -24,6 +24,7 @@ references: !ruby/object:Api::Resource::ReferenceLinks 'AlloyDB': 'https://cloud.google.com/alloydb/docs/' api: 'https://cloud.google.com/alloydb/docs/reference/rest/v1/projects.locations.clusters.users/create' import_format: ['projects/{{project}}/locations/{{location}}/clusters/{{cluster}}/users/{{user_id}}'] +# Skipping the sweeper because instances will be deleted during cluster sweeps skip_sweeper: true autogen_async: true custom_code: !ruby/object:Provider::Terraform::CustomCode From fcf7d34078cbbecc309e7d5d6c7b5198df189f4a Mon Sep 17 00:00:00 2001 From: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:09:52 -0800 Subject: [PATCH 010/200] Add comments for skipped sweepers (#10024) --- mmv1/products/firebase/AndroidApp.yaml | 1 + mmv1/products/firebase/AppleApp.yaml | 1 + mmv1/products/firebase/WebApp.yaml | 1 + 3 files changed, 3 insertions(+) diff --git a/mmv1/products/firebase/AndroidApp.yaml b/mmv1/products/firebase/AndroidApp.yaml index 8cd21b2db2ba..3e58993f5e98 100644 --- a/mmv1/products/firebase/AndroidApp.yaml +++ b/mmv1/products/firebase/AndroidApp.yaml @@ -52,6 +52,7 @@ import_format: '{{app_id}}', ] autogen_async: true +# Sweeper skipped as this resource has customized deletion. skip_sweeper: true identity: - appId diff --git a/mmv1/products/firebase/AppleApp.yaml b/mmv1/products/firebase/AppleApp.yaml index 7c9ab93c8258..f40d18733008 100644 --- a/mmv1/products/firebase/AppleApp.yaml +++ b/mmv1/products/firebase/AppleApp.yaml @@ -52,6 +52,7 @@ import_format: '{{app_id}}' ] autogen_async: true +# Sweeper skipped as this resource has customized deletion. skip_sweeper: true identity: - appId diff --git a/mmv1/products/firebase/WebApp.yaml b/mmv1/products/firebase/WebApp.yaml index e6682fdb76df..1ccebb6f418d 100644 --- a/mmv1/products/firebase/WebApp.yaml +++ b/mmv1/products/firebase/WebApp.yaml @@ -52,6 +52,7 @@ import_format: '{{app_id}}', ] autogen_async: true +# Sweeper skipped as this resource has customized deletion. skip_sweeper: true identity: - appId From 580624e69b30b3a2fa911f092ff118787521a918 Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Wed, 21 Feb 2024 20:13:29 +0100 Subject: [PATCH 011/200] C3 version schema (#9986) * add support for build number in composerEnvironmentVersionRegexp and composerImageVersionDiffSuppress * make build number optional * regroup regex, cleaner comparison of versions * correction --- .../resource_composer_environment.go.erb | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 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 8dae1cc3ab12..536af7709b4b 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 @@ -27,7 +27,7 @@ import ( const ( composerEnvironmentEnvVariablesRegexp = "[a-zA-Z_][a-zA-Z0-9_]*." composerEnvironmentReservedAirflowEnvVarRegexp = "AIRFLOW__[A-Z0-9_]+__[A-Z0-9_]+" - composerEnvironmentVersionRegexp = `composer-(([0-9]+)(\.[0-9]+\.[0-9]+(-preview\.[0-9]+)?)?|latest)-airflow-(([0-9]+)((\.[0-9]+)(\.[0-9]+)?)?)` + composerEnvironmentVersionRegexp = `composer-(([0-9]+)(\.[0-9]+\.[0-9]+(-preview\.[0-9]+)?)?|latest)-airflow-(([0-9]+)((\.[0-9]+)(\.[0-9]+)?)?(-build\.[0-9]+)?)` ) var composerEnvironmentReservedEnvVar = map[string]struct{}{ @@ -2827,7 +2827,7 @@ func composerImageVersionDiffSuppress(_, old, new string, _ *schema.ResourceData versionRe := regexp.MustCompile(composerEnvironmentVersionRegexp) oldVersions := versionRe.FindStringSubmatch(old) newVersions := versionRe.FindStringSubmatch(new) - if oldVersions == nil || len(oldVersions) < 10 { + if oldVersions == nil || len(oldVersions) < 11 { // Somehow one of the versions didn't match the regexp or didn't // have values in the capturing groups. In that case, fall back to // an equality check. @@ -2836,7 +2836,7 @@ func composerImageVersionDiffSuppress(_, old, new string, _ *schema.ResourceData } return old == new } - if newVersions == nil || len(newVersions) < 10 { + if newVersions == nil || len(newVersions) < 11 { // Somehow one of the versions didn't match the regexp or didn't // have values in the capturing groups. In that case, fall back to // an equality check. @@ -2849,9 +2849,11 @@ func composerImageVersionDiffSuppress(_, old, new string, _ *schema.ResourceData oldAirflow := oldVersions[5] oldAirflowMajor := oldVersions[6] oldAirflowMajorMinor := oldVersions[6] + oldVersions[8] + oldAirflowMajorMinorPatch := oldVersions[6] + oldVersions[8] + oldVersions[9] newAirflow := newVersions[5] newAirflowMajor := newVersions[6] newAirflowMajorMinor := newVersions[6] + newVersions[8] + newAirflowMajorMinorPatch := newVersions[6] + newVersions[8] + newVersions[9] // Check Airflow versions. if oldAirflow == oldAirflowMajor || newAirflow == newAirflowMajor { // If one of the Airflow versions specifies only major version @@ -2873,8 +2875,18 @@ func composerImageVersionDiffSuppress(_, old, new string, _ *schema.ResourceData if !eq { return false } + } else if oldAirflow == oldAirflowMajorMinorPatch || newAirflow == newAirflowMajorMinorPatch { + // If one of the Airflow versions specifies only major, minor and patch version + // (like 1.10.15), we can only compare major, minor and patch versions. + eq, err := versionsEqual(oldAirflowMajorMinorPatch, newAirflowMajorMinorPatch) + if err != nil { + log.Printf("[WARN] Could not parse airflow version, %s", err) + } + if !eq { + return false + } } else { - // Otherwise, we compare the full Airflow versions (like 1.10.15). + // Otherwise, we compare the full Airflow versions (like 1.10.15-build.5). eq, err := versionsEqual(oldAirflow, newAirflow) if err != nil { log.Printf("[WARN] Could not parse airflow version, %s", err) From 343ff46df5008cc457392c3baafd0acc6dc97633 Mon Sep 17 00:00:00 2001 From: Max Portocarrero CI&T <105444618+maxi-cit@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:18:48 -0500 Subject: [PATCH 012/200] Add Resource Manager Tags support to 'google_container_cluster' (#9531) * resourceManagerTags added to Cluster Node Config schema * update beta tag * add cluster and node proto tests * add expand and flatten proto * removed beta tag * added to documentation * added resource manager tags to auto pilot * migrating resourceManagerTags tests * migrating node_pools test * migrating additional tests * minor fixes * fixing tests * add in-place update support * fixed tests * fixed annotations * validated clusters and node pools tests. Isolated node pool auto config * isolated resource manager tags from docs * fixed permission issue * fixed spaces * fixed non determinism on tag keys * removed auto_pilot rmts * fixed time_sleep * add depends_on to IAM policies --- .../compute/resource_compute_instance.go.erb | 8 +- .../services/container/node_config.go.erb | 40 +- .../resource_container_cluster.go.erb | 16 +- .../resource_container_cluster_test.go.erb | 150 ++++++- .../resource_container_node_pool.go.erb | 42 ++ .../resource_container_node_pool_test.go.erb | 406 +++++++++++++++++- .../docs/r/container_cluster.html.markdown | 6 +- 7 files changed, 635 insertions(+), 33 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb index 3fb7c963acf1..1a6ad62d42cf 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance.go.erb @@ -651,7 +651,7 @@ func ResourceComputeInstance() *schema.Resource { }, }, - "params": { + "params": { Type: schema.TypeList, MaxItems: 1, Optional: true, @@ -673,7 +673,7 @@ func ResourceComputeInstance() *schema.Resource { Optional: true, Elem: &schema.Schema{Type: schema.TypeString}, Description: `A set of key/value label pairs assigned to the instance. - + **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. Please refer to the field 'effective_labels' for all of the labels present on the resource.`, }, @@ -1422,7 +1422,7 @@ func resourceComputeInstanceCreate(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Error creating instance while setting the security policies: %s", err) } <% end -%> - + err = waitUntilInstanceHasDesiredStatus(config, d) if err != nil { return fmt.Errorf("Error waiting for status: %s", err) @@ -1936,7 +1936,7 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err return fmt.Errorf("Instance had unexpected number of network interfaces: %d", len(instance.NetworkInterfaces)) } - <% unless version == 'ga' -%> + <% unless version == 'ga' -%> updateSecurityPolicy := false for i := 0; i < len(instance.NetworkInterfaces); i++ { prefix := fmt.Sprintf("network_interface.%d", i) 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 af3492f29413..8d53ce85b51d 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.erb +++ b/mmv1/third_party/terraform/services/container/node_config.go.erb @@ -675,6 +675,11 @@ func schemaNodeConfig() *schema.Schema { }, }, }, + "resource_manager_tags": { + Type: schema.TypeMap, + Optional: true, + Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored (both PUT & PATCH) when empty.`, + }, <% unless version == 'ga' -%> "enable_confidential_storage": { Type: schema.TypeBool, @@ -884,6 +889,10 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { nc.ResourceLabels = m } + if v, ok := nodeConfig["resource_manager_tags"]; ok && len(v.(map[string]interface{})) > 0 { + nc.ResourceManagerTags = expandResourceManagerTags(v) + } + if v, ok := nodeConfig["tags"]; ok { tagsList := v.([]interface{}) tags := []string{} @@ -974,7 +983,7 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { nc.EnableConfidentialStorage = v.(bool) } <% end -%> - + <% unless version == "ga" -%> if v, ok := nodeConfig["host_maintenance_policy"]; ok { nc.HostMaintenancePolicy = expandHostMaintenancePolicy(v) @@ -988,6 +997,19 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { return nc } +func expandResourceManagerTags(v interface{}) *container.ResourceManagerTags { + rmts := make(map[string]string) + + if v != nil { + rmts = tpgresource.ConvertStringMap(v.(map[string]interface{})) + } + + return &container.ResourceManagerTags{ + Tags: rmts, + ForceSendFields: []string{"Tags"}, + } +} + func expandWorkloadMetadataConfig(v interface{}) *container.WorkloadMetadataConfig { if v == nil { return nil @@ -1213,7 +1235,8 @@ func flattenNodeConfig(c *container.NodeConfig, v interface{}) []map[string]inte "advanced_machine_features": flattenAdvancedMachineFeaturesConfig(c.AdvancedMachineFeatures), "sole_tenant_config": flattenSoleTenantConfig(c.SoleTenantConfig), "fast_socket": flattenFastSocket(c.FastSocket), - <% unless version == 'ga' -%> + "resource_manager_tags": flattenResourceManagerTags(c.ResourceManagerTags), + <% unless version == 'ga' -%> "enable_confidential_storage": c.EnableConfidentialStorage, <% end -%> }) @@ -1225,6 +1248,19 @@ func flattenNodeConfig(c *container.NodeConfig, v interface{}) []map[string]inte return config } +func flattenResourceManagerTags(c *container.ResourceManagerTags) map[string]interface{} { + rmt := make(map[string]interface{}) + + if c != nil { + for k, v := range c.Tags { + rmt[k] = v + } + + } + + return rmt +} + func flattenAdvancedMachineFeaturesConfig(c *container.AdvancedMachineFeatures) []map[string]interface{} { result := []map[string]interface{}{} if c != nil { 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 0ab9a425f653..00a3f3aaab84 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 @@ -97,6 +97,7 @@ var ( forceNewClusterNodeConfigFields = []string{ "labels", "workload_metadata_config", + "resource_manager_tags", } suppressDiffForAutopilot = schema.SchemaDiffSuppressFunc(func(k, oldValue, newValue string, d *schema.ResourceData) bool { @@ -1424,11 +1425,11 @@ func ResourceContainerCluster() *schema.Resource { "node_pool_defaults": clusterSchemaNodePoolDefaults(), "node_pool_auto_config": { - Type: schema.TypeList, - Optional: true, - Computed: true, - MaxItems: 1, - Description: `Node pool configs that apply to all auto-provisioned node pools in autopilot clusters and node auto-provisioning enabled clusters.`, + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 1, + Description: `Node pool configs that apply to all auto-provisioned node pools in autopilot clusters and node auto-provisioning enabled clusters.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "network_tags": { @@ -5266,7 +5267,7 @@ func expandFleet(configured interface{}) *container.Fleet { return &container.Fleet{ Project: config["project"].(string), } -} +} func expandEnableK8sBetaApis(configured interface{}, enabledAPIs []string) *container.K8sBetaAPIConfig { l := configured.([]interface{}) @@ -5424,6 +5425,7 @@ func expandNodePoolAutoConfig(configured interface{}) *container.NodePoolAutoCon if v, ok := config["network_tags"]; ok && len(v.([]interface{})) > 0 { npac.NetworkTags = expandNodePoolAutoConfigNetworkTags(v) } + return npac } @@ -6129,7 +6131,7 @@ func flattenFleet(c *container.Fleet) []map[string]interface{} { membership_id = match[4] membership_location = match[3] } - + return []map[string]interface{}{ { "project": c.Project, 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 c57254c7e06d..a542384379f6 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 @@ -56,6 +56,43 @@ func TestAccContainerCluster_basic(t *testing.T) { }) } +func TestAccContainerCluster_resourceManagerTags(t *testing.T) { + t.Parallel() + + pid := envvar.GetTestProjectFromEnv() + + randomSuffix := acctest.RandString(t, 10) + clusterName := fmt.Sprintf("tf-test-cluster-%s", randomSuffix) + + 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), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_resourceManagerTags(pid, clusterName, networkName, subnetworkName, randomSuffix), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_container_cluster.primary", "self_link"), + resource.TestCheckResourceAttrSet("google_container_cluster.primary", "node_config.0.resource_manager_tags.%"), + ), + }, + { + ResourceName: "google_container_cluster.primary", + ImportStateId: fmt.Sprintf("us-central1-a/%s", clusterName), + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, + }, + }, + }) +} + func TestAccContainerCluster_networkingModeRoutes(t *testing.T) { t.Parallel() @@ -2843,9 +2880,9 @@ func TestAccContainerCluster_withAutopilot(t *testing.T) { clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccContainerCluster_withAutopilot(pid, containerNetName, clusterName, "us-central1", true, false, ""), @@ -2856,7 +2893,7 @@ func TestAccContainerCluster_withAutopilot(t *testing.T) { { ResourceName: "google_container_cluster.with_autopilot", ImportState: true, - ImportStateVerify: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, @@ -2872,9 +2909,9 @@ func TestAccContainerClusterCustomServiceAccount_withAutopilot(t *testing.T) { serviceAccountName := fmt.Sprintf("tf-test-sa-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccContainerCluster_withAutopilot(pid, containerNetName, clusterName, "us-central1", true, false, serviceAccountName), @@ -2891,7 +2928,7 @@ func TestAccContainerClusterCustomServiceAccount_withAutopilot(t *testing.T) { { ResourceName: "google_container_cluster.with_autopilot", ImportState: true, - ImportStateVerify: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{"min_master_version", "deletion_protection"}, }, }, @@ -2906,9 +2943,9 @@ func TestAccContainerCluster_errorAutopilotLocation(t *testing.T) { clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccContainerCluster_withAutopilot(pid, containerNetName, clusterName, "us-central1-a", true, false, ""), @@ -2926,9 +2963,9 @@ func TestAccContainerCluster_withAutopilotNetworkTags(t *testing.T) { clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccContainerCluster_withAutopilot(pid, containerNetName, clusterName, "us-central1", true, true, ""), @@ -4444,11 +4481,11 @@ func testAccContainerCluster_withIncompatibleMasterVersionNodeVersion(name strin resource "google_container_cluster" "gke_cluster" { name = "%s" location = "us-central1" - + min_master_version = "1.10.9-gke.5" node_version = "1.10.6-gke.11" initial_node_count = 1 - + } `, name) } @@ -6674,7 +6711,7 @@ resource "google_container_cluster" "with_autoprovisioning" { min_master_version = data.google_container_engine_versions.central1a.latest_master_version initial_node_count = 1 deletion_protection = false - + network = "%s" subnetwork = "%s" @@ -9250,7 +9287,7 @@ resource "google_compute_resource_policy" "policy" { resource "google_container_cluster" "cluster" { name = "%s" location = "us-central1-a" - + node_pool { name = "%s" initial_node_count = 2 @@ -9285,7 +9322,7 @@ func testAccContainerCluster_additional_pod_ranges_config(name string, nameCount } `, podRangeNamesStr) } - + return fmt.Sprintf(` resource "google_compute_network" "main" { name = "%s" @@ -9561,3 +9598,86 @@ func testAccContainerCluster_withWorkloadALTSConfig(projectID, name, networkName `, projectID, networkName, subnetworkName, name, enable) } <% end -%> + +func testAccContainerCluster_resourceManagerTags(projectID, clusterName, networkName, subnetworkName, randomSuffix string) string { + return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%[1]s" +} + +resource "google_project_iam_binding" "tagHoldAdmin" { + project = "%[1]s" + role = "roles/resourcemanager.tagHoldAdmin" + members = [ + "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com", + ] +} + +resource "google_project_iam_binding" "tagUser" { + project = "%[1]s" + role = "roles/resourcemanager.tagUser" + members = [ + "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com", + "serviceAccount:${data.google_project.project.number}@cloudservices.gserviceaccount.com", + ] + + depends_on = [google_project_iam_binding.tagHoldAdmin] +} + +resource "time_sleep" "wait_120_seconds" { + create_duration = "120s" + + depends_on = [ + google_project_iam_binding.tagHoldAdmin, + google_project_iam_binding.tagUser + ] +} + +resource "google_tags_tag_key" "key" { + parent = "projects/%[1]s" + short_name = "foobarbaz-%[2]s" + description = "For foo/bar resources" + purpose = "GCE_FIREWALL" + purpose_data = { + network = "%[1]s/%[4]s" + } +} + +resource "google_tags_tag_value" "value" { + parent = "tagKeys/${google_tags_tag_key.key.name}" + short_name = "foo-%[2]s" + description = "For foo resources" +} + +data "google_container_engine_versions" "uscentral1a" { + location = "us-central1-a" +} + +resource "google_container_cluster" "primary" { + name = "%[3]s" + location = "us-central1-a" + min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] + initial_node_count = 1 + + node_config { + machine_type = "n1-standard-1" // can't be e2 because of local-ssd + disk_size_gb = 15 + + resource_manager_tags = { + "tagKeys/${google_tags_tag_key.key.name}" = "tagValues/${google_tags_tag_value.value.name}" + } + } + + deletion_protection = false + network = "%[4]s" + subnetwork = "%[5]s" + + timeouts { + create = "30m" + update = "40m" + } + + depends_on = [time_sleep.wait_120_seconds] +} +`, projectID, randomSuffix, clusterName, networkName, subnetworkName) +} 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 a4208ccfd799..025ed420fdde 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 @@ -1605,6 +1605,48 @@ func nodePoolUpdate(d *schema.ResourceData, meta interface{}, nodePoolInfo *Node log.Printf("[INFO] Updated tags for node pool %s", name) } + if d.HasChange(prefix + "node_config.0.resource_manager_tags") { + req := &container.UpdateNodePoolRequest{ + Name: name, + } + if v, ok := d.GetOk(prefix + "node_config.0.resource_manager_tags"); ok { + req.ResourceManagerTags = expandResourceManagerTags(v) + } + + // sets resource manager tags to the empty list when user removes a previously defined list of tags entriely + // aka the node pool goes from having tags to no longer having any + if req.ResourceManagerTags == nil { + tags := make(map[string]string) + rmTags := &container.ResourceManagerTags{ + Tags: tags, + } + req.ResourceManagerTags = rmTags + } + + 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 resource manager tags", userAgent, + timeout) + } + + if err := retryWhileIncompatibleOperation(timeout, npLockKey, updateF); err != nil { + return err + } + log.Printf("[INFO] Updated resource manager tags for node pool %s", name) + } + if d.HasChange(prefix + "node_config.0.resource_labels") { 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 e06180e6c0e9..42939e9b7e9b 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 @@ -37,6 +37,61 @@ func TestAccContainerNodePool_basic(t *testing.T) { }) } +func TestAccContainerNodePool_resourceManagerTags(t *testing.T) { + t.Parallel() + pid := envvar.GetTestProjectFromEnv() + + randomSuffix := acctest.RandString(t, 10) + clusterName := fmt.Sprintf("tf-test-cluster-%s", randomSuffix) + + 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), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerNodePool_resourceManagerTags(pid, clusterName, networkName, subnetworkName, randomSuffix), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_container_node_pool.primary_nodes", "node_config.0.resource_manager_tags.%"), + ), + }, + { + ResourceName: "google_container_node_pool.primary_nodes", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version", "cluster"}, + }, + { + Config: testAccContainerNodePool_resourceManagerTagsUpdate1(pid, clusterName, networkName, subnetworkName, randomSuffix), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_container_node_pool.primary_nodes", "node_config.0.resource_manager_tags.%"), + ), + }, + { + ResourceName: "google_container_node_pool.primary_nodes", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version", "cluster"}, + }, + { + Config: testAccContainerNodePool_resourceManagerTagsUpdate2(pid, clusterName, networkName, subnetworkName, randomSuffix), + }, + { + ResourceName: "google_container_node_pool.primary_nodes", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version", "cluster"}, + }, + }, + }) +} + func TestAccContainerNodePool_basicWithClusterId(t *testing.T) { t.Parallel() @@ -4132,7 +4187,7 @@ resource "google_container_node_pool" "with_confidential_boot_disk" { name = "%s" location = "us-central1-a" cluster = google_container_cluster.cluster.name - + node_config { image_type = "COS_CONTAINERD" boot_disk_kms_key = "%s" @@ -4149,7 +4204,7 @@ resource "google_container_node_pool" "with_confidential_boot_disk" { } func TestAccContainerNodePool_withoutConfidentialBootDisk(t *testing.T) { - t.Parallel() + t.Parallel() cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) np := fmt.Sprintf("tf-test-np-%s", acctest.RandString(t, 10)) @@ -4193,7 +4248,7 @@ resource "google_container_node_pool" "without_confidential_boot_disk" { name = "%s" location = "us-central1-a" cluster = google_container_cluster.cluster.name - + node_config { image_type = "COS_CONTAINERD" oauth_scopes = [ @@ -4208,3 +4263,348 @@ resource "google_container_node_pool" "without_confidential_boot_disk" { `, cluster, networkName, subnetworkName, np) } <% end -%> + +func testAccContainerNodePool_resourceManagerTags(projectID, clusterName, networkName, subnetworkName, randomSuffix string) string { + return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%[1]s" +} + +resource "google_project_iam_binding" "tagHoldAdmin" { + project = "%[1]s" + role = "roles/resourcemanager.tagHoldAdmin" + members = [ + "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com", + ] +} + +resource "google_project_iam_binding" "tagUser" { + project = "%[1]s" + role = "roles/resourcemanager.tagUser" + members = [ + "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com", + "serviceAccount:${data.google_project.project.number}@cloudservices.gserviceaccount.com", + ] + + depends_on = [google_project_iam_binding.tagHoldAdmin] +} + +resource "time_sleep" "wait_120_seconds" { + create_duration = "120s" + + depends_on = [ + google_project_iam_binding.tagHoldAdmin, + google_project_iam_binding.tagUser + ] +} + +resource "google_tags_tag_key" "key1" { + parent = "projects/%[1]s" + short_name = "foobarbaz1-%[2]s" + description = "For foo/bar1 resources" + purpose = "GCE_FIREWALL" + purpose_data = { + network = "%[1]s/%[4]s" + } +} + +resource "google_tags_tag_value" "value1" { + parent = "tagKeys/${google_tags_tag_key.key1.name}" + short_name = "foo1-%[2]s" + description = "For foo1 resources" +} + +resource "google_tags_tag_key" "key2" { + parent = "projects/%[1]s" + short_name = "foobarbaz2-%[2]s" + description = "For foo/bar2 resources" + purpose = "GCE_FIREWALL" + purpose_data = { + network = "%[1]s/%[4]s" + } + + depends_on = [google_tags_tag_key.key1] +} + +resource "google_tags_tag_value" "value2" { + parent = "tagKeys/${google_tags_tag_key.key2.name}" + short_name = "foo2-%[2]s" + description = "For foo2 resources" +} + +data "google_container_engine_versions" "uscentral1a" { + location = "us-central1-a" +} + +resource "google_container_cluster" "primary" { + name = "%[3]s" + location = "us-central1-a" + min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] + + # We can't create a cluster with no node pool defined, but we want to only use + # separately managed node pools. So we create the smallest possible default + # node pool and immediately delete it. + remove_default_node_pool = true + initial_node_count = 1 + + deletion_protection = false + network = "%[4]s" + subnetwork = "%[5]s" + + timeouts { + create = "30m" + update = "40m" + } + + depends_on = [time_sleep.wait_120_seconds] +} + +# Separately Managed Node Pool +resource "google_container_node_pool" "primary_nodes" { + name = google_container_cluster.primary.name + location = "us-central1-a" + cluster = google_container_cluster.primary.name + + version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] + node_count = 1 + + node_config { + machine_type = "n1-standard-1" // can't be e2 because of local-ssd + disk_size_gb = 15 + + resource_manager_tags = { + "tagKeys/${google_tags_tag_key.key1.name}" = "tagValues/${google_tags_tag_value.value1.name}" + } + } +} +`, projectID, randomSuffix, clusterName, networkName, subnetworkName) +} + +func testAccContainerNodePool_resourceManagerTagsUpdate1(projectID, clusterName, networkName, subnetworkName, randomSuffix string) string { + return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%[1]s" +} + +resource "google_project_iam_binding" "tagHoldAdmin" { + project = "%[1]s" + role = "roles/resourcemanager.tagHoldAdmin" + members = [ + "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com", + ] +} + +resource "google_project_iam_binding" "tagUser" { + project = "%[1]s" + role = "roles/resourcemanager.tagUser" + members = [ + "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com", + "serviceAccount:${data.google_project.project.number}@cloudservices.gserviceaccount.com", + ] + + depends_on = [google_project_iam_binding.tagHoldAdmin] +} + +resource "time_sleep" "wait_120_seconds" { + create_duration = "120s" + + depends_on = [ + google_project_iam_binding.tagHoldAdmin, + google_project_iam_binding.tagUser + ] +} + +resource "google_tags_tag_key" "key1" { + parent = "projects/%[1]s" + short_name = "foobarbaz1-%[2]s" + description = "For foo/bar1 resources" + purpose = "GCE_FIREWALL" + purpose_data = { + network = "%[1]s/%[4]s" + } +} + +resource "google_tags_tag_value" "value1" { + parent = "tagKeys/${google_tags_tag_key.key1.name}" + short_name = "foo1-%[2]s" + description = "For foo1 resources" +} + +resource "google_tags_tag_key" "key2" { + parent = "projects/%[1]s" + short_name = "foobarbaz2-%[2]s" + description = "For foo/bar2 resources" + purpose = "GCE_FIREWALL" + purpose_data = { + network = "%[1]s/%[4]s" + } + + depends_on = [google_tags_tag_key.key1] +} + +resource "google_tags_tag_value" "value2" { + parent = "tagKeys/${google_tags_tag_key.key2.name}" + short_name = "foo2-%[2]s" + description = "For foo2 resources" +} + +data "google_container_engine_versions" "uscentral1a" { + location = "us-central1-a" +} + +resource "google_container_cluster" "primary" { + name = "%[3]s" + location = "us-central1-a" + min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] + + # We can't create a cluster with no node pool defined, but we want to only use + # separately managed node pools. So we create the smallest possible default + # node pool and immediately delete it. + remove_default_node_pool = true + initial_node_count = 1 + + deletion_protection = false + network = "%[4]s" + subnetwork = "%[5]s" + + timeouts { + create = "30m" + update = "40m" + } + + depends_on = [time_sleep.wait_120_seconds] +} + +# Separately Managed Node Pool +resource "google_container_node_pool" "primary_nodes" { + name = google_container_cluster.primary.name + location = "us-central1-a" + cluster = google_container_cluster.primary.name + + version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] + node_count = 1 + + node_config { + machine_type = "n1-standard-1" // can't be e2 because of local-ssd + disk_size_gb = 15 + + resource_manager_tags = { + "tagKeys/${google_tags_tag_key.key1.name}" = "tagValues/${google_tags_tag_value.value1.name}" + "tagKeys/${google_tags_tag_key.key2.name}" = "tagValues/${google_tags_tag_value.value2.name}" + } + } +} +`, projectID, randomSuffix, clusterName, networkName, subnetworkName) +} + +func testAccContainerNodePool_resourceManagerTagsUpdate2(projectID, clusterName, networkName, subnetworkName, randomSuffix string) string { + return fmt.Sprintf(` +data "google_project" "project" { + project_id = "%[1]s" +} + +resource "google_project_iam_binding" "tagHoldAdmin" { + project = "%[1]s" + role = "roles/resourcemanager.tagHoldAdmin" + members = [ + "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com", + ] +} + +resource "google_project_iam_binding" "tagUser" { + project = "%[1]s" + role = "roles/resourcemanager.tagUser" + members = [ + "serviceAccount:service-${data.google_project.project.number}@container-engine-robot.iam.gserviceaccount.com", + "serviceAccount:${data.google_project.project.number}@cloudservices.gserviceaccount.com", + ] + + depends_on = [google_project_iam_binding.tagHoldAdmin] +} + +resource "time_sleep" "wait_120_seconds" { + create_duration = "120s" + + depends_on = [ + google_project_iam_binding.tagHoldAdmin, + google_project_iam_binding.tagUser + ] +} + +resource "google_tags_tag_key" "key1" { + parent = "projects/%[1]s" + short_name = "foobarbaz1-%[2]s" + description = "For foo/bar1 resources" + purpose = "GCE_FIREWALL" + purpose_data = { + network = "%[1]s/%[4]s" + } +} + +resource "google_tags_tag_value" "value1" { + parent = "tagKeys/${google_tags_tag_key.key1.name}" + short_name = "foo1-%[2]s" + description = "For foo1 resources" +} + +resource "google_tags_tag_key" "key2" { + parent = "projects/%[1]s" + short_name = "foobarbaz2-%[2]s" + description = "For foo/bar2 resources" + purpose = "GCE_FIREWALL" + purpose_data = { + network = "%[1]s/%[4]s" + } + + depends_on = [google_tags_tag_key.key1] +} + +resource "google_tags_tag_value" "value2" { + parent = "tagKeys/${google_tags_tag_key.key2.name}" + short_name = "foo2-%[2]s" + description = "For foo2 resources" +} + +data "google_container_engine_versions" "uscentral1a" { + location = "us-central1-a" +} + +resource "google_container_cluster" "primary" { + name = "%[3]s" + location = "us-central1-a" + min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] + + # We can't create a cluster with no node pool defined, but we want to only use + # separately managed node pools. So we create the smallest possible default + # node pool and immediately delete it. + remove_default_node_pool = true + initial_node_count = 1 + + deletion_protection = false + network = "%[4]s" + subnetwork = "%[5]s" + + timeouts { + create = "30m" + update = "40m" + } + + depends_on = [time_sleep.wait_120_seconds] +} + +# Separately Managed Node Pool +resource "google_container_node_pool" "primary_nodes" { + name = google_container_cluster.primary.name + location = "us-central1-a" + cluster = google_container_cluster.primary.name + + version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] + node_count = 1 + + node_config { + machine_type = "n1-standard-1" // can't be e2 because of local-ssd + disk_size_gb = 15 + } +} +`, projectID, randomSuffix, clusterName, networkName, subnetworkName) +} 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 b7713ba6d51c..3c72beba2d55 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 @@ -905,6 +905,8 @@ gvnic { * `tags` - (Optional) The list of instance tags applied to all nodes. Tags are used to identify valid sources or targets for network firewalls. +* `resource_manager_tags` - (Optional) A map of resource manager tag keys and values to be attached to the nodes for managing Compute Engine firewalls using Network Firewall Policies. Tags must be according to specifications found [here](https://cloud.google.com/vpc/docs/tags-firewalls-overview#specifications). A maximum of 5 tag key-value pairs can be specified. Existing tags will be replaced with new values. Tags must be in one of the following formats ([KEY]=[VALUE]) 1. `tagKeys/{tag_key_id}=tagValues/{tag_value_id}` 2. `{org_id}/{tag_key_name}={tag_value_name}` 3. `{project_id}/{tag_key_name}={tag_value_name}`. + * `taint` - (Optional) A list of [Kubernetes taints](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) to apply to nodes. This field will only report drift on taint keys that are @@ -998,7 +1000,7 @@ sole_tenant_config { * `count` (Required) - The number of the guest accelerator cards exposed to this instance. * `gpu_driver_installation_config` (Optional) - Configuration for auto installation of GPU driver. Structure is [documented below](#nested_gpu_driver_installation_config). - + * `gpu_partition_size` (Optional) - Size of partitions to create on the GPU. Valid values are described in the NVIDIA mig [user guide](https://docs.nvidia.com/datacenter/tesla/mig-user-guide/#partitioning). * `gpu_sharing_config` (Optional) - Configuration for GPU sharing. Structure is [documented below](#nested_gpu_sharing_config). @@ -1345,7 +1347,7 @@ exported: * `node_config.0.effective_taints` - List of kubernetes taints applied to each node. Structure is [documented above](#nested_taint). -* `fleet.0.membership` - The resource name of the fleet Membership resource associated to this cluster with format `//gkehub.googleapis.com/projects/{{project}}/locations/{{location}}/memberships/{{name}}`. See the official doc for [fleet management](https://cloud.google.com/kubernetes-engine/docs/fleets-overview). +* `fleet.0.membership` - The resource name of the fleet Membership resource associated to this cluster with format `//gkehub.googleapis.com/projects/{{project}}/locations/{{location}}/memberships/{{name}}`. See the official doc for [fleet management](https://cloud.google.com/kubernetes-engine/docs/fleets-overview). * `fleet.0.membership_id` - The short name of the fleet membership, extracted from `fleet.0.membership`. You can use this field to configure `membership_id` under [google_gkehub_feature_membership](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/gke_hub_feature_membership). From 37fb2ebf10afb245649e86f17bc344bf7b10ef8b Mon Sep 17 00:00:00 2001 From: Oliver Krause <3621164+okrause@users.noreply.github.com> Date: Wed, 21 Feb 2024 22:18:20 +0100 Subject: [PATCH 013/200] Add volume replication support for Google Cloud NetApp Volumes (#9816) * Initial replication commit * Cleanup work - Renamed a lot of files to make clear which resource the belong to - Updated documentation for resource fields - Renamed a few resource fields and changed some types - Disabled the custom code for now. Needs to be discussed first * Update example file * Updated example file * Major updates - Reorganisation of block - Reorganisation of fields to match API documentation - Updated example parameters - Added missing API fields - Improved descriptions - * For replication deletion, stop replication first * Add support for deleting destination volume on replication delete * Make volumes deletable in presence of snapshots. This change will be PRed for volume resource independently. Adding it here while it is not in main. * Improving debug error message * yaml check and format fix * Add wait for mirror to initialize. Required to run destroy shortly after create. * Wait on destroy, not on create * Make deleting a replication more robust - doc improvements - started to implement stop/resume. More work required. - renamed a few files to better reflect what they are good for * adding support for stop/resume * yamlformat and lint * Add force delete to delete volumes with nested snapshots * resource test first version * More changes to make tests solid - Introduced new parameter to wait for mirror_status==MIRRORED - more mirror state reconciliation * Test updates * few cleanups * Make virtual field verifies happy * Minor test improvements * More fine tuning - Remove merge conflict in volume.yaml - make generated test work - make output field work - ignore_read for virtual fields * Resource name change as suggested by @slevenick * Remove snapshot code block and fix typo * Detect manual stop/resume actions * Remove ignore_read for deletion_policy * - Made destinationVolumeParameters immutable. It still requires ignore_read. - removed ignore_read from virtual_fields * destinationVolumeParameters are only evaluated at create. Make the immutable. * Name cleanups and comment improvements * removed comment Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * tabs to spaces in resource block Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> * Updates to address review comments - make wait_for_mirror also work for stop/resume, additionally to create - convert tabs in test resource blocks to spaces - fix typos * Rewording of comments Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> --------- Co-authored-by: G-NamanGupta Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> --- mmv1/products/netapp/VolumeReplication.yaml | 289 +++++++++++++++++ .../netapp_volume_replication.go.erb | 51 +++ ...tapp_volume_replicaton_mirror_state.go.erb | 20 ++ .../netapp_volume_replication_create.tf.erb | 54 ++++ ...tapp_volume_replication_post_create.go.erb | 7 + ...plication_delete_destination_volume.go.erb | 34 ++ ...app_volume_replication_mirror_state.go.erb | 89 +++++ ...lume_replication_stop_before_delete.go.erb | 33 ++ ...resource_netapp_volume_replication_test.go | 306 ++++++++++++++++++ 9 files changed, 883 insertions(+) create mode 100644 mmv1/products/netapp/VolumeReplication.yaml create mode 100644 mmv1/templates/terraform/constants/netapp_volume_replication.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/netapp_volume_replicaton_mirror_state.go.erb create mode 100644 mmv1/templates/terraform/examples/netapp_volume_replication_create.tf.erb create mode 100644 mmv1/templates/terraform/post_create/netapp_volume_replication_post_create.go.erb create mode 100644 mmv1/templates/terraform/post_delete/netapp_volume_replication_delete_destination_volume.go.erb create mode 100644 mmv1/templates/terraform/post_update/netapp_volume_replication_mirror_state.go.erb create mode 100644 mmv1/templates/terraform/pre_delete/netapp_volume_replication_stop_before_delete.go.erb create mode 100644 mmv1/third_party/terraform/services/netapp/resource_netapp_volume_replication_test.go diff --git a/mmv1/products/netapp/VolumeReplication.yaml b/mmv1/products/netapp/VolumeReplication.yaml new file mode 100644 index 000000000000..dd7dde9c7f32 --- /dev/null +++ b/mmv1/products/netapp/VolumeReplication.yaml @@ -0,0 +1,289 @@ +# 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: "VolumeReplication" +description: | + Volume replication creates an asynchronous mirror of a volume in a different location. This capability + lets you use the replicated volume for critical application activity in case of a location-wide outage + or disaster. + + A new destination volume is created as part of the replication resource. It's content is updated on a + schedule with content of the source volume. It can be used as a read-only copy while the mirror is + enabled, or as an independent read-write volume while the mirror is stopped. A destination volume will + also contain the snapshots of the source volume. Resuming a mirror will overwrite all changes on the + destination volume with the content of the source volume. While is mirror is enabled, all configuration + changes done to source or destination volumes are automatically done to both. Please note that the + destination volume is not a resource managed by Terraform. + + Reversing the replication direction is not supported through the provider. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + "Documentation": "https://cloud.google.com/netapp/volumes/docs/protect-data/about-volume-replication" + api: "https://cloud.google.com/netapp/volumes/docs/reference/rest/v1/projects.locations.volumes.replications" +base_url: projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications +self_link: projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications/{{name}} +create_url: projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications?replicationId={{name}} +update_url: projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications/{{name}} +update_verb: :PATCH +update_mask: true +autogen_async: true +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + base_url: "{{op_id}}" +id_format: "projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications/{{name}}" +import_format: + [ + "projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications/{{name}}", + ] +examples: + - !ruby/object:Provider::Terraform::Examples + name: "netapp_volume_replication_create" + primary_resource_id: "test_replication" + vars: + source_pool_name: "source-pool" + destination_pool_name: "destination-pool" + volume_name: "source-volume" + replication_name: "test-replication" + destination_volume: "destination-volume" + network_name: "test-network" + ignore_read_extra: + - "delete_destination_volume" + - "replication_enabled" + - "force_stopping" + - "wait_for_mirror" + test_vars_overrides: + network_name: 'acctest.BootstrapSharedServiceNetworkingConnection(t, "gcnv-network-config-1", acctest.ServiceNetworkWithParentService("netapp.servicenetworking.goog"))' +parameters: + - !ruby/object:Api::Type::String + name: "location" + required: true + immutable: true + url_param_only: true + description: | + Name of region for this resource. The resource needs to be created in the region of the destination volume. + - !ruby/object:Api::Type::String + name: "volumeName" + description: The name of the existing source volume. + required: true + immutable: true + url_param_only: true + - !ruby/object:Api::Type::String + name: "name" + description: The name of the replication. Needs to be unique per location. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::Enum + name: "state" + description: | + Indicates the state of replication resource. State of the mirror itself is indicated in mirrorState. + values: + - :STATE_UNSPECIFIED + - :CREATING + - :READY + - :UPDATING + - :DELETING + - :ERROR + output: true + - !ruby/object:Api::Type::String + name: "stateDetails" + description: | + State details of the replication resource. + output: true + - !ruby/object:Api::Type::Enum + name: "role" + description: | + Reverting a replication can swap source and destination volume roles. This field indicates if the `location` hosts + the source or destination volume. For resume and revert and resume operations it is critical to understand + which volume is the source volume, since it will overwrite changes done to the destination volume. + values: + - :REPLICATION_ROLE_UNSPECIFIED + - :SOURCE + - :DESTINATION + output: true + - !ruby/object:Api::Type::Enum + name: "replicationSchedule" + description: | + Specifies the replication interval. + values: + - :EVERY_10_MINUTES + - :HOURLY + - :DAILY + required: true + - !ruby/object:Api::Type::Enum + name: "mirrorState" + description: | + Indicates the state of the mirror between source and destination volumes. Depending on the amount of data + in your source volume, PREPARING phase can take hours or days. mirrorState = MIRRORED indicates your baseline + transfer ended and destination volume became accessible read-only. TRANSFERRING means a MIRRORED volume + currently receives an update. Updated every 5 minutes. + values: + - :MIRROR_STATE_UNSPECIFIED + - :PREPARING + - :MIRRORED + - :STOPPED + - :TRANSFERRING + custom_flatten: templates/terraform/custom_flatten/netapp_volume_replicaton_mirror_state.go.erb + output: true + - !ruby/object:Api::Type::String + name: "createTime" + description: | + Create time of the active directory. A timestamp in RFC3339 UTC "Zulu" format. Examples: "2023-06-22T09:13:01.617Z". + output: true + - !ruby/object:Api::Type::String + name: "destinationVolume" + description: | + Full resource name of destination volume with format: `projects/{{project}}/locations/{{location}}/volumes/{{volumeId}}` + output: true + - !ruby/object:Api::Type::NestedObject + name: "transferStats" + description: |- + Replication transfer statistics. All statistics are updated every 5 minutes. + output: true + properties: + - !ruby/object:Api::Type::String + name: "transferBytes" + description: | + Number of bytes transferred so far in current transfer. + output: true + - !ruby/object:Api::Type::String + name: "totalTransferDuration" + description: | + Total time taken so far during current transfer. + output: true + - !ruby/object:Api::Type::String + name: "lastTransferBytes" + description: | + Size of last completed transfer in bytes. + output: true + - !ruby/object:Api::Type::String + name: "lastTransferDuration" + description: | + Time taken during last completed transfer. + output: true + - !ruby/object:Api::Type::String + name: "lagDuration" + description: | + The elapsed time since the creation of the snapshot on the source volume that was last replicated + to the destination volume. Lag time represents the difference in age of the destination volume + data in relation to the source volume data. + output: true + - !ruby/object:Api::Type::String + name: "updateTime" + description: | + Time when progress was updated last. A timestamp in RFC3339 UTC "Zulu" format. Examples: "2023-06-22T09:13:01.617Z". + output: true + - !ruby/object:Api::Type::String + name: "lastTransferEndTime" + description: | + Time when last transfer completed. A timestamp in RFC3339 UTC "Zulu" format. Examples: "2023-06-22T09:13:01.617Z". + output: true + - !ruby/object:Api::Type::String + name: "lastTransferError" + description: | + A message describing the cause of the last transfer failure. + output: true + - !ruby/object:Api::Type::KeyValueLabels + name: "labels" + description: | + Labels as key value pairs. Example: `{ "owner": "Bob", "department": "finance", "purpose": "testing" }` + - !ruby/object:Api::Type::NestedObject + name: "destinationVolumeParameters" + description: |- + Destination volume parameters. + # destinationVolumeParameters is only used on CREATE. Will not be returned on READ. + ignore_read: true + properties: + - !ruby/object:Api::Type::String + name: "storagePool" + description: | + Name of an existing storage pool for the destination volume with format: `projects/{{project}}/locations/{{location}}/storagePools/{{poolId}}` + immutable: true + required: true + - !ruby/object:Api::Type::String + name: "volumeId" + description: | + Name for the destination volume to be created. If not specified, the name of the source volume will be used. + immutable: true + default_from_api: true + - !ruby/object:Api::Type::String + name: "shareName" + description: | + Share name for destination volume. If not specified, name of source volume's share name will be used. + immutable: true + default_from_api: true + - !ruby/object:Api::Type::String + name: "description" + description: | + Description for the destination volume. + immutable: true + - !ruby/object:Api::Type::String + name: "sourceVolume" + description: | + Full resource name of source volume with format: `projects/{{project}}/locations/{{location}}/volumes/{{volumeId}}` + output: true + - !ruby/object:Api::Type::Boolean + name: "healthy" + description: | + Condition of the relationship. Can be one of the following: + - true: The replication relationship is healthy. It has not missed the most recent scheduled transfer. + - false: The replication relationship is not healthy. It has missed the most recent scheduled transfer. + output: true + - !ruby/object:Api::Type::String + name: "description" + description: | + An description of this resource. +virtual_fields: + - !ruby/object:Api::Type::Boolean + name: "delete_destination_volume" + description: | + A destination volume is created as part of replication creation. The destination volume will not became + under Terraform management unless you import it manually. If you delete the replication, this volume + will remain. + Setting this parameter to true will delete the *current* destination volume when destroying the + replication. If you reversed the replication direction, this will be your former source volume! + For production use, it is recommended to keep this parameter false to avoid accidental volume + deletion. Handle with care. Default is false. + default_value: false + - !ruby/object:Api::Type::Boolean + name: "replication_enabled" + description: | + Set to false to stop/break the mirror. Stopping the mirror makes the destination volume read-write + and act independently from the source volume. + Set to true to enable/resume the mirror. WARNING: Resuming a mirror overwrites any changes + done to the destination volume with the content of the source volume. + default_value: true + - !ruby/object:Api::Type::Boolean + name: "force_stopping" + description: | + Only replications with mirror_state=MIRRORED can be stopped. A replication in mirror_state=TRANSFERRING + currently receives an update and stopping the update might be undesirable. Set this parameter to true + to stop anyway. All data transferred to the destination will be discarded and content of destination + volume will remain at the state of the last successful update. Default is false. + default_value: false + - !ruby/object:Api::Type::Boolean + name: "wait_for_mirror" + description: | + Replication resource state is independent of mirror_state. With enough data, it can take many hours + for mirror_state to reach MIRRORED. If you want Terraform to wait for the mirror to finish on + create/stop/resume operations, set this parameter to true. Default is false. + default_value: false +custom_code: !ruby/object:Provider::Terraform::CustomCode + constants: templates/terraform/constants/netapp_volume_replication.go.erb + post_create: templates/terraform/post_create/netapp_volume_replication_post_create.go.erb + pre_delete: templates/terraform/pre_delete/netapp_volume_replication_stop_before_delete.go.erb + post_delete: templates/terraform/post_delete/netapp_volume_replication_delete_destination_volume.go.erb + post_update: templates/terraform/post_update/netapp_volume_replication_mirror_state.go.erb diff --git a/mmv1/templates/terraform/constants/netapp_volume_replication.go.erb b/mmv1/templates/terraform/constants/netapp_volume_replication.go.erb new file mode 100644 index 000000000000..10ec7b806253 --- /dev/null +++ b/mmv1/templates/terraform/constants/netapp_volume_replication.go.erb @@ -0,0 +1,51 @@ +// Custom function to wait for mirrorState target states +func NetAppVolumeReplicationWaitForMirror(d *schema.ResourceData, meta interface{}, targetState string) error { + config := meta.(*transport_tpg.Config) + userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) + if err != nil { + return err + } + + url, err := tpgresource.ReplaceVars(d, config, "{{NetappBasePath}}projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications/{{name}}") + if err != nil { + return err + } + + billingProject := "" + + project, err := tpgresource.GetProject(d, config) + if err != nil { + return fmt.Errorf("Error fetching project for volume replication: %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 + } + + for { + 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("NetappVolumeReplication %q", d.Id())) + } + + log.Printf("[DEBUG] waiting for mirrorState. actual: %v, target: %v", res["mirrorState"], targetState) + + if res["mirrorState"] == targetState { + break + } + + time.Sleep(30 * time.Second) + // This method can potentially run for days, e.g. when setting up a replication for a source volume + // with dozens of TiB of data. Timeout handling yes/no? + } + + return nil +} \ No newline at end of file diff --git a/mmv1/templates/terraform/custom_flatten/netapp_volume_replicaton_mirror_state.go.erb b/mmv1/templates/terraform/custom_flatten/netapp_volume_replicaton_mirror_state.go.erb new file mode 100644 index 000000000000..90881e839b6e --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/netapp_volume_replicaton_mirror_state.go.erb @@ -0,0 +1,20 @@ +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Actual state of replication_enabled depends on mirrorState. let's update it. + // This is to pickup manual user STOP/RESUME operations on the replication. + if v == nil { + return v + } + + if v.(string) == "STOPPED" { + if err := d.Set("replication_enabled", false); err != nil { + return fmt.Errorf("Error setting replication_enabled: %s", err) + } + } else { + if err := d.Set("replication_enabled", true); err != nil { + return fmt.Errorf("Error setting replication_enabled: %s", err) + } + } + log.Printf("[DEBUG] value of replication_state : %v", d.Get("replication_enabled")) + + return v +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/netapp_volume_replication_create.tf.erb b/mmv1/templates/terraform/examples/netapp_volume_replication_create.tf.erb new file mode 100644 index 000000000000..07b69c542b2b --- /dev/null +++ b/mmv1/templates/terraform/examples/netapp_volume_replication_create.tf.erb @@ -0,0 +1,54 @@ + +data "google_compute_network" "default" { + name = "<%= ctx[:vars]['network_name'] %>" +} + +resource "google_netapp_storage_pool" "source_pool" { + name = "<%= ctx[:vars]['source_pool_name'] %>" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_storage_pool" "destination_pool" { + name = "<%= ctx[:vars]['destination_pool_name'] %>" + location = "us-west2" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_volume" "source_volume" { + location = google_netapp_storage_pool.source_pool.location + name = "<%= ctx[:vars]['volume_name'] %>" + capacity_gib = 100 + share_name = "<%= ctx[:vars]['volume_name'] %>" + storage_pool = google_netapp_storage_pool.source_pool.name + protocols = [ + "NFSV3" + ] + deletion_policy = "FORCE" +} + +resource "google_netapp_volume_replication" "<%= ctx[:primary_resource_id] %>" { + depends_on = [google_netapp_volume.source_volume] + location = google_netapp_volume.source_volume.location + volume_name = google_netapp_volume.source_volume.name + name = "<%= ctx[:vars]['replication_name'] %>" + replication_schedule = "EVERY_10_MINUTES" + description = "This is a replication resource" + destination_volume_parameters { + storage_pool = google_netapp_storage_pool.destination_pool.id + volume_id = "<%= ctx[:vars]['destination_volume'] %>" + # Keeping the share_name of source and destination the same + # simplifies implementing client failover concepts + share_name = "<%= ctx[:vars]['volume_name'] %>" + description = "This is a replicated volume" + } + # WARNING: Setting delete_destination_volume to true, will delete the + # CURRENT destination volume if the replication is deleted. Omit the field + # or set delete_destination_volume=false to avoid accidental volume deletion. + delete_destination_volume = true + wait_for_mirror = true +} diff --git a/mmv1/templates/terraform/post_create/netapp_volume_replication_post_create.go.erb b/mmv1/templates/terraform/post_create/netapp_volume_replication_post_create.go.erb new file mode 100644 index 000000000000..b2d44a9c063e --- /dev/null +++ b/mmv1/templates/terraform/post_create/netapp_volume_replication_post_create.go.erb @@ -0,0 +1,7 @@ +if d.Get("wait_for_mirror").(bool) == true { + // Wait for mirrorState=MIRRORED before treating the resource as created + err = NetAppVolumeReplicationWaitForMirror(d, meta, "MIRRORED") + if err != nil { + return fmt.Errorf("Error waiting for volume replication to reach mirror_state==MIRRORED: %s", err) + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/post_delete/netapp_volume_replication_delete_destination_volume.go.erb b/mmv1/templates/terraform/post_delete/netapp_volume_replication_delete_destination_volume.go.erb new file mode 100644 index 000000000000..5a14f1fb407c --- /dev/null +++ b/mmv1/templates/terraform/post_delete/netapp_volume_replication_delete_destination_volume.go.erb @@ -0,0 +1,34 @@ +// A replication CREATE also created a destination volume +// A user can chooses to delete the destination volume after deleting the replication +if d.Get("delete_destination_volume").(bool) == true { + log.Printf("[DEBUG] delete_destination_volume is true. Deleting destination volume %v", d.Get("destination_volume")) + destination_volume := d.Get("destination_volume").(string) + del_url, err := tpgresource.ReplaceVars(d, config, "{{NetappBasePath}}"+destination_volume+"?force=true") + if err != nil { + return err + } + + var obj map[string]interface{} + res_del, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "DELETE", + Project: billingProject, + RawURL: del_url, + UserAgent: userAgent, + Body: obj, + Timeout: d.Timeout(schema.TimeoutDelete), + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, "Volume") + } + + err = NetappOperationWaitTime( + config, res_del, project, "Deleting destination volume", userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting destination Volume %q: %#v", destination_volume, res_del) +} \ No newline at end of file diff --git a/mmv1/templates/terraform/post_update/netapp_volume_replication_mirror_state.go.erb b/mmv1/templates/terraform/post_update/netapp_volume_replication_mirror_state.go.erb new file mode 100644 index 000000000000..57a7146702e5 --- /dev/null +++ b/mmv1/templates/terraform/post_update/netapp_volume_replication_mirror_state.go.erb @@ -0,0 +1,89 @@ +// Manage stopping and resuming a mirror + +var obj2 map[string]interface{} +do_change := false +var action string +var targetState string +// state transitions +// there can be a glitch is a transfer starts/ends between reading mirrorState +// and sending the action. This will be very rare. No workaround. +if d.Get("replication_enabled").(bool) == true { + switch d.Get("mirror_state").(string) { + case "STOPPED": + // replication_enabled==true, mirrorState==STOPPED -> resume + action = "resume" + targetState = "MIRRORED" + do_change = true + default: + // replication_enabled==true, mirrorState!=STOPPED -> NOOP + do_change = false + } +} else { + switch d.Get("mirror_state").(string) { + case "MIRRORED": + // replication_enabled==false, mirrorState==MIRRORED -> stop + action = "stop" + targetState = "STOPPED" + do_change = true + case "TRANSFERRING": + // replication_enabled==false, mirrorState==TRANSFERRING -> force stop + // User needs to add force_stopping = true, otherwise will receive error + action = "stop" + targetState = "STOPPED" + do_change = true + case "PREPARING": + // replication_enabled==false, mirrorState==PREPARING -> stop + // Currently cannot be stopped. User will receive following error: + // Error code 3, message: invalid request error: "Replication in preparing state. Please wait until replication is in 'READY' STATE and try again later.". + // User needs to wait until mirrorState=MIRRORED + action = "stop" + targetState = "STOPPED" + do_change = true + default: + // replication_enabled==false, mirrorState==STOPPED -> NOOP + do_change = false + } + + if do_change == true && d.Get("force_stopping").(bool) == true { + obj2 = map[string]interface{}{ + "force": true, + } + } +} + +if do_change { + // We need to send STOP/RESUME API calls + rawurl, err := tpgresource.ReplaceVars(d, config, "{{NetappBasePath}}projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications/{{name}}:"+action) + if err != nil { + return err + } + + res2, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: rawurl, + UserAgent: userAgent, + Body: obj2, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + if err != nil { + return fmt.Errorf("Error stopping/resuming replication %q: %s", d.Id(), err) + } + + err = NetappOperationWaitTime( + config, res2, project, "volume replication "+action, userAgent, + d.Timeout(schema.TimeoutDelete)) + + if err != nil { + return err + } + + // If user specified to wait for mirror operations, wait to reach target state + if d.Get("wait_for_mirror").(bool) == true { + err = NetAppVolumeReplicationWaitForMirror(d, meta, targetState) + if err != nil { + return fmt.Errorf("Error waiting for volume replication to reach mirror_state==%s: %s", targetState, err) + } + } +} diff --git a/mmv1/templates/terraform/pre_delete/netapp_volume_replication_stop_before_delete.go.erb b/mmv1/templates/terraform/pre_delete/netapp_volume_replication_stop_before_delete.go.erb new file mode 100644 index 000000000000..4e5c188acf2a --- /dev/null +++ b/mmv1/templates/terraform/pre_delete/netapp_volume_replication_stop_before_delete.go.erb @@ -0,0 +1,33 @@ +// A replication can only be deleted if mirrorState==STOPPED +// We are about to delete the replication and need to stop the mirror before. +// FYI: Stopping a PREPARING mirror currently doesn't work. User have to wait until +// mirror reaches MIRRORED. +if d.Get("mirror_state") != "STOPPED" { + rawurl, err := tpgresource.ReplaceVars(d, config, "{{NetappBasePath}}projects/{{project}}/locations/{{location}}/volumes/{{volume_name}}/replications/{{name}}:stop") + if err != nil { + return err + } + + reso, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "POST", + Project: billingProject, + RawURL: rawurl, + UserAgent: userAgent, + // We delete anyway, so lets always use force stop + Body: map[string]interface{}{ + "force": true, + }, + Timeout: d.Timeout(schema.TimeoutUpdate), + }) + if err != nil { + return fmt.Errorf("Error stopping volume replication %q before deleting it: %s", d.Id(), err) + } + + err = NetappOperationWaitTime( + config, reso, project, "Deleting volume replication", userAgent, + d.Timeout(schema.TimeoutDelete)) + if err != nil { + return err + } +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_volume_replication_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_volume_replication_test.go new file mode 100644 index 000000000000..e663c41e7274 --- /dev/null +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_volume_replication_test.go @@ -0,0 +1,306 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package netapp_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccNetappVolumeReplication_netappVolumeReplicationCreateExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "network_name": acctest.BootstrapSharedServiceNetworkingConnection(t, "gcnv-network-config-1", acctest.ServiceNetworkWithParentService("netapp.servicenetworking.goog")), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetappVolumeReplicationDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetappVolumeReplication_netappVolumeReplicationCreateExample_basic(context), + }, + { + ResourceName: "google_netapp_volume_replication.test_replication", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"destination_volume_parameters", "location", "volume_name", "name", "delete_destination_volume", "replication_enabled", "force_stopping", "wait_for_mirror", "labels", "terraform_labels"}, + }, + { + Config: testAccNetappVolumeReplication_netappVolumeReplicationCreateExample_stop(context), + }, + { + ResourceName: "google_netapp_volume_replication.test_replication", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"destination_volume_parameters", "location", "volume_name", "name", "delete_destination_volume", "replication_enabled", "force_stopping", "wait_for_mirror", "labels", "terraform_labels"}, + }, + { + Config: testAccNetappVolumeReplication_netappVolumeReplicationCreateExample_resume(context), + }, + { + ResourceName: "google_netapp_volume_replication.test_replication", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"destination_volume_parameters", "location", "volume_name", "name", "delete_destination_volume", "replication_enabled", "force_stopping", "wait_for_mirror", "labels", "terraform_labels"}, + }, + { + Config: testAccNetappVolumeReplication_netappVolumeReplicationCreateExample_update(context), + }, + { + ResourceName: "google_netapp_volume_replication.test_replication", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"destination_volume_parameters", "location", "volume_name", "name", "delete_destination_volume", "replication_enabled", "force_stopping", "wait_for_mirror", "labels", "terraform_labels"}, + }, + }, + }) +} + +// Basic replication +func testAccNetappVolumeReplication_netappVolumeReplicationCreateExample_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "%{network_name}" +} + +resource "google_netapp_storage_pool" "source_pool" { + name = "tf-test-source-pool%{random_suffix}" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_storage_pool" "destination_pool" { + name = "tf-test-destination-pool%{random_suffix}" + location = "us-west2" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_volume" "source_volume" { + location = google_netapp_storage_pool.source_pool.location + name = "tf-test-source-volume%{random_suffix}" + capacity_gib = 100 + share_name = "tf-test-source-volume%{random_suffix}" + storage_pool = google_netapp_storage_pool.source_pool.name + protocols = [ + "NFSV3" + ] + deletion_policy = "FORCE" +} + +resource "google_netapp_volume_replication" "test_replication" { + depends_on = [google_netapp_volume.source_volume] + location = google_netapp_volume.source_volume.location + volume_name = google_netapp_volume.source_volume.name + name = "tf-test-test-replication%{random_suffix}" + replication_schedule = "EVERY_10_MINUTES" + destination_volume_parameters { + storage_pool = google_netapp_storage_pool.destination_pool.id + volume_id = "tf-test-destination-volume%{random_suffix}" + # Keeping the share_name of source and destination the same + # simplifies implementing client failover concepts + share_name = "tf-test-source-volume%{random_suffix}" + description = "This is a replicated volume" + } + delete_destination_volume = true + wait_for_mirror = true +} +`, context) +} + +// Update parameters +func testAccNetappVolumeReplication_netappVolumeReplicationCreateExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "%{network_name}" +} + +resource "google_netapp_storage_pool" "source_pool" { + name = "tf-test-source-pool%{random_suffix}" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_storage_pool" "destination_pool" { + name = "tf-test-destination-pool%{random_suffix}" + location = "us-west2" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_volume" "source_volume" { + location = google_netapp_storage_pool.source_pool.location + name = "tf-test-source-volume%{random_suffix}" + capacity_gib = 100 + share_name = "tf-test-source-volume%{random_suffix}" + storage_pool = google_netapp_storage_pool.source_pool.name + protocols = [ + "NFSV3" + ] + deletion_policy = "FORCE" +} + +resource "google_netapp_volume_replication" "test_replication" { + depends_on = [google_netapp_volume.source_volume] + location = google_netapp_volume.source_volume.location + volume_name = google_netapp_volume.source_volume.name + name = "tf-test-test-replication%{random_suffix}" + replication_schedule = "EVERY_10_MINUTES" + description = "This is a replication resource" + labels = { + key = "test" + value = "replication" + } + destination_volume_parameters { + storage_pool = google_netapp_storage_pool.destination_pool.id + volume_id = "tf-test-destination-volume%{random_suffix}" + # Keeping the share_name of source and destination the same + # simplifies implementing client failover concepts + share_name = "tf-test-source-volume%{random_suffix}" + description = "This is a replicated volume" + } + replication_enabled = true + delete_destination_volume = true + force_stopping = true + wait_for_mirror = true +} +`, context) +} + +// Stop replication +func testAccNetappVolumeReplication_netappVolumeReplicationCreateExample_stop(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "%{network_name}" +} + +resource "google_netapp_storage_pool" "source_pool" { + name = "tf-test-source-pool%{random_suffix}" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_storage_pool" "destination_pool" { + name = "tf-test-destination-pool%{random_suffix}" + location = "us-west2" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_volume" "source_volume" { + location = google_netapp_storage_pool.source_pool.location + name = "tf-test-source-volume%{random_suffix}" + capacity_gib = 100 + share_name = "tf-test-source-volume%{random_suffix}" + storage_pool = google_netapp_storage_pool.source_pool.name + protocols = [ + "NFSV3" + ] + deletion_policy = "FORCE" +} + +resource "google_netapp_volume_replication" "test_replication" { + depends_on = [google_netapp_volume.source_volume] + location = google_netapp_volume.source_volume.location + volume_name = google_netapp_volume.source_volume.name + name = "tf-test-test-replication%{random_suffix}" + replication_schedule = "EVERY_10_MINUTES" + description = "This is a replication resource" + labels = { + key = "test" + value = "replication2" + } + destination_volume_parameters { + storage_pool = google_netapp_storage_pool.destination_pool.id + volume_id = "tf-test-destination-volume%{random_suffix}" + # Keeping the share_name of source and destination the same + # simplifies implementing client failover concepts + share_name = "tf-test-source-volume%{random_suffix}" + description = "This is a replicated volume" + } + replication_enabled = false + delete_destination_volume = true + force_stopping = true + wait_for_mirror = true +} +`, context) +} + +// resume replication +func testAccNetappVolumeReplication_netappVolumeReplicationCreateExample_resume(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_compute_network" "default" { + name = "%{network_name}" +} + +resource "google_netapp_storage_pool" "source_pool" { + name = "tf-test-source-pool%{random_suffix}" + location = "us-central1" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_storage_pool" "destination_pool" { + name = "tf-test-destination-pool%{random_suffix}" + location = "us-west2" + service_level = "PREMIUM" + capacity_gib = 2048 + network = data.google_compute_network.default.id +} + +resource "google_netapp_volume" "source_volume" { + location = google_netapp_storage_pool.source_pool.location + name = "tf-test-source-volume%{random_suffix}" + capacity_gib = 100 + share_name = "tf-test-source-volume%{random_suffix}" + storage_pool = google_netapp_storage_pool.source_pool.name + protocols = [ + "NFSV3" + ] + deletion_policy = "FORCE" +} + +resource "google_netapp_volume_replication" "test_replication" { + depends_on = [google_netapp_volume.source_volume] + location = google_netapp_volume.source_volume.location + volume_name = google_netapp_volume.source_volume.name + name = "tf-test-test-replication%{random_suffix}" + replication_schedule = "HOURLY" + description = "This is a replication resource" + labels = { + key = "test" + value = "replication2" + } + destination_volume_parameters { + storage_pool = google_netapp_storage_pool.destination_pool.id + volume_id = "tf-test-destination-volume%{random_suffix}" + # Keeping the share_name of source and destination the same + # simplifies implementing client failover concepts + share_name = "tf-test-source-volume%{random_suffix}" + description = "This is a replicated volume" + } + replication_enabled = true + delete_destination_volume = true + force_stopping = true + wait_for_mirror = true +} +`, context) +} From d9c78713a1229b452f880d271f76f8923fa9f76b Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 21 Feb 2024 15:42:34 -0800 Subject: [PATCH 014/200] Ensured that beta runs in TeamCity use only beta paths (#10025) * Ensured that beta runs in TeamCity use only beta paths * Added tests for sweeper package path --- .../terraform/.teamcity/CONTRIBUTION_GUIDE.md | 10 ++- .../.teamcity/components/inputs/packages.kt | 62 ++++++++++++++++--- .../projects/project_sweeper_project.kt | 4 +- .../components/projects/reused/mm_upstream.kt | 20 ++++-- .../projects/reused/nightly_tests.kt | 12 +++- .../components/projects/root_project.kt | 13 ++-- .../terraform/.teamcity/tests/sweepers.kt | 51 +++++++++++++++ 7 files changed, 144 insertions(+), 28 deletions(-) diff --git a/mmv1/third_party/terraform/.teamcity/CONTRIBUTION_GUIDE.md b/mmv1/third_party/terraform/.teamcity/CONTRIBUTION_GUIDE.md index 911460cd190c..5d803e699493 100644 --- a/mmv1/third_party/terraform/.teamcity/CONTRIBUTION_GUIDE.md +++ b/mmv1/third_party/terraform/.teamcity/CONTRIBUTION_GUIDE.md @@ -17,6 +17,14 @@ Note: these instructions need to be tested and improved. Please contact @SarahFr You will need to install: * Java 17 * `brew install openjdk@17` +* Maven + * `brew install --ignore-dependencies maven` + +Add the following to `~/.zshrc` and reload your terminal: + +``` +export JAVA_HOME=/usr/local/Cellar/openjdk@17/17.0.9/libexec/openjdk.jdk/Contents/Home +``` ## Getting started @@ -27,7 +35,7 @@ You will need to install: * Run `make validate` to check the code for both: * Errors that prevent the code building * Logical errors in TeamCity-specific logic, e.g. the need for unique identifiers for builds. -* Run `make tests` to run the automated tests defined in `.teamcity/tests` +* Run `make test` to run the automated tests defined in `.teamcity/tests` ## Rough description of the code base diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt index 19b107e2e72d..5ea3d2a5d48a 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt @@ -7,7 +7,7 @@ package generated -var PackagesList = mapOf( +var PackagesListGa = mapOf( "envvar" to mapOf( "name" to "envvar", "displayName" to "Environment Variables", @@ -50,7 +50,7 @@ var PackagesList = mapOf( ) ) -var SweepersList = mapOf( +var SweepersListGa = mapOf( "sweeper" to mapOf( "name" to "sweeper", "displayName" to "Sweeper", @@ -58,11 +58,53 @@ var SweepersList = mapOf( ) ) -fun GetPackageNameList(): List { - var packageNameList: ArrayList = arrayListOf() - PackagesList.forEach{ p -> - var packageName = p.value.getValue("name").toString() - packageNameList.add(packageName) - } - return packageNameList -} +var PackagesListBeta = mapOf( + "envvar" to mapOf( + "name" to "envvar", + "displayName" to "Environment Variables", + "path" to "./google-beta/envvar" + ), + "fwmodels" to mapOf( + "name" to "fwmodels", + "displayName" to "Framework Models", + "path" to "./google-beta/fwmodels" + ), + "fwprovider" to mapOf( + "name" to "fwprovider", + "displayName" to "Framework Provider", + "path" to "./google-beta/fwprovider" + ), + "fwresource" to mapOf( + "name" to "fwresource", + "displayName" to "Framework Resource", + "path" to "./google-beta/fwresource" + ), + "fwtransport" to mapOf( + "name" to "fwtransport", + "displayName" to "Framework Transport", + "path" to "./google-beta/fwtransport" + ), + "provider" to mapOf( + "name" to "provider", + "displayName" to "SDK Provider", + "path" to "./google-beta/provider" + ), + "transport" to mapOf( + "name" to "transport", + "displayName" to "Transport", + "path" to "./google-beta/transport" + ), + "google" to mapOf( + "name" to "google", + "displayName" to "Google", + "path" to "./google-beta" + ) +) + +var SweepersListBeta = mapOf( + "sweeper" to mapOf( + "name" to "sweeper", + "displayName" to "Sweeper", + "path" to "./google-beta/sweeper" + ) +) diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt b/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt index f8da47ef5290..732822a52ff6 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt @@ -12,7 +12,7 @@ import SharedResourceNameBeta import SharedResourceNameGa import SharedResourceNameVcr import builds.* -import generated.SweepersList +import generated.SweepersListGa import jetbrains.buildServer.configs.kotlin.Project import replaceCharsId import vcs_roots.HashiCorpVCSRootGa @@ -31,7 +31,7 @@ fun projectSweeperSubProject(allConfig: AllContextParameters): Project { // Create build config for sweeping project resources // Uses the HashiCorpVCSRootGa VCS Root so that the latest sweepers in hashicorp/terraform-provider-google are used - val serviceSweeperConfig = BuildConfigurationForProjectSweeper("N/A", ProjectSweeperName, SweepersList, projectId, HashiCorpVCSRootGa, sharedResources, gaConfig) + val serviceSweeperConfig = BuildConfigurationForProjectSweeper("N/A", ProjectSweeperName, SweepersListGa, projectId, HashiCorpVCSRootGa, sharedResources, gaConfig) val trigger = NightlyTriggerConfiguration(startHour=12) serviceSweeperConfig.addTrigger(trigger) diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt index 3b57d2fc12c4..c26ed498edd4 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt @@ -13,10 +13,12 @@ import ProviderNameGa import ServiceSweeperName import SharedResourceNameVcr import builds.* -import generated.PackagesList -import generated.ServicesListGa +import generated.PackagesListBeta +import generated.PackagesListGa import generated.ServicesListBeta -import generated.SweepersList +import generated.ServicesListGa +import generated.SweepersListBeta +import generated.SweepersListGa import jetbrains.buildServer.configs.kotlin.BuildType import jetbrains.buildServer.configs.kotlin.Project import jetbrains.buildServer.configs.kotlin.vcs.GitVcsRoot @@ -36,7 +38,13 @@ fun mmUpstream(parentProject: String, providerName: String, vcsRoot: GitVcsRoot, val packageBuildConfigs = BuildConfigurationsForPackages(allPackages, providerName, projectId, vcsRoot, sharedResources, config) // Create build config for sweeping the VCR test project - everything except projects - val serviceSweeperConfig = BuildConfigurationForServiceSweeper(providerName, ServiceSweeperName, SweepersList, projectId, vcsRoot, sharedResources, config) + var sweepersList: Map> + when(providerName) { + ProviderNameGa -> sweepersList = SweepersListGa + ProviderNameBeta -> sweepersList = SweepersListBeta + else -> throw Exception("Provider name not supplied when generating a nightly test subproject") + } + val serviceSweeperConfig = BuildConfigurationForServiceSweeper(providerName, ServiceSweeperName, sweepersList, projectId, vcsRoot, sharedResources, config) val trigger = NightlyTriggerConfiguration(startHour=12) serviceSweeperConfig.addTrigger(trigger) // Only the sweeper is on a schedule in this project @@ -60,10 +68,10 @@ fun mmUpstream(parentProject: String, providerName: String, vcsRoot: GitVcsRoot, fun getAllPackageInProviderVersion(providerName: String): Map> { var allPackages: Map> = mapOf() if (providerName == ProviderNameGa){ - allPackages = PackagesList + ServicesListGa + allPackages = PackagesListGa + ServicesListGa } if (providerName == ProviderNameBeta){ - allPackages = PackagesList + ServicesListBeta + allPackages = PackagesListBeta + ServicesListBeta } return allPackages } \ No newline at end of file diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt index 0c531f952e40..6fda2b7b7ab1 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt @@ -14,8 +14,8 @@ import ServiceSweeperName import SharedResourceNameBeta import SharedResourceNameGa import builds.* -import generated.PackagesList -import generated.SweepersList +import generated.SweepersListBeta +import generated.SweepersListGa import jetbrains.buildServer.configs.kotlin.Project import jetbrains.buildServer.configs.kotlin.vcs.GitVcsRoot import replaceCharsId @@ -44,7 +44,13 @@ fun nightlyTests(parentProject:String, providerName: String, vcsRoot: GitVcsRoot } // Create build config for sweeping the nightly test project - val serviceSweeperConfig = BuildConfigurationForServiceSweeper(providerName, ServiceSweeperName, SweepersList, projectId, vcsRoot, sharedResources, config) + var sweepersList: Map> + when(providerName) { + ProviderNameGa -> sweepersList = SweepersListGa + ProviderNameBeta -> sweepersList = SweepersListBeta + else -> throw Exception("Provider name not supplied when generating a nightly test subproject") + } + val serviceSweeperConfig = BuildConfigurationForServiceSweeper(providerName, ServiceSweeperName, sweepersList, projectId, vcsRoot, sharedResources, config) val sweeperTrigger = NightlyTriggerConfiguration(startHour=12) // Override hour serviceSweeperConfig.addTrigger(sweeperTrigger) diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt index c3ffd869756f..0c130da8eca5 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt @@ -12,7 +12,8 @@ import SharedResourceNameGa import SharedResourceNameVcr import builds.AllContextParameters import builds.readOnlySettings -import generated.GetPackageNameList +import generated.PackagesListBeta +import generated.PackagesListGa import generated.ServicesListBeta import generated.ServicesListGa import jetbrains.buildServer.configs.kotlin.Project @@ -38,21 +39,21 @@ fun googleCloudRootProject(allConfig: AllContextParameters): Project { id = "GA_NIGHTLY_SERVICE_LOCK_SHARED_RESOURCE" name = SharedResourceNameGa enabled = true - resourceType = customValues(getServiceNameList(ServicesListGa) + GetPackageNameList()) + resourceType = customValues(getPackageNameList(ServicesListGa) + getPackageNameList(PackagesListGa)) } // For controlling sweeping of the Beta nightly test project sharedResource { id = "BETA_NIGHTLY_SERVICE_LOCK_SHARED_RESOURCE" name = SharedResourceNameBeta enabled = true - resourceType = customValues(getServiceNameList(ServicesListBeta) + GetPackageNameList()) + resourceType = customValues(getPackageNameList(ServicesListBeta) + getPackageNameList(PackagesListBeta)) } // For controlling sweeping of the PR testing project sharedResource { id = "PR_SERVICE_LOCK_SHARED_RESOURCE" name = SharedResourceNameVcr enabled = true - resourceType = customValues(getServiceNameList(ServicesListBeta) + GetPackageNameList()) // Use Beta list of services here, assuming Beta is a superset of GA + resourceType = customValues(getPackageNameList(ServicesListBeta) + getPackageNameList(PackagesListBeta)) // Use Beta list of services here, assuming Beta is a superset of GA } } @@ -66,11 +67,11 @@ fun googleCloudRootProject(allConfig: AllContextParameters): Project { } } -fun getServiceNameList(servicesList: Map>): List { +fun getPackageNameList(servicesList: Map>): List { var serviceNameList: ArrayList = arrayListOf() servicesList.forEach{ s -> var serviceName = s.value.getValue("name").toString() serviceNameList.add(serviceName) } return serviceNameList -} \ No newline at end of file +} diff --git a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt index 27e55f737a1f..1603aaeda776 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt @@ -9,6 +9,7 @@ package tests import ServiceSweeperName import jetbrains.buildServer.configs.kotlin.BuildType +import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test import jetbrains.buildServer.configs.kotlin.Project @@ -62,6 +63,31 @@ class SweeperTests { assertTrue("env.SKIP_PROJECT_SWEEPER is set to a non-empty string, so project sweepers are skipped. Value = `${value}` ", value != "") } + @Test + fun gaNightlyProjectServiceSweeperRunsInGoogle() { + val project = googleCloudRootProject(testContextParameters()) + + // Find GA nightly test project + val gaProject: Project? = project.subProjects.find { p-> p.name == gaProjectName} + if (gaProject == null) { + Assert.fail("Could not find the Google (GA) project") + } + val gaNightlyTestProject: Project? = gaProject!!.subProjects.find { p-> p.name == nightlyTestsProjectName} + if (gaNightlyTestProject == null) { + Assert.fail("Could not find the Google (GA) Nightly Test project") + } + + // Find sweeper inside + val sweeper: BuildType? = gaNightlyTestProject!!.buildTypes.find { p-> p.name == ServiceSweeperName} + if (sweeper == null) { + Assert.fail("Could not find the sweeper build in the Google (GA) Nightly Test project") + } + + // Check PACKAGE_PATH is in google (not google-beta) + val value = sweeper!!.params.findRawParam("PACKAGE_PATH")!!.value + assertEquals("./google/sweeper", value) + } + @Test fun betaNightlyProjectServiceSweeperSkipsProjectSweep() { val project = googleCloudRootProject(testContextParameters()) @@ -88,4 +114,29 @@ class SweeperTests { val value = sweeper!!.params.findRawParam("env.SKIP_PROJECT_SWEEPER")!!.value assertTrue("env.SKIP_PROJECT_SWEEPER is set to a non-empty string, so project sweepers are skipped. Value = `${value}` ", value != "") } + + @Test + fun betaNightlyProjectServiceSweeperRunsInGoogleBeta() { + val project = googleCloudRootProject(testContextParameters()) + + // Find Beta nightly test project + val betaProject: Project? = project.subProjects.find { p-> p.name == betaProjectName} + if (betaProject == null) { + Assert.fail("Could not find the Google (GA) project") + } + val betaNightlyTestProject: Project? = betaProject!!.subProjects.find { p-> p.name == nightlyTestsProjectName} + if (betaNightlyTestProject == null) { + Assert.fail("Could not find the Google (GA) Nightly Test project") + } + + // Find sweeper inside + val sweeper: BuildType? = betaNightlyTestProject!!.buildTypes.find { p-> p.name == ServiceSweeperName} + if (sweeper == null) { + Assert.fail("Could not find the sweeper build in the Google (GA) Nightly Test project") + } + + // Check PACKAGE_PATH is in google-beta + val value = sweeper!!.params.findRawParam("PACKAGE_PATH")!!.value + assertEquals("./google-beta/sweeper", value) + } } From f45d7c311f1b4b90d56222c7e1ed8929c919b136 Mon Sep 17 00:00:00 2001 From: Yanwei Guo Date: Thu, 22 Feb 2024 09:31:17 -0800 Subject: [PATCH 015/200] Adds description for default value of `cpuidle` field (#10005) * add description * remove tail space --- mmv1/products/cloudrunv2/Service.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index 1d4c3b7a0895..4c7198049bfe 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -430,7 +430,8 @@ properties: - !ruby/object:Api::Type::Boolean name: 'cpuIdle' description: |- - Determines whether CPU should be throttled or not outside of requests. + Determines whether CPU is only allocated during requests. True by default if the parent `resources` field is not set. However, if + `resources` is set, this field must be explicitly set to true to preserve the default behavior. - !ruby/object:Api::Type::Boolean name: 'startupCpuBoost' description: |- From f60f2e6424a7eb3746a8b8cfff9fccceaa272ab7 Mon Sep 17 00:00:00 2001 From: Hamzawy63 <43001514+Hamzawy63@users.noreply.github.com> Date: Thu, 22 Feb 2024 19:29:01 +0100 Subject: [PATCH 016/200] Add location field in DNS authorization resource. (#9968) * Add location field in DNS authorization resource * Fixed the provider version of the updated config --------- Co-authored-by: Hamza Hassan --- .../certificatemanager/DnsAuthorization.yaml | 17 +++- ...ate_manager_dns_authorization_basic.tf.erb | 3 +- ...rtificate_manager_dns_authorization.go.erb | 91 +++++++++++++++++++ ..._manager_dns_authorization_upgrade_test.go | 78 ++++++++++++++++ 4 files changed, 184 insertions(+), 5 deletions(-) create mode 100644 mmv1/templates/terraform/state_migrations/certificate_manager_dns_authorization.go.erb create mode 100644 mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_dns_authorization_upgrade_test.go diff --git a/mmv1/products/certificatemanager/DnsAuthorization.yaml b/mmv1/products/certificatemanager/DnsAuthorization.yaml index bcb50c60c329..33cd7604ed80 100644 --- a/mmv1/products/certificatemanager/DnsAuthorization.yaml +++ b/mmv1/products/certificatemanager/DnsAuthorization.yaml @@ -13,9 +13,9 @@ --- !ruby/object:Api::Resource name: 'DnsAuthorization' -base_url: 'projects/{{project}}/locations/global/dnsAuthorizations' -create_url: 'projects/{{project}}/locations/global/dnsAuthorizations?dnsAuthorizationId={{name}}' -self_link: 'projects/{{project}}/locations/global/dnsAuthorizations/{{name}}' +base_url: 'projects/{{project}}/locations/{{location}}/dnsAuthorizations' +create_url: 'projects/{{project}}/locations/{{location}}/dnsAuthorizations?dnsAuthorizationId={{name}}' +self_link: 'projects/{{project}}/locations/{{location}}/dnsAuthorizations/{{name}}' update_verb: :PATCH update_mask: true description: | @@ -39,7 +39,9 @@ async: !ruby/object:Api::OpAsync docs: !ruby/object:Provider::Terraform::Docs autogen_async: true import_format: - ['projects/{{project}}/locations/global/dnsAuthorizations/{{name}}'] + ['projects/{{project}}/locations/{{location}}/dnsAuthorizations/{{name}}'] +schema_version: 1 +state_upgraders: true examples: - !ruby/object:Provider::Terraform::Examples name: 'certificate_manager_dns_authorization_basic' @@ -58,6 +60,13 @@ parameters: Name of the resource; provided by the client when the resource is created. The name must be 1-64 characters long, and match the regular expression [a-zA-Z][a-zA-Z0-9_-]* which means the first character must be a letter, and all following characters must be a dash, underscore, letter or digit. + - !ruby/object:Api::Type::String + name: 'location' + description: | + The Certificate Manager location. If not specified, "global" is used. + default_value: global + immutable: true + url_param_only: true properties: - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/templates/terraform/examples/certificate_manager_dns_authorization_basic.tf.erb b/mmv1/templates/terraform/examples/certificate_manager_dns_authorization_basic.tf.erb index c5abd47bc47b..a63cbe5392b2 100644 --- a/mmv1/templates/terraform/examples/certificate_manager_dns_authorization_basic.tf.erb +++ b/mmv1/templates/terraform/examples/certificate_manager_dns_authorization_basic.tf.erb @@ -1,6 +1,7 @@ resource "google_certificate_manager_dns_authorization" "<%= ctx[:primary_resource_id] %>" { name = "<%= ctx[:vars]['dns_auth_name'] %>" - description = "The default dnss" + location = "global" + description = "The default dns" domain = "<%= ctx[:vars]['subdomain'] %>.hashicorptest.com" } diff --git a/mmv1/templates/terraform/state_migrations/certificate_manager_dns_authorization.go.erb b/mmv1/templates/terraform/state_migrations/certificate_manager_dns_authorization.go.erb new file mode 100644 index 000000000000..b3d29dc64136 --- /dev/null +++ b/mmv1/templates/terraform/state_migrations/certificate_manager_dns_authorization.go.erb @@ -0,0 +1,91 @@ +func ResourceCertificateManagerDnsAuthorizationUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + log.Printf("[DEBUG] Attributes before migration: %#v", rawState) + // Version 0 didn't support location. Default it to global. + rawState["location"] = "global" + log.Printf("[DEBUG] Attributes after migration: %#v", rawState) + return rawState, nil +} + +func resourceCertificateManagerDnsAuthorizationResourceV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "domain": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `A domain which is being authorized. A DnsAuthorization resource covers a +single domain and its wildcard, e.g. authorization for "example.com" can +be used to issue certificates for "example.com" and "*.example.com".`, + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Name of the resource; provided by the client when the resource is created. +The name must be 1-64 characters long, and match the regular expression [a-zA-Z][a-zA-Z0-9_-]* which means the first character must be a letter, +and all following characters must be a dash, underscore, letter or digit.`, + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: `A human-readable description of the resource.`, + }, + "labels": { + Type: schema.TypeMap, + Optional: true, + Description: `Set of label tags associated with the DNS Authorization resource. + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field 'effective_labels' for all of the labels present on the resource.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "dns_resource_record": { + Type: schema.TypeList, + Computed: true, + Description: `The structure describing the DNS Resource Record that needs to be added +to DNS configuration for the authorization to be usable by +certificate.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "data": { + Type: schema.TypeString, + Computed: true, + Description: `Data of the DNS Resource Record.`, + }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `Fully qualified name of the DNS Resource Record. +E.g. '_acme-challenge.example.com'.`, + }, + "type": { + Type: schema.TypeString, + Computed: true, + Description: `Type of the DNS Resource Record.`, + }, + }, + }, + }, + "effective_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "terraform_labels": { + Type: schema.TypeMap, + Computed: true, + Description: `The combination of labels configured directly on the resource + and default labels configured on the provider.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "project": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, + }, + } + +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_dns_authorization_upgrade_test.go b/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_dns_authorization_upgrade_test.go new file mode 100644 index 000000000000..293628ee322b --- /dev/null +++ b/mmv1/third_party/terraform/services/certificatemanager/resource_certificate_manager_dns_authorization_upgrade_test.go @@ -0,0 +1,78 @@ +package certificatemanager_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +// Tests schema version migration by creating a dns authorization with an old version of the provider (5.15.0) +// and then updating it with the current version the provider. +func TestAccCertificateManagerDnsAuthorization_migration(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + name := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + + oldVersion := map[string]resource.ExternalProvider{ + "google": { + VersionConstraint: "5.15.0", // a version that doesn't support location yet. + Source: "registry.terraform.io/hashicorp/google", + }, + } + newVersion := map[string]func() (*schema.Provider, error){ + "mynewprovider": func() (*schema.Provider, error) { return acctest.TestAccProviders["google"], nil }, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + CheckDestroy: testAccCheckCertificateManagerDnsAuthorizationDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: dnsAuthorizationResourceConfig(name), + ExternalProviders: oldVersion, + }, + { + ResourceName: "google_certificate_manager_dns_authorization.default", + ImportState: true, + ImportStateVerifyIgnore: []string{"location"}, + ExternalProviders: oldVersion, + }, + { + Config: dnsAuthorizationResourceConfigUpdated(name), + ProviderFactories: newVersion, + }, + { + ResourceName: "google_certificate_manager_dns_authorization.default", + ImportState: true, + ImportStateVerifyIgnore: []string{"location"}, + ProviderFactories: newVersion, + }, + }, + }) +} + +func dnsAuthorizationResourceConfig(name string) string { + return fmt.Sprintf(` + resource "google_certificate_manager_dns_authorization" "default" { + name = "%s" + description = "The default dns" + domain = "domain.hashicorptest.com" + } + `, name) +} + +func dnsAuthorizationResourceConfigUpdated(name string) string { + return fmt.Sprintf(` + provider "mynewprovider" {} + + resource "google_certificate_manager_dns_authorization" "default" { + provider = mynewprovider + name = "%s" + description = "The migrated default dns" + domain = "domain.hashicorptest.com" + } + `, name) +} From 1e6f8743250a05b91e6bbae7eec08624e7a37323 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Thu, 22 Feb 2024 14:40:07 -0500 Subject: [PATCH 017/200] Add discoveryengine service (#10017) --- .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 7c1fc897bfa3..33422f4e6948 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -222,6 +222,7 @@ module "project-services" { "datastream.googleapis.com", "deploymentmanager.googleapis.com", "dialogflow.googleapis.com", + "discoveryengine.googleapis.com", "dlp.googleapis.com", "dns.googleapis.com", "documentai.googleapis.com", From a58f0e2a4505a5debeac9813042c60f46567c42e Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Thu, 22 Feb 2024 22:58:09 +0100 Subject: [PATCH 018/200] Add validations for Composer 2/3 only fields (#9917) * block upgrade to composer 3 * make isComposer3 more generic, correct imageVersionChangeValidationFunc * added validation for Composer 2/3 specific fields * add tests for validation * add checks in flattenComposerEnvironmentConfig * Update attributes of fields not used in Composer 3 * make customizeDiff functions beta only * remove Computed from gke_cluster * remove Optional instead of Computed * add envCfg.PrivateEnvironmentConfig is nil check * modify isComposer3 to take string * minor correction to avoid merge conflicts --- .../resource_composer_environment.go.erb | 70 ++++++++-- .../resource_composer_environment_test.go.erb | 131 ++++++++++++++++++ 2 files changed, 193 insertions(+), 8 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 536af7709b4b..0369ce49f4d0 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 @@ -7,6 +7,7 @@ import ( "regexp" "strings" "time" + "context" "github.com/hashicorp/go-version" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" @@ -168,6 +169,10 @@ func ResourceComposerEnvironment() *schema.Resource { tpgresource.DefaultProviderProject, tpgresource.DefaultProviderRegion, tpgresource.SetLabelsDiff, +<% unless version == "ga" -%> + customdiff.ValidateChange("config.0.software_config.0.image_version", imageVersionChangeValidationFunc), + versionValidationCustomizeDiffFunc, +<% end -%> ), Schema: map[string]*schema.Schema{ @@ -1592,10 +1597,15 @@ func flattenComposerEnvironmentConfig(envCfg *composer.EnvironmentConfig) interf transformed["airflow_uri"] = envCfg.AirflowUri transformed["node_config"] = flattenComposerEnvironmentConfigNodeConfig(envCfg.NodeConfig) transformed["software_config"] = flattenComposerEnvironmentConfigSoftwareConfig(envCfg.SoftwareConfig) - transformed["private_environment_config"] = flattenComposerEnvironmentConfigPrivateEnvironmentConfig(envCfg.PrivateEnvironmentConfig) + imageVersion := envCfg.SoftwareConfig.ImageVersion + if !isComposer3(imageVersion){ + transformed["private_environment_config"] = flattenComposerEnvironmentConfigPrivateEnvironmentConfig(envCfg.PrivateEnvironmentConfig) + } <% unless version == "ga" -%> - transformed["enable_private_environment"] = envCfg.PrivateEnvironmentConfig.EnablePrivateEnvironment - transformed["enable_private_builds_only"] = envCfg.PrivateEnvironmentConfig.EnablePrivateBuildsOnly + if isComposer3(imageVersion) && envCfg.PrivateEnvironmentConfig != nil { + transformed["enable_private_environment"] = envCfg.PrivateEnvironmentConfig.EnablePrivateEnvironment + transformed["enable_private_builds_only"] = envCfg.PrivateEnvironmentConfig.EnablePrivateBuildsOnly + } <% end -%> transformed["web_server_network_access_control"] = flattenComposerEnvironmentConfigWebServerNetworkAccessControl(envCfg.WebServerNetworkAccessControl) transformed["database_config"] = flattenComposerEnvironmentConfigDatabaseConfig(envCfg.DatabaseConfig) @@ -1803,7 +1813,9 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformed["web_server"] = []interface{}{transformedWebServer} transformed["worker"] = []interface{}{transformedWorker} <% unless version == "ga" -%> - transformed["dag_processor"] = []interface{}{transformedDagProcessor} + if transformedDagProcessor != nil { + transformed["dag_processor"] = []interface{}{transformedDagProcessor} + } <% end -%> @@ -1982,7 +1994,8 @@ func expandComposerEnvironmentConfig(v interface{}, d *schema.ResourceData, conf composer.PrivateEnvironmentConfig.EnablePrivateEnvironment in API. Check image version to avoid overriding EnablePrivateEnvironment in case of other versions. */ - if isComposer3(d, config) { + imageVersion := d.Get("config.0.software_config.0.image_version").(string) + if isComposer3(imageVersion) { transformed.PrivateEnvironmentConfig = &composer.PrivateEnvironmentConfig{} if enablePrivateEnvironmentRaw, ok := original["enable_private_environment"]; ok { transformed.PrivateEnvironmentConfig.EnablePrivateEnvironment = enablePrivateEnvironmentRaw.(bool) @@ -2934,7 +2947,48 @@ func versionsEqual(old, new string) (bool, error) { return o.Equal(n), nil } -func isComposer3(d *schema.ResourceData, config *transport_tpg.Config) bool { - image_version := d.Get("config.0.software_config.0.image_version").(string) - return strings.Contains(image_version, "composer-3") +func isComposer3(imageVersion string) bool { + return strings.Contains(imageVersion, "composer-3") } + +func imageVersionChangeValidationFunc(ctx context.Context, old, new, meta any) error { + if old.(string) != "" && !isComposer3(old.(string)) && isComposer3(new.(string)) { + return fmt.Errorf("upgrade to composer 3 is not yet supported") + } + return nil +} + +func validateComposer3FieldUsage(d *schema.ResourceDiff, key string, requireComposer3 bool) error { + _, ok := d.GetOk(key) + imageVersion := d.Get("config.0.software_config.0.image_version").(string) + if ok && ( isComposer3(imageVersion) != requireComposer3 ) { + if requireComposer3 { + return fmt.Errorf("error in configuration, %s should only be used in Composer 3", key) + } else { + return fmt.Errorf("error in configuration, %s should not be used in Composer 3", key) + } + } + return nil +} + +func versionValidationCustomizeDiffFunc(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error { + composer3FieldUsagePolicy := map[string]bool{ + "config.0.node_config.0.max_pods_per_node": false, // not allowed in composer 3 + "config.0.node_config.0.enable_ip_masq_agent": false, + "config.0.node_config.0.config.0.node_config.0.ip_allocation_policy": false, + "config.0.private_environment_config": false, + "config.0.master_authorized_networks_config": false, + "config.0.node_config.0.composer_network_attachment": true, // allowed only in composer 3 + "config.0.node_config.0.composer_internal_ipv4_cidr_block": true, + "config.0.software_config.0.web_server_plugins_mode": true, + "config.0.enable_private_environment": true, + "config.0.enable_private_builds_only": true, + "config.0.workloads_config.0.dag_processor": true, + } + for key, allowed := range composer3FieldUsagePolicy { + if err := validateComposer3FieldUsage(d, key, allowed); err != nil { + return err + } + } + return nil +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb index 80e870eac07a..1ddb9257f35e 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb @@ -1186,6 +1186,77 @@ func TestAccComposerEnvironmentComposer3_update(t *testing.T) { }) } +func TestAccComposerEnvironmentComposer3_upgrade_expectError(t *testing.T) { + t.Parallel() + + envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) + network := fmt.Sprintf("%s-%d", testComposerNetworkPrefix, acctest.RandInt(t)) + subnetwork := network + "-1" + errorRegExp, _ := regexp.Compile(".*upgrade to composer 3 is not yet supported.*") + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComposerEnvironmentComposer2_empty(envName, network, subnetwork), + }, + { + Config: testAccComposerEnvironmentComposer3_empty(envName, network, subnetwork), + ExpectError: errorRegExp, + }, + // This is a terrible clean-up step in order to get destroy to succeed, + // due to dangling firewall rules left by the Composer Environment blocking network deletion. + // TODO: Remove this check if firewall rules bug gets fixed by Composer. + { + PlanOnly: true, + ExpectNonEmptyPlan: false, + Config: testAccComposerEnvironmentComposer2_empty(envName, network, subnetwork), + Check: testAccCheckClearComposerEnvironmentFirewalls(t, network), + }, + }, + }) +} + +func TestAccComposerEnvironmentComposer2_usesUnsupportedField_expectError(t *testing.T) { + t.Parallel() + + envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) + errorRegExp, _ := regexp.Compile(".*error in configuration, .* should only be used in Composer 3.*") + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComposerEnvironmentComposer2_usesUnsupportedField(envName), + ExpectError: errorRegExp, + }, + }, + }) +} + +func TestAccComposerEnvironmentComposer3_usesUnsupportedField_expectError(t *testing.T) { + t.Parallel() + + envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) + errorRegExp, _ := regexp.Compile(".*error in configuration, .* should not be used in Composer 3.*") + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComposerEnvironmentComposer3_usesUnsupportedField(envName), + ExpectError: errorRegExp, + }, + }, + }) +} + // Checks Composer 3 specific updatable fields. func TestAccComposerEnvironmentComposer3_updateToEmpty(t *testing.T) { t.Parallel() @@ -2835,6 +2906,34 @@ resource "google_project_iam_member" "composer-worker" { } <% unless version == "ga" -%> +func testAccComposerEnvironmentComposer2_empty(name, network, subnetwork string) string { + return fmt.Sprintf(` +resource "google_composer_environment" "test" { + name = "%s" + region = "us-central1" + config { + software_config { + image_version = "composer-2-airflow-2" + } + } +} + +// use a separate network to avoid conflicts with other tests running in parallel +// that use the default network/subnet +resource "google_compute_network" "test" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "test" { + name = "%s" + ip_cidr_range = "10.2.0.0/16" + region = "us-central1" + network = google_compute_network.test.self_link +} +`, name, network, subnetwork) +} + func testAccComposerEnvironmentComposer3_empty(name, network, subnetwork string) string { return fmt.Sprintf(` resource "google_composer_environment" "test" { @@ -2863,6 +2962,38 @@ resource "google_compute_subnetwork" "test" { `, name, network, subnetwork) } +func testAccComposerEnvironmentComposer2_usesUnsupportedField(name string) string { +return fmt.Sprintf(` +resource "google_composer_environment" "test" { + name = "%s" + region = "us-central1" + config { + software_config { + image_version = "composer-2-airflow-2" + web_server_plugins_mode = "ENABLED" + } + } +} +`, name) +} + +func testAccComposerEnvironmentComposer3_usesUnsupportedField(name string) string { +return fmt.Sprintf(` +resource "google_composer_environment" "test" { + name = "%s" + region = "us-central1" + config { + node_config { + enable_ip_masq_agent = true + } + software_config { + image_version = "composer-3-airflow-2" + } + } +} +`, name) +} + func testAccComposerEnvironmentComposer3_basic(name, network, subnetwork string) string { return fmt.Sprintf(` resource "google_composer_environment" "test" { From c4260af062bfbc3dd321ad3990ba3a735d537291 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 22 Feb 2024 15:36:59 -0800 Subject: [PATCH 019/200] Made TestAccContainerCluster_withGatewayApiConfig error regex more forgiving (#10034) Fixed https://github.com/hashicorp/terraform-provider-google/issues/17319 --- .../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 a542384379f6..3699a6ba9662 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 @@ -4230,7 +4230,7 @@ func TestAccContainerCluster_withGatewayApiConfig(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccContainerCluster_withGatewayApiConfig(clusterName, "CANARY", networkName, subnetworkName), - ExpectError: regexp.MustCompile(`expected gateway_api_config\.0\.channel to be one of \[CHANNEL_DISABLED CHANNEL_EXPERIMENTAL CHANNEL_STANDARD\], got CANARY`), + ExpectError: regexp.MustCompile(`expected gateway_api_config\.0\.channel to be one of [^,]+, got CANARY`), }, { Config: testAccContainerCluster_withGatewayApiConfig(clusterName, "CHANNEL_DISABLED", networkName, subnetworkName), From 1470d00e90e813f69d09aa9f55589884cbc27900 Mon Sep 17 00:00:00 2001 From: Hamzawy63 <43001514+Hamzawy63@users.noreply.github.com> Date: Fri, 23 Feb 2024 17:33:59 +0100 Subject: [PATCH 020/200] Add ceritificateManagerCertificates field to ComputeRegionTargetHttpsProxy resource (#10011) Co-authored-by: Hamza Hassan --- .../compute/RegionTargetHttpsProxy.yaml | 34 ++++++++++++++++--- .../compute_region_target_https_proxy.go.erb | 15 ++++++++ .../compute_region_target_https_proxy.go.erb | 10 ++++++ ...oxy_certificate_manager_certificate.tf.erb | 28 +++++++++++++++ 4 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 mmv1/templates/terraform/decoders/compute_region_target_https_proxy.go.erb create mode 100644 mmv1/templates/terraform/encoders/compute_region_target_https_proxy.go.erb create mode 100644 mmv1/templates/terraform/examples/region_target_https_proxy_certificate_manager_certificate.tf.erb diff --git a/mmv1/products/compute/RegionTargetHttpsProxy.yaml b/mmv1/products/compute/RegionTargetHttpsProxy.yaml index 723d03ad87af..553bd1a5655a 100644 --- a/mmv1/products/compute/RegionTargetHttpsProxy.yaml +++ b/mmv1/products/compute/RegionTargetHttpsProxy.yaml @@ -41,6 +41,9 @@ async: !ruby/object:Api::OpAsync error: !ruby/object:Api::OpAsync::Error path: 'error/errors' message: 'message' +custom_code: !ruby/object:Provider::Terraform::CustomCode + encoder: templates/terraform/encoders/compute_region_target_https_proxy.go.erb + decoder: templates/terraform/decoders/compute_region_target_https_proxy.go.erb examples: - !ruby/object:Provider::Terraform::Examples name: 'region_target_https_proxy_basic' @@ -51,6 +54,14 @@ examples: region_url_map_name: 'url-map' region_backend_service_name: 'backend-service' region_health_check_name: 'http-health-check' + - !ruby/object:Provider::Terraform::Examples + name: 'region_target_https_proxy_certificate_manager_certificate' + primary_resource_id: 'default' + vars: + region_target_https_proxy_name: 'target-http-proxy' + certificate_manager_certificate_name: 'my-certificate' + region_url_map_name: 'url-map' + region_backend_service_name: 'backend-service' parameters: - !ruby/object:Api::Type::ResourceRef name: 'region' @@ -109,13 +120,26 @@ properties: # update_verb: :POST # update_url: # 'projects/{{project}}/regions/{{region}}/targetHttpsProxies/{{name}}/setQuicOverride' + - !ruby/object:Api::Type::Array + name: 'certificateManagerCertificates' + description: | + URLs to certificate manager certificate resources that are used to authenticate connections between users and the load balancer. + Currently, you may specify up to 15 certificates. Certificate manager certificates do not apply when the load balancing scheme is set to INTERNAL_SELF_MANAGED. + sslCertificates and certificateManagerCertificates fields can not be defined together. + Accepted format is `//certificatemanager.googleapis.com/projects/{project}/locations/{location}/certificates/{resourceName}` or just the self_link `projects/{project}/locations/{location}/certificates/{resourceName}` + update_verb: :POST + update_url: 'projects/{{project}}/regions/{{region}}/targetHttpsProxies/{{name}}/setSslCertificates' + item_type: Api::Type::String + custom_expand: 'templates/terraform/custom_expand/certificate_manager_certificate_construct_full_url.go.erb' + diff_suppress_func: 'tpgresource.CompareResourceNames' + conflicts: + - ssl_certificates - !ruby/object:Api::Type::Array name: 'sslCertificates' description: | - A list of RegionSslCertificate resources that are used to authenticate - connections between users and the load balancer. Currently, exactly - one SSL certificate must be specified. - required: true + URLs to SslCertificate resources that are used to authenticate connections between users and the load balancer. + At least one SSL certificate must be specified. Currently, you may specify up to 15 SSL certificates. + sslCertificates do not apply when the load balancing scheme is set to INTERNAL_SELF_MANAGED. update_verb: :POST update_url: 'projects/{{project}}/regions/{{region}}/targetHttpsProxies/{{name}}/setSslCertificates' item_type: !ruby/object:Api::Type::ResourceRef @@ -124,6 +148,8 @@ properties: imports: 'selfLink' description: 'The SSL certificates used by this TargetHttpsProxy' custom_expand: 'templates/terraform/custom_expand/array_resourceref_with_validation.go.erb' + conflicts: + - certificate_manager_certificates - !ruby/object:Api::Type::ResourceRef name: 'sslPolicy' resource: 'RegionSslPolicy' diff --git a/mmv1/templates/terraform/decoders/compute_region_target_https_proxy.go.erb b/mmv1/templates/terraform/decoders/compute_region_target_https_proxy.go.erb new file mode 100644 index 000000000000..0a72fe1c476a --- /dev/null +++ b/mmv1/templates/terraform/decoders/compute_region_target_https_proxy.go.erb @@ -0,0 +1,15 @@ +// Since both sslCertificates and certificateManagerCertificates maps to the same API field (sslCertificates), we need to check the types +// of certificates that exist in the array and decide whether to change the field to certificateManagerCertificate or not. +// The decoder logic depends on the fact that the API does not allow mixed type of certificates and it returns +// certificate manager certificates in the format of //certificatemanager.googleapis.com/projects/*/locations/*/certificates/* +if sslCertificates, ok := res["sslCertificates"].([]interface{}); ok && len(sslCertificates) > 0 { + regPat, _ := regexp.Compile("//certificatemanager.googleapis.com/projects/(.*)/locations/(.*)/certificates/(.*)") + + if regPat.MatchString(sslCertificates[0].(string)) { + // It is enough to check only the type of one of the provided certificates beacuse all the certificates should be the same type. + log.Printf("[DEBUG] The field sslCertificates contains certificateManagerCertificates, the field name will be converted to certificateManagerCertificates") + res["certificateManagerCertificates"] = res["sslCertificates"] + delete(res, "sslCertificates") + } +} +return res, nil \ No newline at end of file diff --git a/mmv1/templates/terraform/encoders/compute_region_target_https_proxy.go.erb b/mmv1/templates/terraform/encoders/compute_region_target_https_proxy.go.erb new file mode 100644 index 000000000000..168d4a65c5ef --- /dev/null +++ b/mmv1/templates/terraform/encoders/compute_region_target_https_proxy.go.erb @@ -0,0 +1,10 @@ + +if _, ok := obj["certificateManagerCertificates"]; ok { + // The field certificateManagerCertificates should not be included in the API request, and it should be renamed to `sslCertificates` + // The API does not allow using both certificate manager certificates and sslCertificates. If that changes + // in the future, the encoder logic should change accordingly because this will mean that both fields are no longer mutual exclusive. + log.Printf("[DEBUG] converting the field CertificateManagerCertificates to sslCertificates before sending the request") + obj["sslCertificates"] = obj["certificateManagerCertificates"] + delete(obj, "certificateManagerCertificates") +} +return obj, nil \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/region_target_https_proxy_certificate_manager_certificate.tf.erb b/mmv1/templates/terraform/examples/region_target_https_proxy_certificate_manager_certificate.tf.erb new file mode 100644 index 000000000000..05c8d90b46f9 --- /dev/null +++ b/mmv1/templates/terraform/examples/region_target_https_proxy_certificate_manager_certificate.tf.erb @@ -0,0 +1,28 @@ +resource "google_compute_region_target_https_proxy" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['region_target_https_proxy_name'] %>" + url_map = google_compute_region_url_map.default.id + certificate_manager_certificates = ["//certificatemanager.googleapis.com/${google_certificate_manager_certificate.default.id}"] # [google_certificate_manager_certificate.default.id] is also acceptable +} + +resource "google_certificate_manager_certificate" "default" { + name = "<%= ctx[:vars]['certificate_manager_certificate_name'] %>" + location = "us-central1" + self_managed { + pem_certificate = file("test-fixtures/cert.pem") + pem_private_key = file("test-fixtures/private-key.pem") + } +} + +resource "google_compute_region_url_map" "default" { + name = "<%= ctx[:vars]['region_url_map_name'] %>" + default_service = google_compute_region_backend_service.default.id + region = "us-central1" +} + +resource "google_compute_region_backend_service" "default" { + name = "<%= ctx[:vars]['region_backend_service_name'] %>" + region = "us-central1" + protocol = "HTTPS" + timeout_sec = 30 + load_balancing_scheme = "INTERNAL_MANAGED" +} \ No newline at end of file From 326caf3235a24fbb7e8140baed87619a409712a6 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 23 Feb 2024 08:56:40 -0800 Subject: [PATCH 021/200] Added missing quote marks to TEST_PREFIX (#10035) Without this, | gets interpreted as a pipe and the test count always becomes 0 if there are multiple prefixes supplied --- .../terraform/.teamcity/components/builds/build_steps.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt index 4faed1046b65..78f942cf380d 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt @@ -118,7 +118,7 @@ fun BuildSteps.runAcceptanceTests() { exit 0 fi - export TEST_COUNT=${'$'}(./test-binary -test.list=%TEST_PREFIX% | wc -l) + export TEST_COUNT=${'$'}(./test-binary -test.list="%TEST_PREFIX%" | wc -l) echo "Found ${'$'}{TEST_COUNT} tests that match the given test prefix %TEST_PREFIX%" if test ${'$'}TEST_COUNT -le "0"; then echo "Skipping test execution; no tests to run" From 77453ca7f52504372082b2f2b9e1b3aebd388b26 Mon Sep 17 00:00:00 2001 From: Sneha-at Date: Fri, 23 Feb 2024 09:45:18 -0800 Subject: [PATCH 022/200] Promote enable_confidential_storage from beta to GA (#9993) --- mmv1/third_party/terraform/go.mod.erb | 42 ++++----- mmv1/third_party/terraform/go.sum | 88 +++++++++---------- .../services/container/node_config.go.erb | 8 +- .../resource_container_cluster_test.go.erb | 2 - .../resource_container_node_pool_test.go.erb | 3 - .../docs/r/container_cluster.html.markdown | 3 +- 6 files changed, 67 insertions(+), 79 deletions(-) diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index 0d5943fb44fc..2d2a0081a295 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -25,21 +25,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.20.0 - golang.org/x/oauth2 v0.16.0 - google.golang.org/api v0.156.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 - google.golang.org/grpc v1.60.1 + golang.org/x/net v0.21.0 + golang.org/x/oauth2 v0.17.0 + google.golang.org/api v0.166.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 + google.golang.org/grpc v1.61.1 google.golang.org/protobuf v1.32.0 ) require ( bitbucket.org/creachadair/stringset v0.0.8 // indirect - cloud.google.com/go v0.111.0 // indirect - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go v0.112.0 // indirect + cloud.google.com/go/compute v1.23.4 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect - cloud.google.com/go/longrunning v0.5.4 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/longrunning v0.5.5 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect @@ -48,7 +48,7 @@ require ( github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cloudflare/circl v1.3.3 // 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/cncf/xds/go v0.0.0-20231109132714-523115ebc101 // 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 @@ -62,9 +62,9 @@ require ( 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.5.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/googleapis/gax-go/v2 v2.12.1 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-plugin v1.6.0 // indirect @@ -91,19 +91,19 @@ require ( github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/zclconf/go-cty v1.14.1 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect - golang.org/x/crypto v0.18.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 // indirect + go.opentelemetry.io/otel v1.23.0 // indirect + go.opentelemetry.io/otel/metric v1.23.0 // indirect + go.opentelemetry.io/otel/trace v1.23.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/mod v0.14.0 // indirect golang.org/x/sync v0.6.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // 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 b265f1fc3590..70ac88701502 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -1,18 +1,18 @@ 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.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= -cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= 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.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= 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.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= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0 h1:s4Y6r6RrYLBnqosGXLwR0h1Gqr0VT3wgd6rqvHsD9OE= @@ -43,8 +43,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX 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/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creachadair/staticfile v0.1.2/go.mod h1:a3qySzCIXEprDGxk6tSxSI+dBBdLzqeBOMhZ+o2d3pM= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -120,12 +120,12 @@ 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.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.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/googleapis/gax-go/v2 v2.12.1 h1:9F8GV9r9ztXyAi00gsMQHNoF51xPZm8uj1dpYt2ZETM= +github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= 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= @@ -249,17 +249,17 @@ github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 h1:P+/g8GpuJGYbOp2tAdKrIPUX9JO02q8Q0YNlHolpibA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= +go.opentelemetry.io/otel v1.23.0 h1:Df0pqjqExIywbMCMTxkAwzjLZtRf+bBKLbUcpxO2C9E= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= +go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= 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= @@ -269,8 +269,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= 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= @@ -295,11 +295,11 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -328,14 +328,14 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= 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= @@ -363,8 +363,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= -google.golang.org/api v0.156.0 h1:yloYcGbBtVYjLKQe4enCunxvwn3s2w/XPrrhVf6MsvQ= -google.golang.org/api v0.156.0/go.mod h1:bUSmn4KFO0Q+69zo9CNIDp4Psi6BqM0np0CbzKRSiSY= +google.golang.org/api v0.166.0 h1:6m4NUwrZYhAaVIHZWxaKjw1L1vNAjtMwORmKRyEEo24= +google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= 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.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -373,20 +373,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-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0= -google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 h1:s1w3X6gQxwrLEpxnLd/qXTVLgQE2yXwaOaoa6IlY/+o= -google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0/go.mod h1:CAny0tYF+0/9rmDB9fahA9YLzX3+AEVl1qXbv5hhj6c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 h1:gphdwh0npgs8elJ4T6J+DQJHPVF7RsuJHCfwztUb4J4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1:x9PwdEgd11LgK+orcck69WVRo7DezSO4VUMPI4xpc8A= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 h1:hZB7eLIaYlW9qXRfCq/qDaPdbeY3757uARz5Vvfv+cY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk= 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.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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= 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 8d53ce85b51d..089c5943aaea 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.erb +++ b/mmv1/third_party/terraform/services/container/node_config.go.erb @@ -680,14 +680,12 @@ func schemaNodeConfig() *schema.Schema { Optional: true, Description: `A map of resource manager tags. Resource manager tag keys and values have the same definition as resource manager tags. Keys must be in the format tagKeys/{tag_key_id}, and values are in the format tagValues/456. The field is ignored (both PUT & PATCH) when empty.`, }, - <% unless version == 'ga' -%> "enable_confidential_storage": { Type: schema.TypeBool, Optional: true, ForceNew: true, Description: `If enabled boot disks are configured with confidential mode.`, }, - <% end -%> }, }, } @@ -978,12 +976,10 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { nc.SoleTenantConfig = expandSoleTenantConfig(v) } - <% unless version == 'ga' -%> if v,ok := nodeConfig["enable_confidential_storage"]; ok { nc.EnableConfidentialStorage = v.(bool) } - <% end -%> - + <% unless version == "ga" -%> if v, ok := nodeConfig["host_maintenance_policy"]; ok { nc.HostMaintenancePolicy = expandHostMaintenancePolicy(v) @@ -1236,9 +1232,7 @@ func flattenNodeConfig(c *container.NodeConfig, v interface{}) []map[string]inte "sole_tenant_config": flattenSoleTenantConfig(c.SoleTenantConfig), "fast_socket": flattenFastSocket(c.FastSocket), "resource_manager_tags": flattenResourceManagerTags(c.ResourceManagerTags), - <% unless version == 'ga' -%> "enable_confidential_storage": c.EnableConfidentialStorage, - <% end -%> }) if len(c.OauthScopes) > 0 { 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 3699a6ba9662..910fba9602b0 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 @@ -9389,7 +9389,6 @@ func testAccContainerCluster_additional_pod_ranges_config(name string, nameCount `, name, name, name, aprc) } -<% unless version == 'ga' -%> func TestAccContainerCluster_withConfidentialBootDisk(t *testing.T) { t.Parallel() @@ -9558,7 +9557,6 @@ resource "google_container_cluster" "without_confidential_boot_disk" { } `, clusterName, npName, networkName, subnetworkName) } -<% end -%> <% unless version == 'ga' -%> func testAccContainerCluster_withWorkloadALTSConfig(projectID, name, networkName, subnetworkName string, enable bool) string { 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 42939e9b7e9b..ec3e852d8ce6 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 @@ -4135,8 +4135,6 @@ resource "google_container_node_pool" "np" { } <% end -%> -<% unless version == 'ga' -%> - func TestAccContainerNodePool_withConfidentialBootDisk(t *testing.T) { t.Parallel() @@ -4262,7 +4260,6 @@ resource "google_container_node_pool" "without_confidential_boot_disk" { } `, cluster, networkName, subnetworkName, np) } -<% end -%> func testAccContainerNodePool_resourceManagerTags(projectID, clusterName, networkName, subnetworkName, randomSuffix string) string { return fmt.Sprintf(` 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 3c72beba2d55..983dd05befe4 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 @@ -790,8 +790,7 @@ The `master_authorized_networks_config.cidr_blocks` block supports: * `disk_type` - (Optional) Type of the disk attached to each node (e.g. 'pd-standard', 'pd-balanced' or 'pd-ssd'). If unspecified, the default disk type is 'pd-standard' -* `enable_confidential_storage` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) -Enabling Confidential Storage will create boot disk with confidential mode. It is disabled by default. +* `enable_confidential_storage` - (Optional) Enabling Confidential Storage will create boot disk with confidential mode. It is disabled by default. * `ephemeral_storage_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Parameters for the ephemeral storage filesystem. If unspecified, ephemeral storage is backed by the boot disk. Structure is [documented below](#nested_ephemeral_storage_config). From 39bd019d029e4f9f69179a8b5545bfe3f83ff966 Mon Sep 17 00:00:00 2001 From: Shogo Watanabe <1286807+nownabe@users.noreply.github.com> Date: Sat, 24 Feb 2024 03:33:32 +0900 Subject: [PATCH 023/200] Add IAM resources for Cloud Deploy Target (#9927) * Add IAM resources for Cloud Deploy Target * update * add back import_format --- mmv1/products/clouddeploy/Target.yaml | 40 +++++++++++++++++++ .../examples/clouddeploy_target_basic.tf.erb | 4 ++ 2 files changed, 44 insertions(+) create mode 100644 mmv1/products/clouddeploy/Target.yaml create mode 100644 mmv1/templates/terraform/examples/clouddeploy_target_basic.tf.erb diff --git a/mmv1/products/clouddeploy/Target.yaml b/mmv1/products/clouddeploy/Target.yaml new file mode 100644 index 000000000000..b8ab9d6fd154 --- /dev/null +++ b/mmv1/products/clouddeploy/Target.yaml @@ -0,0 +1,40 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'Target' +description: | + The Cloud Deploy `Target` resource. +base_url: 'projects/{{project}}/locations/{{location}}/targets' +self_link: 'projects/{{project}}/locations/{{location}}/targets/{{name}}' +exclude_resource: true +id_format: 'projects/{{project}}/locations/{{location}}/targets/{{name}}' +import_format: + - 'projects/{{project}}/locations/{{location}}/targets/{{name}}' +iam_policy: !ruby/object:Api::Resource::IamPolicy + parent_resource_attribute: 'name' + method_name_separator: ':' + base_url: 'projects/{{project}}/locations/{{location}}/targets/{{name}}' + import_format: ['projects/{{project}}/locations/{{location}}/targets/{{name}}', '{{name}}'] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'clouddeploy_target_basic' + primary_resource_id: 'default' + primary_resource_name: 'fmt.Sprintf("tf-test-cd-target%s", context["random_suffix"])' + vars: + target: 'cd-target' +properties: + - !ruby/object:Api::Type::String + name: "name" + description: "Dummy property." + required: true diff --git a/mmv1/templates/terraform/examples/clouddeploy_target_basic.tf.erb b/mmv1/templates/terraform/examples/clouddeploy_target_basic.tf.erb new file mode 100644 index 000000000000..5fd51566834c --- /dev/null +++ b/mmv1/templates/terraform/examples/clouddeploy_target_basic.tf.erb @@ -0,0 +1,4 @@ +resource "google_clouddeploy_target" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['target'] %>" + location = "us-central1" + } From 0ce23ad244ece88e2e71b7a556e5f55841d1e514 Mon Sep 17 00:00:00 2001 From: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:32:33 -0800 Subject: [PATCH 024/200] Add comments to skipped sweepers (#10028) --- mmv1/products/secretmanager/SecretVersion.yaml | 1 + mmv1/products/spanner/Database.yaml | 1 + mmv1/products/sql/Database.yaml | 1 + 3 files changed, 3 insertions(+) diff --git a/mmv1/products/secretmanager/SecretVersion.yaml b/mmv1/products/secretmanager/SecretVersion.yaml index 0161b2e6d0d3..9db3d9e31bcb 100644 --- a/mmv1/products/secretmanager/SecretVersion.yaml +++ b/mmv1/products/secretmanager/SecretVersion.yaml @@ -20,6 +20,7 @@ delete_url: '{{name}}:destroy' delete_verb: :POST description: | A secret version resource. +# Sweeper skipped as this resource has customized deletion. skip_sweeper: true examples: - !ruby/object:Provider::Terraform::Examples diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index 9feb815c7cb9..ea33c9ad211c 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -41,6 +41,7 @@ async: !ruby/object:Api::OpAsync path: 'error' message: 'message' autogen_async: true +# Sweeper skipped as this resource has customized deletion. skip_sweeper: true id_format: '{{instance}}/{{name}}' import_format: diff --git a/mmv1/products/sql/Database.yaml b/mmv1/products/sql/Database.yaml index 1c6c56a9ed14..eca5f0a5c533 100644 --- a/mmv1/products/sql/Database.yaml +++ b/mmv1/products/sql/Database.yaml @@ -30,6 +30,7 @@ import_format: '{{instance}}/{{name}}', '{{name}}', ] +# Sweeper skipped as this resource has customized deletion. skip_sweeper: true examples: - !ruby/object:Provider::Terraform::Examples From 7beb4e694352b2164ca630357ad429c03a69f707 Mon Sep 17 00:00:00 2001 From: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Date: Fri, 23 Feb 2024 14:16:01 -0800 Subject: [PATCH 025/200] Add sweepers for gkebackupPlan and restorePlan (#10026) --- mmv1/products/gkebackup/BackupPlan.yaml | 1 - mmv1/products/gkebackup/RestorePlan.yaml | 1 - 2 files changed, 2 deletions(-) diff --git a/mmv1/products/gkebackup/BackupPlan.yaml b/mmv1/products/gkebackup/BackupPlan.yaml index f3937b278d0c..26733710637e 100644 --- a/mmv1/products/gkebackup/BackupPlan.yaml +++ b/mmv1/products/gkebackup/BackupPlan.yaml @@ -105,7 +105,6 @@ examples: deletion_protection: 'false' test_env_vars: project: :PROJECT_NAME -skip_sweeper: true parameters: - !ruby/object:Api::Type::String name: 'location' diff --git a/mmv1/products/gkebackup/RestorePlan.yaml b/mmv1/products/gkebackup/RestorePlan.yaml index 479946268fda..38bcb5216b5c 100644 --- a/mmv1/products/gkebackup/RestorePlan.yaml +++ b/mmv1/products/gkebackup/RestorePlan.yaml @@ -134,7 +134,6 @@ examples: subnetwork_name: 'acctest.BootstrapSubnet(t, "gke-cluster", acctest.BootstrapSharedTestNetwork(t, "gke-cluster"))' oics_vars_overrides: deletion_protection: 'false' -skip_sweeper: true parameters: - !ruby/object:Api::Type::String name: 'location' From 8365dfab7960fb8cc9aa5b169d5f9178271f58fa Mon Sep 17 00:00:00 2001 From: Obada Alabbadi <76101898+obada-ab@users.noreply.github.com> Date: Fri, 23 Feb 2024 23:16:55 +0100 Subject: [PATCH 026/200] add `remote_function_options` to bigquery_routine (#9893) * Add dataGovernanceType and remoteFunctionOptions to bigquery_routine * add function-sources.zip to biguquery fixtures * fix resource names in TestAccBigQueryRoutine * add bigquery routine remote function example --- mmv1/products/bigquery/Routine.yaml | 50 +++++- ...c.tf.erb => bigquery_routine_basic.tf.erb} | 0 ...on.tf.erb => bigquery_routine_json.tf.erb} | 0 ...tf.erb => bigquery_routine_pyspark.tf.erb} | 0 ... bigquery_routine_pyspark_mainfile.tf.erb} | 0 .../bigquery_routine_remote_function.tf.erb | 27 +++ ....erb => bigquery_routine_spark_jar.tf.erb} | 0 ...tvf.tf.erb => bigquery_routine_tvf.tf.erb} | 0 .../resource_bigquery_routine_test.go | 168 ++++++++++++++++++ .../test-fixtures/function-source.zip | Bin 0 -> 458 bytes 10 files changed, 239 insertions(+), 6 deletions(-) rename mmv1/templates/terraform/examples/{big_query_routine_basic.tf.erb => bigquery_routine_basic.tf.erb} (100%) rename mmv1/templates/terraform/examples/{big_query_routine_json.tf.erb => bigquery_routine_json.tf.erb} (100%) rename mmv1/templates/terraform/examples/{big_query_routine_pyspark.tf.erb => bigquery_routine_pyspark.tf.erb} (100%) rename mmv1/templates/terraform/examples/{big_query_routine_pyspark_mainfile.tf.erb => bigquery_routine_pyspark_mainfile.tf.erb} (100%) create mode 100644 mmv1/templates/terraform/examples/bigquery_routine_remote_function.tf.erb rename mmv1/templates/terraform/examples/{big_query_routine_spark_jar.tf.erb => bigquery_routine_spark_jar.tf.erb} (100%) rename mmv1/templates/terraform/examples/{big_query_routine_tvf.tf.erb => bigquery_routine_tvf.tf.erb} (100%) create mode 100644 mmv1/third_party/terraform/services/bigquery/test-fixtures/function-source.zip diff --git a/mmv1/products/bigquery/Routine.yaml b/mmv1/products/bigquery/Routine.yaml index 513a80b503d4..3dbbfd3b0577 100644 --- a/mmv1/products/bigquery/Routine.yaml +++ b/mmv1/products/bigquery/Routine.yaml @@ -26,7 +26,7 @@ import_format: ['projects/{{project}}/datasets/{{dataset_id}}/routines/{{routine_id}}'] examples: - !ruby/object:Provider::Terraform::Examples - name: 'big_query_routine_basic' + name: 'bigquery_routine_basic' primary_resource_id: 'sproc' primary_resource_name: "fmt.Sprintf(\"tf_test_dataset_id%s\", context[\"random_suffix\"\ @@ -35,7 +35,7 @@ examples: dataset_id: 'dataset_id' routine_id: 'routine_id' - !ruby/object:Provider::Terraform::Examples - name: 'big_query_routine_json' + name: 'bigquery_routine_json' primary_resource_id: 'sproc' primary_resource_name: "fmt.Sprintf(\"tf_test_dataset_id%s\", context[\"random_suffix\"\ @@ -44,7 +44,7 @@ examples: dataset_id: 'dataset_id' routine_id: 'routine_id' - !ruby/object:Provider::Terraform::Examples - name: 'big_query_routine_tvf' + name: 'bigquery_routine_tvf' primary_resource_id: 'sproc' primary_resource_name: "fmt.Sprintf(\"tf_test_dataset_id%s\", context[\"random_suffix\"\ @@ -53,26 +53,34 @@ examples: dataset_id: 'dataset_id' routine_id: 'routine_id' - !ruby/object:Provider::Terraform::Examples - name: 'big_query_routine_pyspark' + name: 'bigquery_routine_pyspark' primary_resource_id: 'pyspark' vars: dataset_id: 'dataset_id' connection_id: 'connection_id' routine_id: 'routine_id' - !ruby/object:Provider::Terraform::Examples - name: 'big_query_routine_pyspark_mainfile' + name: 'bigquery_routine_pyspark_mainfile' primary_resource_id: 'pyspark_mainfile' vars: dataset_id: 'dataset_id' connection_id: 'connection_id' routine_id: 'routine_id' - !ruby/object:Provider::Terraform::Examples - name: 'big_query_routine_spark_jar' + name: 'bigquery_routine_spark_jar' primary_resource_id: 'spark_jar' vars: dataset_id: 'dataset_id' connection_id: 'connection_id' routine_id: 'routine_id' + - !ruby/object:Provider::Terraform::Examples + skip_test: true + name: 'bigquery_routine_remote_function' + primary_resource_id: 'remote_function' + vars: + dataset_id: 'dataset_id' + connection_id: 'connection_id' + routine_id: 'routine_id' properties: - !ruby/object:Api::Type::NestedObject name: routineReference @@ -283,3 +291,33 @@ properties: description: | The fully qualified name of a class in jarUris, for example, com.example.wordcount. Exactly one of mainClass and main_jar_uri field should be set for Java/Scala language type. + - !ruby/object:Api::Type::NestedObject + name: 'remoteFunctionOptions' + description: Remote function specific options. + properties: + - !ruby/object:Api::Type::String + name: 'endpoint' + description: | + Endpoint of the user-provided remote service, e.g. + `https://us-east1-my_gcf_project.cloudfunctions.net/remote_add` + - !ruby/object:Api::Type::String + name: 'connection' + description: | + Fully qualified name of the user-provided connection object which holds + the authentication information to send requests to the remote service. + Format: "projects/{projectId}/locations/{locationId}/connections/{connectionId}" + - !ruby/object:Api::Type::KeyValuePairs + name: 'userDefinedContext' + description: | + User-defined context as a set of key/value pairs, which will be sent as function + invocation context together with batched arguments in the requests to the remote + service. The total number of bytes of keys and values must be less than 8KB. + + An object containing a list of "key": value pairs. Example: + `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'maxBatchingRows' + description: | + Max number of rows in each batch sent to the remote service. If absent or if 0, + BigQuery dynamically decides the number of rows in a batch. diff --git a/mmv1/templates/terraform/examples/big_query_routine_basic.tf.erb b/mmv1/templates/terraform/examples/bigquery_routine_basic.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/big_query_routine_basic.tf.erb rename to mmv1/templates/terraform/examples/bigquery_routine_basic.tf.erb diff --git a/mmv1/templates/terraform/examples/big_query_routine_json.tf.erb b/mmv1/templates/terraform/examples/bigquery_routine_json.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/big_query_routine_json.tf.erb rename to mmv1/templates/terraform/examples/bigquery_routine_json.tf.erb diff --git a/mmv1/templates/terraform/examples/big_query_routine_pyspark.tf.erb b/mmv1/templates/terraform/examples/bigquery_routine_pyspark.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/big_query_routine_pyspark.tf.erb rename to mmv1/templates/terraform/examples/bigquery_routine_pyspark.tf.erb diff --git a/mmv1/templates/terraform/examples/big_query_routine_pyspark_mainfile.tf.erb b/mmv1/templates/terraform/examples/bigquery_routine_pyspark_mainfile.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/big_query_routine_pyspark_mainfile.tf.erb rename to mmv1/templates/terraform/examples/bigquery_routine_pyspark_mainfile.tf.erb diff --git a/mmv1/templates/terraform/examples/bigquery_routine_remote_function.tf.erb b/mmv1/templates/terraform/examples/bigquery_routine_remote_function.tf.erb new file mode 100644 index 000000000000..9ef5b2a0dd2a --- /dev/null +++ b/mmv1/templates/terraform/examples/bigquery_routine_remote_function.tf.erb @@ -0,0 +1,27 @@ +resource "google_bigquery_dataset" "test" { + dataset_id = "<%= ctx[:vars]['dataset_id'] %>" +} + +resource "google_bigquery_connection" "test" { + connection_id = "<%= ctx[:vars]['connection_id'] %>" + location = "US" + cloud_resource { } +} + +resource "google_bigquery_routine" "<%= ctx[:primary_resource_id] %>" { + dataset_id = google_bigquery_dataset.test.dataset_id + routine_id = "<%= ctx[:vars]['routine_id'] %>" + routine_type = "SCALAR_FUNCTION" + definition_body = "" + + return_type = "{\"typeKind\" : \"STRING\"}" + + remote_function_options { + endpoint = "https://us-east1-my_gcf_project.cloudfunctions.net/remote_add" + connection = google_bigquery_connection.test.name + max_batching_rows = "10" + user_defined_context = { + "z": "1.5", + } + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/big_query_routine_spark_jar.tf.erb b/mmv1/templates/terraform/examples/bigquery_routine_spark_jar.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/big_query_routine_spark_jar.tf.erb rename to mmv1/templates/terraform/examples/bigquery_routine_spark_jar.tf.erb diff --git a/mmv1/templates/terraform/examples/big_query_routine_tvf.tf.erb b/mmv1/templates/terraform/examples/bigquery_routine_tvf.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/big_query_routine_tvf.tf.erb rename to mmv1/templates/terraform/examples/bigquery_routine_tvf.tf.erb diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_routine_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_routine_test.go index bd106a6f079b..00f5763b505b 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_routine_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_routine_test.go @@ -173,3 +173,171 @@ resource "google_bigquery_routine" "spark_jar" { } `, context) } + +func TestAccBigQueryRoutine_bigQueryRoutineRemoteFunction(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "zip_path": "./test-fixtures/function-source.zip", + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryRoutineDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryRoutine_bigQueryRoutineRemoteFunction(context), + }, + { + ResourceName: "google_bigquery_routine.remote_function_routine", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBigQueryRoutine_bigQueryRoutineRemoteFunction_Update(context), + }, + { + ResourceName: "google_bigquery_routine.remote_function_routine", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccBigQueryRoutine_bigQueryRoutineRemoteFunction(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_storage_bucket" "default" { + name = "%{random_suffix}-gcf-source" + location = "US" + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "object" { + name = "function-source.zip" + bucket = google_storage_bucket.default.name + source = "%{zip_path}" +} + +resource "google_cloudfunctions2_function" "default" { + name = "function-v2-0" + location = "us-central1" + description = "a new function" + + build_config { + runtime = "nodejs18" + entry_point = "helloHttp" + source { + storage_source { + bucket = google_storage_bucket.default.name + object = google_storage_bucket_object.object.name + } + } + } + + service_config { + max_instance_count = 1 + available_memory = "256M" + timeout_seconds = 60 + } +} + +resource "google_bigquery_connection" "test" { + connection_id = "tf_test_connection_id%{random_suffix}" + location = "US" + cloud_resource { } +} + +resource "google_bigquery_dataset" "test" { + dataset_id = "tf_test_dataset_id%{random_suffix}" +} + +resource "google_bigquery_routine" "remote_function_routine" { + dataset_id = "${google_bigquery_dataset.test.dataset_id}" + routine_id = "tf_test_routine_id%{random_suffix}" + routine_type = "SCALAR_FUNCTION" + definition_body = "" + + return_type = "{\"typeKind\" : \"STRING\"}" + + remote_function_options { + endpoint = google_cloudfunctions2_function.default.service_config[0].uri + connection = "${google_bigquery_connection.test.name}" + max_batching_rows = "10" + user_defined_context = { + "z": "1.5", + } + } +} +`, context) +} + +func testAccBigQueryRoutine_bigQueryRoutineRemoteFunction_Update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_storage_bucket" "default" { + name = "%{random_suffix}-gcf-source" + location = "US" + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "object" { + name = "function-source.zip" + bucket = google_storage_bucket.default.name + source = "%{zip_path}" +} + +resource "google_cloudfunctions2_function" "default2" { + name = "function-v2-1" + location = "us-central1" + description = "a new new function" + + build_config { + runtime = "nodejs18" + entry_point = "helloHttp" + source { + storage_source { + bucket = google_storage_bucket.default.name + object = google_storage_bucket_object.object.name + } + } + } + + service_config { + max_instance_count = 1 + available_memory = "256M" + timeout_seconds = 60 + } +} + +resource "google_bigquery_connection" "test2" { + connection_id = "tf_test_connection2_id%{random_suffix}" + location = "US" + cloud_resource { } +} + +resource "google_bigquery_dataset" "test" { + dataset_id = "tf_test_dataset_id%{random_suffix}" +} + +resource "google_bigquery_routine" "remote_function_routine" { + dataset_id = "${google_bigquery_dataset.test.dataset_id}" + routine_id = "tf_test_routine_id%{random_suffix}" + routine_type = "SCALAR_FUNCTION" + definition_body = "" + + return_type = "{\"typeKind\" : \"STRING\"}" + + remote_function_options { + endpoint = google_cloudfunctions2_function.default2.service_config[0].uri + connection = "${google_bigquery_connection.test2.name}" + max_batching_rows = "5" + user_defined_context = { + "z": "1.2", + "w": "test", + } + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/bigquery/test-fixtures/function-source.zip b/mmv1/third_party/terraform/services/bigquery/test-fixtures/function-source.zip new file mode 100644 index 0000000000000000000000000000000000000000..1cb571888ef575c261c2c42e8315daddbb653b5a GIT binary patch literal 458 zcmWIWW@Zs#U|`^2Fbc5`5s?gR?g8?)fJGP>GV@YWEA+C8U3-1GnhgZpzFQs@;p$xQ zlJUr;rRFcLUF)$oIeX<#Kvz}y@!q?(c5?5tPquQz7UjxFE@bKtma^5VeBD{q?V7DQ z^YlWIx%GQKdjC`19Mq9~-ML3zm3_;!EVr4>kHXF!oZwj68u?}gv(@5RRo5TbY+ks$ z<==AI@WjY(^?y}9%RiaB$F#`S^w0LRr8gJ?P+Yt`ex_Fd(6xR*%mc&)iOJcC>8U_B z=jVx@-ph4Vfyd$D-Q^rNx7sH!xAR<>A+pmO>_D}O5o3PC@B#&PV36>4;W@Hj!z#UpZ>yZE~?9g?g eyBMKm6Of7Q{s3=QHjpe65EcMw9Yzoj7XSctwvFxp literal 0 HcmV?d00001 From 7c2fc273c82b16d883976068d13a2bf9d52ef16b Mon Sep 17 00:00:00 2001 From: NA2047 <12290725+NA2047@users.noreply.github.com> Date: Fri, 23 Feb 2024 18:14:54 -0500 Subject: [PATCH 027/200] Adding documentaiton build_worker_pool (#10022) --- .../website/docs/r/cloudfunctions_function.html.markdown | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown index 8a8b26b87091..5cfb46f700fe 100644 --- a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown @@ -149,6 +149,8 @@ Please refer to the field 'effective_labels' for all of the labels present on th * `build_environment_variables` - (Optional) A set of key/value environment variable pairs available during build time. +* `build_worker_pool` - (Optional) Name of the Cloud Build Custom Worker Pool that should be used to build the function. + * `vpc_connector` - (Optional) The VPC Network Connector that this cloud function can connect to. It should be set up as fully-qualified URI. The format of this field is `projects/*/locations/*/connectors/*`. * `vpc_connector_egress_settings` - (Optional) The egress settings for the connector, controlling what traffic is diverted through it. Allowed values are `ALL_TRAFFIC` and `PRIVATE_RANGES_ONLY`. Defaults to `PRIVATE_RANGES_ONLY`. If unset, this field preserves the previously set value. From 5599650ebf0ace9601ddfea4dd785741c7e359b9 Mon Sep 17 00:00:00 2001 From: Yuki Watanabe <47182350+yuki0920@users.noreply.github.com> Date: Sat, 24 Feb 2024 08:53:34 +0900 Subject: [PATCH 028/200] docs: fix import example in google_project_iam (#10007) Fix the example in the `google_project_iam` documentation. https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_project_iam#import --- .../terraform/website/docs/r/google_project_iam.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown index 419315c503d7..33ee748e341d 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown @@ -228,7 +228,7 @@ An [`import` block](https://developer.hashicorp.com/terraform/language/import) ( ```tf import { - id = ""{{project_id}} roles/viewer user:foo@example.com"m" + id = "{{project_id}} roles/viewer user:foo@example.com" to = google_project_iam_member.default } ``` From b361a7b4732fee45a86abe87bfd1e809dda47ec6 Mon Sep 17 00:00:00 2001 From: Scott Suarez Date: Mon, 26 Feb 2024 10:09:25 -0800 Subject: [PATCH 029/200] ScottSuarez not on vacation anymore (#10052) * I'm on vaction :) * ScottSuarez not vaction anymore * ScottSuarez not vaction anymore --- .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 fd151935d98b..c1f5081de1ca 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -49,7 +49,6 @@ var ( onVacationReviewers = []string{ "zli82016", "NickElliot", - "ScottSuarez", } ) From 14a412945fd6d802dcdb8bd2ead14891268334b4 Mon Sep 17 00:00:00 2001 From: askubis Date: Mon, 26 Feb 2024 19:34:13 +0100 Subject: [PATCH 030/200] Promote (R)IGM.AllInstancesConfig to V1 (#9964) --- ...urce_compute_instance_group_manager.go.erb | 25 ------------------- ...compute_instance_group_manager_test.go.erb | 6 ----- ...mpute_region_instance_group_manager.go.erb | 21 ---------------- ..._region_instance_group_manager_test.go.erb | 4 --- ...mpute_instance_group_manager.html.markdown | 6 ++--- ...egion_instance_group_manager.html.markdown | 6 ++--- 6 files changed, 6 insertions(+), 62 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb index d61f2457be99..878c8c2a2545 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb @@ -316,7 +316,6 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { }, }, - <% unless version == "ga" -%> "all_instances_config": { Type: schema.TypeList, Optional: true, @@ -341,7 +340,6 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { }, }, }, - <% end -%> "wait_for_instances": { Type: schema.TypeBool, Optional: true, @@ -353,12 +351,7 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { Optional: true, Default: "STABLE", ValidateFunc: validation.StringInSlice([]string{"STABLE", "UPDATED"}, false), - - <% if version == "ga" -%> - Description: `When used with wait_for_instances specifies the status to wait for. When STABLE is specified this resource will wait until the instances are stable before returning. When UPDATED is set, it will wait for the version target to be reached and any per instance configs to be effective as well as all instances to be stable before returning.`, - <% else -%> Description: `When used with wait_for_instances specifies the status to wait for. When STABLE is specified this resource will wait until the instances are stable before returning. When UPDATED is set, it will wait for the version target to be reached and any per instance configs to be effective and all instances configs to be effective as well as all instances to be stable before returning.`, - <% end -%> }, "stateful_internal_ip": { Type: schema.TypeList, @@ -454,7 +447,6 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { }, }, }, - <% unless version == "ga" -%> "all_instances_config": { Type: schema.TypeList, Computed: true, @@ -469,7 +461,6 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { }, }, }, - <% end -%> "stateful": { Type: schema.TypeList, Computed: true, @@ -589,9 +580,7 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte Versions: expandVersions(d.Get("version").([]interface{})), UpdatePolicy: expandUpdatePolicy(d.Get("update_policy").([]interface{})), InstanceLifecyclePolicy: expandInstanceLifecyclePolicy(d.Get("instance_lifecycle_policy").([]interface{})), - <% unless version == "ga" -%> AllInstancesConfig: expandAllInstancesConfig(nil, d.Get("all_instances_config").([]interface{})), - <% end -%> StatefulPolicy: expandStatefulPolicy(d), // Force send TargetSize to allow a value of 0. @@ -815,13 +804,11 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf if err = d.Set("instance_lifecycle_policy", flattenInstanceLifecyclePolicy(manager.InstanceLifecyclePolicy)); err != nil { return fmt.Errorf("Error setting instance lifecycle policy in state: %s", err.Error()) } - <% unless version == "ga" -%> if manager.AllInstancesConfig != nil { if err = d.Set("all_instances_config", flattenAllInstancesConfig(manager.AllInstancesConfig)); err != nil { return fmt.Errorf("Error setting all_instances_config in state: %s", err.Error()) } } - <% end -%> if err = d.Set("status", flattenStatus(manager.Status)); err != nil { return fmt.Errorf("Error setting status in state: %s", err.Error()) } @@ -892,7 +879,6 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte change = true } - <% unless version == "ga" -%> if d.HasChange("all_instances_config") { oldAic, newAic := d.GetChange("all_instances_config") if newAic == nil || len(newAic.([]interface{})) == 0 { @@ -902,7 +888,6 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte } change = true } - <% end -%> if d.HasChange("stateful_internal_ip") || d.HasChange("stateful_external_ip") || d.HasChange("stateful_disk") { updatedManager.StatefulPolicy = expandStatefulPolicy(d) @@ -1045,11 +1030,7 @@ func resourceComputeInstanceGroupManagerDelete(d *schema.ResourceData, meta inte func computeIGMWaitForInstanceStatus(d *schema.ResourceData, meta interface{}) error { waitForUpdates := d.Get("wait_for_instances_status").(string) == "UPDATED" conf := resource.StateChangeConf{ - <% if version == "ga" -%> - Pending: []string{"creating", "error", "updating per instance configs", "reaching version target"}, - <% else -%> Pending: []string{"creating", "error", "updating per instance configs", "reaching version target", "updating all instances config"}, - <% end -%> Target: []string{"created"}, Refresh: waitForInstancesRefreshFunc(getManager, waitForUpdates, d, meta), Timeout: d.Timeout(schema.TimeoutCreate), @@ -1400,7 +1381,6 @@ func flattenInstanceLifecyclePolicy(instanceLifecyclePolicy *compute.InstanceGro return results } -<% unless version == "ga" -%> func expandAllInstancesConfig(old []interface{}, new []interface{}) *compute.InstanceGroupManagerAllInstancesConfig { var properties *compute.InstancePropertiesPatch for _, raw := range new { @@ -1456,7 +1436,6 @@ func flattenAllInstancesConfig(allInstancesConfig *compute.InstanceGroupManagerA results = append(results, props) return results } -<% end -%> func flattenStatus(status *compute.InstanceGroupManagerStatus) []map[string]interface{} { results := []map[string]interface{}{} @@ -1465,11 +1444,9 @@ func flattenStatus(status *compute.InstanceGroupManagerStatus) []map[string]inte "stateful": flattenStatusStateful(status.Stateful), "version_target": flattenStatusVersionTarget(status.VersionTarget), } - <% unless version == "ga" -%> if status.AllInstancesConfig != nil { data["all_instances_config"] = flattenStatusAllInstancesConfig(status.AllInstancesConfig) } - <% end -%> results = append(results, data) return results } @@ -1502,7 +1479,6 @@ func flattenStatusVersionTarget(versionTarget *compute.InstanceGroupManagerStatu return results } -<% unless version == "ga" -%> func flattenStatusAllInstancesConfig(allInstancesConfig *compute.InstanceGroupManagerStatusAllInstancesConfig) []map[string]interface{} { results := []map[string]interface{}{} data := map[string]interface{}{ @@ -1511,7 +1487,6 @@ func flattenStatusAllInstancesConfig(allInstancesConfig *compute.InstanceGroupMa results = append(results, data) return results } -<% end -%> func resourceInstanceGroupManagerStateImporter(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { if err := d.Set("wait_for_instances", false); err != nil { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.erb index 7c3322419219..c02ed9a13c1b 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.erb @@ -660,7 +660,6 @@ resource "google_compute_instance_group_manager" "igm-update" { name = "customhttp" port = 8080 } -<% unless version == "ga" -%> all_instances_config { metadata = { foo = "bar" @@ -669,7 +668,6 @@ resource "google_compute_instance_group_manager" "igm-update" { doo = "dad" } } -<% end -%> instance_lifecycle_policy { force_update_on_repair = "YES" @@ -766,7 +764,6 @@ resource "google_compute_instance_group_manager" "igm-update" { port = 8443 } -<% unless version == "ga" -%> all_instances_config { metadata = { doo = "dad" @@ -775,7 +772,6 @@ resource "google_compute_instance_group_manager" "igm-update" { foo = "bar" } } -<% end -%> instance_lifecycle_policy { force_update_on_repair = "NO" @@ -1780,7 +1776,6 @@ resource "google_compute_instance_group_manager" "igm-basic" { max_surge_fixed = 0 max_unavailable_percent = 50 } -<% unless version == "ga" -%> all_instances_config { metadata = { doo = "dad" @@ -1789,7 +1784,6 @@ resource "google_compute_instance_group_manager" "igm-basic" { foo = "bar" } } -<% end -%> instance_lifecycle_policy { force_update_on_repair = "YES" } diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb index 8530b1e3e6b5..46cfbffd60e9 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb @@ -208,12 +208,7 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Optional: true, Default: "STABLE", ValidateFunc: validation.StringInSlice([]string{"STABLE", "UPDATED"}, false), - - <% if version == "ga" -%> - Description: `When used with wait_for_instances specifies the status to wait for. When STABLE is specified this resource will wait until the instances are stable before returning. When UPDATED is set, it will wait for the version target to be reached and any per instance configs to be effective as well as all instances to be stable before returning.`, - <% else -%> Description: `When used with wait_for_instances specifies the status to wait for. When STABLE is specified this resource will wait until the instances are stable before returning. When UPDATED is set, it will wait for the version target to be reached and any per instance configs to be effective and all instances configs to be effective as well as all instances to be stable before returning.`, - <% end -%> }, "auto_healing_policies": { @@ -365,7 +360,6 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { }, }, }, - <% unless version == "ga" -%> "all_instances_config": { Type: schema.TypeList, Optional: true, @@ -390,7 +384,6 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { }, }, }, - <% end -%> "stateful_internal_ip": { Type: schema.TypeList, Optional: true, @@ -481,7 +474,6 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { }, }, }, - <% unless version == "ga" -%> "all_instances_config": { Type: schema.TypeList, Computed: true, @@ -496,7 +488,6 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { }, }, }, - <% end -%> "stateful": { Type: schema.TypeList, Computed: true, @@ -562,9 +553,7 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met Versions: expandVersions(d.Get("version").([]interface{})), UpdatePolicy: expandRegionUpdatePolicy(d.Get("update_policy").([]interface{})), InstanceLifecyclePolicy: expandInstanceLifecyclePolicy(d.Get("instance_lifecycle_policy").([]interface{})), - <% unless version == "ga" -%> AllInstancesConfig: expandAllInstancesConfig(nil, d.Get("all_instances_config").([]interface{})), - <% end -%> DistributionPolicy: expandDistributionPolicy(d), StatefulPolicy: expandStatefulPolicy(d), // Force send TargetSize to allow size of 0. @@ -602,11 +591,7 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met func computeRIGMWaitForInstanceStatus(d *schema.ResourceData, meta interface{}) error { waitForUpdates := d.Get("wait_for_instances_status").(string) == "UPDATED" conf := resource.StateChangeConf{ - <% if version == "ga" -%> - Pending: []string{"creating", "error", "updating per instance configs", "reaching version target"}, - <% else -%> Pending: []string{"creating", "error", "updating per instance configs", "reaching version target", "updating all instances config"}, - <% end -%> Target: []string{"created"}, Refresh: waitForInstancesRefreshFunc(getRegionalManager, waitForUpdates, d, meta), Timeout: d.Timeout(schema.TimeoutCreate), @@ -674,11 +659,9 @@ func waitForInstancesRefreshFunc(f getInstanceManagerFunc, waitForUpdates bool, if !m.Status.VersionTarget.IsReached { return false, "reaching version target", nil } - <% unless version == "ga" -%> if !m.Status.AllInstancesConfig.Effective { return false, "updating all instances config", nil } - <% end -%> } return true, "created", nil } else { @@ -763,13 +746,11 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta if err = d.Set("instance_lifecycle_policy", flattenInstanceLifecyclePolicy(manager.InstanceLifecyclePolicy)); err != nil { return fmt.Errorf("Error setting instance lifecycle policy in state: %s", err.Error()) } - <% unless version == "ga" -%> if manager.AllInstancesConfig != nil { if err = d.Set("all_instances_config", flattenAllInstancesConfig(manager.AllInstancesConfig)); err != nil { return fmt.Errorf("Error setting all_instances_config in state: %s", err.Error()) } } - <% end -%> if err = d.Set("stateful_disk", flattenStatefulPolicy(manager.StatefulPolicy)); err != nil { return fmt.Errorf("Error setting stateful_disk in state: %s", err.Error()) } @@ -852,7 +833,6 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met change = true } - <% unless version == "ga" -%> if d.HasChange("all_instances_config") { oldAic, newAic := d.GetChange("all_instances_config") if newAic == nil || len(newAic.([]interface{})) == 0 { @@ -862,7 +842,6 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met } change = true } - <% end -%> if d.HasChange("list_managed_instances_results") { updatedManager.ListManagedInstancesResults = d.Get("list_managed_instances_results").(string) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.erb index a5470d09b032..4e4ef9645074 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.erb @@ -562,7 +562,6 @@ resource "google_compute_region_instance_group_manager" "igm-update" { port = 8080 } -<% unless version == "ga" -%> all_instances_config { metadata = { foo = "bar" @@ -571,7 +570,6 @@ resource "google_compute_region_instance_group_manager" "igm-update" { doo = "dad" } } -<% end -%> instance_lifecycle_policy { force_update_on_repair = "YES" @@ -668,7 +666,6 @@ resource "google_compute_region_instance_group_manager" "igm-update" { port = 8443 } -<% unless version == "ga" -%> all_instances_config { metadata = { doo = "dad" @@ -677,7 +674,6 @@ resource "google_compute_region_instance_group_manager" "igm-update" { foo = "bar" } } -<% end -%> instance_lifecycle_policy { force_update_on_repair = "NO" diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown index f6dead3b4382..a79b67e8c81c 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown @@ -153,7 +153,7 @@ The following arguments are supported: * `auto_healing_policies` - (Optional) The autohealing policies for this managed instance group. You can specify only one value. Structure is [documented below](#nested_auto_healing_policies). For more information, see the [official documentation](https://cloud.google.com/compute/docs/instance-groups/creating-groups-of-managed-instances#monitoring_groups). -* `all_instances_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) +* `all_instances_config` - (Optional) Properties to set on all instances in the group. After setting allInstancesConfig on the group, you must update the group's instances to apply the configuration. @@ -226,9 +226,9 @@ all_instances_config { } ``` -* `metadata` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)), The metadata key-value pairs that you want to patch onto the instance. For more information, see [Project and instance metadata](https://cloud.google.com/compute/docs/metadata#project_and_instance_metadata). +* `metadata` - (Optional), The metadata key-value pairs that you want to patch onto the instance. For more information, see [Project and instance metadata](https://cloud.google.com/compute/docs/metadata#project_and_instance_metadata). -* `labels` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)), The label key-value pairs that you want to patch onto the instance. +* `labels` - (Optional), The label key-value pairs that you want to patch onto the instance. - - - diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown index 0a16ac30b14f..cad9a1343d81 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown @@ -155,7 +155,7 @@ The following arguments are supported: * `auto_healing_policies` - (Optional) The autohealing policies for this managed instance group. You can specify only one value. Structure is documented below. For more information, see the [official documentation](https://cloud.google.com/compute/docs/instance-groups/creating-groups-of-managed-instances#monitoring_groups). -* `all_instances_config` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) +* `all_instances_config` - (Optional) Properties to set on all instances in the group. After setting allInstancesConfig on the group, you must update the group's instances to apply the configuration. @@ -235,9 +235,9 @@ all_instances_config { } ``` -* `metadata` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)), The metadata key-value pairs that you want to patch onto the instance. For more information, see [Project and instance metadata](https://cloud.google.com/compute/docs/metadata#project_and_instance_metadata). +* `metadata` - (Optional), The metadata key-value pairs that you want to patch onto the instance. For more information, see [Project and instance metadata](https://cloud.google.com/compute/docs/metadata#project_and_instance_metadata). -* `labels` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)), The label key-value pairs that you want to patch onto the instance. +* `labels` - (Optional), The label key-value pairs that you want to patch onto the instance. - - - From c3ce700765fbc4b3dc9896da767194b8eda9a13d Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Mon, 26 Feb 2024 19:18:08 +0000 Subject: [PATCH 031/200] Promote metric settings in compute region autoscaler to GA (#10045) --- mmv1/products/compute/RegionAutoscaler.yaml | 3 --- .../compute/resource_compute_region_autoscaler_test.go.erb | 4 ---- 2 files changed, 7 deletions(-) diff --git a/mmv1/products/compute/RegionAutoscaler.yaml b/mmv1/products/compute/RegionAutoscaler.yaml index 931e07443408..7ef41e624626 100644 --- a/mmv1/products/compute/RegionAutoscaler.yaml +++ b/mmv1/products/compute/RegionAutoscaler.yaml @@ -140,7 +140,6 @@ properties: Defines operating mode for this policy. - !ruby/object:Api::Type::NestedObject name: 'scaleDownControl' - min_version: beta description: | Defines scale down controls to reduce the risk of response latency and outages due to abrupt scale-in events @@ -265,7 +264,6 @@ properties: required: true - !ruby/object:Api::Type::Double name: 'singleInstanceAssignment' - min_version: beta description: | If scaling is based on a per-group metric value that represents the total amount of work to be done or resource usage, set this value to @@ -341,7 +339,6 @@ properties: (if you are using gce_instance resource type). If multiple TimeSeries are returned upon the query execution, the autoscaler will sum their respective values to obtain its scaling value. - min_version: beta - !ruby/object:Api::Type::NestedObject name: 'loadBalancingUtilization' description: | diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_autoscaler_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_autoscaler_test.go.erb index 1d6f65491513..64f15c2fb80e 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_autoscaler_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_autoscaler_test.go.erb @@ -217,14 +217,12 @@ resource "google_compute_region_autoscaler" "foobar" { target = 0.5 predictive_method = "OPTIMIZE_AVAILABILITY" } -<% unless version == 'ga' -%> scale_down_control { max_scaled_down_replicas { percent = 80 } time_window_sec = 300 } -<% end -%> } } `, autoscalerName) @@ -269,14 +267,12 @@ resource "google_compute_region_autoscaler" "foobar" { cpu_utilization { target = 0.5 } -<% unless version == 'ga' -%> scale_down_control { max_scaled_down_replicas { percent = 80 } time_window_sec = 300 } -<% end -%> scaling_schedules { name = "every-weekday-morning" description = "Increase to 2 every weekday at 7AM for 6 hours." From b449d45a3ff892722c699d8a38e84a3309a31b9c Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Mon, 26 Feb 2024 11:36:01 -0800 Subject: [PATCH 032/200] Fixed flakiness in TestAccDataPipelinePipeline_dataPipelinePipelineExample (#10040) --- mmv1/products/datapipeline/Pipeline.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mmv1/products/datapipeline/Pipeline.yaml b/mmv1/products/datapipeline/Pipeline.yaml index c3e24c9fcd9e..1bf821d94bff 100644 --- a/mmv1/products/datapipeline/Pipeline.yaml +++ b/mmv1/products/datapipeline/Pipeline.yaml @@ -31,6 +31,8 @@ examples: primary_resource_name: 'fmt.Sprintf("tf-test-my-pipeline%s", context["random_suffix"])' primary_resource_id: 'primary' + ignore_read_extra: + - 'schedule_info.0.next_job_time' vars: pipeline_name: 'my-pipeline' account_id: 'my-account' From 7faaacc8f1d429d6d0d6317ba98e962bf9bd1ae4 Mon Sep 17 00:00:00 2001 From: ajaybgunjal1 <161062655+ajaybgunjal1@users.noreply.github.com> Date: Mon, 26 Feb 2024 20:46:06 +0000 Subject: [PATCH 033/200] Retry delete network step while creating a google project. (#10046) --- .../services/resourcemanager/resource_google_project.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go index acf1db96fa56..1d2c97855fe0 100644 --- a/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go +++ b/mmv1/third_party/terraform/services/resourcemanager/resource_google_project.go @@ -227,7 +227,13 @@ func resourceGoogleProjectCreate(d *schema.ResourceData, meta interface{}) error return errwrap.Wrapf("Error enabling the Compute Engine API required to delete the default network: {{err}} ", err) } - if err = forceDeleteComputeNetwork(d, config, project.ProjectId, "default"); err != nil { + err = forceDeleteComputeNetwork(d, config, project.ProjectId, "default") + // Retry if API is not yet enabled. + if err != nil && transport_tpg.IsGoogleApiErrorWithCode(err, 403) { + time.Sleep(10 * time.Second) + err = forceDeleteComputeNetwork(d, config, project.ProjectId, "default") + } + if err != nil { if transport_tpg.IsGoogleApiErrorWithCode(err, 404) { log.Printf("[DEBUG] Default network not found for project %q, no need to delete it", project.ProjectId) } else { From 3e13564ac5d3ac814949b399e0fd56058445a717 Mon Sep 17 00:00:00 2001 From: Hossein Golestani Date: Mon, 26 Feb 2024 13:46:12 -0800 Subject: [PATCH 034/200] Adding the namespace_labels field to the GKE Hub Scope resource (#9972) * initial commit for scope-level namespace labels * Add validation exceptions for the field of the GKEHub Scope and Namespace resources to be of type * Undoing unnecessary changes * Fixing the type of Scope namespace_labels field --- mmv1/products/gkehub2/Scope.yaml | 8 ++++++++ .../terraform/examples/gkehub_scope_basic.tf.erb | 5 +++++ .../services/gkehub2/resource_gke_hub_scope_test.go | 10 ++++++++++ 3 files changed, 23 insertions(+) diff --git a/mmv1/products/gkehub2/Scope.yaml b/mmv1/products/gkehub2/Scope.yaml index 7c12b64c03b4..ff73465a443e 100644 --- a/mmv1/products/gkehub2/Scope.yaml +++ b/mmv1/products/gkehub2/Scope.yaml @@ -117,6 +117,14 @@ properties: - :READY - :DELETING - :UPDATING + - !ruby/object:Api::Type::KeyValuePairs + name: 'namespaceLabels' + description: | + Scope-level cluster namespace labels. For the member clusters bound + to the Scope, these labels are applied to each namespace under the + Scope. Scope-level labels take precedence over Namespace-level + labels (`namespace_labels` in the Fleet Namespace resource) if they + share a key. Keys and values must be Kubernetes-conformant. - !ruby/object:Api::Type::KeyValueLabels name: 'labels' description: | diff --git a/mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb b/mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb index 107fa956c82d..63efb8be3c78 100644 --- a/mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb +++ b/mmv1/templates/terraform/examples/gkehub_scope_basic.tf.erb @@ -1,5 +1,10 @@ resource "google_gke_hub_scope" "<%= ctx[:primary_resource_id] %>" { scope_id = "<%= ctx[:vars]['resource_name'] %>" + namespace_labels = { + keyb = "valueb" + keya = "valuea" + keyc = "valuec" + } labels = { keyb = "valueb" keya = "valuea" diff --git a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go index 967fe08c4bc2..be00b628a7c6 100644 --- a/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go +++ b/mmv1/third_party/terraform/services/gkehub2/resource_gke_hub_scope_test.go @@ -47,6 +47,11 @@ func testAccGKEHub2Scope_gkehubScopeBasicExample_basic(context map[string]interf return acctest.Nprintf(` resource "google_gke_hub_scope" "scope" { scope_id = "tf-test-scope%{random_suffix}" + namespace_labels = { + keyb = "valueb" + keya = "valuea" + keyc = "valuec" + } labels = { keyb = "valueb" keya = "valuea" @@ -60,6 +65,11 @@ func testAccGKEHub2Scope_gkehubScopeBasicExample_update(context map[string]inter return acctest.Nprintf(` resource "google_gke_hub_scope" "scope" { scope_id = "tf-test-scope%{random_suffix}" + namespace_labels = { + updated_keyb = "updated_valueb" + updated_keya = "updated_valuea" + updated_keyc = "updated_valuec" + } labels = { updated_keyb = "updated_valueb" updated_keya = "updated_valuea" From 76474ecb686e095b4436de3ce17d739a2a1a4b21 Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Mon, 26 Feb 2024 22:54:28 +0100 Subject: [PATCH 035/200] Support connectivity fields for Composer 3 (#9889) * add composer_network_attachment * indicate conflicting configs * commas * no need for bidirectional conflict definition (generates double errors) * protect nit PrivateClusterConfig * for optimizing error messages about conflicts * add 2 step update for composer_network_attachment * make composer_network_attachment available in beta only * add two step update for network and subnetwork * corrections in 2 phase update for network/subnetwork * remove composer3 check(CustomizeDiff will solve this), filter api error, add tests (unsetting netwok/subnetwork not working) * added ForceNewIf fot network/subnetwork, problem with unsetting these fields remains * add docs for composer_network_attachment * add test for network attachment * ignore non empty plan in network attachment test * add networkAttachment update and conflicting fields tests * add ComputedIf for network, change isComposer3 * minor corrections * remove computedIf * filter equivalent values of network/subnetwork in ForceNewIf * simplify ResourceConditionFunc, add beta/ga version conditions * typo * more general comparison of network references * use tpgresource.CompareSelfLinkRelativePaths instead of custom function * modify isComposer3 to avoid merge conflicts later. * removing this since documentation is handled in other PR and to avoid conflicts while merging. * replace ExpectNonEmptyPlan with lifecycle.ignore_changes * add testcase for changing network attachment to network and subnetwork * add third step to TestAccComposerEnvironmentComposer3_updateWithNetworkAndSubnetwork * modify tests to use different network for attachment * remove unused constant * remove ExpectNonEmptyPlan (already replaced with lifecycle.ignore_changes) --- .../resource_composer_environment.go.erb | 109 +++++- .../resource_composer_environment_test.go.erb | 357 ++++++++++++++++-- 2 files changed, 441 insertions(+), 25 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 0369ce49f4d0..e192b510fa65 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 @@ -170,7 +170,9 @@ func ResourceComposerEnvironment() *schema.Resource { tpgresource.DefaultProviderRegion, tpgresource.SetLabelsDiff, <% unless version == "ga" -%> - customdiff.ValidateChange("config.0.software_config.0.image_version", imageVersionChangeValidationFunc), + customdiff.ForceNewIf("config.0.node_config.0.network", forceNewCustomDiff("config.0.node_config.0.network")), + customdiff.ForceNewIf("config.0.node_config.0.subnetwork", forceNewCustomDiff("config.0.node_config.0.subnetwork")), + customdiff.ValidateChange("config.0.software_config.0.image_version", imageVersionChangeValidationFunc), versionValidationCustomizeDiffFunc, <% end -%> ), @@ -242,17 +244,37 @@ func ResourceComposerEnvironment() *schema.Resource { Type: schema.TypeString, Computed: true, Optional: true, +<% if version == "ga" -%> ForceNew: true, +<% else -%> + ForceNew: false, + ConflictsWith: []string{"config.0.node_config.0.composer_network_attachment"}, +<% end -%> DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `The Compute Engine machine type used for cluster instances, specified as a name or relative resource name. For example: "projects/{project}/zones/{zone}/machineTypes/{machineType}". Must belong to the enclosing environment's project and region/zone. The network must belong to the environment's project. If unspecified, the "default" network ID in the environment's project is used. If a Custom Subnet Network is provided, subnetwork must also be provided.`, }, "subnetwork": { Type: schema.TypeString, Optional: true, +<% if version == "ga" -%> ForceNew: true, +<% else -%> + ForceNew: false, + Computed: true, + ConflictsWith: []string{"config.0.node_config.0.composer_network_attachment"}, +<% end -%> DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, - Description: `The Compute Engine subnetwork to be used for machine communications, , specified as a self-link, relative resource name (e.g. "projects/{project}/regions/{region}/subnetworks/{subnetwork}"), or by name. If subnetwork is provided, network must also be provided and the subnetwork must belong to the enclosing environment's project and region.`, + Description: `The Compute Engine subnetwork to be used for machine communications, specified as a self-link, relative resource name (e.g. "projects/{project}/regions/{region}/subnetworks/{subnetwork}"), or by name. If subnetwork is provided, network must also be provided and the subnetwork must belong to the enclosing environment's project and region.`, + }, +<% unless version == "ga" -%> + "composer_network_attachment": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: false, + Description: `PSC (Private Service Connect) Network entry point. Customers can pre-create the Network Attachment and point Cloud Composer environment to use. It is possible to share network attachment among many environments, provided enough IP addresses are available.`, }, +<% end -%> "disk_size_gb": { Type: schema.TypeInt, Computed: true, @@ -1195,6 +1217,68 @@ func resourceComposerEnvironmentUpdate(d *schema.ResourceData, meta interface{}) return err } +<% unless version == "ga" -%> + noChangeErrorMessage := "Update request does not result in any change to the environment's configuration" + if d.HasChange("config.0.node_config.0.network") || d.HasChange("config.0.node_config.0.subnetwork"){ + // step 1: update with empty network and subnetwork + patchObjEmpty := &composer.Environment{ + Config: &composer.EnvironmentConfig{ + NodeConfig: &composer.NodeConfig{}, + }, + } + err = resourceComposerEnvironmentPatchField("config.nodeConfig.network,config.nodeConfig.subnetwork", userAgent, patchObjEmpty, d, tfConfig) + if err != nil && !strings.Contains(err.Error(), noChangeErrorMessage){ + return err + } + + // step 2: update with new network and subnetwork, if new values are not empty + if (config.NodeConfig.Network != "" && config.NodeConfig.Subnetwork != ""){ + patchObj := &composer.Environment{ + Config: &composer.EnvironmentConfig{ + NodeConfig: &composer.NodeConfig{}, + }, + } + if config != nil && config.NodeConfig != nil { + patchObj.Config.NodeConfig.Network = config.NodeConfig.Network + patchObj.Config.NodeConfig.Subnetwork = config.NodeConfig.Subnetwork + } + err = resourceComposerEnvironmentPatchField("config.nodeConfig.network,config.nodeConfig.subnetwork", userAgent, patchObj, d, tfConfig) + if err != nil { + return err + } + } + } + + if d.HasChange("config.0.node_config.0.composer_network_attachment") { + // step 1: update with empty composer_network_attachment + patchObjEmpty := &composer.Environment{ + Config: &composer.EnvironmentConfig{ + NodeConfig: &composer.NodeConfig{}, + }, + } + err = resourceComposerEnvironmentPatchField("config.nodeConfig.composerNetworkAttachment", userAgent, patchObjEmpty, d, tfConfig) + if err != nil && !strings.Contains(err.Error(), noChangeErrorMessage){ + return err + } + + // step 2: update with new composer_network_attachment + if (config.NodeConfig.ComposerNetworkAttachment != ""){ + patchObj := &composer.Environment{ + Config: &composer.EnvironmentConfig{ + NodeConfig: &composer.NodeConfig{}, + }, + } + if config != nil && config.NodeConfig != nil { + patchObj.Config.NodeConfig.ComposerNetworkAttachment = config.NodeConfig.ComposerNetworkAttachment + } + err = resourceComposerEnvironmentPatchField("config.nodeConfig.composerNetworkAttachment", userAgent, patchObj, d, tfConfig) + if err != nil { + return err + } + } + } +<% end -%> + <% unless version == "ga" -%> if d.HasChange("config.0.software_config.0.image_version") { patchObj := &composer.Environment{ @@ -1853,6 +1937,9 @@ func flattenComposerEnvironmentConfigNodeConfig(nodeCfg *composer.NodeConfig) in transformed["machine_type"] = nodeCfg.MachineType transformed["network"] = nodeCfg.Network transformed["subnetwork"] = nodeCfg.Subnetwork +<% unless version == "ga" -%> + transformed["composer_network_attachment"] = nodeCfg.ComposerNetworkAttachment +<% end -%> transformed["disk_size_gb"] = nodeCfg.DiskSizeGb transformed["service_account"] = nodeCfg.ServiceAccount transformed["oauth_scopes"] = flattenComposerEnvironmentConfigNodeConfigOauthScopes(nodeCfg.OauthScopes) @@ -2470,6 +2557,13 @@ func expandComposerEnvironmentConfigNodeConfig(v interface{}, d *schema.Resource } transformed.Subnetwork = transformedSubnetwork } + +<% unless version == "ga" -%> + if v, ok := original["composer_network_attachment"]; ok { + transformed.ComposerNetworkAttachment = v.(string) + } +<% end -%> + transformedIPAllocationPolicy, err := expandComposerEnvironmentIPAllocationPolicy(original["ip_allocation_policy"], d, config) if err != nil { return nil, err @@ -2951,6 +3045,17 @@ func isComposer3(imageVersion string) bool { return strings.Contains(imageVersion, "composer-3") } +func forceNewCustomDiff(key string) customdiff.ResourceConditionFunc { + return func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) bool { + old, new := d.GetChange(key) + imageVersion := d.Get("config.0.software_config.0.image_version").(string) + if isComposer3(imageVersion) || tpgresource.CompareSelfLinkRelativePaths("", old.(string), new.(string), nil) { + return false + } + return true + } +} + func imageVersionChangeValidationFunc(ctx context.Context, old, new, meta any) error { if old.(string) != "" && !isComposer3(old.(string)) && isComposer3(new.(string)) { return fmt.Errorf("upgrade to composer 3 is not yet supported") diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb index 1ddb9257f35e..bde25f487b1f 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb @@ -21,6 +21,7 @@ import ( const testComposerEnvironmentPrefix = "tf-test-composer-env" const testComposerNetworkPrefix = "tf-test-composer-net" const testComposerBucketPrefix = "tf-test-composer-bucket" +const testComposerNetworkAttachmentPrefix = "tf-test-composer-nta" func allComposerServiceAgents() []string { return []string{ @@ -1186,13 +1187,13 @@ func TestAccComposerEnvironmentComposer3_update(t *testing.T) { }) } -func TestAccComposerEnvironmentComposer3_upgrade_expectError(t *testing.T) { +func TestAccComposerEnvironmentComposer3_withNetworkSubnetworkAndAttachment_expectError(t *testing.T) { t.Parallel() envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) network := fmt.Sprintf("%s-%d", testComposerNetworkPrefix, acctest.RandInt(t)) subnetwork := network + "-1" - errorRegExp, _ := regexp.Compile(".*upgrade to composer 3 is not yet supported.*") + networkAttachment := fmt.Sprintf("%s-%d", testComposerNetworkAttachmentPrefix, acctest.RandInt(t)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -1200,58 +1201,128 @@ func TestAccComposerEnvironmentComposer3_upgrade_expectError(t *testing.T) { CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComposerEnvironmentComposer2_empty(envName, network, subnetwork), + Config: testAccComposerEnvironmentComposer3_withNetworkSubnetworkAndAttachment_expectError(envName, networkAttachment, network, subnetwork), + ExpectError: regexp.MustCompile("Conflicting configuration arguments"), }, + // This is a terrible clean-up step in order to get destroy to succeed, + // due to dangling firewall rules left by the Composer Environment blocking network deletion. + // TODO: Remove this check if firewall rules bug gets fixed by Composer. { - Config: testAccComposerEnvironmentComposer3_empty(envName, network, subnetwork), - ExpectError: errorRegExp, + PlanOnly: true, + ExpectNonEmptyPlan: true, + Config: testAccComposerEnvironmentComposer3_basic(envName, network, subnetwork), + Check: testAccCheckClearComposerEnvironmentFirewalls(t, network), + }, + }, + }) +} + +func TestAccComposerEnvironmentComposer3_withNetworkAttachment(t *testing.T) { + t.Parallel() + + envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) + network := fmt.Sprintf("%s-%d", testComposerNetworkPrefix, acctest.RandInt(t)) + subnetwork := network + "-1" + networkAttachment := fmt.Sprintf("%s-%d", testComposerNetworkAttachmentPrefix, acctest.RandInt(t)) + fullFormNetworkAttachmentName := fmt.Sprintf("projects/%s/regions/%s/networkAttachments/%s", envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), networkAttachment) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComposerEnvironmentComposer3_withNetworkAttachment(envName, networkAttachment, network, subnetwork), + }, + { + ResourceName: "google_composer_environment.test", + ImportState: true, + ImportStateVerify: true, }, // This is a terrible clean-up step in order to get destroy to succeed, // due to dangling firewall rules left by the Composer Environment blocking network deletion. // TODO: Remove this check if firewall rules bug gets fixed by Composer. { PlanOnly: true, - ExpectNonEmptyPlan: false, - Config: testAccComposerEnvironmentComposer2_empty(envName, network, subnetwork), + Config: testAccComposerEnvironmentComposer3_withNetworkAttachment(envName, fullFormNetworkAttachmentName, network, subnetwork), Check: testAccCheckClearComposerEnvironmentFirewalls(t, network), + ExpectNonEmptyPlan: true, }, }, }) } -func TestAccComposerEnvironmentComposer2_usesUnsupportedField_expectError(t *testing.T) { +func TestAccComposerEnvironmentComposer3_updateWithNetworkAttachment(t *testing.T) { t.Parallel() envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) - errorRegExp, _ := regexp.Compile(".*error in configuration, .* should only be used in Composer 3.*") + network := fmt.Sprintf("%s-%d", testComposerNetworkPrefix, acctest.RandInt(t)) + subnetwork := network + "-1" + networkAttachment := fmt.Sprintf("%s-%d", testComposerNetworkAttachmentPrefix, acctest.RandInt(t)) + fullFormNetworkAttachmentName := fmt.Sprintf("projects/%s/regions/%s/networkAttachments/%s", envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), networkAttachment) acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComposerEnvironmentComposer2_usesUnsupportedField(envName), - ExpectError: errorRegExp, + Config: testAccComposerEnvironmentComposer3_withNetworkAndSubnetwork(envName, networkAttachment, network, subnetwork), + }, + { + Config: testAccComposerEnvironmentComposer3_withNetworkAttachment(envName, networkAttachment, network, subnetwork), + }, + { + ResourceName: "google_composer_environment.test", + ImportState: true, + ImportStateVerify: true, + }, + // This is a terrible clean-up step in order to get destroy to succeed, + // due to dangling firewall rules left by the Composer Environment blocking network deletion. + // TODO: Remove this check if firewall rules bug gets fixed by Composer. + { + PlanOnly: true, + Config: testAccComposerEnvironmentComposer3_withNetworkAttachment(envName, fullFormNetworkAttachmentName, network, subnetwork), + Check: testAccCheckClearComposerEnvironmentFirewalls(t, network), + ExpectNonEmptyPlan: true, }, }, }) } -func TestAccComposerEnvironmentComposer3_usesUnsupportedField_expectError(t *testing.T) { +func TestAccComposerEnvironmentComposer3_updateWithNetworkAndSubnetwork(t *testing.T) { t.Parallel() envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) - errorRegExp, _ := regexp.Compile(".*error in configuration, .* should not be used in Composer 3.*") + network := fmt.Sprintf("%s-%d", testComposerNetworkPrefix, acctest.RandInt(t)) + subnetwork := network + "-1" + networkAttachment := fmt.Sprintf("%s-%d", testComposerNetworkAttachmentPrefix, acctest.RandInt(t)) + fullFormNetworkAttachmentName := fmt.Sprintf("projects/%s/regions/%s/networkAttachments/%s", envvar.GetTestProjectFromEnv(), envvar.GetTestRegionFromEnv(), networkAttachment) acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccComposerEnvironmentComposer3_usesUnsupportedField(envName), - ExpectError: errorRegExp, + Config: testAccComposerEnvironmentComposer3_withNetworkAttachment(envName, networkAttachment, network, subnetwork), + }, + { + Config: testAccComposerEnvironmentComposer3_withNetworkAndSubnetwork(envName, networkAttachment, network, subnetwork), + }, + { + ResourceName: "google_composer_environment.test", + ImportState: true, + ImportStateVerify: true, + }, + // This is a terrible clean-up step in order to get destroy to succeed, + // due to dangling firewall rules left by the Composer Environment blocking network deletion. + // TODO: Remove this check if firewall rules bug gets fixed by Composer. + { + PlanOnly: true, + Config: testAccComposerEnvironmentComposer3_withNetworkAttachment(envName, fullFormNetworkAttachmentName, network, subnetwork), + Check: testAccCheckClearComposerEnvironmentFirewalls(t, network), + ExpectNonEmptyPlan: true, }, }, }) @@ -1266,7 +1337,7 @@ func TestAccComposerEnvironmentComposer3_updateToEmpty(t *testing.T) { subnetwork := network + "-1" acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), Steps: []resource.TestStep{ @@ -1303,7 +1374,7 @@ func TestAccComposerEnvironmentComposer3_updateFromEmpty(t *testing.T) { subnetwork := network + "-1" acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, + PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), Steps: []resource.TestStep{ @@ -1330,6 +1401,77 @@ func TestAccComposerEnvironmentComposer3_updateFromEmpty(t *testing.T) { }, }) } + +func TestAccComposerEnvironmentComposer3_upgrade_expectError(t *testing.T) { + t.Parallel() + + envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) + network := fmt.Sprintf("%s-%d", testComposerNetworkPrefix, acctest.RandInt(t)) + subnetwork := network + "-1" + errorRegExp, _ := regexp.Compile(".*upgrade to composer 3 is not yet supported.*") + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComposerEnvironmentComposer2_empty(envName, network, subnetwork), + }, + { + Config: testAccComposerEnvironmentComposer3_empty(envName, network, subnetwork), + ExpectError: errorRegExp, + }, + // This is a terrible clean-up step in order to get destroy to succeed, + // due to dangling firewall rules left by the Composer Environment blocking network deletion. + // TODO: Remove this check if firewall rules bug gets fixed by Composer. + { + PlanOnly: true, + ExpectNonEmptyPlan: false, + Config: testAccComposerEnvironmentComposer2_empty(envName, network, subnetwork), + Check: testAccCheckClearComposerEnvironmentFirewalls(t, network), + }, + }, + }) +} + +func TestAccComposerEnvironmentComposer2_usesUnsupportedField_expectError(t *testing.T) { + t.Parallel() + + envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) + errorRegExp, _ := regexp.Compile(".*error in configuration, .* should only be used in Composer 3.*") + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComposerEnvironmentComposer2_usesUnsupportedField(envName), + ExpectError: errorRegExp, + }, + }, + }) +} + +func TestAccComposerEnvironmentComposer3_usesUnsupportedField_expectError(t *testing.T) { + t.Parallel() + + envName := fmt.Sprintf("%s-%d", testComposerEnvironmentPrefix, acctest.RandInt(t)) + errorRegExp, _ := regexp.Compile(".*error in configuration, .* should not be used in Composer 3.*") + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccComposerEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComposerEnvironmentComposer3_usesUnsupportedField(envName), + ExpectError: errorRegExp, + }, + }, + }) +} <% end -%> func testAccComposerEnvironment_customBucket(bucketName, envName, network, subnetwork string) string { @@ -2943,6 +3085,10 @@ resource "google_composer_environment" "test" { software_config { image_version = "composer-3-airflow-2" } + node_config { + network = google_compute_network.test.id + subnetwork = google_compute_subnetwork.test.id + } } } @@ -3000,11 +3146,13 @@ resource "google_composer_environment" "test" { name = "%s" region = "us-central1" config { - software_config { - image_version = "composer-3-airflow-2" - } node_config { composer_internal_ipv4_cidr_block = "100.64.128.0/20" + network = google_compute_network.test.id + subnetwork = google_compute_subnetwork.test.id + } + software_config { + image_version = "composer-3-airflow-2" } workloads_config { dag_processor { @@ -3041,6 +3189,8 @@ resource "google_composer_environment" "test" { region = "us-central1" config { node_config { + network = google_compute_network.test_1.id + subnetwork = google_compute_subnetwork.test_1.id composer_internal_ipv4_cidr_block = "100.64.128.0/20" } software_config { @@ -3072,7 +3222,168 @@ resource "google_compute_subnetwork" "test" { region = "us-central1" network = google_compute_network.test.self_link } -`, name, network, subnetwork) + +resource "google_compute_network" "test_1" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "test_1" { + name = "%s" + ip_cidr_range = "10.3.0.0/16" + region = "us-central1" + network = google_compute_network.test_1.self_link +} +`, name, network, subnetwork, network + "-update", subnetwork + "update") +} + +func testAccComposerEnvironmentComposer3_withNetworkAttachment(name, networkAttachment, network, subnetwork string) string { + return fmt.Sprintf(` +resource "google_composer_environment" "test" { + name = "%s" + region = "us-central1" + config { + node_config { + composer_network_attachment = google_compute_network_attachment.test.id + } + software_config { + image_version = "composer-3-airflow-2" + } + } +} + +resource "google_compute_network_attachment" "test" { + name = "%s" + region = "us-central1" + subnetworks = [ google_compute_subnetwork.test-att.id ] + connection_preference = "ACCEPT_MANUAL" + // Composer 3 is modifying producer_accept_lists outside terraform, ignoring this change for now + lifecycle { + ignore_changes = [producer_accept_lists] + } +} + +resource "google_compute_network" "test-att" { + name = "%s-att" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "test-att" { + name = "%s-att" + ip_cidr_range = "10.3.0.0/16" + region = "us-central1" + network = google_compute_network.test-att.self_link +} + +// use a separate network to avoid conflicts with other tests running in parallel +// that use the default network/subnet +resource "google_compute_network" "test" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "test" { + name = "%s" + ip_cidr_range = "10.2.0.0/16" + region = "us-central1" + network = google_compute_network.test.self_link +} +`, name, networkAttachment, network, subnetwork, network, subnetwork) +} + +func testAccComposerEnvironmentComposer3_withNetworkAndSubnetwork(name, networkAttachment, network, subnetwork string) string { + return fmt.Sprintf(` +resource "google_composer_environment" "test" { + name = "%s" + region = "us-central1" + config { + node_config { + network = google_compute_network.test.id + subnetwork = google_compute_subnetwork.test.id + } + software_config { + image_version = "composer-3-airflow-2" + } + } +} + +resource "google_compute_network_attachment" "test" { + name = "%s" + region = "us-central1" + subnetworks = [ google_compute_subnetwork.test-att.id ] + connection_preference = "ACCEPT_MANUAL" + // Composer 3 is modifying producer_accept_lists outside terraform, ignoring this change for now + lifecycle { + ignore_changes = [producer_accept_lists] + } +} + +resource "google_compute_network" "test-att" { + name = "%s-att" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "test-att" { + name = "%s-att" + ip_cidr_range = "10.3.0.0/16" + region = "us-central1" + network = google_compute_network.test-att.self_link +} + +// use a separate network to avoid conflicts with other tests running in parallel +// that use the default network/subnet +resource "google_compute_network" "test" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "test" { + name = "%s" + ip_cidr_range = "10.2.0.0/16" + region = "us-central1" + network = google_compute_network.test.self_link +} +`, name, networkAttachment, network, subnetwork, network, subnetwork) +} + +func testAccComposerEnvironmentComposer3_withNetworkSubnetworkAndAttachment_expectError(name, networkAttachment, network, subnetwork string) string { + return fmt.Sprintf(` +resource "google_composer_environment" "test" { + name = "%s" + region = "us-central1" + config { + node_config { + network = google_compute_network.test.id + subnetwork = google_compute_subnetwork.test.id + composer_network_attachment = google_compute_network_attachment.test.id + } + software_config { + image_version = "composer-3-airflow-2" + } + } +} + +resource "google_compute_network_attachment" "test" { + name = "%s" + region = "us-central1" + subnetworks = [ google_compute_subnetwork.test.id ] + connection_preference = "ACCEPT_MANUAL" +} + +// use a separate network to avoid conflicts with other tests running in parallel +// that use the default network/subnet +resource "google_compute_network" "test" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "test" { + name = "%s" + ip_cidr_range = "10.2.0.0/16" + region = "us-central1" + network = google_compute_network.test.self_link +} +`, name, networkAttachment, network, subnetwork) } <% end -%> From 9f8d2aa14d34b8b09e65cb2e91179895fb2f30a5 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 27 Feb 2024 10:03:51 +0000 Subject: [PATCH 036/200] Fix resource name to have sweepable prefix (#9984) --- .../resource_compute_region_target_tcp_proxy_test.go.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_target_tcp_proxy_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_target_tcp_proxy_test.go.erb index 6b7cfd194215..535218117c07 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_target_tcp_proxy_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_target_tcp_proxy_test.go.erb @@ -13,9 +13,9 @@ import ( func TestAccComputeRegionTargetTcpProxy_update(t *testing.T) { t.Parallel() - target := fmt.Sprintf("trtcp-test-%s", acctest.RandString(t, 10)) - backend := fmt.Sprintf("trtcp-test-%s", acctest.RandString(t, 10)) - hc := fmt.Sprintf("trtcp-test-%s", acctest.RandString(t, 10)) + target := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + backend := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + hc := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, From b1f7bf9b0987f3040fd4820f34587b7101fa77c7 Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Tue, 27 Feb 2024 20:16:04 +0530 Subject: [PATCH 037/200] doc(spanner): update documents to have example for IAM conditions use with google spanner database (#10049) --- .../docs/r/spanner_database_iam.html.markdown | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/mmv1/third_party/terraform/website/docs/r/spanner_database_iam.html.markdown b/mmv1/third_party/terraform/website/docs/r/spanner_database_iam.html.markdown index 1de101713eb3..ef09772c1fd0 100644 --- a/mmv1/third_party/terraform/website/docs/r/spanner_database_iam.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/spanner_database_iam.html.markdown @@ -39,6 +39,32 @@ resource "google_spanner_database_iam_policy" "database" { } ``` +With IAM Conditions: + +```hcl +data "google_iam_policy" "admin" { + binding { + role = "roles/editor" + + members = [ + "user:jane@example.com", + ] + + condition { + title = "My Role" + description = "Grant permissions on my_role" + expression = "(resource.type == \"spanner.googleapis.com/DatabaseRole\" && (resource.name.endsWith(\"/myrole\")))" + } + } +} + +resource "google_spanner_database_iam_policy" "database" { + instance = "your-instance-name" + database = "your-database-name" + policy_data = data.google_iam_policy.admin.policy_data +} +``` + ## google\_spanner\_database\_iam\_binding ```hcl @@ -53,6 +79,26 @@ resource "google_spanner_database_iam_binding" "database" { } ``` +With IAM Conditions: + +```hcl +resource "google_spanner_database_iam_binding" "database" { + instance = "your-instance-name" + database = "your-database-name" + role = "roles/compute.networkUser" + + members = [ + "user:jane@example.com", + ] + + condition { + title = "My Role" + description = "Grant permissions on my_role" + expression = "(resource.type == \"spanner.googleapis.com/DatabaseRole\" && (resource.name.endsWith(\"/myrole\")))" + } +} +``` + ## google\_spanner\_database\_iam\_member ```hcl @@ -64,6 +110,23 @@ resource "google_spanner_database_iam_member" "database" { } ``` +With IAM Conditions: + +```hcl +resource "google_spanner_database_iam_member" "database" { + instance = "your-instance-name" + database = "your-database-name" + role = "roles/compute.networkUser" + member = "user:jane@example.com" + + condition { + title = "My Role" + description = "Grant permissions on my_role" + expression = "(resource.type == \"spanner.googleapis.com/DatabaseRole\" && (resource.name.endsWith(\"/myrole\")))" + } +} +``` + ## Argument Reference The following arguments are supported: @@ -91,6 +154,23 @@ The following arguments are supported: * `project` - (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. +* `condition` - (Optional) An [IAM Condition](https://cloud.google.com/iam/docs/conditions-overview) for a given binding. + Structure is [documented below](#nested_condition). + +--- + +The `condition` block supports: + +* `expression` - (Required) Textual representation of an expression in Common Expression Language syntax. + +* `title` - (Required) A title for the expression, i.e. a short string describing its purpose. + +* `description` - (Optional) An optional description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + +~> **Warning:** Terraform considers the `role` and condition contents (`title`+`description`+`expression`) as the +identifier for the binding. This means that if any part of the condition is changed out-of-band, Terraform will +consider it to be an entirely different resource and will treat it as such. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are From aee8d1d332c09af8dda321a9a466cd8ae7232602 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 27 Feb 2024 14:51:19 +0000 Subject: [PATCH 038/200] Promote Cloud Deploy Automation to GA (#10043) * Add Cloud Deploy Automation * Attempt to solve the test errors based on https://yaqs.corp.google.com/eng/q/7753655943518224384 * Add update test for the new automation resource * fix lint errors * fix lint errors * fix errors in GA provider test * add the missing test * add a full test * Attempt to fix the acceptance test errors * fix a lint error * mark labels as default_from_api:true * fix advance rollout rule definition * Mark service_account as 'ignore_read: true' * Fix test errors * Resolve review comments * Format test file * promote google_clouddeploy_automation to GA * promote google_clouddeploy_automation to GA * fix lint errors --- mmv1/products/clouddeploy/Automation.yaml | 5 +- .../clouddeploy_automation_basic.tf.erb | 2 - .../clouddeploy_automation_full.tf.erb | 2 - ...> resource_clouddeploy_automation_test.go} | 81 +++++++++---------- 4 files changed, 38 insertions(+), 52 deletions(-) rename mmv1/third_party/terraform/services/clouddeploy/{resource_clouddeploy_automation_test.go.erb => resource_clouddeploy_automation_test.go} (57%) diff --git a/mmv1/products/clouddeploy/Automation.yaml b/mmv1/products/clouddeploy/Automation.yaml index 6af88d3d88f4..bb46c92440bb 100644 --- a/mmv1/products/clouddeploy/Automation.yaml +++ b/mmv1/products/clouddeploy/Automation.yaml @@ -21,7 +21,7 @@ references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/deploy/docs/api/reference/rest/v1/projects.locations.deliveryPipelines.automations' base_url: 'projects/{{project}}/locations/{{location}}/deliveryPipelines/{{delivery_pipeline}}/automations' self_link: 'projects/{{project}}/locations/{{location}}/deliveryPipelines/{{delivery_pipeline}}/automations/{{name}}' -min_version: beta + create_url: 'projects/{{project}}/locations/{{location}}/deliveryPipelines/{{delivery_pipeline}}/automations?automationId={{name}}' update_verb: :PATCH update_mask: true @@ -51,7 +51,6 @@ autogen_async: true examples: - !ruby/object:Provider::Terraform::Examples name: "clouddeploy_automation_basic" - min_version: beta primary_resource_id: "b-automation" vars: automation: "cd-automation" @@ -60,7 +59,7 @@ examples: service_account: :SERVICE_ACCT - !ruby/object:Provider::Terraform::Examples name: "clouddeploy_automation_full" - min_version: beta + primary_resource_id: "f-automation" vars: automation: "cd-automation" diff --git a/mmv1/templates/terraform/examples/clouddeploy_automation_basic.tf.erb b/mmv1/templates/terraform/examples/clouddeploy_automation_basic.tf.erb index fa7ad4fb230e..41b460f1aefb 100644 --- a/mmv1/templates/terraform/examples/clouddeploy_automation_basic.tf.erb +++ b/mmv1/templates/terraform/examples/clouddeploy_automation_basic.tf.erb @@ -1,5 +1,4 @@ resource "google_clouddeploy_automation" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta name = "<%= ctx[:vars]['automation'] %>" project = google_clouddeploy_delivery_pipeline.pipeline.project location = google_clouddeploy_delivery_pipeline.pipeline.location @@ -19,7 +18,6 @@ resource "google_clouddeploy_automation" "<%= ctx[:primary_resource_id] %>" { } resource "google_clouddeploy_delivery_pipeline" "pipeline" { - provider = google-beta name = "<%= ctx[:vars]['delivery_pipeline'] %>" location = "us-central1" serial_pipeline { diff --git a/mmv1/templates/terraform/examples/clouddeploy_automation_full.tf.erb b/mmv1/templates/terraform/examples/clouddeploy_automation_full.tf.erb index 8cd21d0e10d3..51bf98d1bca1 100644 --- a/mmv1/templates/terraform/examples/clouddeploy_automation_full.tf.erb +++ b/mmv1/templates/terraform/examples/clouddeploy_automation_full.tf.erb @@ -1,5 +1,4 @@ resource "google_clouddeploy_automation" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta name = "<%= ctx[:vars]['automation'] %>" location = "us-central1" delivery_pipeline = google_clouddeploy_delivery_pipeline.pipeline.name @@ -40,7 +39,6 @@ resource "google_clouddeploy_automation" "<%= ctx[:primary_resource_id] %>" { } resource "google_clouddeploy_delivery_pipeline" "pipeline" { - provider = google-beta name = "<%= ctx[:vars]['delivery_pipeline'] %>" location = "us-central1" serial_pipeline { diff --git a/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_automation_test.go.erb b/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_automation_test.go similarity index 57% rename from mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_automation_test.go.erb rename to mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_automation_test.go index 601f55640516..82f1fe3a0e5c 100644 --- a/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_automation_test.go.erb +++ b/mmv1/third_party/terraform/services/clouddeploy/resource_clouddeploy_automation_test.go @@ -1,56 +1,52 @@ -<% autogen_exception -%> package clouddeploy_test - -<% unless version == 'ga' -%> import ( - "testing" + "testing" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "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-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" ) func TestAccClouddeployAutomation_update(t *testing.T) { - t.Parallel() + t.Parallel() - context := map[string]interface{}{ - "service_account": envvar.GetTestServiceAccountFromEnv(t), - "random_suffix": acctest.RandString(t, 10), - } + context := map[string]interface{}{ + "service_account": envvar.GetTestServiceAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), - CheckDestroy: testAccCheckClouddeployAutomationDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccClouddeployAutomation_basic(context), - }, - { - ResourceName: "google_clouddeploy_automation.automation", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "delivery_pipeline", "annotations", "labels", "terraform_labels"}, - }, - { - Config: testAccClouddeployAutomation_update(context), - }, - { - ResourceName: "google_clouddeploy_automation.automation", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"location", "delivery_pipeline", "annotations", "labels", "terraform_labels"}, - }, - }, - }) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckClouddeployAutomationDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccClouddeployAutomation_basic(context), + }, + { + ResourceName: "google_clouddeploy_automation.automation", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "delivery_pipeline", "annotations", "labels", "terraform_labels"}, + }, + { + Config: testAccClouddeployAutomation_update(context), + }, + { + ResourceName: "google_clouddeploy_automation.automation", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "delivery_pipeline", "annotations", "labels", "terraform_labels"}, + }, + }, + }) } func testAccClouddeployAutomation_basic(context map[string]interface{}) string { - return acctest.Nprintf(` + return acctest.Nprintf(` resource "google_clouddeploy_automation" "automation" { - provider = google-beta name = "tf-test-cd-automation%{random_suffix}" location = "us-central1" delivery_pipeline = google_clouddeploy_delivery_pipeline.pipeline.name @@ -71,7 +67,6 @@ resource "google_clouddeploy_automation" "automation" { } resource "google_clouddeploy_delivery_pipeline" "pipeline" { - provider = google-beta name = "tf-test-cd-pipeline%{random_suffix}" location = "us-central1" serial_pipeline { @@ -85,10 +80,9 @@ resource "google_clouddeploy_delivery_pipeline" "pipeline" { } func testAccClouddeployAutomation_update(context map[string]interface{}) string { - return acctest.Nprintf(` + return acctest.Nprintf(` resource "google_clouddeploy_automation" "automation" { - provider = google-beta name = "tf-test-cd-automation%{random_suffix}" location = "us-central1" delivery_pipeline = google_clouddeploy_delivery_pipeline.pipeline.name @@ -129,7 +123,6 @@ resource "google_clouddeploy_automation" "automation" { } resource "google_clouddeploy_delivery_pipeline" "pipeline" { - provider = google-beta name = "tf-test-cd-pipeline%{random_suffix}" location = "us-central1" serial_pipeline { @@ -141,5 +134,3 @@ resource "google_clouddeploy_delivery_pipeline" "pipeline" { } `, context) } -<% end -%> - From 0a3c61d90cd8ed2f6c66e5ab52afc0805330ef2e Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Tue, 27 Feb 2024 11:59:17 -0500 Subject: [PATCH 039/200] Add cloudquota service (#10063) --- .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 33422f4e6948..a6f8c58a5f69 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -196,6 +196,7 @@ module "project-services" { "cloudidentity.googleapis.com", "cloudiot.googleapis.com", "cloudkms.googleapis.com", + "cloudquotas.googleapis.com", "cloudresourcemanager.googleapis.com", "cloudscheduler.googleapis.com", "cloudtasks.googleapis.com", From d4a4dc20c5b871e685e6043cb66011102b8ff27c Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Tue, 27 Feb 2024 09:26:34 -0800 Subject: [PATCH 040/200] TeamCity: Add validating GHAs that check Kotlin files listing services (#9999) * services diff gha * add needs * use setup-go@v3 * add artifacts * remove checkout * update directory * update common-copy.yaml * update common-copy.yaml * remove data print * add pull-request check on teamcitydiff * update paths in GHA * add exit code in diff_check * update exit output * add exit code diff_check.go * services_beta diff check support * beta services support args * add arg for services kt file * services_ga.kt in gha * move diff_check to tools folder * remove go command * provide path for artifacts download * add cd in Build Provider * update diff_check_beta.yml * fix paths * yml typo beta * directory testing * directory testing * fix directory issues with commands * refactor tools/teamcity-diff-check/main.go * directory check * typo * remove common copy * generate both providers into one gha * type artifacts name * add -o flag into artifacts download * use merge multiple artifacts * use artifact@v4 * use mmv1 directory for services file * remove .zip * output missing services from diff * find artifacts folder * use beta provider as only artifact * include google ga and beta in gha * artifact name * -o flag in artifacts * output stdout from go list command * diff test * output beta main.go * remove err check * remove services print / refactor for final review * output cleanup * uncomment go list err * regex assert * add check for new services in PR / set googleServices as groundtruth in serviceDifference function * add actions/checkout * logic fix * add needs: check-pr * add mmv1/products for pull-request event * set force depth 0 * Update .github/workflows/teamcity-services-diff-check.yml Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> * Update .github/workflows/teamcity-services-diff-check.yml Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> * use text file for services, add if statement in gha * directory typo * typo * typo in grep * quotations on if statement * unquote GITHUB_OUTPUT * add quotes on output.services * if test * echo output * github_output error fix * services.outputs * proper if statement syntax gpush * invalid 0 format * add missing assignment * fix openfile error * remove types in pull_request trigger * send txt files to correct directory * check services directory for ls command * add weekly workflow for teamcity diff check * change name for weekly check --------- Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --- .../teamcity-services-diff-check-weekly.yml | 71 ++++++++++++++ .../teamcity-services-diff-check.yml | 94 +++++++++++++++++++ tools/teamcity-diff-check/main.go | 92 ++++++++++++++++++ 3 files changed, 257 insertions(+) create mode 100644 .github/workflows/teamcity-services-diff-check-weekly.yml create mode 100644 .github/workflows/teamcity-services-diff-check.yml create mode 100644 tools/teamcity-diff-check/main.go diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml new file mode 100644 index 000000000000..49289dc24ea0 --- /dev/null +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -0,0 +1,71 @@ +name: TeamCity Services Weekly Diff Check +permissions: read-all + +on: + schedule: + # Runs every tuesday morning + - cron: '0 4 * * 2' + +jobs: + terraform-provider-google: + uses: ./.github/workflows/build-downstream.yml + with: + repo: 'terraform-provider-google' + + terraform-provider-google-beta: + uses: ./.github/workflows/build-downstream.yml + with: + repo: 'terraform-provider-google-beta' + + teamcity-services-diff-check: + needs: [terraform-provider-google, terraform-provider-google-beta] + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + + - name: Download built artifacts - GA provider + uses: actions/download-artifact@v2 + with: + name: artifact-terraform-provider-google + path: artifacts + + - name: Unzip the artifacts and delete the zip + run: | + unzip -o artifacts/output.zip -d ./provider + rm artifacts/output.zip + + - name: Download built artifacts - Beta provider + uses: actions/download-artifact@v2 + with: + name: artifact-terraform-provider-google-beta + path: artifacts + + - name: Unzip the artifacts and delete the zip + run: | + unzip -o artifacts/output.zip -d ./provider + rm artifacts/output.zip + + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: '^1.20' + + - name: Cache Go modules and build cache + uses: actions/cache@v3 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: ${{ runner.os }}-test-terraform-provider-google-${{hashFiles('go.sum','google-*/transport/**','google-*/tpgresource/**','google-*/acctest/**','google-*/envvar/**','google-*/sweeper/**','google-*/verify/**') }} + restore-keys: | + ${{ runner.os }}-test-terraform-provider-google-${{ hashFiles('go.sum') }} + ${{ runner.os }}-test-terraform-provider-google- + + - name: Diff Check + run: | + ls provider/google/services > tools/teamcity-diff-check/services_ga.txt + ls provider/google-beta/services > tools/teamcity-diff-check/services_beta.txt + cd tools/teamcity-diff-check + go run main.go -service_file=services_ga + go run main.go -service_file=services_beta + \ No newline at end of file diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml new file mode 100644 index 000000000000..535ff9fb6293 --- /dev/null +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -0,0 +1,94 @@ +name: TeamCity Services Diff Check +permissions: read-all + +on: + workflow_dispatch: + pull_request: + paths: + - '.github/workflows/teamcity-services-diff-check.yml' + - 'mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt' + - 'mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt' + - 'mmv1/products/**' +jobs: + check-pr: + runs-on: ubuntu-22.04 + outputs: + services: ${{steps.services.outputs.services}} + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - id: services + name: "Check for New Services" + run: | + newServices=$(($(git diff --name-only --diff-filter=A origin/main HEAD | grep -P "mmv1/products/.*/product.yaml" | wc -l))) + echo "services=$newServices" >> "${GITHUB_OUTPUT}" + if [ "$newServices" = "0" ];then + echo "No new service found." + fi + terraform-provider-google: + if: ${{needs.check-pr.outputs.services != '0'}} + needs: check-pr + uses: ./.github/workflows/build-downstream.yml + with: + repo: 'terraform-provider-google' + + terraform-provider-google-beta: + if: ${{needs.check-pr.outputs.services != '0'}} + needs: check-pr + uses: ./.github/workflows/build-downstream.yml + with: + repo: 'terraform-provider-google-beta' + + teamcity-services-diff-check: + needs: [terraform-provider-google, terraform-provider-google-beta] + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v3 + + - name: Download built artifacts - GA provider + uses: actions/download-artifact@v2 + with: + name: artifact-terraform-provider-google + path: artifacts + + - name: Unzip the artifacts and delete the zip + run: | + unzip -o artifacts/output.zip -d ./provider + rm artifacts/output.zip + + - name: Download built artifacts - Beta provider + uses: actions/download-artifact@v2 + with: + name: artifact-terraform-provider-google-beta + path: artifacts + + - name: Unzip the artifacts and delete the zip + run: | + unzip -o artifacts/output.zip -d ./provider + rm artifacts/output.zip + + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: '^1.20' + + - name: Cache Go modules and build cache + uses: actions/cache@v3 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: ${{ runner.os }}-test-terraform-provider-google-${{hashFiles('go.sum','google-*/transport/**','google-*/tpgresource/**','google-*/acctest/**','google-*/envvar/**','google-*/sweeper/**','google-*/verify/**') }} + restore-keys: | + ${{ runner.os }}-test-terraform-provider-google-${{ hashFiles('go.sum') }} + ${{ runner.os }}-test-terraform-provider-google- + + - name: Diff Check + run: | + ls provider/google/services > tools/teamcity-diff-check/services_ga.txt + ls provider/google-beta/services > tools/teamcity-diff-check/services_beta.txt + cd tools/teamcity-diff-check + go run main.go -service_file=services_ga + go run main.go -service_file=services_beta + \ No newline at end of file diff --git a/tools/teamcity-diff-check/main.go b/tools/teamcity-diff-check/main.go new file mode 100644 index 000000000000..b3a71436e8fa --- /dev/null +++ b/tools/teamcity-diff-check/main.go @@ -0,0 +1,92 @@ +package main + +import ( + "bufio" + "flag" + "fmt" + "io" + "os" + "regexp" +) + +var serviceFile = flag.String("service_file", "services_ga", "kotlin service file to be parsed") + +func serviceDifference(gS, tS []string) []string { + t := make(map[string]struct{}, len(tS)) + for _, s := range tS { + t[s] = struct{}{} + } + + var diff []string + for _, s := range gS { + if _, found := t[s]; !found { + diff = append(diff, s) + } + } + + return diff +} + +func main() { + flag.Parse() + + file, err := os.Open(*serviceFile + ".txt") + if err != nil { + fmt.Println(err) + return + } + defer file.Close() + + googleServices := []string{} + scanner := bufio.NewScanner(file) + for scanner.Scan() { + googleServices = append(googleServices, scanner.Text()) + } + + //////////////////////////////////////////////////////////////////////////////// + + f, err := os.Open(fmt.Sprintf("../../mmv1/third_party/terraform/.teamcity/components/inputs/%s", *serviceFile+".kt")) + if err != nil { + panic(err) + } + + // Get the file size + stat, err := f.Stat() + if err != nil { + fmt.Println(err) + return + } + + // Read the file into a byte slice + bs := make([]byte, stat.Size()) + _, err = bufio.NewReader(f).Read(bs) + if err != nil && err != io.EOF { + fmt.Println(err) + return + } + + // Regex pattern captures "services" from *serviceFile. + pattern := regexp.MustCompile(`(?m)"(?P\w+)"\sto\s+mapOf`) + + template := []byte("$service") + + dst := []byte{} + teamcityServices := []string{} + + // For each match of the regex in the content. + for _, submatches := range pattern.FindAllSubmatchIndex(bs, -1) { + service := pattern.Expand(dst, template, bs, submatches) + teamcityServices = append(teamcityServices, string(service)) + } + if len(teamcityServices) == 0 { + fmt.Fprintf(os.Stderr, "teamcityServices error: regex produced no matches.\n") + os.Exit(1) + } + + if diff := serviceDifference(googleServices, teamcityServices); len(diff) != 0 { + fmt.Fprintf(os.Stderr, "error: diff in %s\n", *serviceFile) + fmt.Fprintf(os.Stderr, "Missing Services: %s\n", diff) + os.Exit(1) + } + +} From ff1142ab03e0d6b5d35a6a8f95b82820d6e8a179 Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Tue, 27 Feb 2024 12:12:48 -0800 Subject: [PATCH 041/200] Fixed `runtime` in app engine tests (#10047) --- .../app_engine_application_url_dispatch_rules_basic.tf.erb | 2 +- .../examples/app_engine_service_network_settings.tf.erb | 2 +- .../examples/app_engine_service_split_traffic.tf.erb | 4 ++-- .../terraform/examples/app_engine_standard_app_version.tf.erb | 4 ++-- .../terraform/examples/iap_app_engine_service.tf.erb | 2 +- .../terraform/examples/iap_app_engine_version.tf.erb | 2 +- .../resource_app_engine_service_network_settings_test.go | 4 ++-- .../docs/d/monitoring_app_engine_service.html.markdown | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/mmv1/templates/terraform/examples/app_engine_application_url_dispatch_rules_basic.tf.erb b/mmv1/templates/terraform/examples/app_engine_application_url_dispatch_rules_basic.tf.erb index dad8252eecaa..2bda703ff567 100644 --- a/mmv1/templates/terraform/examples/app_engine_application_url_dispatch_rules_basic.tf.erb +++ b/mmv1/templates/terraform/examples/app_engine_application_url_dispatch_rules_basic.tf.erb @@ -15,7 +15,7 @@ resource "google_app_engine_application_url_dispatch_rules" "<%= ctx[:primary_re resource "google_app_engine_standard_app_version" "admin_v3" { version_id = "v3" service = "admin" - runtime = "nodejs10" + runtime = "nodejs20" entrypoint { shell = "node ./app.js" diff --git a/mmv1/templates/terraform/examples/app_engine_service_network_settings.tf.erb b/mmv1/templates/terraform/examples/app_engine_service_network_settings.tf.erb index 53f48b2c235c..3bef5a62a6ef 100644 --- a/mmv1/templates/terraform/examples/app_engine_service_network_settings.tf.erb +++ b/mmv1/templates/terraform/examples/app_engine_service_network_settings.tf.erb @@ -14,7 +14,7 @@ resource "google_app_engine_standard_app_version" "internalapp" { service = "internalapp" delete_service_on_destroy = true - runtime = "nodejs10" + runtime = "nodejs20" entrypoint { shell = "node ./app.js" } diff --git a/mmv1/templates/terraform/examples/app_engine_service_split_traffic.tf.erb b/mmv1/templates/terraform/examples/app_engine_service_split_traffic.tf.erb index 8c85ce8bd13f..8e2ff3ecbece 100644 --- a/mmv1/templates/terraform/examples/app_engine_service_split_traffic.tf.erb +++ b/mmv1/templates/terraform/examples/app_engine_service_split_traffic.tf.erb @@ -14,7 +14,7 @@ resource "google_app_engine_standard_app_version" "liveapp_v1" { service = "liveapp" delete_service_on_destroy = true - runtime = "nodejs10" + runtime = "nodejs20" entrypoint { shell = "node ./app.js" } @@ -33,7 +33,7 @@ resource "google_app_engine_standard_app_version" "liveapp_v2" { service = "liveapp" noop_on_destroy = true - runtime = "nodejs10" + runtime = "nodejs20" entrypoint { shell = "node ./app.js" } diff --git a/mmv1/templates/terraform/examples/app_engine_standard_app_version.tf.erb b/mmv1/templates/terraform/examples/app_engine_standard_app_version.tf.erb index 64234c1dba0f..75696c694955 100644 --- a/mmv1/templates/terraform/examples/app_engine_standard_app_version.tf.erb +++ b/mmv1/templates/terraform/examples/app_engine_standard_app_version.tf.erb @@ -18,7 +18,7 @@ resource "google_project_iam_member" "storage_viewer" { resource "google_app_engine_standard_app_version" "<%= ctx[:primary_resource_id] %>" { version_id = "v1" service = "myapp" - runtime = "nodejs10" + runtime = "nodejs20" entrypoint { shell = "node ./app.js" @@ -55,7 +55,7 @@ resource "google_app_engine_standard_app_version" "<%= ctx[:primary_resource_id] resource "google_app_engine_standard_app_version" "myapp_v2" { version_id = "v2" service = "myapp" - runtime = "nodejs10" + runtime = "nodejs20" app_engine_apis = true entrypoint { diff --git a/mmv1/templates/terraform/examples/iap_app_engine_service.tf.erb b/mmv1/templates/terraform/examples/iap_app_engine_service.tf.erb index 37f79449f02b..dff90f5307e6 100644 --- a/mmv1/templates/terraform/examples/iap_app_engine_service.tf.erb +++ b/mmv1/templates/terraform/examples/iap_app_engine_service.tf.erb @@ -36,7 +36,7 @@ resource "google_app_engine_standard_app_version" "version" { project = google_app_engine_application.app.project version_id = "v2" service = "default" - runtime = "nodejs10" + runtime = "nodejs20" noop_on_destroy = true // TODO: Removed basic scaling once automatic_scaling refresh behavior is fixed. diff --git a/mmv1/templates/terraform/examples/iap_app_engine_version.tf.erb b/mmv1/templates/terraform/examples/iap_app_engine_version.tf.erb index 92df16cdac3b..6cf3eef2d0d8 100644 --- a/mmv1/templates/terraform/examples/iap_app_engine_version.tf.erb +++ b/mmv1/templates/terraform/examples/iap_app_engine_version.tf.erb @@ -12,7 +12,7 @@ resource "google_storage_bucket_object" "object" { resource "google_app_engine_standard_app_version" "version" { version_id = "%{random_suffix}" service = "default" - runtime = "nodejs10" + runtime = "nodejs20" noop_on_destroy = false entrypoint { diff --git a/mmv1/third_party/terraform/services/appengine/resource_app_engine_service_network_settings_test.go b/mmv1/third_party/terraform/services/appengine/resource_app_engine_service_network_settings_test.go index 6e55010a6df5..35e35974c066 100644 --- a/mmv1/third_party/terraform/services/appengine/resource_app_engine_service_network_settings_test.go +++ b/mmv1/third_party/terraform/services/appengine/resource_app_engine_service_network_settings_test.go @@ -56,7 +56,7 @@ resource "google_app_engine_standard_app_version" "app" { service = "app-%{random_suffix}" delete_service_on_destroy = true - runtime = "nodejs10" + runtime = "nodejs20" entrypoint { shell = "node ./app.js" } @@ -96,7 +96,7 @@ resource "google_app_engine_standard_app_version" "app" { service = "app-%{random_suffix}" delete_service_on_destroy = true - runtime = "nodejs10" + runtime = "nodejs20" entrypoint { shell = "node ./app.js" } diff --git a/mmv1/third_party/terraform/website/docs/d/monitoring_app_engine_service.html.markdown b/mmv1/third_party/terraform/website/docs/d/monitoring_app_engine_service.html.markdown index 03525dcd6102..188d6e46e372 100644 --- a/mmv1/third_party/terraform/website/docs/d/monitoring_app_engine_service.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/monitoring_app_engine_service.html.markdown @@ -34,7 +34,7 @@ data "google_monitoring_app_engine_service" "srv" { resource "google_app_engine_standard_app_version" "myapp" { version_id = "v1" service = "myapp" - runtime = "nodejs10" + runtime = "nodejs20" entrypoint { shell = "node ./app.js" From 47d6f3bb8e09b0a6265cee24852e973bcb326513 Mon Sep 17 00:00:00 2001 From: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Date: Wed, 28 Feb 2024 03:14:54 +0530 Subject: [PATCH 042/200] Fix google_notebooks_instance labels not being able to be updated (#9933) * add labels to runtime update test * Add labels to ImportStateVerifyIgnore * fix indentation --- .../notebooks/resource_notebooks_runtime_test.go.erb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mmv1/third_party/terraform/services/notebooks/resource_notebooks_runtime_test.go.erb b/mmv1/third_party/terraform/services/notebooks/resource_notebooks_runtime_test.go.erb index efa7a1d6055a..74669dc44525 100644 --- a/mmv1/third_party/terraform/services/notebooks/resource_notebooks_runtime_test.go.erb +++ b/mmv1/third_party/terraform/services/notebooks/resource_notebooks_runtime_test.go.erb @@ -25,6 +25,7 @@ func TestAccNotebooksRuntime_update(t *testing.T) { ResourceName: "google_notebooks_runtime.runtime", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNotebooksRuntime_update(context), @@ -33,6 +34,7 @@ func TestAccNotebooksRuntime_update(t *testing.T) { ResourceName: "google_notebooks_runtime.runtime", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { Config: testAccNotebooksRuntime_basic(context), @@ -41,6 +43,7 @@ func TestAccNotebooksRuntime_update(t *testing.T) { ResourceName: "google_notebooks_runtime.runtime", ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, }, }) @@ -101,6 +104,9 @@ resource "google_notebooks_runtime" "runtime" { reserved_ip_range = "192.168.255.0/24" } } + labels = { + k = "val" + } } `, context) } From 06158615392af1782802f6b509bbbb737cbeacf8 Mon Sep 17 00:00:00 2001 From: Matt Santa Date: Wed, 28 Feb 2024 09:51:37 -0500 Subject: [PATCH 043/200] Add IAM resources for Cloud Deploy Custom Target Type (#10051) * Add IAM resources for Cloud Deploy Custom Target Type * Add base url override for Cloud Deploy Custom Target Type IAM policy * Update import format for IAM policy and primary resource name to examples for IAM generated tests --- mmv1/products/clouddeploy/CustomTargetType.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mmv1/products/clouddeploy/CustomTargetType.yaml b/mmv1/products/clouddeploy/CustomTargetType.yaml index d805ae20bbbd..49820c07a124 100644 --- a/mmv1/products/clouddeploy/CustomTargetType.yaml +++ b/mmv1/products/clouddeploy/CustomTargetType.yaml @@ -48,20 +48,28 @@ import_format: [ 'projects/{{project}}/locations/{{location}}/customTargetTypes/{{name}}' ] +iam_policy: !ruby/object:Api::Resource::IamPolicy + parent_resource_attribute: 'name' + method_name_separator: ':' + base_url: 'projects/{{project}}/locations/{{location}}/customTargetTypes/{{name}}' + import_format: ['projects/{{project}}/locations/{{location}}/customTargetTypes/{{name}}', '{{name}}'] examples: - !ruby/object:Provider::Terraform::Examples name: "clouddeploy_custom_target_type_basic" primary_resource_id: "custom-target-type" + primary_resource_name: 'fmt.Sprintf("tf-test-my-custom-target-type%s", context["random_suffix"])' vars: custom_target_type_name: "my-custom-target-type" - !ruby/object:Provider::Terraform::Examples name: "clouddeploy_custom_target_type_git_skaffold_modules" primary_resource_id: "custom-target-type" + primary_resource_name: 'fmt.Sprintf("tf-test-my-custom-target-type%s", context["random_suffix"])' vars: custom_target_type_name: "my-custom-target-type" - !ruby/object:Provider::Terraform::Examples name: "clouddeploy_custom_target_type_gcs_skaffold_modules" primary_resource_id: "custom-target-type" + primary_resource_name: 'fmt.Sprintf("tf-test-my-custom-target-type%s", context["random_suffix"])' vars: custom_target_type_name: "my-custom-target-type" parameters: From 78bdab3f3f67d49ef8ae7acd941f9079fc9abf2b Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 28 Feb 2024 17:07:29 +0000 Subject: [PATCH 044/200] Remove unneeded cache step in TeamCity-related GHAs, lint GHA files (#10075) * Remove unneeded GHA steps - do we need to cache here? * Whitespace * Test change with fake new service * Resolve build error in fake service * Re-order GHA steps and add name * Add name to checkout step * Add comments, remove extra whitespace * Remove fake new service --- .../teamcity-services-diff-check-weekly.yml | 38 +++++++--------- .../teamcity-services-diff-check.yml | 45 ++++++++----------- 2 files changed, 34 insertions(+), 49 deletions(-) diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 49289dc24ea0..577924f7cdaf 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -11,24 +11,30 @@ jobs: uses: ./.github/workflows/build-downstream.yml with: repo: 'terraform-provider-google' - + terraform-provider-google-beta: uses: ./.github/workflows/build-downstream.yml with: repo: 'terraform-provider-google-beta' - + teamcity-services-diff-check: needs: [terraform-provider-google, terraform-provider-google-beta] runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 - + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: '^1.20' + - name: Download built artifacts - GA provider uses: actions/download-artifact@v2 with: name: artifact-terraform-provider-google path: artifacts - + - name: Unzip the artifacts and delete the zip run: | unzip -o artifacts/output.zip -d ./provider @@ -39,33 +45,19 @@ jobs: with: name: artifact-terraform-provider-google-beta path: artifacts - + - name: Unzip the artifacts and delete the zip run: | unzip -o artifacts/output.zip -d ./provider rm artifacts/output.zip - - name: Setup Go - uses: actions/setup-go@v3 - with: - go-version: '^1.20' - - - name: Cache Go modules and build cache - uses: actions/cache@v3 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-test-terraform-provider-google-${{hashFiles('go.sum','google-*/transport/**','google-*/tpgresource/**','google-*/acctest/**','google-*/envvar/**','google-*/sweeper/**','google-*/verify/**') }} - restore-keys: | - ${{ runner.os }}-test-terraform-provider-google-${{ hashFiles('go.sum') }} - ${{ runner.os }}-test-terraform-provider-google- - - name: Diff Check run: | + # Create lists of service packages in providers ls provider/google/services > tools/teamcity-diff-check/services_ga.txt ls provider/google-beta/services > tools/teamcity-diff-check/services_beta.txt + + # Run tool to compare service packages in the providers vs those listed in TeamCity config files cd tools/teamcity-diff-check go run main.go -service_file=services_ga go run main.go -service_file=services_beta - \ No newline at end of file diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml index 535ff9fb6293..8034d6f87b43 100644 --- a/.github/workflows/teamcity-services-diff-check.yml +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -15,11 +15,12 @@ jobs: outputs: services: ${{steps.services.outputs.services}} steps: - - uses: actions/checkout@v3 + - name: Checkout Repository + uses: actions/checkout@v3 with: fetch-depth: 0 - - id: services - name: "Check for New Services" + - name: "Check for New Services" + id: services run: | newServices=$(($(git diff --name-only --diff-filter=A origin/main HEAD | grep -P "mmv1/products/.*/product.yaml" | wc -l))) echo "services=$newServices" >> "${GITHUB_OUTPUT}" @@ -32,26 +33,32 @@ jobs: uses: ./.github/workflows/build-downstream.yml with: repo: 'terraform-provider-google' - + terraform-provider-google-beta: if: ${{needs.check-pr.outputs.services != '0'}} needs: check-pr uses: ./.github/workflows/build-downstream.yml with: repo: 'terraform-provider-google-beta' - + teamcity-services-diff-check: needs: [terraform-provider-google, terraform-provider-google-beta] runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 - + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: '^1.20' + - name: Download built artifacts - GA provider uses: actions/download-artifact@v2 with: name: artifact-terraform-provider-google path: artifacts - + - name: Unzip the artifacts and delete the zip run: | unzip -o artifacts/output.zip -d ./provider @@ -62,33 +69,19 @@ jobs: with: name: artifact-terraform-provider-google-beta path: artifacts - + - name: Unzip the artifacts and delete the zip run: | unzip -o artifacts/output.zip -d ./provider rm artifacts/output.zip - - name: Setup Go - uses: actions/setup-go@v3 - with: - go-version: '^1.20' - - - name: Cache Go modules and build cache - uses: actions/cache@v3 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-test-terraform-provider-google-${{hashFiles('go.sum','google-*/transport/**','google-*/tpgresource/**','google-*/acctest/**','google-*/envvar/**','google-*/sweeper/**','google-*/verify/**') }} - restore-keys: | - ${{ runner.os }}-test-terraform-provider-google-${{ hashFiles('go.sum') }} - ${{ runner.os }}-test-terraform-provider-google- - - name: Diff Check run: | + # Create lists of service packages in providers ls provider/google/services > tools/teamcity-diff-check/services_ga.txt ls provider/google-beta/services > tools/teamcity-diff-check/services_beta.txt + + # Run tool to compare service packages in the providers vs those listed in TeamCity config files cd tools/teamcity-diff-check go run main.go -service_file=services_ga go run main.go -service_file=services_beta - \ No newline at end of file From d3bed7da18dc98ec5db0d42c57d27ed1b2d1cab0 Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Wed, 28 Feb 2024 14:31:13 -0500 Subject: [PATCH 045/200] Add output to identifiers, check for project as well as projectsId (#10081) * Add output to identifiers, check for project as well as projectsId * Correct identifier behavior * Rubocop --- mmv1/openapi_generate/parser.rb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/mmv1/openapi_generate/parser.rb b/mmv1/openapi_generate/parser.rb index 57f013b7ec93..fe5d9a3008a8 100644 --- a/mmv1/openapi_generate/parser.rb +++ b/mmv1/openapi_generate/parser.rb @@ -33,7 +33,9 @@ def run def write_object(name, obj, type, url_param) field = nil case name - when 'projectsId' + when 'projectsId', 'project' + # projectsId and project are omitted in MMv1 as they are inferred from + # the presence of {{project}} in the URL return field when 'locationsId' name = 'location' @@ -126,6 +128,12 @@ def write_object(name, obj, type, url_param) field.instance_variable_set(:@output, obj.read_only) end + # x-google-identifier fields are described by AIP 203 and are represented + # as output only in Terraform. + if obj.instance_variable_get(:@raw_schema)['x-google-identifier'] + field.instance_variable_set(:@output, true) + end + if (obj.respond_to?(:write_only) && obj.write_only) \ || obj.instance_variable_get(:@raw_schema)['x-google-immutable'] field.instance_variable_set(:@immutable, true) @@ -155,8 +163,8 @@ def parse_openapi(spec_path, resource_path, resource_name) parameters = [] path.post.parameters.each do |param| parameter_object = write_object(param.name, param, param.schema.type, true) - # Ignore standard requestId field - next if param.name == 'requestId' + # Ignore standard requestId and validateOnly params + next if param.name == 'requestId' || param.name == 'validateOnly' next if parameter_object.nil? # All parameters are immutable From 7bec87db4c492db6df3582289f4ce3c03bf1cb61 Mon Sep 17 00:00:00 2001 From: Nick Elliot Date: Wed, 28 Feb 2024 12:47:27 -0800 Subject: [PATCH 046/200] remove nickelliot/zli82016 from vacation reviewers (#10080) * Update membership.go * Update membership.go --- .ci/magician/github/membership.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index c1f5081de1ca..908970d1b08f 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -46,10 +46,7 @@ var ( trustedContributors = []string{} // 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{ - "zli82016", - "NickElliot", - } + onVacationReviewers = []string{} ) type UserType int64 From 77cf5ebede6fc998566e491b1bc7447f4f2cf509 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 28 Feb 2024 13:16:09 -0800 Subject: [PATCH 047/200] Update enrolled_teams.yml (#10082) --- tools/issue-labeler/labeler/enrolled_teams.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/issue-labeler/labeler/enrolled_teams.yml b/tools/issue-labeler/labeler/enrolled_teams.yml index de8934d4019e..f2d88536d0c8 100755 --- a/tools/issue-labeler/labeler/enrolled_teams.yml +++ b/tools/issue-labeler/labeler/enrolled_teams.yml @@ -181,6 +181,7 @@ service/compute-l7-load-balancer: - google_compute_target_https_proxy - google_compute_region_target_https_proxy service/compute-managed: + team: gcp-managed-instance-groups-terraform resources: - google_compute_instance_group_manager.* - google_compute_region_instance_group_manager.* From 01aba8f193c130c5a3b64d03c1687d81543c8bac Mon Sep 17 00:00:00 2001 From: wj-chen Date: Wed, 28 Feb 2024 13:20:37 -0800 Subject: [PATCH 048/200] Fix resource_bigquery_dataset ID validation (#10027) * fix resource_bigquery_dataset ID validation * skip the new validation tests for VCR * update dataset IDs to be valid in terraform-google-conversion example files * update more dataset IDs in the CAI files --- .../constants/bigquery_dataset.go.erb | 2 +- .../resource_bigquery_dataset_test.go | 43 +++++++++++++++++++ .../tests/data/example_bigquery_dataset.json | 4 +- .../tests/data/example_bigquery_dataset.tf | 2 +- .../example_bigquery_dataset_iam_binding.json | 4 +- .../example_bigquery_dataset_iam_binding.tf | 2 +- .../example_bigquery_dataset_iam_member.json | 4 +- .../example_bigquery_dataset_iam_member.tf | 2 +- .../example_bigquery_dataset_iam_policy.json | 4 +- .../example_bigquery_dataset_iam_policy.tf | 2 +- 10 files changed, 56 insertions(+), 13 deletions(-) diff --git a/mmv1/templates/terraform/constants/bigquery_dataset.go.erb b/mmv1/templates/terraform/constants/bigquery_dataset.go.erb index 0e89a4a63500..3a5f4b930334 100644 --- a/mmv1/templates/terraform/constants/bigquery_dataset.go.erb +++ b/mmv1/templates/terraform/constants/bigquery_dataset.go.erb @@ -1,4 +1,4 @@ -const datasetIdRegexp = `[0-9A-Za-z_]+` +const datasetIdRegexp = `^[0-9A-Za-z_]+$` func validateDatasetId(v interface{}, k string) (ws []string, errors []error) { value := v.(string) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go index a4bd6a1a5dea..f4c23fd09306 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go @@ -2,6 +2,8 @@ package bigquery_test import ( "fmt" + "regexp" + "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -326,6 +328,47 @@ func TestAccBigQueryDataset_storageBillModel(t *testing.T) { }) } +func TestAccBigQueryDataset_invalidCharacterInID(t *testing.T) { + t.Parallel() + // Not an acceptance test. + acctest.SkipIfVcr(t) + + datasetID := fmt.Sprintf("tf_test_%s-with-hyphens", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDataset(datasetID), + ExpectError: regexp.MustCompile("must contain only letters.+numbers.+or underscores.+"), + }, + }, + }) +} + +func TestAccBigQueryDataset_invalidLongID(t *testing.T) { + t.Parallel() + // Not an acceptance test. + acctest.SkipIfVcr(t) + + datasetSuffix := acctest.RandString(t, 10) + datasetID := fmt.Sprintf("tf_test_%s", strings.Repeat(datasetSuffix, 200)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDataset(datasetID), + ExpectError: regexp.MustCompile(".+cannot be greater than 1,024 characters"), + }, + }, + }) +} + func testAccAddTable(t *testing.T, datasetID string, tableID string) resource.TestCheckFunc { // Not actually a check, but adds a table independently of terraform return func(s *terraform.State) error { diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json index c55d9a2c4ee6..427f48a3e41b 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json @@ -1,6 +1,6 @@ [ { - "name": "//bigquery.googleapis.com/projects/{{.Provider.project}}/datasets/test-dataset", + "name": "//bigquery.googleapis.com/projects/{{.Provider.project}}/datasets/test_dataset", "asset_type": "bigquery.googleapis.com/Dataset", "ancestry_path": "{{.Ancestry}}/project/{{.Provider.project}}", "resource": { @@ -11,7 +11,7 @@ "data": { "friendlyName": "", "datasetReference": { - "datasetId": "test-dataset" + "datasetId": "test_dataset" }, "labels": { "env": "dev" diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf index 44bd499f16c0..a72c95ae1fe6 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf @@ -28,7 +28,7 @@ provider "google" { } resource "google_bigquery_dataset" "default" { - dataset_id = "test-dataset" + dataset_id = "test_dataset" location = "EU" default_table_expiration_ms = 3600000 diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json index 770149249ec3..e76f11d2022e 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json @@ -1,6 +1,6 @@ [ { - "name": "//bigquery.googleapis.com/projects/{{.Provider.project}}/datasets/test-dataset", + "name": "//bigquery.googleapis.com/projects/{{.Provider.project}}/datasets/test_dataset", "asset_type": "bigquery.googleapis.com/Dataset", "ancestry_path": "{{.Ancestry}}/project/{{.Provider.project}}", "resource": { @@ -10,7 +10,7 @@ "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { "datasetReference": { - "datasetId": "test-dataset" + "datasetId": "test_dataset" }, "defaultTableExpirationMs": 3600000, "labels": { diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf index f8330b074568..12e8b8626361 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf @@ -28,7 +28,7 @@ provider "google" { } resource "google_bigquery_dataset" "example_dataset" { - dataset_id = "test-dataset" + dataset_id = "test_dataset" location = "EU" project = "{{.Provider.project}}" default_table_expiration_ms = 3600000 diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json index 7aed9ac6ce97..c0b0e3053ef5 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json @@ -1,6 +1,6 @@ [ { - "name": "//bigquery.googleapis.com/projects/{{.Provider.project}}/datasets/test-dataset", + "name": "//bigquery.googleapis.com/projects/{{.Provider.project}}/datasets/test_dataset", "asset_type": "bigquery.googleapis.com/Dataset", "ancestry_path": "{{.Ancestry}}/project/{{.Provider.project}}", "resource": { @@ -10,7 +10,7 @@ "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { "datasetReference": { - "datasetId": "test-dataset" + "datasetId": "test_dataset" }, "defaultTableExpirationMs": 3600000, "labels": { diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf index f7d87317adeb..337e4d1b7988 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf @@ -28,7 +28,7 @@ provider "google" { } resource "google_bigquery_dataset" "example_dataset" { - dataset_id = "test-dataset" + dataset_id = "test_dataset" location = "EU" project = "{{.Provider.project}}" default_table_expiration_ms = 3600000 diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json index 5908f8d7600c..f00a09b317b4 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json @@ -1,6 +1,6 @@ [ { - "name": "//bigquery.googleapis.com/projects/{{.Provider.project}}/datasets/test-dataset", + "name": "//bigquery.googleapis.com/projects/{{.Provider.project}}/datasets/test_dataset", "asset_type": "bigquery.googleapis.com/Dataset", "ancestry_path": "{{.Ancestry}}/project/{{.Provider.project}}", "resource": { @@ -10,7 +10,7 @@ "parent": "//cloudresourcemanager.googleapis.com/projects/{{.Provider.project}}", "data": { "datasetReference": { - "datasetId": "test-dataset" + "datasetId": "test_dataset" }, "defaultTableExpirationMs": 3600000, "labels": { diff --git a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf index ae6554fe8d28..89a2450aecb2 100644 --- a/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf +++ b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf @@ -28,7 +28,7 @@ provider "google" { } resource "google_bigquery_dataset" "example-dataset" { - dataset_id = "test-dataset" + dataset_id = "test_dataset" location = "EU" project = "{{.Provider.project}}" default_table_expiration_ms = 3600000 From 92183abb882f90d455edddb24afa22cfde0089f3 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Wed, 28 Feb 2024 14:29:25 -0800 Subject: [PATCH 049/200] Prevent duplicate entries in vcr results (#10068) * Prevent duplicate entries in vcr results * Create empty map * Only collect result from current test --- .ci/magician/vcr/tester.go | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/.ci/magician/vcr/tester.go b/.ci/magician/vcr/tester.go index 592cf1925a9b..23e740100916 100644 --- a/.ci/magician/vcr/tester.go +++ b/.ci/magician/vcr/tester.go @@ -223,12 +223,13 @@ func (vt *Tester) Run(mode Mode, version provider.Version, testDirs []string) (* logFileName := filepath.Join(vt.baseDir, "testlogs", fmt.Sprintf("%s_test.log", mode.Lower())) // Write output (or error) to test log. // Append to existing log file. - previousLog, _ := vt.rnr.ReadFile(logFileName) - if previousLog != "" { - output = previousLog + "\n" + output + allOutput, _ := vt.rnr.ReadFile(logFileName) + if allOutput != "" { + allOutput += "\n" } - if err := vt.rnr.WriteFile(logFileName, output); err != nil { - return nil, fmt.Errorf("error writing log: %v, test output: %v", err, output) + allOutput += output + if err := vt.rnr.WriteFile(logFileName, allOutput); err != nil { + return nil, fmt.Errorf("error writing log: %v, test output: %v", err, allOutput) } return collectResult(output), testErr } @@ -319,7 +320,7 @@ func (vt *Tester) runInParallel(mode Mode, version provider.Version, testDir, te "-parallel", "1", "-v", - "-run=" + test, + "-run=" + test + "$", "-timeout", replayingTimeout, "-ldflags=-X=github.com/hashicorp/terraform-provider-google-beta/version.ProviderVersion=acc", @@ -473,19 +474,26 @@ func (vt *Tester) printLogs(logPath string) { func collectResult(output string) *Result { matches := testResultsExpression.FindAllStringSubmatch(output, -1) - results := make(map[string][]string, 4) + resultSets := make(map[string]map[string]struct{}, 4) for _, submatches := range matches { if len(submatches) != 3 { fmt.Printf("Warning: unexpected regex match found in test output: %v", submatches) continue } - results[submatches[1]] = append(results[submatches[1]], submatches[2]) + if _, ok := resultSets[submatches[1]]; !ok { + resultSets[submatches[1]] = make(map[string]struct{}) + } + resultSets[submatches[1]][submatches[2]] = struct{}{} } + results := make(map[string][]string, 4) results["PANIC"] = testPanicExpression.FindAllString(output, -1) - sort.Strings(results["FAIL"]) - sort.Strings(results["PASS"]) - sort.Strings(results["SKIP"]) sort.Strings(results["PANIC"]) + for _, kind := range []string{"FAIL", "PASS", "SKIP"} { + for test := range resultSets[kind] { + results[kind] = append(results[kind], test) + } + sort.Strings(results[kind]) + } return &Result{ FailedTests: results["FAIL"], PassedTests: results["PASS"], From 2c4db3255e15c372f8ae11802f01e49af070535b Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Wed, 28 Feb 2024 14:32:56 -0800 Subject: [PATCH 050/200] Split github tokens (#9988) * Split github tokens * Update .ci/gcb-generate-diffs-new.yml Co-authored-by: Stephen Lewis (Burrows) * Remove redundant downstreams token * Make diff processor use new token * Update path to markdown file * Replace GITHUB_TOKEN * Make github tokens optional for generate downstream * Allow either github token to be used * Replace GITHUB_TOKEN * Move environment variable lookup out of constructor * Update .ci/magician/vcr/tester.go Co-authored-by: Stephen Lewis (Burrows) * Add downstream token * Make request reviewer use GITHUB_TOKEN and tgc integration use GITHUB_TOKEN_CLASSIC * Apply suggestions from code review Co-authored-by: Stephen Lewis (Burrows) --------- Co-authored-by: Stephen Lewis (Burrows) --- .ci/gcb-community-checker.yml | 6 +-- .ci/gcb-contributor-membership-checker.yml | 6 +-- .ci/gcb-generate-diffs-new.yml | 36 ++++++++------- .ci/gcb-push-downstream.yml | 44 +++++++++---------- .ci/gcb-vcr-nightly.yml | 2 +- .ci/magician/cmd/check_cassettes.go | 4 +- .ci/magician/cmd/community_checker.go | 7 ++- .ci/magician/cmd/generate_comment.go | 7 +-- .ci/magician/cmd/generate_comment_test.go | 28 ++++++------ .ci/magician/cmd/generate_downstream.go | 20 +++++++-- .ci/magician/cmd/membership_checker.go | 7 ++- .ci/magician/cmd/request_reviewer.go | 7 ++- .ci/magician/cmd/request_service_reviewers.go | 7 ++- .ci/magician/cmd/test_terraform_vcr.go | 7 +-- .ci/magician/cmd/test_tgc.go | 7 ++- .ci/magician/cmd/test_tpg.go | 7 ++- .ci/magician/github/init.go | 15 ++----- .ci/magician/vcr/tester.go | 2 +- .../test_tgc_integration.sh | 6 +-- .../go-plus/vcr-cassette-merger/vcr_merge.sh | 4 +- tools/diff-processor/README.md | 2 +- tools/diff-processor/labels/get_issue.go | 2 +- tools/diff-processor/rules/rule_test.go | 2 +- 23 files changed, 136 insertions(+), 99 deletions(-) diff --git a/.ci/gcb-community-checker.yml b/.ci/gcb-community-checker.yml index 37b2e4955ca1..0eac9a4666e7 100644 --- a/.ci/gcb-community-checker.yml +++ b/.ci/gcb-community-checker.yml @@ -61,7 +61,7 @@ steps: - name: 'gcr.io/graphite-docker-images/go-plus' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: community-checker - secretEnv: ["GITHUB_TOKEN", "GENERATE_DIFFS_TRIGGER"] + secretEnv: ["GITHUB_TOKEN_MAGIC_MODULES", "GENERATE_DIFFS_TRIGGER"] timeout: 8000s args: - "community-checker" @@ -74,7 +74,7 @@ steps: availableSecrets: secretManager: - - versionName: projects/673497134629/secrets/github-magician-token/versions/latest - env: GITHUB_TOKEN + - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-magic-modules/versions/latest + env: GITHUB_TOKEN_MAGIC_MODULES - versionName: projects/673497134629/secrets/ci-trigger-generate-diffs/versions/latest env: GENERATE_DIFFS_TRIGGER diff --git a/.ci/gcb-contributor-membership-checker.yml b/.ci/gcb-contributor-membership-checker.yml index c7b2cc3cc89a..f40bc6d69c5b 100644 --- a/.ci/gcb-contributor-membership-checker.yml +++ b/.ci/gcb-contributor-membership-checker.yml @@ -62,7 +62,7 @@ steps: entrypoint: "/workspace/.ci/scripts/go-plus/magician/exec.sh" id: contributor-membership-checker secretEnv: - ["GITHUB_TOKEN", "GENERATE_DIFFS_TRIGGER", "COMMUNITY_CHECKER_TRIGGER"] + ["GITHUB_TOKEN_MAGIC_MODULES", "GENERATE_DIFFS_TRIGGER", "COMMUNITY_CHECKER_TRIGGER"] timeout: 8000s args: - "membership-checker" @@ -75,8 +75,8 @@ steps: availableSecrets: secretManager: - - versionName: projects/673497134629/secrets/github-magician-token/versions/latest - env: GITHUB_TOKEN + - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-magic-modules/versions/latest + env: GITHUB_TOKEN_MAGIC_MODULES - versionName: projects/673497134629/secrets/ci-trigger-generate-diffs/versions/latest env: GENERATE_DIFFS_TRIGGER - versionName: projects/673497134629/secrets/ci-trigger-community-checker/versions/latest diff --git a/.ci/gcb-generate-diffs-new.yml b/.ci/gcb-generate-diffs-new.yml index c19d5c5ebdd9..e775b5a37d39 100644 --- a/.ci/gcb-generate-diffs-new.yml +++ b/.ci/gcb-generate-diffs-new.yml @@ -72,7 +72,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: tpg-head - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS"] waitFor: ["build-magician-binary"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -86,7 +86,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: tpg-base - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS"] waitFor: ["build-magician-binary"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -99,7 +99,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS"] id: tpgb-head waitFor: ["build-magician-binary"] env: @@ -114,7 +114,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: tpgb-base - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS"] waitFor: ["build-magician-binary"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -128,7 +128,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: tgc-head - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS"] waitFor: ["build-magician-binary"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -142,7 +142,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: tgc-base - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS"] waitFor: ["build-magician-binary"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -156,7 +156,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: tf-oics-head - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS"] waitFor: ["build-magician-binary"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -170,7 +170,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: tf-oics-base - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS"] waitFor: ["build-magician-binary"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -184,7 +184,7 @@ steps: - name: 'gcr.io/graphite-docker-images/go-plus' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' id: diff - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS", "GITHUB_TOKEN_MAGIC_MODULES"] args: - 'generate-comment' env: @@ -198,7 +198,7 @@ steps: id: tgc-test allowFailure: true entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_MAGIC_MODULES"] waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] args: - 'test-tgc' @@ -210,7 +210,7 @@ steps: id: tgc-test-integration entrypoint: '/workspace/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh' allowFailure: true - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_MAGIC_MODULES"] waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] env: - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT @@ -229,7 +229,7 @@ steps: id: tpgb-test allowFailure: true entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_MAGIC_MODULES"] waitFor: ["tpgb-head", "tpgb-base"] args: - 'test-tpg' @@ -242,7 +242,7 @@ steps: id: tpg-test allowFailure: true entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_MAGIC_MODULES"] waitFor: ["tpg-head", "tpg-base"] args: - 'test-tpg' @@ -254,7 +254,7 @@ steps: - name: 'gcr.io/graphite-docker-images/go-plus' id: gcb-tpg-vcr-test entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN", "GOOGLE_BILLING_ACCOUNT", "GOOGLE_CUST_ID", "GOOGLE_FIRESTORE_PROJECT", "GOOGLE_IDENTITY_USER", "GOOGLE_MASTER_BILLING_ACCOUNT", "GOOGLE_ORG", "GOOGLE_ORG_2", "GOOGLE_ORG_DOMAIN", "GOOGLE_PROJECT", "GOOGLE_PROJECT_NUMBER", "GOOGLE_SERVICE_ACCOUNT", "SA_KEY", "GOOGLE_PUBLIC_AVERTISED_PREFIX_DESCRIPTION", "GOOGLE_TPU_V2_VM_RUNTIME_VERSION"] + secretEnv: ["GITHUB_TOKEN_DOWNSTREAMS", "GITHUB_TOKEN_MAGIC_MODULES", "GOOGLE_BILLING_ACCOUNT", "GOOGLE_CUST_ID", "GOOGLE_FIRESTORE_PROJECT", "GOOGLE_IDENTITY_USER", "GOOGLE_MASTER_BILLING_ACCOUNT", "GOOGLE_ORG", "GOOGLE_ORG_2", "GOOGLE_ORG_DOMAIN", "GOOGLE_PROJECT", "GOOGLE_PROJECT_NUMBER", "GOOGLE_SERVICE_ACCOUNT", "SA_KEY", "GOOGLE_PUBLIC_AVERTISED_PREFIX_DESCRIPTION", "GOOGLE_TPU_V2_VM_RUNTIME_VERSION"] waitFor: ["diff"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -271,7 +271,7 @@ steps: - name: 'gcr.io/graphite-docker-images/go-plus' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_MAGIC_MODULES"] waitFor: ["diff"] args: - 'request-service-reviewers' @@ -284,8 +284,10 @@ options: availableSecrets: secretManager: - - versionName: projects/673497134629/secrets/github-magician-token/versions/latest - env: GITHUB_TOKEN + - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-downstreams/versions/latest + env: GITHUB_TOKEN_DOWNSTREAMS + - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-magic-modules/versions/latest + env: GITHUB_TOKEN_MAGIC_MODULES - versionName: projects/673497134629/secrets/ci-test-billing-account/versions/latest env: GOOGLE_BILLING_ACCOUNT - versionName: projects/673497134629/secrets/ci-test-cust-id/versions/latest diff --git a/.ci/gcb-push-downstream.yml b/.ci/gcb-push-downstream.yml index 0f325a15a17c..9b0b58493ab5 100644 --- a/.ci/gcb-push-downstream.yml +++ b/.ci/gcb-push-downstream.yml @@ -33,7 +33,6 @@ steps: - name: 'gcr.io/graphite-docker-images/bash-plus' entrypoint: '/workspace/.ci/scripts/bash-plus/downstream-waiter/wait_for_commit.sh' id: tpg-sync - secretEnv: ["GITHUB_TOKEN"] waitFor: ["checkout"] args: - 'tpg-sync' @@ -42,7 +41,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_CLASSIC"] id: tpg-push waitFor: ["tpg-sync", "build-magician-binary"] env: @@ -56,22 +55,21 @@ steps: - name: 'gcr.io/cloud-builders/git' waitFor: ["tpg-push"] - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_CLASSIC"] entrypoint: 'bash' args: - -c - | if [ "$BRANCH_NAME" == "main" ]; then - git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpg-sync + git push https://modular-magician:$$GITHUB_TOKEN_CLASSIC@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpg-sync else - git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpg-sync-$BRANCH_NAME + git push https://modular-magician:$$GITHUB_TOKEN_CLASSIC@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpg-sync-$BRANCH_NAME fi # TPGB - name: 'gcr.io/graphite-docker-images/bash-plus' entrypoint: '/workspace/.ci/scripts/bash-plus/downstream-waiter/wait_for_commit.sh' id: tpgb-sync - secretEnv: ["GITHUB_TOKEN"] waitFor: ["checkout"] args: - 'tpgb-sync' @@ -80,7 +78,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_CLASSIC"] id: tpgb-push waitFor: ["tpgb-sync", "build-magician-binary"] env: @@ -94,22 +92,21 @@ steps: - name: 'gcr.io/cloud-builders/git' waitFor: ["tpgb-push"] - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_CLASSIC"] entrypoint: 'bash' args: - -c - | if [ "$BRANCH_NAME" == "main" ]; then - git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpgb-sync + git push https://modular-magician:$$GITHUB_TOKEN_CLASSIC@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpgb-sync else - git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpgb-sync-$BRANCH_NAME + git push https://modular-magician:$$GITHUB_TOKEN_CLASSIC@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpgb-sync-$BRANCH_NAME fi # TGC - name: 'gcr.io/graphite-docker-images/bash-plus' entrypoint: '/workspace/.ci/scripts/bash-plus/downstream-waiter/wait_for_commit.sh' id: tgc-sync - secretEnv: ["GITHUB_TOKEN"] waitFor: ["checkout"] args: - 'tgc-sync' @@ -118,7 +115,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_CLASSIC"] id: tgc-push waitFor: ["tgc-sync", "tpgb-push"] env: @@ -132,22 +129,21 @@ steps: - name: 'gcr.io/cloud-builders/git' waitFor: ["tgc-push"] - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_CLASSIC"] entrypoint: 'bash' args: - -c - | if [ "$BRANCH_NAME" == "main" ]; then - git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tgc-sync + git push https://modular-magician:$$GITHUB_TOKEN_CLASSIC@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tgc-sync else - git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tgc-sync-$BRANCH_NAME + git push https://modular-magician:$$GITHUB_TOKEN_CLASSIC@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tgc-sync-$BRANCH_NAME fi # TF-OICS - name: 'gcr.io/graphite-docker-images/bash-plus' entrypoint: '/workspace/.ci/scripts/bash-plus/downstream-waiter/wait_for_commit.sh' id: tf-oics-sync - secretEnv: ["GITHUB_TOKEN"] waitFor: ["checkout"] args: - 'tf-oics-sync' @@ -156,7 +152,7 @@ steps: - name: 'gcr.io/graphite-docker-images/build-environment' entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_CLASSIC"] id: tf-oics-push waitFor: ["tf-oics-sync", "build-magician-binary"] env: @@ -170,20 +166,20 @@ steps: - name: 'gcr.io/cloud-builders/git' waitFor: ["tf-oics-push"] - secretEnv: ["GITHUB_TOKEN"] + secretEnv: ["GITHUB_TOKEN_CLASSIC"] entrypoint: 'bash' args: - -c - | if [ "$BRANCH_NAME" == "main" ]; then - git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tf-oics-sync + git push https://modular-magician:$$GITHUB_TOKEN_CLASSIC@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tf-oics-sync else - git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tf-oics-sync-$BRANCH_NAME + git push https://modular-magician:$$GITHUB_TOKEN_CLASSIC@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tf-oics-sync-$BRANCH_NAME fi - name: 'gcr.io/graphite-docker-images/go-plus' entrypoint: '/workspace/.ci/scripts/go-plus/vcr-cassette-merger/vcr_merge.sh' - secretEnv: ["GITHUB_TOKEN", "GOOGLE_PROJECT"] + secretEnv: ["GITHUB_TOKEN_CLASSIC", "GOOGLE_PROJECT"] id: vcr-merge waitFor: ["tpg-push"] env: @@ -196,7 +192,7 @@ steps: waitFor: ["vcr-merge"] entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' secretEnv: - - "GITHUB_TOKEN" + - "GITHUB_TOKEN_DOWNSTREAMS" - "GOOGLE_BILLING_ACCOUNT" - "GOOGLE_CUST_ID" - "GOOGLE_FIRESTORE_PROJECT" @@ -228,7 +224,9 @@ logsBucket: 'gs://cloudbuild-downstream-builder-logs' availableSecrets: secretManager: - versionName: projects/673497134629/secrets/github-classic--repo-workflow/versions/latest - env: GITHUB_TOKEN + env: GITHUB_TOKEN_CLASSIC + - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-downstreams/versions/latest + env: GITHUB_TOKEN_DOWNSTREAMS - versionName: projects/673497134629/secrets/ci-test-billing-account/versions/latest env: GOOGLE_BILLING_ACCOUNT - versionName: projects/673497134629/secrets/ci-test-cust-id/versions/latest diff --git a/.ci/gcb-vcr-nightly.yml b/.ci/gcb-vcr-nightly.yml index fb3bbf8663c3..3664d6312d34 100644 --- a/.ci/gcb-vcr-nightly.yml +++ b/.ci/gcb-vcr-nightly.yml @@ -42,4 +42,4 @@ availableSecrets: - versionName: projects/673497134629/secrets/ci-test-public-advertised-prefix-description/versions/latest env: GOOGLE_PUBLIC_AVERTISED_PREFIX_DESCRIPTION - versionName: projects/673497134629/secrets/ci-test-tpu-v2-vm-runtime-version/versions/latest - env: GOOGLE_TPU_V2_VM_RUNTIME_VERSION \ No newline at end of file + env: GOOGLE_TPU_V2_VM_RUNTIME_VERSION diff --git a/.ci/magician/cmd/check_cassettes.go b/.ci/magician/cmd/check_cassettes.go index 321bb83eda69..f5977ec0be29 100644 --- a/.ci/magician/cmd/check_cassettes.go +++ b/.ci/magician/cmd/check_cassettes.go @@ -13,7 +13,7 @@ import ( var ccEnvironmentVariables = [...]string{ "COMMIT_SHA", - "GITHUB_TOKEN", + "GITHUB_TOKEN_DOWNSTREAMS", "GOCACHE", "GOPATH", "GOOGLE_BILLING_ACCOUNT", @@ -62,7 +62,7 @@ var checkCassettesCmd = &cobra.Command{ os.Exit(1) } - ctlr := source.NewController(env["GOPATH"], "modular-magician", env["GITHUB_TOKEN"], rnr) + ctlr := source.NewController(env["GOPATH"], "modular-magician", env["GITHUB_TOKEN_DOWNSTREAMS"], rnr) vt, err := vcr.NewTester(env, rnr) if err != nil { diff --git a/.ci/magician/cmd/community_checker.go b/.ci/magician/cmd/community_checker.go index f968ca74abff..2ec024952520 100644 --- a/.ci/magician/cmd/community_checker.go +++ b/.ci/magician/cmd/community_checker.go @@ -64,7 +64,12 @@ var communityApprovalCmd = &cobra.Command{ baseBranch := args[5] fmt.Println("Base Branch: ", baseBranch) - gh := github.NewClient() + githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + os.Exit(1) + } + gh := github.NewClient(githubToken) cb := cloudbuild.NewClient() execCommunityChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch, gh, cb) }, diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index f7ad2e5a8b0a..b00ab9986d6e 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -35,7 +35,8 @@ var gcEnvironmentVariables = [...]string{ "BUILD_ID", "BUILD_STEP", "COMMIT_SHA", - "GITHUB_TOKEN", + "GITHUB_TOKEN_DOWNSTREAMS", + "GITHUB_TOKEN_MAGIC_MODULES", "GOPATH", "HOME", "PATH", @@ -70,13 +71,13 @@ var generateCommentCmd = &cobra.Command{ env[ev] = val } - gh := github.NewClient() + gh := github.NewClient(env["GITHUB_TOKEN_MAGIC_MODULES"]) rnr, err := exec.NewRunner() if err != nil { fmt.Println("Error creating a runner: ", err) os.Exit(1) } - ctlr := source.NewController(filepath.Join("workspace", "go"), "modular-magician", env["GITHUB_TOKEN"], rnr) + ctlr := source.NewController(filepath.Join("workspace", "go"), "modular-magician", env["GITHUB_TOKEN_DOWNSTREAMS"], rnr) execGenerateComment(env, gh, rnr, ctlr) }, } diff --git a/.ci/magician/cmd/generate_comment_test.go b/.ci/magician/cmd/generate_comment_test.go index 46f90886f180..c8a1c14ed487 100644 --- a/.ci/magician/cmd/generate_comment_test.go +++ b/.ci/magician/cmd/generate_comment_test.go @@ -28,22 +28,22 @@ func TestExecGenerateComment(t *testing.T) { } ctlr := source.NewController("/mock/dir/go", "modular-magician", "*******", mr) env := map[string]string{ - "BUILD_ID": "build1", - "BUILD_STEP": "17", - "COMMIT_SHA": "sha1", - "GITHUB_TOKEN": "*******", - "PR_NUMBER": "pr1", - "PROJECT_ID": "project1", + "BUILD_ID": "build1", + "BUILD_STEP": "17", + "COMMIT_SHA": "sha1", + "GITHUB_TOKEN_MAGIC_MODULES": "*******", + "PR_NUMBER": "pr1", + "PROJECT_ID": "project1", } diffProcessorEnv := map[string]string{ - "BUILD_ID": "build1", - "BUILD_STEP": "17", - "COMMIT_SHA": "sha1", - "GITHUB_TOKEN": "*******", - "NEW_REF": "auto-pr-pr1", - "OLD_REF": "auto-pr-pr1-old", - "PR_NUMBER": "pr1", - "PROJECT_ID": "project1", + "BUILD_ID": "build1", + "BUILD_STEP": "17", + "COMMIT_SHA": "sha1", + "GITHUB_TOKEN_MAGIC_MODULES": "*******", + "NEW_REF": "auto-pr-pr1", + "OLD_REF": "auto-pr-pr1-old", + "PR_NUMBER": "pr1", + "PROJECT_ID": "project1", } execGenerateComment(env, gh, mr, ctlr) diff --git a/.ci/magician/cmd/generate_downstream.go b/.ci/magician/cmd/generate_downstream.go index 033563bda007..f2469d95074a 100644 --- a/.ci/magician/cmd/generate_downstream.go +++ b/.ci/magician/cmd/generate_downstream.go @@ -19,10 +19,14 @@ var changelogExp = regexp.MustCompile("(?s)```release-note.*?```") var gdEnvironmentVariables = [...]string{ "BASE_BRANCH", - "GITHUB_TOKEN", "GOPATH", } +var gdTokenEnvironmentVariables = [...]string{ + "GITHUB_TOKEN_CLASSIC", + "GITHUB_TOKEN_DOWNSTREAMS", +} + var generateDownstreamCmd = &cobra.Command{ Use: "generate-downstream", Short: "Run generate downstream", @@ -47,13 +51,23 @@ var generateDownstreamCmd = &cobra.Command{ env[ev] = val } - gh := github.NewClient() + var githubToken string + for _, ev := range gdTokenEnvironmentVariables { + val, ok := os.LookupEnv(ev) + if ok { + env[ev] = val + githubToken = val + break + } + } + + gh := github.NewClient(githubToken) rnr, err := exec.NewRunner() if err != nil { fmt.Println("Error creating a runner: ", err) os.Exit(1) } - ctlr := source.NewController(env["GOPATH"], "modular-magician", env["GITHUB_TOKEN"], rnr) + ctlr := source.NewController(env["GOPATH"], "modular-magician", githubToken, rnr) if len(args) != 4 { fmt.Printf("Wrong number of arguments %d, expected 4\n", len(args)) diff --git a/.ci/magician/cmd/membership_checker.go b/.ci/magician/cmd/membership_checker.go index 4af9c95b81bc..71ffda29a253 100644 --- a/.ci/magician/cmd/membership_checker.go +++ b/.ci/magician/cmd/membership_checker.go @@ -72,7 +72,12 @@ var membershipCheckerCmd = &cobra.Command{ baseBranch := args[5] fmt.Println("Base Branch: ", baseBranch) - gh := github.NewClient() + githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + os.Exit(1) + } + gh := github.NewClient(githubToken) cb := cloudbuild.NewClient() execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch, gh, cb) }, diff --git a/.ci/magician/cmd/request_reviewer.go b/.ci/magician/cmd/request_reviewer.go index b5deed4e828e..8ed8661a4e61 100644 --- a/.ci/magician/cmd/request_reviewer.go +++ b/.ci/magician/cmd/request_reviewer.go @@ -48,7 +48,12 @@ var requestReviewerCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { prNumber := args[0] fmt.Println("PR Number: ", prNumber) - gh := github.NewClient() + githubToken, ok := os.LookupEnv("GITHUB_TOKEN") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN environment variable") + os.Exit(1) + } + gh := github.NewClient(githubToken) execRequestReviewer(prNumber, gh) }, } diff --git a/.ci/magician/cmd/request_service_reviewers.go b/.ci/magician/cmd/request_service_reviewers.go index d1efff417ac5..33abd8d1ca1f 100644 --- a/.ci/magician/cmd/request_service_reviewers.go +++ b/.ci/magician/cmd/request_service_reviewers.go @@ -40,7 +40,12 @@ var requestServiceReviewersCmd = &cobra.Command{ prNumber := args[0] fmt.Println("PR Number: ", prNumber) - gh := github.NewClient() + githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + os.Exit(1) + } + gh := github.NewClient(githubToken) execRequestServiceReviewers(prNumber, gh, labeler.EnrolledTeamsYaml) }, } diff --git a/.ci/magician/cmd/test_terraform_vcr.go b/.ci/magician/cmd/test_terraform_vcr.go index 2749ddd586c0..3c979ef3ab84 100644 --- a/.ci/magician/cmd/test_terraform_vcr.go +++ b/.ci/magician/cmd/test_terraform_vcr.go @@ -15,7 +15,8 @@ import ( ) var ttvEnvironmentVariables = [...]string{ - "GITHUB_TOKEN", + "GITHUB_TOKEN_DOWNSTREAMS", + "GITHUB_TOKEN_MAGIC_MODULES", "GOCACHE", "GOPATH", "GOOGLE_BILLING_ACCOUNT", @@ -59,13 +60,13 @@ var testTerraformVCRCmd = &cobra.Command{ baseBranch = "main" } - gh := github.NewClient() + gh := github.NewClient(env["GITHUB_TOKEN_MAGIC_MODULES"]) rnr, err := exec.NewRunner() if err != nil { fmt.Println("Error creating a runner: ", err) os.Exit(1) } - ctlr := source.NewController(env["GOPATH"], "modular-magician", env["GITHUB_TOKEN"], rnr) + ctlr := source.NewController(env["GOPATH"], "modular-magician", env["GITHUB_TOKEN_DOWNSTREAMS"], rnr) vt, err := vcr.NewTester(env, rnr) if err != nil { diff --git a/.ci/magician/cmd/test_tgc.go b/.ci/magician/cmd/test_tgc.go index 9f0edf2f29bf..54fd97394612 100644 --- a/.ci/magician/cmd/test_tgc.go +++ b/.ci/magician/cmd/test_tgc.go @@ -36,7 +36,12 @@ var testTGCCmd = &cobra.Command{ commit := os.Getenv("COMMIT_SHA") pr := os.Getenv("PR_NUMBER") - gh := github.NewClient() + githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + os.Exit(1) + } + gh := github.NewClient(githubToken) execTestTGC(commit, pr, gh) }, diff --git a/.ci/magician/cmd/test_tpg.go b/.ci/magician/cmd/test_tpg.go index c8923ad42106..58d216d512ff 100644 --- a/.ci/magician/cmd/test_tpg.go +++ b/.ci/magician/cmd/test_tpg.go @@ -42,7 +42,12 @@ var testTPGCmd = &cobra.Command{ commit := os.Getenv("COMMIT_SHA") pr := os.Getenv("PR_NUMBER") - gh := github.NewClient() + githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + os.Exit(1) + } + gh := github.NewClient(githubToken) execTestTPG(version, commit, pr, gh) }, diff --git a/.ci/magician/github/init.go b/.ci/magician/github/init.go index a931ad5efca5..d64995aa46b7 100644 --- a/.ci/magician/github/init.go +++ b/.ci/magician/github/init.go @@ -15,22 +15,13 @@ */ package github -import ( - "fmt" - "os" -) - // Client for GitHub interactions. type Client struct { token string } -func NewClient() *Client { - githubToken, ok := os.LookupEnv("GITHUB_TOKEN") - if !ok { - fmt.Println("Did not provide GITHUB_TOKEN environment variable") - os.Exit(1) +func NewClient(token string) *Client { + return &Client{ + token: token, } - - return &Client{token: githubToken} } diff --git a/.ci/magician/vcr/tester.go b/.ci/magician/vcr/tester.go index 23e740100916..46e4a36473c1 100644 --- a/.ci/magician/vcr/tester.go +++ b/.ci/magician/vcr/tester.go @@ -199,7 +199,7 @@ func (vt *Tester) Run(mode Mode, version provider.Version, testDirs []string) (* } var printedEnv string for ev, val := range env { - if ev == "SA_KEY" || ev == "GITHUB_TOKEN" { + if ev == "SA_KEY" || strings.HasPrefix(ev, "GITHUB_TOKEN") { val = "{hidden}" } printedEnv += fmt.Sprintf("%s=%s\n", ev, val) diff --git a/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh b/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh index a17d7099ff44..8f4ead70dc18 100755 --- a/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh +++ b/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh @@ -12,7 +12,7 @@ github_username=modular-magician new_branch="auto-pr-$pr_number" -git_remote=https://$github_username:$GITHUB_TOKEN@github.com/$github_username/$gh_repo +git_remote=https://github.com/$github_username/$gh_repo local_path=$GOPATH/src/github.com/GoogleCloudPlatform/$gh_repo mkdir -p "$(dirname $local_path)" git clone $git_remote $local_path --branch $new_branch --depth 2 @@ -38,7 +38,7 @@ post_body=$( jq -n \ curl \ -X POST \ - -u "$github_username:$GITHUB_TOKEN" \ + -u "$github_username:$GITHUB_TOKEN_MAGIC_MODULES" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/$mm_commit_sha" \ -d "$post_body" @@ -68,7 +68,7 @@ post_body=$( jq -n \ curl \ -X POST \ - -u "$github_username:$GITHUB_TOKEN" \ + -u "$github_username:$GITHUB_TOKEN_MAGIC_MODULES" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/$mm_commit_sha" \ -d "$post_body" diff --git a/.ci/scripts/go-plus/vcr-cassette-merger/vcr_merge.sh b/.ci/scripts/go-plus/vcr-cassette-merger/vcr_merge.sh index 93d7be0a77a3..7440af55c075 100755 --- a/.ci/scripts/go-plus/vcr-cassette-merger/vcr_merge.sh +++ b/.ci/scripts/go-plus/vcr-cassette-merger/vcr_merge.sh @@ -11,7 +11,7 @@ else echo "BASE_BRANCH: $BASE_BRANCH" fi -PR_NUMBER=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \ +PR_NUMBER=$(curl -s -H "Authorization: token ${GITHUB_TOKEN_CLASSIC}" \ "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls?state=closed&base=$BASE_BRANCH&sort=updated&direction=desc" | \ jq -r ".[] | if .merge_commit_sha == \"$REFERENCE\" then .number else empty end") @@ -40,4 +40,4 @@ if [ $? -eq 0 ]; then fi -set -e \ No newline at end of file +set -e diff --git a/tools/diff-processor/README.md b/tools/diff-processor/README.md index 7cd410dd854a..3bb107cae9d1 100644 --- a/tools/diff-processor/README.md +++ b/tools/diff-processor/README.md @@ -16,7 +16,7 @@ bin/diff-processor breaking-changes # Add labels to a PR based on the resources changed between OLD_REF and NEW_REF # The token used must have write access to issues -GITHUB_TOKEN=github_token bin/diff-processor add-labels PR_ID [--dry-run] +GITHUB_TOKEN_MAGIC_MODULES=github_token bin/diff-processor add-labels PR_ID [--dry-run] ``` ## Test diff --git a/tools/diff-processor/labels/get_issue.go b/tools/diff-processor/labels/get_issue.go index fe9b5a235d8a..c9d756892a48 100644 --- a/tools/diff-processor/labels/get_issue.go +++ b/tools/diff-processor/labels/get_issue.go @@ -20,7 +20,7 @@ func GetIssue(repository string, id uint64) (labeler.Issue, error) { return issue, fmt.Errorf("Error creating request: %w", err) } req.Header.Add("Accept", "application/vnd.github+json") - req.Header.Add("Authorization", "Bearer "+os.Getenv("GITHUB_TOKEN")) + req.Header.Add("Authorization", "Bearer "+os.Getenv("GITHUB_TOKEN_MAGIC_MODULES")) req.Header.Add("X-GitHub-Api-Version", "2022-11-28") resp, err := client.Do(req) if err != nil { diff --git a/tools/diff-processor/rules/rule_test.go b/tools/diff-processor/rules/rule_test.go index c68deed47d2c..2ed61fd00c9a 100644 --- a/tools/diff-processor/rules/rule_test.go +++ b/tools/diff-processor/rules/rule_test.go @@ -23,7 +23,7 @@ func TestUniqueRuleIdentifiers(t *testing.T) { func TestMarkdownIdentifiers(t *testing.T) { // Define the Markdown file path relative to the importer - mdFilePath := "../../../docs/content/develop/breaking-changes.md" + mdFilePath := "../../../docs/content/develop/breaking-changes/breaking-changes.md" // Read the Markdown file mdContent, err := ioutil.ReadFile(mdFilePath) From 0877c4f31b868c7e359af2cf2eba97990f772a08 Mon Sep 17 00:00:00 2001 From: askubis Date: Thu, 29 Feb 2024 10:46:49 +0100 Subject: [PATCH 051/200] Instance lifecycle policy default action on failure implementation (#10050) --- mmv1/third_party/terraform/go.mod.erb | 2 +- mmv1/third_party/terraform/go.sum | 4 ++-- .../resource_compute_instance_group_manager.go.erb | 9 +++++++++ ...source_compute_instance_group_manager_test.go.erb | 12 ++++++++++++ ...urce_compute_region_instance_group_manager.go.erb | 7 +++++++ ...compute_region_instance_group_manager_test.go.erb | 11 +++++++++++ .../r/compute_instance_group_manager.html.markdown | 7 ++++--- ...mpute_region_instance_group_manager.html.markdown | 7 +++++-- 8 files changed, 51 insertions(+), 8 deletions(-) diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index 2d2a0081a295..b5d4fd065d93 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -27,7 +27,7 @@ require ( github.com/sirupsen/logrus v1.8.1 golang.org/x/net v0.21.0 golang.org/x/oauth2 v0.17.0 - google.golang.org/api v0.166.0 + google.golang.org/api v0.167.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 google.golang.org/grpc v1.61.1 google.golang.org/protobuf v1.32.0 diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 70ac88701502..6837513a22df 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -363,8 +363,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T 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= -google.golang.org/api v0.166.0 h1:6m4NUwrZYhAaVIHZWxaKjw1L1vNAjtMwORmKRyEEo24= -google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= +google.golang.org/api v0.167.0 h1:CKHrQD1BLRii6xdkatBDXyKzM0mkawt2QP+H3LtPmSE= +google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= 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.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb index 878c8c2a2545..97baae34251f 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb @@ -305,6 +305,13 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { Description: `The instance lifecycle policy for this managed instance group.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "default_action_on_failure": { + Type: schema.TypeString, + Default: "REPAIR", + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"REPAIR", "DO_NOTHING"}, true), + Description: `Default behavior for all instance or health check failures.`, + }, "force_update_on_repair": { Type: schema.TypeString, Default: "NO", @@ -1188,6 +1195,7 @@ func expandInstanceLifecyclePolicy(configured []interface{}) *compute.InstanceGr for _, raw := range configured { data := raw.(map[string]interface{}) instanceLifecyclePolicy.ForceUpdateOnRepair = data["force_update_on_repair"].(string) + instanceLifecyclePolicy.DefaultActionOnFailure = data["default_action_on_failure"].(string) } return instanceLifecyclePolicy } @@ -1376,6 +1384,7 @@ func flattenInstanceLifecyclePolicy(instanceLifecyclePolicy *compute.InstanceGro if instanceLifecyclePolicy != nil { ilp := map[string]interface{}{} ilp["force_update_on_repair"] = instanceLifecyclePolicy.ForceUpdateOnRepair + ilp["default_action_on_failure"] = instanceLifecyclePolicy.DefaultActionOnFailure results = append(results, ilp) } return results diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.erb index c02ed9a13c1b..a600804fbf66 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager_test.go.erb @@ -116,6 +116,9 @@ func TestAccInstanceGroupManager_update(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccInstanceGroupManager_update(template1, target1, description, igm), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_instance_group_manager.igm-update", "instance_lifecycle_policy.0.default_action_on_failure", "DO_NOTHING"), + ), }, { ResourceName: "google_compute_instance_group_manager.igm-update", @@ -125,6 +128,9 @@ func TestAccInstanceGroupManager_update(t *testing.T) { }, { Config: testAccInstanceGroupManager_update2(template1, target1, target2, template2, description, igm), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_instance_group_manager.igm-update", "instance_lifecycle_policy.0.default_action_on_failure", "REPAIR"), + ), }, { ResourceName: "google_compute_instance_group_manager.igm-update", @@ -134,6 +140,9 @@ func TestAccInstanceGroupManager_update(t *testing.T) { }, { Config: testAccInstanceGroupManager_update3(template1, target1, target2, template2, description2, igm), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_instance_group_manager.igm-update", "instance_lifecycle_policy.0.default_action_on_failure", "REPAIR"), + ), }, { ResourceName: "google_compute_instance_group_manager.igm-update", @@ -671,6 +680,7 @@ resource "google_compute_instance_group_manager" "igm-update" { instance_lifecycle_policy { force_update_on_repair = "YES" + default_action_on_failure = "DO_NOTHING" } } `, template, target, description, igm) @@ -775,6 +785,7 @@ resource "google_compute_instance_group_manager" "igm-update" { instance_lifecycle_policy { force_update_on_repair = "NO" + default_action_on_failure = "REPAIR" } } `, template1, target1, target2, template2, description, igm) @@ -1786,6 +1797,7 @@ resource "google_compute_instance_group_manager" "igm-basic" { } instance_lifecycle_policy { force_update_on_repair = "YES" + default_action_on_failure = "REPAIR" } wait_for_instances = true wait_for_instances_status = "UPDATED" diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb index 46cfbffd60e9..8c756656264c 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb @@ -263,6 +263,13 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Description: `The instance lifecycle policy for this managed instance group.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ + "default_action_on_failure": { + Type: schema.TypeString, + Default: "REPAIR", + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"REPAIR", "DO_NOTHING"}, true), + Description: `Default behavior for all instance or health check failures.`, + }, "force_update_on_repair": { Type: schema.TypeString, Default: "NO", diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.erb index 4e4ef9645074..c071b8b13f05 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager_test.go.erb @@ -83,6 +83,9 @@ func TestAccRegionInstanceGroupManager_update(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccRegionInstanceGroupManager_update(template1, target1, igm), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_region_instance_group_manager.igm-update", "instance_lifecycle_policy.0.default_action_on_failure", "DO_NOTHING"), + ), }, { ResourceName: "google_compute_region_instance_group_manager.igm-update", @@ -92,6 +95,9 @@ func TestAccRegionInstanceGroupManager_update(t *testing.T) { }, { Config: testAccRegionInstanceGroupManager_update2(template1, target1, target2, template2, igm), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_region_instance_group_manager.igm-update", "instance_lifecycle_policy.0.default_action_on_failure", "REPAIR"), + ), }, { ResourceName: "google_compute_region_instance_group_manager.igm-update", @@ -101,6 +107,9 @@ func TestAccRegionInstanceGroupManager_update(t *testing.T) { }, { Config: testAccRegionInstanceGroupManager_update3(template1, target1, target2, template2, igm), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_compute_region_instance_group_manager.igm-update", "instance_lifecycle_policy.0.default_action_on_failure", "REPAIR"), + ), }, { ResourceName: "google_compute_region_instance_group_manager.igm-update", @@ -573,6 +582,7 @@ resource "google_compute_region_instance_group_manager" "igm-update" { instance_lifecycle_policy { force_update_on_repair = "YES" + default_action_on_failure = "DO_NOTHING" } } `, template, target, igm) @@ -677,6 +687,7 @@ resource "google_compute_region_instance_group_manager" "igm-update" { instance_lifecycle_policy { force_update_on_repair = "NO" + default_action_on_failure = "REPAIR" } } `, template1, target1, target2, template2, igm) diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown index a79b67e8c81c..834633b6b6d9 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown @@ -205,12 +205,13 @@ update_policy { ```hcl instance_lifecycle_policy { - force_update_on_repair = "YES" + force_update_on_repair = "YES" + default_action_on_failure = "DO_NOTHING" } ``` -* `force_update_on_repair` - (Optional, (https://terraform.io/docs/providers/google/guides/provider_versions.html)), Specifies whether to apply the group's latest configuration when repairing a VM. Valid options are: `YES`, `NO`. If `YES` and you updated the group's instance template or per-instance configurations after the VM was created, then these changes are applied when VM is repaired. If `NO` (default), then updates are applied in accordance with the group's update policy type. - +* `force_update_on_repair` - (Optional), Specifies whether to apply the group's latest configuration when repairing a VM. Valid options are: `YES`, `NO`. If `YES` and you updated the group's instance template or per-instance configurations after the VM was created, then these changes are applied when VM is repaired. If `NO` (default), then updates are applied in accordance with the group's update policy type. +* `default_action_on_failure` - (Optional), Default behavior for all instance or health check failures. Valid options are: `REPAIR`, `DO_NOTHING`. If `DO_NOTHING` then instances will not be repaired. If `REPAIR` (default), then failed instances will be repaired. - - - The `all_instances_config` block supports: diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown index cad9a1343d81..8dfbf3ee9a9f 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown @@ -215,11 +215,14 @@ update_policy { ```hcl instance_lifecycle_policy { - force_update_on_repair = "YES" + force_update_on_repair = "YES" + default_action_on_failure = "DO_NOTHING" } ``` -* `force_update_on_repair` - (Optional, (https://terraform.io/docs/providers/google/guides/provider_versions.html)), Specifies whether to apply the group's latest configuration when repairing a VM. Valid options are: YES, NO. If YES and you updated the group's instance template or per-instance configurations after the VM was created, then these changes are applied when VM is repaired. If NO (default), then updates are applied in accordance with the group's update policy type. +* `force_update_on_repair` - (Optional), Specifies whether to apply the group's latest configuration when repairing a VM. Valid options are: `YES`, `NO`. If `YES` and you updated the group's instance template or per-instance configurations after the VM was created, then these changes are applied when VM is repaired. If `NO` (default), then updates are applied in accordance with the group's update policy type. +* `default_action_on_failure` - (Optional), Default behavior for all instance or health check failures. Valid options are: `REPAIR`, `DO_NOTHING`. If `DO_NOTHING` then instances will not be repaired. If `REPAIR` (default), then failed instances will be repaired. + - - - The `all_instances_config` block supports: From 0518fd9fb82bbab049d85e280d98589b0aa5ffb9 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 29 Feb 2024 15:49:13 +0000 Subject: [PATCH 052/200] Add wait in `TestAccAppEngineStandardAppVersion_update` test to avoid 'API has not been used in project' error (#10076) * Add wait in acc test to avoid 'API has not been used in project' error * Add external provider `time` * Fix defect when referencing google_project resource --- ...esource_app_engine_standard_app_version_test.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/appengine/resource_app_engine_standard_app_version_test.go b/mmv1/third_party/terraform/services/appengine/resource_app_engine_standard_app_version_test.go index 225c6134f61f..024b3d6a5931 100644 --- a/mmv1/third_party/terraform/services/appengine/resource_app_engine_standard_app_version_test.go +++ b/mmv1/third_party/terraform/services/appengine/resource_app_engine_standard_app_version_test.go @@ -20,7 +20,10 @@ func TestAccAppEngineStandardAppVersion_update(t *testing.T) { acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckAppEngineStandardAppVersionDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + CheckDestroy: testAccCheckAppEngineStandardAppVersionDestroyProducer(t), Steps: []resource.TestStep{ { Config: testAccAppEngineStandardAppVersion_python(context), @@ -161,11 +164,20 @@ resource "google_project_service" "project" { disable_dependent_services = false } +resource "time_sleep" "wait_60_seconds" { + depends_on = [google_project.my_project] + + create_duration = "60s" +} + resource "google_project_service" "vpcaccess_api" { project = google_project.my_project.project_id service = "vpcaccess.googleapis.com" disable_dependent_services = false + + # Needed for CI tests for permissions to propagate, should not be needed for actual usage + depends_on = [time_sleep.wait_60_seconds] } resource "google_vpc_access_connector" "bar" { From 025526fd1b93ea052c3ee0dbf7e480d6b71ac981 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Thu, 29 Feb 2024 13:55:47 -0800 Subject: [PATCH 053/200] Set GITHUB_TOKEN environment variable for hub (#10091) --- .ci/magician/cmd/generate_downstream.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.ci/magician/cmd/generate_downstream.go b/.ci/magician/cmd/generate_downstream.go index f2469d95074a..b8605905f242 100644 --- a/.ci/magician/cmd/generate_downstream.go +++ b/.ci/magician/cmd/generate_downstream.go @@ -68,6 +68,17 @@ var generateDownstreamCmd = &cobra.Command{ os.Exit(1) } ctlr := source.NewController(env["GOPATH"], "modular-magician", githubToken, rnr) + oldToken := os.Getenv("GITHUB_TOKEN") + if err := os.Setenv("GITHUB_TOKEN", githubToken); err != nil { + fmt.Println("Error setting GITHUB_TOKEN environment variable: ", err) + os.Exit(1) + } + defer func() { + if err := os.Setenv("GITHUB_TOKEN", oldToken); err != nil { + fmt.Println("Error setting GITHUB_TOKEN environment variable: ", err) + os.Exit(1) + } + }() if len(args) != 4 { fmt.Printf("Wrong number of arguments %d, expected 4\n", len(args)) From fd6d4b71cd7f8fbeb67f161391157f71966a73a0 Mon Sep 17 00:00:00 2001 From: yiyinglovecoding <113492735+yiyinglovecoding@users.noreply.github.com> Date: Thu, 29 Feb 2024 14:12:25 -0800 Subject: [PATCH 054/200] fix forceNew on master_ipv4_cidr_block and private_endpoint_subnetwork (#10089) --- .../services/container/resource_container_cluster.go.erb | 2 -- 1 file changed, 2 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 00a3f3aaab84..b3471ce17ca3 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 @@ -1664,7 +1664,6 @@ func ResourceContainerCluster() *schema.Resource { Type: schema.TypeString, Computed: true, Optional: true, - ForceNew: true, AtLeastOneOf: privateClusterConfigKeys, ValidateFunc: verify.OrEmpty(validation.IsCIDRNetwork(28, 28)), Description: `The IP range in CIDR notation to use for the hosted master network. This range will be used for assigning private IP addresses to the cluster master(s) and the ILB VIP. This range must not overlap with any other ranges in use within the cluster's network, and it must be a /28 subnet. See Private Cluster Limitations for more details. This field only applies to private clusters, when enable_private_nodes is true.`, @@ -1682,7 +1681,6 @@ func ResourceContainerCluster() *schema.Resource { "private_endpoint_subnetwork": { Type: schema.TypeString, Optional: true, - ForceNew: true, AtLeastOneOf: privateClusterConfigKeys, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `Subnetwork in cluster's network where master's endpoint will be provisioned.`, From 03df3b2c751ce0e8d10998b903fa0ba51c2cbb8b Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Thu, 29 Feb 2024 16:19:31 -0600 Subject: [PATCH 055/200] make go-converted YAML compatible with go compiler (#10033) Co-authored-by: Zhenhua Li Co-authored-by: Nick Elliot --- mmv1/api/async.go | 220 ++++ mmv1/api/object.go | 82 ++ mmv1/api/product.go | 207 ++++ mmv1/api/product.rb | 4 - mmv1/api/product/version.go | 52 + mmv1/api/resource.go | 275 +++++ mmv1/api/resource/iam_policy.go | 168 +++ mmv1/api/resource/nested_query.go | 65 ++ mmv1/api/resource/reference_links.go | 39 + mmv1/api/timeouts.go | 51 + mmv1/api/type.go | 977 ++++++++++++++++++ mmv1/compiler.rb | 6 +- mmv1/go.mod | 5 + mmv1/go.sum | 3 + mmv1/google/yaml_validator.go | 155 +++ mmv1/main.go | 108 ++ mmv1/products/datafusion/go_instance.yaml | 298 ++++++ mmv1/products/datafusion/go_product.yaml | 35 + mmv1/products/pubsub/go_Schema.yaml | 84 ++ mmv1/products/pubsub/go_Subscription.yaml | 420 ++++++++ mmv1/products/pubsub/go_Topic.yaml | 150 +++ mmv1/products/pubsub/go_product.yaml | 22 + mmv1/provider/terraform.rb | 30 +- mmv1/provider/terraform/custom_code.go | 206 ++++ mmv1/provider/terraform/docs.go | 61 ++ mmv1/provider/terraform/examples.go | 339 ++++++ mmv1/provider/terraform/sub_template.rb | 7 + .../terraform/product_yaml_conversion.erb | 135 +++ mmv1/templates/terraform/yaml_conversion.erb | 550 ++++++++++ .../terraform/yaml_conversion_field.erb | 210 ++++ mmv1/third_party/go.mod | 2 + 31 files changed, 4959 insertions(+), 7 deletions(-) create mode 100644 mmv1/api/async.go create mode 100644 mmv1/api/object.go create mode 100644 mmv1/api/product.go create mode 100644 mmv1/api/product/version.go create mode 100644 mmv1/api/resource.go create mode 100644 mmv1/api/resource/iam_policy.go create mode 100644 mmv1/api/resource/nested_query.go create mode 100644 mmv1/api/resource/reference_links.go create mode 100644 mmv1/api/timeouts.go create mode 100644 mmv1/api/type.go create mode 100644 mmv1/go.mod create mode 100644 mmv1/go.sum create mode 100644 mmv1/google/yaml_validator.go create mode 100644 mmv1/main.go create mode 100644 mmv1/products/datafusion/go_instance.yaml create mode 100644 mmv1/products/datafusion/go_product.yaml create mode 100644 mmv1/products/pubsub/go_Schema.yaml create mode 100644 mmv1/products/pubsub/go_Subscription.yaml create mode 100644 mmv1/products/pubsub/go_Topic.yaml create mode 100644 mmv1/products/pubsub/go_product.yaml create mode 100644 mmv1/provider/terraform/custom_code.go create mode 100644 mmv1/provider/terraform/docs.go create mode 100644 mmv1/provider/terraform/examples.go create mode 100644 mmv1/templates/terraform/product_yaml_conversion.erb create mode 100644 mmv1/templates/terraform/yaml_conversion.erb create mode 100644 mmv1/templates/terraform/yaml_conversion_field.erb create mode 100644 mmv1/third_party/go.mod diff --git a/mmv1/api/async.go b/mmv1/api/async.go new file mode 100644 index 000000000000..55d756fa8312 --- /dev/null +++ b/mmv1/api/async.go @@ -0,0 +1,220 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package api + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// require 'api/object' +// require 'api/timeout' + +// Base class from which other Async classes can inherit. +type Async struct { + // Embed YamlValidator object + google.YamlValidator + + // Describes an operation + Operation Operation + + // The list of methods where operations are used. + Actions []string +} + +// def validate +// super + +// check :operation, type: Operation +// check :actions, default: %w[create delete update], type: ::Array, item_type: ::String +// end + +// def allow?(method) +// @actions.include?(method.downcase) +// end + +// Base async operation type +type Operation struct { + google.YamlValidator + + // Contains information about an long-running operation, to make + // requests for the state of an operation. + + Timeouts Timeouts + + Result Result +} + +// def validate +// check :result, type: Result +// check :timeouts, type: Api::Timeouts +// end + +// Base result class +type Result struct { + google.YamlValidator + + // Contains information about the result of an Operation + + ResourceInsideResponse bool +} + +// def validate +// super +// check :resource_inside_response, type: :boolean, default: false +// end + +// Represents an asynchronous operation definition +type OpAsync struct { + // TODO: Should embed Async or not? + // < Async + + Operation OpAsyncOperation + + Result OpAsyncResult + + Status OpAsyncStatus + + Error OpAsyncError + + // If true, include project as an argument to OperationWaitTime. + // It is intended for resources that calculate project/region from a selflink field + IncludeProject bool `yaml:"include_project"` + + // The list of methods where operations are used. + Actions []string +} + +// def initialize(operation, result, status, error) +// super() +// @operation = operation +// @result = result +// @status = status +// @error = error +// end + +// def validate +// super + +// check :operation, type: Operation, required: true +// check :result, type: Result, default: Result.new +// check :status, type: Status +// check :error, type: Error +// check :actions, default: %w[create delete update], type: ::Array, item_type: ::String +// check :include_project, type: :boolean, default: false +// end + +// The main implementation of Operation, +// corresponding to common GCP Operation resources. +type OpAsyncOperation struct { + // TODO: Should embed Operation or not? + // < Async::Operation + Kind string + + Path string + + BaseUrl string `yaml:"base_url"` + + WaitMs int `yaml:"wait_ms"` + + Timeouts Timeouts + + // Use this if the resource includes the full operation url. + FullUrl string `yaml:"full_url"` +} + +// def initialize(path, base_url, wait_ms, timeouts) +// super() +// @path = path +// @base_url = base_url +// @wait_ms = wait_ms +// @timeouts = timeouts +// end + +// def validate +// super + +// check :kind, type: String +// check :path, type: String +// check :base_url, type: String +// check :wait_ms, type: Integer + +// check :full_url, type: String + +// conflicts %i[base_url full_url] +// end + +// Represents the results of an Operation request +type OpAsyncResult struct { + Result Result `yaml:",inline"` + + Path string +} + +// def initialize(path = nil, resource_inside_response = nil) +// super() +// @path = path +// @resource_inside_response = resource_inside_response +// end + +// def validate +// super + +// check :path, type: String +// end + +// Provides information to parse the result response to check operation +// status +type OpAsyncStatus struct { + google.YamlValidator + + Path string + + Complete bool + + Allowed []bool +} + +// def initialize(path, complete, allowed) +// super() +// @path = path +// @complete = complete +// @allowed = allowed +// end + +// def validate +// super +// check :path, type: String +// check :allowed, type: Array, item_type: [::String, :boolean] +// end + +// Provides information on how to retrieve errors of the executed operations +type OpAsyncError struct { + google.YamlValidator + + Path string + + Message string +} + +// def initialize(path, message) +// super() +// @path = path +// @message = message +// end + +// def validate +// super +// check :path, type: String +// check :message, type: String +// end diff --git a/mmv1/api/object.go b/mmv1/api/object.go new file mode 100644 index 000000000000..5b2edb1f67ca --- /dev/null +++ b/mmv1/api/object.go @@ -0,0 +1,82 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package api + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// require 'google/extensions' +// require 'google/logger' +// require 'google/yaml_validator' + +// Represents an object that has a (mandatory) name +type NamedObject struct { + google.YamlValidator + + Name string + + // original value of :name before the provider override happens + // same as :name if not overridden in provider + ApiName string `yaml:"api_name"` +} + +// func (n *Named) string_array(arr) { +// types = arr.map(&:class).uniq +// types.size == 1 && types[0] == String +// } + +// func (n *Named) deep_merge(arr1, arr2) { +// // Scopes is an array of standard strings. In which case return the +// // version in the overrides. This allows scopes to be removed rather +// // than allowing for a merge of the two arrays +// if string_array?(arr1) +// return arr2.nil? ? arr1 : arr2 +// end + +// // Merge any elements that exist in both +// result = arr1.map do |el1| +// other = arr2.select { |el2| el1.name == el2.name }.first +// other.nil? ? el1 : el1.merge(other) +// end + +// // Add any elements of arr2 that don't exist in arr1 +// result + arr2.reject do |el2| +// arr1.any? { |el1| el2.name == el1.name } +// end +// } + +// func (n *Named) merge(other) { +// result = self.class.new +// instance_variables.each do |v| +// result.instance_variable_set(v, instance_variable_get(v)) +// end + +// other.instance_variables.each do |v| +// if other.instance_variable_get(v).instance_of?(Array) +// result.instance_variable_set(v, deep_merge(result.instance_variable_get(v), +// other.instance_variable_get(v))) +// else +// result.instance_variable_set(v, other.instance_variable_get(v)) +// end +// end + +// result +// } + +// func (n *Named) validate() { +// super +// check :name, type: String, required: true +// check :api_name, type: String, default: @name +// } diff --git a/mmv1/api/product.go b/mmv1/api/product.go new file mode 100644 index 000000000000..f7b7b4235804 --- /dev/null +++ b/mmv1/api/product.go @@ -0,0 +1,207 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package api + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + +// require 'api/object' +// require 'api/product/version' +// require 'google/logger' +// require 'compile/core' +// require 'json' + +// Represents a product to be managed +type Product struct { + NamedObject `yaml:",inline"` + + // include Compile::Core + + // Inherited: + // The name of the product's API capitalised in the appropriate places. + // This isn't just the API name because it doesn't meaningfully separate + // words in the api name - "accesscontextmanager" vs "AccessContextManager" + // Example inputs: "Compute", "AccessContextManager" + // Name string + + // Display Name: The full name of the GCP product; eg "Cloud Bigtable" + + Objects []interface{} + + // The list of permission scopes available for the service + // For example: `https://www.googleapis.com/auth/compute` + + Scopes []string + + // The API versions of this product + + Versions []product.Version + + // The base URL for the service API endpoint + // For example: `https://www.googleapis.com/compute/v1/` + + BaseUrl string `yaml:"base_url"` + + // A function reference designed for the rare case where you + // need to use retries in operation calls. Used for the service api + // as it enables itself (self referential) and can result in occasional + // failures on operation_get. see github.com/hashicorp/terraform-provider-google/issues/9489 + + OperationRetry string `yaml:"operation_retry"` + + Async OpAsync + + LegacyName string `yaml:"legacy_name"` + + ClientName string `yaml:"client_name"` +} + +// def validate +// super +// set_variables @objects, :__product + +// // name comes from Named, and product names must start with a capital +// caps = ('A'..'Z').to_a +// unless caps.include? @name[0] +// raise "product name `//{@name}` must start with a capital letter." +// end + +// check :display_name, type: String +// check :objects, type: Array, item_type: Api::Resource +// check :scopes, type: Array, item_type: String, required: true +// check :operation_retry, type: String + +// check :async, type: Api::Async +// check :legacy_name, type: String +// check :client_name, type: String + +// check :versions, type: Array, item_type: Api::Product::Version, required: true +// end + +// // ==================== +// // Custom Getters +// // ==================== + +// // The name of the product's API; "compute", "accesscontextmanager" +// def api_name +// name.downcase +// end + +// // The product full name is the "display name" in string form intended for +// // users to read in documentation; "Google Compute Engine", "Cloud Bigtable" +// def display_name +// if @display_name.nil? +// name.space_separated +// else +// @display_name +// end +// end + +// // Most general version that exists for the product +// // If GA is present, use that, else beta, else alpha +// def lowest_version +// Version::ORDER.each do |ordered_version_name| +// @versions.each do |product_version| +// return product_version if ordered_version_name == product_version.name +// end +// end +// raise "Unable to find lowest version for product //{display_name}" +// end + +// def version_obj(name) +// @versions.each do |v| +// return v if v.name == name +// end + +// raise "API version '//{name}' does not exist for product '//{@name}'" +// end + +// // Get the version of the object specified by the version given if present +// // Or else fall back to the closest version in the chain defined by Version::ORDER +// def version_obj_or_closest(name) +// return version_obj(name) if exists_at_version(name) + +// // versions should fall back to the closest version to them that exists +// name ||= Version::ORDER[0] +// lower_versions = Version::ORDER[0..Version::ORDER.index(name)] + +// lower_versions.reverse_each do |version| +// return version_obj(version) if exists_at_version(version) +// end + +// raise "Could not find object for version //{name} and product //{display_name}" +// end + +// def exists_at_version_or_lower(name) +// // Versions aren't normally going to be empty since products need a +// // base_url. This nil check exists for atypical products, like _bundle. +// return true if @versions.nil? + +// name ||= Version::ORDER[0] +// return false unless Version::ORDER.include?(name) + +// (0..Version::ORDER.index(name)).each do |i| +// return true if exists_at_version(Version::ORDER[i]) +// end +// false +// end + +// def exists_at_version(name) +// // Versions aren't normally going to be empty since products need a +// // base_url. This nil check exists for atypical products, like _bundle. +// return true if @versions.nil? + +// @versions.any? { |v| v.name == name } +// end + +// // Not a conventional setter, so ignore rubocop's warning +// // rubocop:disable Naming/AccessorMethodName +// def set_properties_based_on_version(version) +// @base_url = version.base_url +// end +// // rubocop:enable Naming/AccessorMethodName + +// // ==================== +// // Debugging Methods +// // ==================== + +// def to_s +// // relies on the custom to_json definitions +// JSON.pretty_generate(self) +// end + +// // Prints a dot notation path to where the field is nested within the parent +// // object when called on a property. eg: parent.meta.label.foo +// // Redefined on Product to terminate the calls up the parent chain. +// def lineage +// name +// end + +// def to_json(opts = nil) +// json_out = {} + +// instance_variables.each do |v| +// if v == :@objects +// json_out['@resources'] = objects.to_h { |o| [o.name, o] } +// elsif instance_variable_get(v) == false || instance_variable_get(v).nil? +// // ignore false or missing because omitting them cleans up result +// // and both are the effective defaults of their types +// else +// json_out[v] = instance_variable_get(v) +// end +// end + +// JSON.generate(json_out, opts) +// end diff --git a/mmv1/api/product.rb b/mmv1/api/product.rb index cd5f11b560c5..66e56c87d6ab 100644 --- a/mmv1/api/product.rb +++ b/mmv1/api/product.rb @@ -51,10 +51,6 @@ class Product < Api::NamedObject # failures on operation_get. see github.com/hashicorp/terraform-provider-google/issues/9489 attr_reader :operation_retry - # The APIs required to be enabled for this product. - # Usually just the product's API - attr_reader :apis_required - attr_reader :async attr_reader :legacy_name diff --git a/mmv1/api/product/version.go b/mmv1/api/product/version.go new file mode 100644 index 000000000000..16027fa61035 --- /dev/null +++ b/mmv1/api/product/version.go @@ -0,0 +1,52 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package product + +// require 'api/object' + +var ORDER = [...]string{"ga", "beta", "alpha", "private"} + +// A version of the API for a given product / API group +// In GCP, different product versions are generally ordered where alpha is +// a superset of beta, and beta a superset of GA. Each version will have a +// different version url. +type Version struct { + // TODO: Should embed NamedObject or not? + // < Api::NamedObject + // include Comparable + + // attr_reader + CaiBaseUrl string `yaml:"cai_base_url"` + + // attr_accessor + BaseUrl string `yaml:"base_url"` + + // attr_accessor + Name string +} + +// def validate +// super +// check :cai_base_url, type: String, required: false +// check :base_url, type: String, required: true +// check :name, type: String, allowed: ORDER, required: true +// end + +// def to_s +// "//{name}: //{base_url}" +// end + +// def <=>(other) +// ORDER.index(name) <=> ORDER.index(other.name) if other.is_a?(Version) +// end diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go new file mode 100644 index 000000000000..75557aaee73b --- /dev/null +++ b/mmv1/api/resource.go @@ -0,0 +1,275 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package api + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/resource" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider/terraform" +) + +type Resource struct { + // Embed NamedObject + NamedObject `yaml:",inline"` + + // [Required] A description of the resource that's surfaced in provider + // documentation. + Description string + + // [Required] (Api::Resource::ReferenceLinks) Reference links provided in + // downstream documentation. + References resource.ReferenceLinks + + // [Required] The GCP "relative URI" of a resource, relative to the product + // base URL. It can often be inferred from the `create` path. + BaseUrl string `yaml:"base_url"` + + // ==================== + // Common Configuration + // ==================== + // + // [Optional] The minimum API version this resource is in. Defaults to ga. + MinVersion string `yaml:"min_version"` + + // [Optional] If set to true, don't generate the resource. + Exclude bool + + // [Optional] If set to true, the resource is not able to be updated. + Immutable bool + + // [Optional] If set to true, this resource uses an update mask to perform + // updates. This is typical of newer GCP APIs. + UpdateMask bool `yaml:"update_mask"` + + // [Optional] If set to true, the object has a `self_link` field. This is + // typical of older GCP APIs. + HasSelfLink bool `yaml:"has_self_link"` + + // [Optional] The validator "relative URI" of a resource, relative to the product + // base URL. Specific to defining the resource as a CAI asset. + CaiBaseUrl string `yaml:"cai_base_url"` + + // ==================== + // URL / HTTP Configuration + // ==================== + // + // [Optional] The "identity" URL of the resource. Defaults to: + // * base_url when the create_verb is :POST + // * self_link when the create_verb is :PUT or :PATCH + SelfLink string `yaml:"self_link"` + + // [Optional] The URL used to creating the resource. Defaults to: + // * collection url when the create_verb is :POST + // * self_link when the create_verb is :PUT or :PATCH + CreateUrl string `yaml:"create_url"` + + // [Optional] The URL used to delete the resource. Defaults to the self + // link. + DeleteUrl string `yaml:"delete_url"` + + // [Optional] The URL used to update the resource. Defaults to the self + // link. + UpdateUrl string `yaml:"update_url"` + // [Optional] The HTTP verb used during create. Defaults to :POST. + CreateVerb string `yaml:"create_verb"` + + // [Optional] The HTTP verb used during read. Defaults to :GET. + ReadVerb string `yaml:"read_verb"` + + // [Optional] The HTTP verb used during update. Defaults to :PUT. + UpdateVerb string `yaml:"update_verb"` + + // [Optional] The HTTP verb used during delete. Defaults to :DELETE. + DeleteVerb string `yaml:"delete_verb"` + + // [Optional] Additional Query Parameters to append to GET. Defaults to "" + ReadQueryParams string `yaml:"read_query_params"` + + // ==================== + // Collection / Identity URL Configuration + // ==================== + // + // [Optional] This is the name of the list of items + // within the collection (list) json. Will default to the + // camelcase plural name of the resource. + CollectionUrlKey string `yaml:"collection_url_key"` + + // [Optional] An ordered list of names of parameters that uniquely identify + // the resource. + // Generally, it's safe to leave empty, in which case it defaults to `name`. + // Other values are normally useful in cases where an object has a parent + // and is identified by some non-name value, such as an ip+port pair. + // If you're writing a fine-grained resource (eg with nested_query) a value + // must be set. + Identity []string + + // [Optional] (Api::Resource::NestedQuery) This is useful in case you need + // to change the query made for GET requests only. In particular, this is + // often used to extract an object from a parent object or a collection. + // Note that if both nested_query and custom_code.decoder are provided, + // the decoder will be included within the code handling the nested query. + NestedQuery resource.NestedQuery `yaml:"nested_query"` + + // ==================== + // IAM Configuration + // ==================== + // + // [Optional] (Api::Resource::IamPolicy) Configuration of a resource's + // resource-specific IAM Policy. + IamPolicy resource.IamPolicy `yaml:"iam_policy"` + + // [Optional] If set to true, don't generate the resource itself; only + // generate the IAM policy. + // TODO rewrite: rename? + ExcludeResource bool `yaml:"exclude_resource"` + + // [Optional] GCP kind, e.g. `compute//disk` + Kind string + + // [Optional] If set to true, indicates that a resource is not configurable + // such as GCP regions. + Readonly bool + + // ==================== + // Terraform Overrides + // ==================== + // [Optional] If non-empty, overrides the full filename prefix + // i.e. google/resource_product_{{resource_filename_override}}.go + // i.e. google/resource_product_{{resource_filename_override}}_test.go + FilenameOverride string `yaml:"filename_override"` + + // If non-empty, overrides the full given resource name. + // i.e. 'google_project' for resourcemanager.Project + // Use Provider::Terraform::Config.legacy_name to override just + // product name. + // Note: This should not be used for vanity names for new products. + // This was added to handle preexisting handwritten resources that + // don't match the natural generated name exactly, and to support + // services with a mix of handwritten and generated resources. + LegacyName string `yaml:"legacy_name"` + + // The Terraform resource id format used when calling //setId(...). + // For instance, `{{name}}` means the id will be the resource name. + IdFormat string `yaml:"id_format"` + + // Override attribute used to handwrite the formats for generating regex strings + // that match templated values to a self_link when importing, only necessary when + // a resource is not adequately covered by the standard provider generated options. + // Leading a token with `%` + // i.e. {{%parent}}/resource/{{resource}} + // will allow that token to hold multiple /'s. + ImportFormat []string `yaml:"import_format"` + + CustomCode terraform.CustomCode `yaml:"custom_code"` + + Docs terraform.Docs + + // This block inserts entries into the customdiff.All() block in the + // resource schema -- the code for these custom diff functions must + // be included in the resource constants or come from tpgresource + CustomDiff []string `yaml:"custom_diff"` + + // Lock name for a mutex to prevent concurrent API calls for a given + // resource. + Mutex string + + // Examples in documentation. Backed by generated tests, and have + // corresponding OiCS walkthroughs. + Examples []terraform.Examples + + // Virtual fields on the Terraform resource. Usage and differences from url_param_only + // are documented in provider/terraform/virtual_fields.rb + VirtualFields interface{} `yaml:"virtual_fields"` + + // If true, generates product operation handling logic. + AutogenAsync bool `yaml:"autogen_async"` + + // If true, resource is not importable + ExcludeImport bool `yaml:"exclude_import"` + + // If true, exclude resource from Terraform Validator + // (i.e. terraform-provider-conversion) + ExcludeTgc bool `yaml:"exclude_tgc"` + + // If true, skip sweeper generation for this resource + SkipSweeper bool `yaml:"skip_sweeper"` + + Timeouts Timeouts + + // An array of function names that determine whether an error is retryable. + ErrorRetryPredicates []string `yaml:"error_retry_predicates"` + + // An array of function names that determine whether an error is not retryable. + ErrorAbortPredicates []string `yaml:"error_abort_predicates"` + + // Optional attributes for declaring a resource's current version and generating + // state_upgrader code to the output .go file from files stored at + // mmv1/templates/terraform/state_migrations/ + // used for maintaining state stability with resources first provisioned on older api versions. + SchemaVersion int `yaml:"schema_version"` + + // From this schema version on, state_upgrader code is generated for the resource. + // When unset, state_upgrade_base_schema_version defauts to 0. + // Normally, it is not needed to be set. + StateUpgradeBaseSchemaVersion int `yaml:"state_upgrade_base_schema_version"` + + StateUpgraders bool `yaml:"state_upgraders"` + + // This block inserts the named function and its attribute into the + // resource schema -- the code for the migrate_state function must + // be included in the resource constants or come from tpgresource + // included for backwards compatibility as an older state migration method + // and should not be used for new resources. + MigrateState string `yaml:"migrate_state"` + + // Set to true for resources that are unable to be deleted, such as KMS keyrings or project + // level resources such as firebase project + SkipDelete bool `yaml:"skip_delete"` + + // Set to true for resources that are unable to be read from the API, such as + // public ca external account keys + SkipRead bool `yaml:"skip_read"` + + // Set to true for resources that wish to disable automatic generation of default provider + // value customdiff functions + // TODO rewrite: 1 instance used + SkipDefaultCdiff bool `yaml:"skip_default_cdiff"` + + // This enables resources that get their project via a reference to a different resource + // instead of a project field to use User Project Overrides + SupportsIndirectUserProjectOverride bool `yaml:"supports_indirect_user_project_override"` + + // If true, the resource's project field can be specified as either the short form project + // id or the long form projects/project-id. The extra projects/ string will be removed from + // urls and ids. This should only be used for resources that previously supported long form + // project ids for backwards compatibility. + LegacyLongFormProject bool `yaml:"legacy_long_form_project"` + + // Function to transform a read error so that handleNotFound recognises + // it as a 404. This should be added as a handwritten fn that takes in + // an error and returns one. + ReadErrorTransform string `yaml:"read_error_transform"` + + // If true, resources that failed creation will be marked as tainted. As a consequence + // these resources will be deleted and recreated on the next apply call. This pattern + // is preferred over deleting the resource directly in post_create_failure hooks. + TaintResourceOnFailedCreate bool `yaml:"taint_resource_on_failed_create"` + + // Add a deprecation message for a resource that's been deprecated in the API. + DeprecationMessage string `yaml:"deprecation_message"` + + Properties []Type + + Parameters []Type +} + +// TODO: rewrite functions diff --git a/mmv1/api/resource/iam_policy.go b/mmv1/api/resource/iam_policy.go new file mode 100644 index 000000000000..1c47394ad0fc --- /dev/null +++ b/mmv1/api/resource/iam_policy.go @@ -0,0 +1,168 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resource + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// Information about the IAM policy for this resource +// Several GCP resources have IAM policies that are scoped to +// and accessed via their parent resource +// See: https://cloud.google.com/iam/docs/overview +type IamPolicy struct { + google.YamlValidator + + // boolean of if this binding should be generated + + // attr_reader + Exclude bool + + // boolean of if this binding should be generated + + // attr_reader + ExcludeTgc bool + + // Boolean of if tests for IAM resources should exclude import test steps + // Used to handle situations where typical generated IAM tests cannot import + // due to the parent resource having an API-generated id + + // attr_reader + SkipImportTest bool + + // Character that separates resource identifier from method call in URL + // For example, PubSub subscription uses {resource}:getIamPolicy + // While Compute subnetwork uses {resource}/getIamPolicy + + // attr_reader + MethodNameSeparator string + + // The terraform type of the parent resource if it is not the same as the + // IAM resource. The IAP product needs these as its IAM policies refer + // to compute resources + + // attr_reader + ParentResourceType string + + // Some resources allow retrieving the IAM policy with GET requests, + // others expect POST requests + + // attr_reader + FetchIamPolicyVerb string + + // Last part of URL for fetching IAM policy. + + // attr_reader + FetchIamPolicyMethod string + + // Some resources allow setting the IAM policy with POST requests, + // others expect PUT requests + + // attr_reader + SetIamPolicyVerb string + + // Last part of URL for setting IAM policy. + + // attr_reader + SetIamPolicyMethod string + + // Whether the policy JSON is contained inside of a 'policy' object. + + // attr_reader + WrappedPolicyObj bool + + // Certain resources allow different sets of roles to be set with IAM policies + // This is a role that is acceptable for the given IAM policy resource for use in tests + + // attr_reader + AllowedIamRole string + + // This is a role that grants create/read/delete for the parent resource for use in tests. + // If set, the test runner will receive a binding to this role in _policy tests in order to + // avoid getting locked out of the resource. + + // attr_reader + AdminIamRole string + + // Certain resources need an attribute other than "id" from their parent resource + // Especially when a parent is not the same type as the IAM resource + + // attr_reader + ParentResourceAttribute string + + // If the IAM resource test needs a new project to be created, this is the name of the project + + // attr_reader + TestProjectName string + + // Resource name may need a custom diff suppress function. Default is to use + // CompareSelfLinkOrResourceName + + // attr_reader + CustomDiffSuppress *string + + // Some resources (IAP) use fields named differently from the parent resource. + // We need to use the parent's attributes to create an IAM policy, but they may not be + // named as the IAM IAM resource expects. + // This allows us to specify a file (relative to MM root) containing a partial terraform + // config with the test/example attributes of the IAM resource. + + // attr_reader + ExampleConfigBody string + + // How the API supports IAM conditions + + // attr_reader + IamConditionsRequestType string + + // Allows us to override the base_url of the resource. This is required for Cloud Run as the + // IAM resources use an entirely different base URL from the actual resource + + // attr_reader + BaseUrl string + + // Allows us to override the import format of the resource. Useful for Cloud Run where we need + // variables that are outside of the base_url qualifiers. + + // attr_reader + ImportFormat []string + + // Allows us to override the self_link of the resource. This is required for Artifact Registry + // to prevent breaking changes + + // attr_reader + SelfLink string + + // [Optional] Version number in the request payload. + // if set, it overrides the default IamPolicyVersion + + // attr_reader + IamPolicyVersion string + + // [Optional] Min version to make IAM resources available at + // If unset, defaults to 'ga' + + // attr_reader + MinVersion string + + // [Optional] Check to see if zone value should be replaced with GOOGLE_ZONE in iam tests + // Defaults to true + + // attr_reader + SubstituteZoneValue bool +} + +// func (p *IamPolicy) validate() { + +// } diff --git a/mmv1/api/resource/nested_query.go b/mmv1/api/resource/nested_query.go new file mode 100644 index 000000000000..9cc55e737037 --- /dev/null +++ b/mmv1/api/resource/nested_query.go @@ -0,0 +1,65 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resource + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// require 'api/object' +// require 'google/string_utils' + +// Metadata for resources that are nested within a parent resource, as +// a list of resources or single object within the parent. +// e.g. Fine-grained resources +type NestedQuery struct { + google.YamlValidator + + // A list of keys to traverse in order. + // i.e. backendBucket --> cdnPolicy.signedUrlKeyNames + // should be ["cdnPolicy", "signedUrlKeyNames"] + + // attr_reader : + Keys []string + + // If true, we expect the the nested list to be + // a list of IDs for the nested resource, rather + // than a list of nested resource objects + // i.e. backendBucket.cdnPolicy.signedUrlKeyNames is a list of key names + // rather than a list of the actual key objects + + // attr_reader : + IsListOfIds bool + + // If true, the resource is created/updated/deleted by patching + // the parent resource and appropriate encoders/update_encoders/pre_delete + // custom code will be included automatically. Only use if parent resource + // does not have a separate endpoint (set as create/delete/update_urls) + // for updating this resource. + // The resulting encoded data will be mapped as + // { + // keys[-1] : list_of_objects + // } + + // attr_reader : + ModifyByPatch bool +} + +// def validate +// super + +// check :keys, type: Array, item_type: String, required: true +// check :is_list_of_ids, type: :boolean, default: false +// check :modify_by_patch, type: :boolean, default: false +// end diff --git a/mmv1/api/resource/reference_links.go b/mmv1/api/resource/reference_links.go new file mode 100644 index 000000000000..6237308ffb4d --- /dev/null +++ b/mmv1/api/resource/reference_links.go @@ -0,0 +1,39 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package resource + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// Represents a list of documentation links. +type ReferenceLinks struct { + google.YamlValidator + + // guides containing + // name: The title of the link + // value: The URL to navigate on click + + //attr_reader + Guides map[string]string + + // the url of the API guide + + //attr_reader + Api string +} + +// func (l *ReferenceLinks) validate() { + +// } diff --git a/mmv1/api/timeouts.go b/mmv1/api/timeouts.go new file mode 100644 index 000000000000..41134697a969 --- /dev/null +++ b/mmv1/api/timeouts.go @@ -0,0 +1,51 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package api + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// require 'api/object' + +// Default timeout for all operation types is 20, the Terraform default (https://www.terraform.io/plugin/sdkv2/resources/retries-and-customizable-timeouts) +// minutes. This can be overridden for each resource. +const DEFAULT_INSERT_TIMEOUT_MINUTES = 20 +const DEFAULT_UPDATE_TIMEOUT_MINUTES = 20 +const DEFAULT_DELETE_TIMEOUT_MINUTES = 20 + +// Provides timeout information for the different operation types +type Timeouts struct { + google.YamlValidator + + InsertMinutes int `yaml:"insert_minutes"` + + UpdateMinutes int `yaml:"update_minutes"` + + DeleteMinutes int `yaml:"delete_minutes"` +} + +// def initialize +// super + +// validate +// end + +// def validate +// super + +// check :insert_minutes, type: Integer, default: DEFAULT_INSERT_TIMEOUT_MINUTES +// check :update_minutes, type: Integer, default: DEFAULT_UPDATE_TIMEOUT_MINUTES +// check :delete_minutes, type: Integer, default: DEFAULT_DELETE_TIMEOUT_MINUTES +// end diff --git a/mmv1/api/type.go b/mmv1/api/type.go new file mode 100644 index 000000000000..b65547f1c9f3 --- /dev/null +++ b/mmv1/api/type.go @@ -0,0 +1,977 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package api + +// require 'api/object' +// require 'google/string_utils' +// require 'provider/terraform/validation' + +// Represents a property type +type Type struct { + NamedObject `yaml:",inline"` + + // TODO: improve the parsing of properties based on type in resource yaml files. + Type string + + // TODO: set a specific type intead of interface{} + DefaultValue interface{} `yaml:"default_value"` + + Description string + + Exclude bool + + // Add a deprecation message for a field that's been deprecated in the API + // use the YAML chomping folding indicator (>-) if this is a multiline + // string, as providers expect a single-line one w/o a newline. + DeprecationMessage string `yaml:"deprecation_message"` + + // Add a removed message for fields no longer supported in the API. This should + // be used for fields supported in one version but have been removed from + // a different version. + RemovedMessage string `yaml:"removed_message"` + + // If set value will not be sent to server on sync. + // For nested fields, this also needs to be set on each descendant (ie. self, + // child, etc.). + Output bool + + // If set to true, changes in the field's value require recreating the + // resource. + // For nested fields, this only applies at the current level. This means + // it should be explicitly added to each field that needs the ForceNew + // behavior. + Immutable bool + + // url_param_only will not send the field in the resource body and will + // not attempt to read the field from the API response. + // NOTE - this doesn't work for nested fields + UrlParamOnly bool `yaml:"url_param_only"` + + // For nested fields, this only applies within the parent. + // For example, an optional parent can contain a required child. + Required bool + + // Additional query Parameters to append to GET calls. + ReadQueryParams string `yaml:"read_query_params"` + + UpdateVerb string `yaml:"update_verb"` + + UpdateUrl string `yaml:"update_url"` + + // Some updates only allow updating certain fields at once (generally each + // top-level field can be updated one-at-a-time). If this is set, we group + // fields to update by (verb, url, fingerprint, id) instead of just + // (verb, url, fingerprint), to allow multiple fields to reuse the same + // endpoints. + UpdateId string `yaml:"update_id"` + + // The fingerprint value required to update this field. Downstreams should + // GET the resource and parse the fingerprint value while doing each update + // call. This ensures we can supply the fingerprint to each distinct + // request. + FingerprintName string `yaml:"fingerprint_name"` + + // If true, we will include the empty value in requests made including + // this attribute (both creates and updates). This rarely needs to be + // set to true, and corresponds to both the "NullFields" and + // "ForceSendFields" concepts in the autogenerated API clients. + SendEmptyValue bool `yaml:"send_empty_value"` + + // [Optional] If true, empty nested objects are sent to / read from the + // API instead of flattened to null. + // The difference between this and send_empty_value is that send_empty_value + // applies when the key of an object is empty; this applies when the values + // are all nil / default. eg: "expiration: null" vs "expiration: {}" + // In the case of Terraform, this occurs when a block in config has optional + // values, and none of them are used. Terraform returns a nil instead of an + // empty map[string]interface{} like we'd expect. + AllowEmptyObject bool `yaml:"allow_empty_object"` + + MinVersion string `yaml:"min_version"` + + ExactVersion string `yaml:"exact_version"` + + // A list of properties that conflict with this property. Uses the "lineage" + // field to identify the property eg: parent.meta.label.foo + Conflicts []string + + // A list of properties that at least one of must be set. + AtLeastOneOf []string `yaml:"at_least_one_of"` + + // A list of properties that exactly one of must be set. + ExactlyOneOf []string `yaml:"exactly_one_of"` + + // A list of properties that are required to be set together. + RequiredWith []string `yaml:"required_with"` + + // Can only be overridden - we should never set this ourselves. + // TODO: set a specific type intead of interface{} + NewType interface{} + + // A pattern that maps expected user input to expected API input. + // TODO: remove? + Pattern string + + Properties []Type + + EnumValues []string `yaml:"enum_values"` + + ItemType string `yaml:"item_type"` + + // ==================== + // Terraform Overrides + // ==================== + + // Adds a DiffSuppressFunc to the schema + DiffSuppressFunc string `yaml:"diff_suppress_func"` + + StateFunc string `yaml:"state_func"` // Adds a StateFunc to the schema + + Sensitive bool // Adds `Sensitive: true` to the schema + + // Does not set this value to the returned API value. Useful for fields + // like secrets where the returned API value is not helpful. + IgnoreRead bool `yaml:"ignore_read"` + + // Adds a ValidateFunc to the schema + Validation bool + + // Indicates that this is an Array that should have Set diff semantics. + UnorderedList bool `yaml:"unordered_list"` + + IsSet bool `yaml:"is_set"` // Uses a Set instead of an Array + + // Optional function to determine the unique ID of an item in the set + // If not specified, schema.HashString (when elements are string) or + // schema.HashSchema are used. + SetHashFunc string `yaml:"set_hash_func"` + + // if true, then we get the default value from the Google API if no value + // is set in the terraform configuration for this field. + // It translates to setting the field to Computed & Optional in the schema. + // For nested fields, this only applies at the current level. This means + // it should be explicitly added to each field that needs the defaulting + // behavior. + DefaultFromApi bool `yaml:"default_from_api"` + + // https://github.com/hashicorp/terraform/pull/20837 + // Apply a ConfigMode of SchemaConfigModeAttr to the field. + // This should be avoided for new fields, and only used with old ones. + SchemaConfigModeAttr bool `yaml:"schema_config_mode_attr"` + + // Names of fields that should be included in the updateMask. + UpdateMaskFields []string `yaml:"update_mask_fields"` + + // For a TypeMap, the expander function to call on the key. + // Defaults to expandString. + KeyExpander string `yaml:"key_expander"` + + // For a TypeMap, the DSF to apply to the key. + KeyDiffSuppressFunc string `yaml:"key_diff_suppress_func"` + + // ==================== + // Schema Modifications + // ==================== + // Schema modifications change the schema of a resource in some + // fundamental way. They're not very portable, and will be hard to + // generate so we should limit their use. Generally, if you're not + // converting existing Terraform resources, these shouldn't be used. + // + // With great power comes great responsibility. + + // Flattens a NestedObject by removing that field from the Terraform + // schema but will preserve it in the JSON sent/retrieved from the API + // + // EX: a API schema where fields are nested (eg: `one.two.three`) and we + // desire the properties of the deepest nested object (eg: `three`) to + // become top level properties in the Terraform schema. By overriding + // the properties `one` and `one.two` and setting flatten_object then + // all the properties in `three` will be at the root of the TF schema. + // + // We need this for cases where a field inside a nested object has a + // default, if we can't spend a breaking change to fix a misshapen + // field, or if the UX is _much_ better otherwise. + // + // WARN: only fully flattened properties are currently supported. In the + // example above you could not flatten `one.two` without also flattening + // all of it's parents such as `one` + FlattenObject bool `yaml:"flatten_object"` + + // =========== + // Custom code + // =========== + // All custom code attributes are string-typed. The string should + // be the name of a template file which will be compiled in the + // specified / described place. + + // A custom expander replaces the default expander for an attribute. + // It is called as part of Create, and as part of Update if + // object.input is false. It can return an object of any type, + // so the function header *is* part of the custom code template. + // As with flatten, `property` and `prefix` are available. + CustomExpand string `yaml:"custom_expand"` + + // A custom flattener replaces the default flattener for an attribute. + // It is called as part of Read. It can return an object of any + // type, and may sometimes need to return an object with non-interface{} + // type so that the d.Set() call will succeed, so the function + // header *is* a part of the custom code template. To help with + // creating the function header, `property` and `prefix` are available, + // just as they are in the standard flattener template. + CustomFlatten string `yaml:"custom_flatten"` + + __resource Resource + + // TODO: set a specific type intead of interface{} + __parent interface{} // is nil for top-level properties +} + +const MAX_NAME = 20 + +// func (t *Type) validate() { +// super +// check :description, type: ::String, required: true +// check :exclude, type: :boolean, default: false, required: true +// check :deprecation_message, type: ::String +// check :removed_message, type: ::String +// check :min_version, type: ::String +// check :exact_version, type: ::String +// check :output, type: :boolean +// check :required, type: :boolean +// check :send_empty_value, type: :boolean +// check :allow_empty_object, type: :boolean +// check :url_param_only, type: :boolean +// check :read_query_params, type: ::String +// check :immutable, type: :boolean + +// raise 'Property cannot be output and required at the same time.' \ +// if @output && @required + +// check :update_verb, type: Symbol, allowed: %i[POST PUT PATCH NONE], +// default: @__resource&.update_verb + +// check :update_url, type: ::String +// check :update_id, type: ::String +// check :fingerprint_name, type: ::String +// check :pattern, type: ::String + +// check_default_value_property +// check_conflicts +// check_at_least_one_of +// check_exactly_one_of +// check_required_with + +// check :sensitive, type: :boolean, default: false +// check :is_set, type: :boolean, default: false +// check :default_from_api, type: :boolean, default: false +// check :unordered_list, type: :boolean, default: false +// check :schema_config_mode_attr, type: :boolean, default: false + +// // technically set as a default everywhere, but only maps will use this. +// check :key_expander, type: ::String, default: 'tpgresource.ExpandString' +// check :key_diff_suppress_func, type: ::String + +// check :diff_suppress_func, type: ::String +// check :state_func, type: ::String +// check :validation, type: Provider::Terraform::Validation +// check :set_hash_func, type: ::String + +// check :custom_flatten, type: ::String +// check :custom_expand, type: ::String + +// raise "'default_value' and 'default_from_api' cannot be both set" \ +// if @default_from_api && !@default_value.nil? +// } + +// func (t *Type) to_s() { +// JSON.pretty_generate(self) +// } + +// Prints a dot notation path to where the field is nested within the parent +// object. eg: parent.meta.label.foo +// The only intended purpose is to allow better error messages. Some objects +// and at some points in the build this doesn't output a valid output. +// func (t *Type) lineage() { +// return name&.underscore if __parent.nil? + +// "//{__parent.lineage}.//{name&.underscore}" +// } + +// Prints the access path of the field in the configration eg: metadata.0.labels +// The only intended purpose is to get the value of the labes field by calling d.Get(). +// func (t *Type) terraform_lineage() { +// return name&.underscore if __parent.nil? || __parent.flatten_object + +// "//{__parent.terraform_lineage}.0.//{name&.underscore}" +// } + +// func (t *Type) to_json(opts) { +// ignore fields that will contain references to parent resources and +// those which will be added later +// ignored_fields = %i[@resource @__parent @__resource @api_name @update_verb +// @__name @name @properties] +// json_out = {} + +// instance_variables.each do |v| +// if v == :@conflicts && instance_variable_get(v).empty? +// // ignore empty conflict arrays +// elsif v == :@at_least_one_of && instance_variable_get(v).empty? +// // ignore empty at_least_one_of arrays +// elsif v == :@exactly_one_of && instance_variable_get(v).empty? +// // ignore empty exactly_one_of arrays +// elsif v == :@required_with && instance_variable_get(v).empty? +// // ignore empty required_with arrays +// elsif instance_variable_get(v) == false || instance_variable_get(v).nil? +// // ignore false booleans as non-existence indicates falsey +// elsif !ignored_fields.include? v +// json_out[v] = instance_variable_get(v) +// end +// end + +// // convert properties to a hash based on name for nested readability +// json_out.merge!(properties&.map { |p| [p.name, p] }.to_h) \ +// if respond_to? 'properties' + +// JSON.generate(json_out, opts) +// } + +// func (t *Type) check_default_value_property() { +// return if @default_value.nil? + +// case self +// when Api::Type::String +// clazz = ::String +// when Api::Type::Integer +// clazz = ::Integer +// when Api::Type::Double +// clazz = ::Float +// when Api::Type::Enum +// clazz = ::Symbol +// when Api::Type::Boolean +// clazz = :boolean +// when Api::Type::ResourceRef +// clazz = [::String, ::Hash] +// else +// raise "Update 'check_default_value_property' method to support " \ +// "default value for type //{self.class}" +// end + +// check :default_value, type: clazz +// } + +// Checks that all conflicting properties actually exist. +// This currently just returns if empty, because we don't want to do the check, since +// this list will have a full path for nested attributes. +// func (t *Type) check_conflicts() { +// check :conflicts, type: ::Array, default: [], item_type: ::String + +// return if @conflicts.empty? +// } + +// Returns list of properties that are in conflict with this property. +// func (t *Type) conflicting() { +// return [] unless @__resource + +// @conflicts +// } + +// Checks that all properties that needs at least one of their fields actually exist. +// This currently just returns if empty, because we don't want to do the check, since +// this list will have a full path for nested attributes. +// func (t *Type) check_at_least_one_of() { +// check :at_least_one_of, type: ::Array, default: [], item_type: ::String + +// return if @at_least_one_of.empty? +// } + +// Returns list of properties that needs at least one of their fields set. +// func (t *Type) at_least_one_of_list() { +// return [] unless @__resource + +// @at_least_one_of +// } + +// Checks that all properties that needs exactly one of their fields actually exist. +// This currently just returns if empty, because we don't want to do the check, since +// this list will have a full path for nested attributes. +// func (t *Type) check_exactly_one_of() { +// check :exactly_one_of, type: ::Array, default: [], item_type: ::String + +// return if @exactly_one_of.empty? +// } + +// Returns list of properties that needs exactly one of their fields set. +// func (t *Type) exactly_one_of_list() { +// return [] unless @__resource + +// @exactly_one_of +// } + +// Checks that all properties that needs required with their fields actually exist. +// This currently just returns if empty, because we don't want to do the check, since +// this list will have a full path for nested attributes. +// func (t *Type) check_required_with() { +// check :required_with, type: ::Array, default: [], item_type: ::String + +// return if @required_with.empty? +// } + +// Returns list of properties that needs required with their fields set. +// func (t *Type) required_with_list() { +// // return [] unless @__resource + +// // @required_with +// } + +// func (t *Type) type() { +// // self.class.name.split('::').last +// } + +// func (t *Type) parent() { +// // @__parent +// } + +// func (t *Type) min_version() { +// // if @min_version.nil? +// // @__resource.min_version +// // else +// // @__resource.__product.version_obj(@min_version) +// // end +// } + +// func (t *Type) exact_version() { +// // return nil if @exact_version.nil? || @exact_version.empty? + +// // @__resource.__product.version_obj(@exact_version) +// } + +// func (t *Type) exclude_if_not_in_version!(version) { +// // @exclude ||= exact_version != version unless exact_version.nil? +// // @exclude ||= version < min_version +// } + +// // Overriding is_a? to enable class overrides. +// // Ruby does not let you natively change types, so this is the next best +// // thing. +// func (t *Type) is_a?(clazz) { +// // return Module.const_get(@new_type).new.is_a?(clazz) if @new_type + +// // super(clazz) +// } + +// // Overriding class to enable class overrides. +// // Ruby does not let you natively change types, so this is the next best +// // thing. +// func (t *Type) class() { +// // return Module.const_get(@new_type) if @new_type + +// // super +// } + +// // Returns nested properties for this property. +// func (t *Type) nested_properties() { +// // nil +// } + +// func (t *Type) removed() { +// // !(@removed_message.nil? || @removed_message == '') +// } + +// func (t *Type) deprecated() { +// // !(@deprecation_message.nil? || @deprecation_message == '') +// } + +// // private + +// // A constant value to be provided as field +// type Constant struct { +// // < Type +// value + +// func (t *Type) validate +// @description = "This is always //{value}." +// super +// end +// } + +// // Represents a primitive (non-composite) type. +// class Primitive < Type +// end + +// // Represents a boolean +// class Boolean < Primitive +// end + +// // Represents an integer +// class Integer < Primitive +// end + +// // Represents a double +// class Double < Primitive +// end + +// // Represents a string +// class String < Primitive +// func (t *Type) initialize(name = nil) +// super() + +// @name = name +// end + +// PROJECT = Api::Type::String.new('project') +// NAME = Api::Type::String.new('name') +// end + +// // Properties that are fetched externally +// class FetchedExternal < Type + +// func (t *Type) validate +// @conflicts ||= [] +// @at_least_one_of ||= [] +// @exactly_one_of ||= [] +// @required_with ||= [] +// end + +// func (t *Type) api_name +// name +// end +// end + +// class Path < Primitive +// end + +// // Represents a fingerprint. A fingerprint is an output-only +// // field used for optimistic locking during updates. +// // They are fetched from the GCP response. +// class Fingerprint < FetchedExternal +// func (t *Type) validate +// super +// @output = true if @output.nil? +// end +// end + +// // Represents a timestamp +// class Time < Primitive +// end + +// // A base class to tag objects that are composed by other objects (arrays, +// // nested objects, etc) +// class Composite < Type +// end + +// // Forwarding declaration to allow defining Array::NESTED_ARRAY_TYPE +// class NestedObject < Composite +// end + +// // Forwarding declaration to allow defining Array::RREF_ARRAY_TYPE +// class ResourceRef < Type +// end + +// // Represents an array, and stores its items' type +// class Array < Composite +// item_type +// min_size +// max_size + +// func (t *Type) validate +// super +// if @item_type.is_a?(NestedObject) || @item_type.is_a?(ResourceRef) +// @item_type.set_variable(@name, :__name) +// @item_type.set_variable(@__resource, :__resource) +// @item_type.set_variable(self, :__parent) +// end +// check :item_type, type: [::String, NestedObject, ResourceRef, Enum], required: true + +// unless @item_type.is_a?(NestedObject) || @item_type.is_a?(ResourceRef) \ +// || @item_type.is_a?(Enum) || type?(@item_type) +// raise "Invalid type //{@item_type}" +// end + +// check :min_size, type: ::Integer +// check :max_size, type: ::Integer +// end + +// func (t *Type) property_class +// case @item_type +// when NestedObject, ResourceRef +// type = @item_type.property_class +// when Enum +// raise 'aaaa' +// else +// type = property_ns_prefix +// type << get_type(@item_type).new(@name).type +// end +// type[-1] = "//{type[-1].camelize(:upper)}Array" +// type +// end + +// func (t *Type) exclude_if_not_in_version!(version) +// super +// @item_type.exclude_if_not_in_version!(version) \ +// if @item_type.is_a? NestedObject +// end + +// func (t *Type) nested_properties +// return @item_type.nested_properties.reject(&:exclude) \ +// if @item_type.is_a?(Api::Type::NestedObject) + +// super +// end + +// func (t *Type) item_type_class +// return @item_type \ +// if @item_type.instance_of?(Class) + +// Object.const_get(@item_type) +// end +// end + +// // Represents an enum, and store is valid values +// class Enum < Primitive +// values +// skip_docs_values + +// func (t *Type) validate +// super +// check :values, type: ::Array, item_type: [Symbol, ::String, ::Integer], required: true +// check :skip_docs_values, type: :boolean +// end + +// func (t *Type) merge(other) +// result = self.class.new +// instance_variables.each do |v| +// result.instance_variable_set(v, instance_variable_get(v)) +// end + +// other.instance_variables.each do |v| +// if other.instance_variable_get(v).instance_of?(Array) +// result.instance_variable_set(v, deep_merge(result.instance_variable_get(v), +// other.instance_variable_get(v))) +// else +// result.instance_variable_set(v, other.instance_variable_get(v)) +// end +// end + +// result +// end +// end + +// // Represents a 'selfLink' property, which returns the URI of the resource. +// class SelfLink < FetchedExternal +// EXPORT_KEY = 'selfLink'.freeze + +// resource + +// func (t *Type) name +// EXPORT_KEY +// end + +// func (t *Type) out_name +// EXPORT_KEY.underscore +// end +// end + +// // Represents a reference to another resource +// class ResourceRef < Type +// // The fields which can be overridden in provider.yaml. +// module Fields +// resource +// imports +// end +// include Fields + +// func (t *Type) validate +// super +// @name = @resource if @name.nil? +// @description = "A reference to //{@resource} resource" \ +// if @description.nil? + +// return if @__resource.nil? || @__resource.exclude || @exclude + +// check :resource, type: ::String, required: true +// check :imports, type: ::String, required: TrueClass + +// // TODO: (camthornton) product reference may not exist yet +// return if @__resource.__product.nil? + +// check_resource_ref_property_exists +// end + +// func (t *Type) property +// props = resource_ref.all_user_properties +// .select { |prop| prop.name == @imports } +// return props.first unless props.empty? +// end + +// func (t *Type) resource_ref +// product = @__resource.__product +// resources = product.objects.select { |obj| obj.name == @resource } + +// resources[0] +// end + +// func (t *Type) property_class +// type = property_ns_prefix +// type << [@resource, @imports, 'Ref'] +// type[-1] = type[-1].join('_').camelize(:upper) +// type +// end + +// private + +// func (t *Type) check_resource_ref_property_exists +// return unless defined?(resource_ref.all_user_properties) + +// exported_props = resource_ref.all_user_properties +// exported_props << Api::Type::String.new('selfLink') \ +// if resource_ref.has_self_link +// raise "'//{@imports}' does not exist on '//{@resource}'" \ +// if exported_props.none? { |p| p.name == @imports } +// end +// end + +// // An structured object composed of other objects. +// class NestedObject < Composite + +// func (t *Type) validate +// @description = 'A nested object resource' if @description.nil? +// @name = @__name if @name.nil? +// super + +// raise "Properties missing on //{name}" if @properties.nil? + +// @properties.each do |p| +// p.set_variable(@__resource, :__resource) +// p.set_variable(self, :__parent) +// end +// check :properties, type: ::Array, item_type: Api::Type, required: true +// end + +// func (t *Type) property_class +// type = property_ns_prefix +// type << [@__resource.name, @name] +// type[-1] = type[-1].join('_').camelize(:upper) +// type +// end + +// // Returns all properties including the ones that are excluded +// // This is used for PropertyOverride validation +// func (t *Type) all_properties +// @properties +// end + +// func (t *Type) properties +// raise "Field '//{lineage}' properties are nil!" if @properties.nil? + +// @properties.reject(&:exclude) +// end + +// func (t *Type) nested_properties +// properties +// end + +// // Returns the list of top-level properties once any nested objects with +// // flatten_object set to true have been collapsed +// func (t *Type) root_properties +// properties.flat_map do |p| +// if p.flatten_object +// p.root_properties +// else +// p +// end +// end +// end + +// func (t *Type) exclude_if_not_in_version!(version) +// super +// @properties.each { |p| p.exclude_if_not_in_version!(version) } +// end +// end + +// // An array of string -> string key -> value pairs, such as labels. +// // While this is technically a map, it's split out because it's a much +// // simpler property to generate and means we can avoid conditional logic +// // in Map. +// class KeyValuePairs < Composite +// // Ignore writing the "effective_labels" and "effective_annotations" fields to API. +// ignore_write + +// func (t *Type) initialize(name: nil, output: nil, api_name: nil, description: nil, min_version: nil, +// ignore_write: nil, update_verb: nil, update_url: nil, immutable: nil) +// super() + +// @name = name +// @output = output +// @api_name = api_name +// @description = description +// @min_version = min_version +// @ignore_write = ignore_write +// @update_verb = update_verb +// @update_url = update_url +// @immutable = immutable +// end + +// func (t *Type) validate +// super +// check :ignore_write, type: :boolean, default: false + +// return if @__resource.__product.nil? + +// product_name = @__resource.__product.name +// resource_name = @__resource.name + +// if lineage == 'labels' || lineage == 'metadata.labels' || +// lineage == 'configuration.labels' +// if !(is_a? Api::Type::KeyValueLabels) && +// // The label value must be empty string, so skip this resource +// !(product_name == 'CloudIdentity' && resource_name == 'Group') && + +// // The "labels" field has type Array, so skip this resource +// !(product_name == 'DeploymentManager' && resource_name == 'Deployment') && + +// // https://github.com/hashicorp/terraform-provider-google/issues/16219 +// !(product_name == 'Edgenetwork' && resource_name == 'Network') && + +// // https://github.com/hashicorp/terraform-provider-google/issues/16219 +// !(product_name == 'Edgenetwork' && resource_name == 'Subnet') && + +// // "userLabels" is the resource labels field +// !(product_name == 'Monitoring' && resource_name == 'NotificationChannel') && + +// // The "labels" field has type Array, so skip this resource +// !(product_name == 'Monitoring' && resource_name == 'MetricDescriptor') +// raise "Please use type KeyValueLabels for field //{lineage} " \ +// "in resource //{product_name}///{resource_name}" +// end +// elsif is_a? Api::Type::KeyValueLabels +// raise "Please don't use type KeyValueLabels for field //{lineage} " \ +// "in resource //{product_name}///{resource_name}" +// end + +// if lineage == 'annotations' || lineage == 'metadata.annotations' +// if !(is_a? Api::Type::KeyValueAnnotations) && +// // The "annotations" field has "ouput: true", so skip this eap resource +// !(product_name == 'Gkeonprem' && resource_name == 'BareMetalAdminClusterEnrollment') +// raise "Please use type KeyValueAnnotations for field //{lineage} " \ +// "in resource //{product_name}///{resource_name}" +// end +// elsif is_a? Api::Type::KeyValueAnnotations +// raise "Please don't use type KeyValueAnnotations for field //{lineage} " \ +// "in resource //{product_name}///{resource_name}" +// end +// end + +// func (t *Type) field_min_version +// @min_version +// end +// end + +// // An array of string -> string key -> value pairs used specifically for the "labels" field. +// // The field name with this type should be "labels" literally. +// class KeyValueLabels < KeyValuePairs +// func (t *Type) validate +// super +// return unless @name != 'labels' + +// raise "The field //{name} has the type KeyValueLabels, but the field name is not 'labels'!" +// end +// end + +// // An array of string -> string key -> value pairs used for the "terraform_labels" field. +// class KeyValueTerraformLabels < KeyValuePairs +// end + +// // An array of string -> string key -> value pairs used for the "effective_labels" +// // and "effective_annotations" fields. +// class KeyValueEffectiveLabels < KeyValuePairs +// end + +// // An array of string -> string key -> value pairs used specifically for the "annotations" field. +// // The field name with this type should be "annotations" literally. +// class KeyValueAnnotations < KeyValuePairs +// func (t *Type) validate +// super +// return unless @name != 'annotations' + +// raise "The field //{name} has the type KeyValueAnnotations,\ +// but the field name is not 'annotations'!" +// end +// end + +// // Map from string keys -> nested object entries +// class Map < Composite +// // .yaml. +// module Fields +// // The type definition of the contents of the map. +// value_type + +// // While the API doesn't give keys an explicit name, we specify one +// // because in Terraform the key has to be a property of the object. +// // +// // The name of the key. Used in the Terraform schema as a field name. +// key_name + +// // A description of the key's format. Used in Terraform to describe +// // the field in documentation. +// key_description +// end +// include Fields + +// func (t *Type) validate +// super +// check :key_name, type: ::String, required: true +// check :key_description, type: ::String + +// @value_type.set_variable(@name, :__name) +// @value_type.set_variable(@__resource, :__resource) +// @value_type.set_variable(self, :__parent) +// check :value_type, type: Api::Type::NestedObject, required: true +// raise "Invalid type //{@value_type}" unless type?(@value_type) +// end + +// func (t *Type) nested_properties +// @value_type.nested_properties.reject(&:exclude) +// end +// end + +// // Support for schema ValidateFunc functionality. +// class Validation < Object +// // Ensures the value matches this regex +// regex +// function + +// func (t *Type) validate +// super + +// check :regex, type: String +// check :function, type: String +// end +// end + +// func (t *Type) type?(type) +// type.is_a?(Type) || !get_type(type).nil? +// end + +// func (t *Type) get_type(type) +// Module.const_get(type) +// end + +// func (t *Type) property_ns_prefix +// [ +// 'Google', +// @__resource.__product.name.camelize(:upper), +// 'Property' +// ] +// end +// end diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 4767f53c5f6d..9b2160026bc4 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -177,7 +177,8 @@ resources = [] Dir["#{product_name}/*"].each do |file_path| next if File.basename(file_path) == 'product.yaml' \ - || File.extname(file_path) != '.yaml' + || File.extname(file_path) != '.yaml' \ + || File.basename(file_path).include?('go_') if override_dir # Skip if resource will be merged in the override loop @@ -197,7 +198,8 @@ ovr_prod_dir = File.join(override_dir, product_name) Dir["#{ovr_prod_dir}/*"].each do |override_path| next if File.basename(override_path) == 'product.yaml' \ - || File.extname(override_path) != '.yaml' + || File.extname(override_path) != '.yaml' \ + || File.basename(file_path).include?('go_') file_path = File.join(product_name, File.basename(override_path)) res_yaml = if File.exist?(file_path) diff --git a/mmv1/go.mod b/mmv1/go.mod new file mode 100644 index 000000000000..e9a5cebeee40 --- /dev/null +++ b/mmv1/go.mod @@ -0,0 +1,5 @@ +module github.com/GoogleCloudPlatform/magic-modules/mmv1 + +go 1.20 + +require gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/mmv1/go.sum b/mmv1/go.sum new file mode 100644 index 000000000000..75346616b19b --- /dev/null +++ b/mmv1/go.sum @@ -0,0 +1,3 @@ +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/mmv1/google/yaml_validator.go b/mmv1/google/yaml_validator.go new file mode 100644 index 000000000000..282b43b5f41e --- /dev/null +++ b/mmv1/google/yaml_validator.go @@ -0,0 +1,155 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google + +import ( + "log" + + "gopkg.in/yaml.v2" +) + +// A helper class to validate contents coming from YAML files. +type YamlValidator struct{} + +func (v *YamlValidator) Parse(content []byte, obj interface{}) { + // TODO(nelsonjr): Allow specifying which symbols to restrict it further. + // But it requires inspecting all configuration files for symbol sources, + // such as Enum values. Leaving it as a nice-to-have for the future. + if err := yaml.Unmarshal(content, obj); err != nil { + log.Fatalf("Cannot unmarshal data: %v", err) + } +} + +// func (v *YamlValidator) allowed_classes() { +// ObjectSpace.each_object(Class).select do |klass| +// klass < Google::YamlValidator +// end.push(Time, Symbol) +// } + +// func (v *YamlValidator) validate() { +// Google::LOGGER.debug "Validating //{self.class} '//{@name}'" +// check_extraneous_properties +// } + +// func (v *YamlValidator) set_variable(value, property) { +// Google::LOGGER.debug "Setting variable of //{value} to //{self}" +// instance_variable_set("@//{property}", value) +// } + +// Does all validation checking for a particular variable. +// options: +// :default - the default value for this variable if its nil +// :type - the allowed types (single or array) that this value can be +// :item_type - the allowed types that all values in this array should be +// (implied that type == array) +// :allowed - the allowed values that this non-array variable should be. +// :required - is the variable required? (defaults: false) +// func (v *YamlValidator) check(variable, **opts) { +// value = instance_variable_get("@//{variable}") + +// // Set default value. +// if !opts[:default].nil? && value.nil? +// instance_variable_set("@//{variable}", opts[:default]) +// value = instance_variable_get("@//{variable}") +// end + +// // Check if value is required. Print nested path if available. +// lineage_path = respond_to?('lineage') ? lineage : '' +// raise "//{lineage_path} > Missing '//{variable}'" if value.nil? && opts[:required] +// return if value.nil? + +// // Check type +// check_property_value(variable, value, opts[:type]) if opts[:type] + +// // Check item_type +// if value.is_a?(Array) +// raise "//{lineage_path} > //{variable} must have item_type on arrays" unless opts[:item_type] + +// value.each_with_index do |o, index| +// check_property_value("//{variable}[//{index}]", o, opts[:item_type]) +// end +// end + +// // Check if value is allowed +// return unless opts[:allowed] +// raise "//{value} on //{variable} should be one of //{opts[:allowed]}" \ +// unless opts[:allowed].include?(value) +// } + +// func (v *YamlValidator) conflicts(list) { +// value_checked = false +// list.each do |item| +// next if instance_variable_get("@//{item}").nil? +// raise "//{list.join(',')} cannot be set at the same time" if value_checked + +// value_checked = true +// end +// } + +// private + +// func (v *YamlValidator) check_type(name, object, type) { +// if type == :boolean +// return unless [TrueClass, FalseClass].find_index(object.class).nil? +// elsif type.is_a? ::Array +// return if type.find_index(:boolean) && [TrueClass, FalseClass].find_index(object.class) +// return unless type.find_index(object.class).nil? +// // check if class is or inherits from type +// elsif object.class <= type +// return +// end +// raise "Property '//{name}' is '//{object.class}' instead of '//{type}'" +// } + +// func (v *YamlValidator) log_check_type(object) { +// if object.respond_to?(:name) +// Google::LOGGER.debug "Checking object //{object.name}" +// else +// Google::LOGGER.debug "Checking object //{object}" +// end +// } + +// func (v *YamlValidator) check_property_value(property, prop_value, type) { +// Google::LOGGER.debug "Checking '//{property}' on //{object_display_name}" +// check_type property, prop_value, type unless type.nil? +// prop_value.validate if prop_value.is_a?(Api::Object) +// } + +// func (v *YamlValidator) check_extraneous_properties() { +// instance_variables.each do |variable| +// var_name = variable.id2name[1..] +// next if var_name.start_with?('__') + +// Google::LOGGER.debug "Validating '//{var_name}' on //{object_display_name}" +// raise "Extraneous variable '//{var_name}' in //{object_display_name}" \ +// unless methods.include?(var_name.intern) +// end +// } + +// func (v *YamlValidator) set_variables(objects, property) { +// return if objects.nil? + +// objects.each do |object| +// object.set_variable(self, property) if object.respond_to?(:set_variable) +// end +// } + +// func (v *YamlValidator) ensure_property_does_not_exist(property) { +// raise "Conflict of property '//{property}' for object '//{self}'" \ +// unless instance_variable_get("@//{property}").nil? +// } + +// func (v *YamlValidator) object_display_name() { +// "//{@name}" +// } diff --git a/mmv1/main.go b/mmv1/main.go new file mode 100644 index 000000000000..a7726a9a22f1 --- /dev/null +++ b/mmv1/main.go @@ -0,0 +1,108 @@ +package main + +import ( + "encoding/json" + "fmt" + "log" + "os" + "path" + "path/filepath" + "sort" + "strings" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +func main() { + var products_to_generate []string + var all_products = true + + var all_product_files []string = make([]string, 0) + + files, err := filepath.Glob("products/**/product.yaml") + if err != nil { + return + } + for _, file_path := range files { + dir := filepath.Dir(file_path) + all_product_files = append(all_product_files, fmt.Sprintf("products/%s", filepath.Base(dir))) + } + + if all_products { + products_to_generate = all_product_files + } + + if products_to_generate == nil || len(products_to_generate) == 0 { + log.Fatalf("No product.yaml file found.") + } + + // Building compute takes a long time and can't be parallelized within the product + // so lets build it first + sort.Slice(all_product_files, func(i int, j int) bool { + if all_product_files[i] == "compute" { + return true + } + return false + }) + + yamlValidator := google.YamlValidator{} + + for _, product_name := range all_product_files { + product_yaml_path := path.Join(product_name, "go_product.yaml") + + // TODO: uncomment the error check that if the product.yaml exists for each product + // after Go-converted product.yaml files are complete for all products + + // if _, err := os.Stat(product_yaml_path); errors.Is(err, os.ErrNotExist) { + // log.Fatalf("%s does not contain a product.yaml file", product_name) + // } + + if _, err := os.Stat(product_yaml_path); err == nil { + log.Printf("product_yaml_path %#v", product_yaml_path) + + productYaml, err := os.ReadFile(product_yaml_path) + if err != nil { + log.Fatalf("Cannot open the file: %v", productYaml) + } + productApi := api.Product{} + yamlValidator.Parse(productYaml, &productApi) + + // TODO: remove these lines, which are for debugging + prod, _ := json.Marshal(&productApi) + log.Printf("prod %s", string(prod)) + + resourceFiles, err := filepath.Glob(fmt.Sprintf("%s/*", product_name)) + if err != nil { + log.Fatalf("Cannot get resources files: %v", err) + } + for _, resourceYamlPath := range resourceFiles { + if filepath.Base(resourceYamlPath) == "product.yaml" || filepath.Ext(resourceYamlPath) != ".yaml" { + continue + } + + // TODO REMOVE: limiting test block + // if !strings.Contains(resourceYamlPath, "datafusion") { + // continue + // } + + // Prepend "go_" to the Go yaml files' name to distinguish with the ruby yaml files + if filepath.Base(resourceYamlPath) == "go_product.yaml" || !strings.HasPrefix(filepath.Base(resourceYamlPath), "go_") { + continue + } + + log.Printf(" resourceYamlPath %s", resourceYamlPath) + resourceYaml, err := os.ReadFile(resourceYamlPath) + if err != nil { + log.Fatalf("Cannot open the file: %v", resourceYamlPath) + } + resource := api.Resource{} + yamlValidator.Parse(resourceYaml, &resource) + + // TODO: remove these lines, which are for debugging + res, _ := json.Marshal(&resource) + log.Printf("resource %s", string(res)) + } + } + } +} diff --git a/mmv1/products/datafusion/go_instance.yaml b/mmv1/products/datafusion/go_instance.yaml new file mode 100644 index 000000000000..729cf2079292 --- /dev/null +++ b/mmv1/products/datafusion/go_instance.yaml @@ -0,0 +1,298 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +name: 'Instance' +description: | + Represents a Data Fusion instance. +references: + guides: + 'Official Documentation': 'https://cloud.google.com/data-fusion/docs/' + api: 'https://cloud.google.com/data-fusion/docs/reference/rest/v1beta1/projects.locations.instances' +docs: +base_url: 'projects/{{project}}/locations/{{region}}/instances' +create_url: 'projects/{{project}}/locations/{{region}}/instances?instanceId={{name}}' +update_verb: 'PATCH' +timeouts: + insert_minutes: 90 + update_minutes: 25 + delete_minutes: 50 +autogen_async: true +async: + operation: + base_url: '{{op_id}}' + path: 'name' + wait_ms: 1000 + result: + path: 'response' + resource_inside_response: true + error: + path: 'error' + message: 'message' +iam_policy: + method_name_separator: ':' + parent_resource_attribute: 'name' + import_format: + - 'projects/{{project}}/locations/{{location}}/instances/{{name}}' + - '{{name}}' +custom_code: + constants: 'templates/terraform/constants/data_fusion_instance_option.go.erb' + pre_update: 'templates/terraform/pre_update/datafusion_instance_update.go.erb' +examples: + - name: 'data_fusion_instance_basic' + primary_resource_id: 'basic_instance' + primary_resource_name: 'basic_instance' + vars: + instance_name: 'my-instance' + prober_test_run: '' + test_vars_overrides: + 'prober_test_run': '`options = { prober_test_run = "true" }`' + - name: 'data_fusion_instance_full' + primary_resource_id: 'extended_instance' + primary_resource_name: 'extended_instance' + vars: + instance_name: 'my-instance' + ip_alloc: 'datafusion-ip-alloc' + network_name: 'datafusion-full-network' + prober_test_run: '' + test_vars_overrides: + 'prober_test_run': '`options = { prober_test_run = "true" }`' + - name: 'data_fusion_instance_cmek' + primary_resource_id: 'cmek' + primary_resource_name: 'cmek' + vars: + instance_name: 'my-instance' + - name: 'data_fusion_instance_enterprise' + primary_resource_id: 'enterprise_instance' + primary_resource_name: 'enterprise_instance' + vars: + instance_name: 'my-instance' + prober_test_run: '' + test_vars_overrides: + 'prober_test_run': '`options = { prober_test_run = "true" }`' + - name: 'data_fusion_instance_event' + primary_resource_id: 'event' + primary_resource_name: 'event' + vars: + instance_name: 'my-instance' + - name: 'data_fusion_instance_zone' + primary_resource_id: 'zone' + primary_resource_name: 'zone' + vars: + instance_name: 'my-instance' +parameters: + - name: 'region' + type: String + description: "The region of the Data Fusion instance." + url_param_only: true + required: false + immutable: true + ignore_read: true + default_from_api: true +properties: + - name: 'name' + type: String + description: "The ID of the instance or a fully qualified identifier for the instance." + required: true + immutable: true + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + custom_expand: 'templates/terraform/custom_expand/shortname_to_url.go.erb' + - name: 'description' + type: String + description: "An optional description of the instance." + immutable: true + - name: 'type' + type: Enum + description: "Represents the type of Data Fusion instance. Each type is configured with +the default settings for processing and memory. +- BASIC: Basic Data Fusion instance. In Basic type, the user will be able to create data pipelines +using point and click UI. However, there are certain limitations, such as fewer number +of concurrent pipelines, no support for streaming pipelines, etc. +- ENTERPRISE: Enterprise Data Fusion instance. In Enterprise type, the user will have more features +available, such as support for streaming pipelines, higher number of concurrent pipelines, etc. +- DEVELOPER: Developer Data Fusion instance. In Developer type, the user will have all features available but +with restrictive capabilities. This is to help enterprises design and develop their data ingestion and integration +pipelines at low cost." + required: true + immutable: true + enum_values: + - 'BASIC' + - 'ENTERPRISE' + - 'DEVELOPER' + - name: 'enableStackdriverLogging' + type: Boolean + description: "Option to enable Stackdriver Logging." + - name: 'enableStackdriverMonitoring' + type: Boolean + description: "Option to enable Stackdriver Monitoring." + - name: 'enableRbac' + type: Boolean + description: "Option to enable granular role-based access control." + - name: 'labels' + type: KeyValueLabels + description: "The resource labels for instance to use to annotate any related underlying resources, +such as Compute Engine VMs. + + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field `effective_labels` for all of the labels present on the resource." + immutable: false + - name: 'options' + type: KeyValuePairs + description: "Map of additional options used to configure the behavior of Data Fusion instance." + immutable: true + default_from_api: true + diff_suppress_func: 'instanceOptionsDiffSuppress' + - name: 'createTime' + type: String + description: "The time the instance was created in RFC3339 UTC 'Zulu' format, accurate to nanoseconds." + output: true + - name: 'updateTime' + type: String + description: "The time the instance was last updated in RFC3339 UTC 'Zulu' format, accurate to nanoseconds." + output: true + - name: 'state' + type: Enum + description: "The current state of this Data Fusion instance. +- CREATING: Instance is being created +- RUNNING: Instance is running and ready for requests +- FAILED: Instance creation failed +- DELETING: Instance is being deleted +- UPGRADING: Instance is being upgraded +- RESTARTING: Instance is being restarted" + output: true + enum_values: + - 'CREATING' + - 'RUNNING' + - 'FAILED' + - 'DELETING' + - 'UPGRADING' + - 'RESTARTING' + - name: 'stateMessage' + type: String + description: "Additional information about the current state of this Data Fusion instance if available." + output: true + - name: 'serviceEndpoint' + type: String + description: "Endpoint on which the Data Fusion UI and REST APIs are accessible." + output: true + - name: 'version' + type: String + description: "Current version of the Data Fusion." + default_from_api: true + - name: 'serviceAccount' + type: String + description: "Service account which will be used to access resources in the customer project." + min_version: 'beta' + output: true + deprecation_message: '`service_account` is deprecated and will be removed in a future major release. Instead, use `tenant_project_id` to extract the tenant project ID.' + - name: 'privateInstance' + type: Boolean + description: "Specifies whether the Data Fusion instance should be private. If set to +true, all Data Fusion nodes will have private IP addresses and will not be +able to access the public internet." + immutable: true + - name: 'dataprocServiceAccount' + type: String + description: "User-managed service account to set on Dataproc when Cloud Data Fusion creates Dataproc to run data processing pipelines." + immutable: true + - name: 'tenantProjectId' + type: String + description: "The name of the tenant project." + output: true + - name: 'gcsBucket' + type: String + description: "Cloud Storage bucket generated by Data Fusion in the customer project." + output: true + - name: 'networkConfig' + type: NestedObject + description: "Network configuration options. These are required when a private Data Fusion instance is to be created." + immutable: true + properties: + - name: 'ipAllocation' + type: String + description: "The IP range in CIDR notation to use for the managed Data Fusion instance + nodes. This range must not overlap with any other ranges used in the Data Fusion instance network." + required: true + immutable: true + - name: 'network' + type: String + description: "Name of the network in the project with which the tenant project + will be peered for executing pipelines. In case of shared VPC where the network resides in another host + project the network should specified in the form of projects/{host-project-id}/global/networks/{network}" + required: true + immutable: true + - name: 'zone' + type: String + description: "Name of the zone in which the Data Fusion instance will be created. Only DEVELOPER instances use this field." + immutable: true + default_from_api: true + - name: 'displayName' + type: String + description: "Display name for an instance." + immutable: true + - name: 'apiEndpoint' + type: String + description: "Endpoint on which the REST APIs is accessible." + output: true + - name: 'p4ServiceAccount' + type: String + description: "P4 service account for the customer project." + output: true + - name: 'cryptoKeyConfig' + type: NestedObject + description: "The crypto key configuration. This field is used by the Customer-Managed Encryption Keys (CMEK) feature." + immutable: true + properties: + - name: 'keyReference' + type: String + description: "The name of the key which is used to encrypt/decrypt customer data. For key in Cloud KMS, the key should be in the format of projects/*/locations/*/keyRings/*/cryptoKeys/*." + required: true + immutable: true + - name: 'eventPublishConfig' + type: NestedObject + description: "Option to enable and pass metadata for event publishing." + properties: + - name: 'enabled' + type: Boolean + description: "Option to enable Event Publishing." + required: true + - name: 'topic' + type: String + description: "The resource name of the Pub/Sub topic. Format: projects/{projectId}/topics/{topic_id}" + required: true + immutable: true + - name: 'accelerators' + type: Array + description: "List of accelerators enabled for this CDF instance. + +If accelerators are enabled it is possible a permadiff will be created with the Options field. +Users will need to either manually update their state file to include these diffed options, or include the field in a [lifecycle ignore changes block](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes)." + item_type: NestedObject + properties: + - name: 'acceleratorType' + type: Enum + description: "The type of an accelator for a CDF instance." + required: true + enum_values: + - 'CDC' + - 'HEALTHCARE' + - 'CCAI_INSIGHTS' + - name: 'state' + type: Enum + description: "The type of an accelator for a CDF instance." + required: true + enum_values: + - 'ENABLED' + - 'DISABLED' diff --git a/mmv1/products/datafusion/go_product.yaml b/mmv1/products/datafusion/go_product.yaml new file mode 100644 index 000000000000..69c8c197dddc --- /dev/null +++ b/mmv1/products/datafusion/go_product.yaml @@ -0,0 +1,35 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +name: 'DataFusion' +display_name: 'Cloud Data Fusion' +versions: + - name: 'beta' + base_url: 'https://datafusion.googleapis.com/v1beta1/' + - name: 'ga' + base_url: 'https://datafusion.googleapis.com/v1/' +scopes: + - 'https://www.googleapis.com/auth/cloud-platform' +async: + operation: + base_url: '{{op_id}}' + path: 'name' + wait_ms: 1000 + result: + path: 'response' + resource_inside_response: true + error: + path: 'error' + message: 'message' diff --git a/mmv1/products/pubsub/go_Schema.yaml b/mmv1/products/pubsub/go_Schema.yaml new file mode 100644 index 000000000000..edcdbbd7d7d5 --- /dev/null +++ b/mmv1/products/pubsub/go_Schema.yaml @@ -0,0 +1,84 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +name: 'Schema' +description: | + A schema is a format that messages must follow, + creating a contract between publisher and subscriber that Pub/Sub will enforce. +references: + guides: + 'Creating and managing schemas': 'https://cloud.google.com/pubsub/docs/schemas' + api: 'https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.schemas' +docs: +base_url: 'projects/{{project}}/schemas' +create_url: 'projects/{{project}}/schemas?schemaId={{name}}' +update_url: 'projects/{{project}}/schemas/{{name}}:commit' +update_verb: 'POST' +update_mask: false +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +async: + check_response_func_existence: 'transport_tpg.PollCheckForExistence' + check_response_func_absence: 'transport_tpg.PollCheckForAbsence' + suppress_error: false + target_occurrences: 10 +iam_policy: + method_name_separator: ':' + parent_resource_attribute: 'schema' +custom_code: + update_encoder: 'templates/terraform/update_encoder/pubsub_schema.erb' +examples: + - name: 'pubsub_schema_basic' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + schema_name: 'example-schema' + - name: 'pubsub_schema_protobuf' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + schema_name: 'example' + test_env_vars: + project_name: 'PROJECT_NAME' +parameters: + - name: 'name' + type: String + description: "The ID to use for the schema, which will become the final component of the schema's resource name." + required: true + immutable: true + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + custom_expand: 'templates/terraform/custom_expand/resource_from_self_link.go.erb' +properties: + - name: 'type' + type: Enum + description: "The type of the schema definition" + default_value: TYPE_UNSPECIFIED + enum_values: + - 'TYPE_UNSPECIFIED' + - 'PROTOCOL_BUFFER' + - 'AVRO' + - '' + - name: 'definition' + type: String + description: "The definition of the schema. +This should contain a string representing the full definition of the schema +that is a valid schema definition of the type specified in type. Changes +to the definition commit new [schema revisions](https://cloud.google.com/pubsub/docs/commit-schema-revision). +A schema can only have up to 20 revisions, so updates that fail with an +error indicating that the limit has been reached require manually +[deleting old revisions](https://cloud.google.com/pubsub/docs/delete-schema-revision)." diff --git a/mmv1/products/pubsub/go_Subscription.yaml b/mmv1/products/pubsub/go_Subscription.yaml new file mode 100644 index 000000000000..ad7bd11d8ddd --- /dev/null +++ b/mmv1/products/pubsub/go_Subscription.yaml @@ -0,0 +1,420 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +name: 'Subscription' +description: | + A named resource representing the stream of messages from a single, + specific topic, to be delivered to the subscribing application. +references: + guides: + 'Managing Subscriptions': 'https://cloud.google.com/pubsub/docs/admin#managing_subscriptions' + api: 'https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions' +docs: + note: 'You can retrieve the email of the Google Managed Pub/Sub Service Account used for forwarding +by using the `google_project_service_identity` resource. +' +base_url: 'projects/{{project}}/subscriptions' +create_verb: 'PUT' +update_url: 'projects/{{project}}/subscriptions/{{name}}' +update_verb: 'PATCH' +update_mask: true +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +async: + check_response_func_existence: 'transport_tpg.PollCheckForExistence' + check_response_func_absence: 'transport_tpg.PollCheckForAbsence' + suppress_error: true + target_occurrences: 1 +custom_code: + constants: 'templates/terraform/constants/subscription.go.erb' + encoder: 'templates/terraform/encoders/no_send_name.go.erb' + update_encoder: 'templates/terraform/update_encoder/pubsub_subscription.erb' +examples: + - name: 'pubsub_subscription_push' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + - name: 'pubsub_subscription_pull' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + - name: 'pubsub_subscription_dead_letter' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + - name: 'pubsub_subscription_push_bq' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + dataset_id: 'example_dataset' + table_id: 'example_table' + - name: 'pubsub_subscription_push_bq_table_schema' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + dataset_id: 'example_dataset' + table_id: 'example_table' + - name: 'pubsub_subscription_push_cloudstorage' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + bucket_name: 'example-bucket' + - name: 'pubsub_subscription_push_cloudstorage_avro' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + bucket_name: 'example-bucket' +parameters: +properties: + - name: 'name' + type: String + description: "Name of the subscription." + pattern: 'projects/{{project}}/subscriptions/{{name}}' + required: true + immutable: true + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + custom_expand: 'templates/terraform/custom_expand/shortname_to_url.go.erb' + - name: 'topic' + type: ResourceRef + description: "A reference to a Topic resource, of the form projects/{project}/topics/{{name}} +(as in the id property of a google_pubsub_topic), or just a topic name if +the topic is in the same project as the subscription." + pattern: 'projects/{{project}}/topics/{{topic}}' + required: true + immutable: true + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + custom_expand: 'templates/terraform/custom_expand/computed_subscription_topic.erb' + resource: 'Topic' + imports: 'name' + - name: 'labels' + type: KeyValueLabels + description: "A set of key/value label pairs to assign to this Subscription. + + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field `effective_labels` for all of the labels present on the resource." + immutable: false + - name: 'bigqueryConfig' + type: NestedObject + description: "If delivery to BigQuery is used with this subscription, this field is used to configure it. +Either pushConfig, bigQueryConfig or cloudStorageConfig can be set, but not combined. +If all three are empty, then the subscriber will pull and ack messages using API methods." + conflicts: + - push_config + - cloud_storage_config + properties: + - name: 'table' + type: String + description: "The name of the table to which to write data, of the form {projectId}:{datasetId}.{tableId}" + required: true + - name: 'useTopicSchema' + type: Boolean + description: "When true, use the topic's schema as the columns to write to in BigQuery, if it exists. + Only one of use_topic_schema and use_table_schema can be set." + conflicts: + - use_table_schema + - name: 'useTableSchema' + type: Boolean + description: "When true, use the BigQuery table's schema as the columns to write to in BigQuery. Messages + must be published in JSON format. Only one of use_topic_schema and use_table_schema can be set." + conflicts: + - use_topic_schema + - name: 'writeMetadata' + type: Boolean + description: "When true, write the subscription name, messageId, publishTime, attributes, and orderingKey to additional columns in the table. + The subscription name, messageId, and publishTime fields are put in their own columns while all other message properties (other than data) are written to a JSON object in the attributes column." + - name: 'dropUnknownFields' + type: Boolean + description: "When true and use_topic_schema or use_table_schema is true, any fields that are a part of the topic schema or message schema that + are not part of the BigQuery table schema are dropped when writing to BigQuery. Otherwise, the schemas must be kept in sync + and any messages with extra fields are not written and remain in the subscription's backlog." + - name: 'cloudStorageConfig' + type: NestedObject + description: "If delivery to Cloud Storage is used with this subscription, this field is used to configure it. +Either pushConfig, bigQueryConfig or cloudStorageConfig can be set, but not combined. +If all three are empty, then the subscriber will pull and ack messages using API methods." + conflicts: + - push_config + - bigquery_config + properties: + - name: 'bucket' + type: String + description: "User-provided name for the Cloud Storage bucket. The bucket must be created by the user. The bucket name must be without any prefix like 'gs://'." + required: true + - name: 'filenamePrefix' + type: String + description: "User-provided prefix for Cloud Storage filename." + - name: 'filenameSuffix' + type: String + description: "User-provided suffix for Cloud Storage filename. Must not end in '/'." + - name: 'maxDuration' + type: String + description: "The maximum duration that can elapse before a new Cloud Storage file is created. Min 1 minute, max 10 minutes, default 5 minutes. + May not exceed the subscription's acknowledgement deadline. + A duration in seconds with up to nine fractional digits, ending with 's'. Example: '3.5s'." + default_value: 300s + - name: 'maxBytes' + type: Integer + description: "The maximum bytes that can be written to a Cloud Storage file before a new file is created. Min 1 KB, max 10 GiB. + The maxBytes limit may be exceeded in cases where messages are larger than the limit." + - name: 'state' + type: Enum + description: "An output-only field that indicates whether or not the subscription can receive messages." + output: true + enum_values: + - 'ACTIVE' + - 'PERMISSION_DENIED' + - 'NOT_FOUND' + - name: 'avroConfig' + type: NestedObject + description: "If set, message data will be written to Cloud Storage in Avro format." + properties: + - name: 'writeMetadata' + type: Boolean + description: "When true, write the subscription name, messageId, publishTime, attributes, and orderingKey as additional fields in the output." + - name: 'pushConfig' + type: NestedObject + description: "If push delivery is used with this subscription, this field is used to +configure it. An empty pushConfig signifies that the subscriber will +pull and ack messages using API methods." + conflicts: + - bigquery_config + - cloud_storage_config + properties: + - name: 'oidcToken' + type: NestedObject + description: "If specified, Pub/Sub will generate and attach an OIDC JWT token as + an Authorization header in the HTTP request for every pushed message." + properties: + - name: 'serviceAccountEmail' + type: String + description: "Service account email to be used for generating the OIDC token. + The caller (for subscriptions.create, subscriptions.patch, and + subscriptions.modifyPushConfig RPCs) must have the + iam.serviceAccounts.actAs permission for the service account." + required: true + - name: 'audience' + type: String + description: "Audience to be used when generating OIDC token. The audience claim + identifies the recipients that the JWT is intended for. The audience + value is a single case-sensitive string. Having multiple values (array) + for the audience field is not supported. More info about the OIDC JWT + token audience here: https://tools.ietf.org/html/rfc7519#section-4.1.3 + Note: if not specified, the Push endpoint URL will be used." + - name: 'pushEndpoint' + type: String + description: "A URL locating the endpoint to which messages should be pushed. + For example, a Webhook endpoint might use + 'https://example.com/push'." + required: true + - name: 'attributes' + type: KeyValuePairs + description: "Endpoint configuration attributes. + + Every endpoint has a set of API supported attributes that can + be used to control different aspects of the message delivery. + + The currently supported attribute is x-goog-version, which you + can use to change the format of the pushed message. This + attribute indicates the version of the data expected by + the endpoint. This controls the shape of the pushed message + (i.e., its fields and metadata). The endpoint version is + based on the version of the Pub/Sub API. + + If not present during the subscriptions.create call, + it will default to the version of the API used to make + such call. If not present during a subscriptions.modifyPushConfig + call, its value will not be changed. subscriptions.get + calls will always return a valid version, even if the + subscription was created without this attribute. + + The possible values for this attribute are: + + - v1beta1: uses the push format defined in the v1beta1 Pub/Sub API. + - v1 or v1beta2: uses the push format defined in the v1 Pub/Sub API." + diff_suppress_func: 'tpgresource.IgnoreMissingKeyInMap("x-goog-version")' + - name: 'noWrapper' + type: NestedObject + description: "When set, the payload to the push endpoint is not wrapped.Sets the + `data` field as the HTTP body for delivery." + custom_flatten: 'templates/terraform/custom_flatten/pubsub_no_wrapper_write_metadata_flatten.go.erb' + properties: + - name: 'writeMetadata' + type: Boolean + description: "When true, writes the Pub/Sub message metadata to + `x-goog-pubsub-:` headers of the HTTP request. Writes the + Pub/Sub message attributes to `:` headers of the HTTP request." + required: true + send_empty_value: true + - name: 'ackDeadlineSeconds' + type: Integer + description: "This value is the maximum time after a subscriber receives a message +before the subscriber should acknowledge the message. After message +delivery but before the ack deadline expires and before the message is +acknowledged, it is an outstanding message and will not be delivered +again during that time (on a best-effort basis). + +For pull subscriptions, this value is used as the initial value for +the ack deadline. To override this value for a given message, call +subscriptions.modifyAckDeadline with the corresponding ackId if using +pull. The minimum custom deadline you can specify is 10 seconds. The +maximum custom deadline you can specify is 600 seconds (10 minutes). +If this parameter is 0, a default value of 10 seconds is used. + +For push delivery, this value is also used to set the request timeout +for the call to the push endpoint. + +If the subscriber never acknowledges the message, the Pub/Sub system +will eventually redeliver the message." + default_from_api: true + - name: 'messageRetentionDuration' + type: String + description: "How long to retain unacknowledged messages in the subscription's +backlog, from the moment a message is published. If +retain_acked_messages is true, then this also configures the retention +of acknowledged messages, and thus configures how far back in time a +subscriptions.seek can be done. Defaults to 7 days. Cannot be more +than 7 days (`'604800s'`) or less than 10 minutes (`'600s'`). + +A duration in seconds with up to nine fractional digits, terminated +by 's'. Example: `'600.5s'`." + default_value: 604800s + - name: 'retainAckedMessages' + type: Boolean + description: "Indicates whether to retain acknowledged messages. If `true`, then +messages are not expunged from the subscription's backlog, even if +they are acknowledged, until they fall out of the +messageRetentionDuration window." + - name: 'expirationPolicy' + type: NestedObject + description: "A policy that specifies the conditions for this subscription's expiration. +A subscription is considered active as long as any connected subscriber +is successfully consuming messages from the subscription or is issuing +operations on the subscription. If expirationPolicy is not set, a default +policy with ttl of 31 days will be used. If it is set but ttl is '', the +resource never expires. The minimum allowed value for expirationPolicy.ttl +is 1 day." + default_from_api: true + send_empty_value: true + allow_empty_object: true + properties: + - name: 'ttl' + type: String + description: "Specifies the 'time-to-live' duration for an associated resource. The + resource expires if it is not active for a period of ttl. + If ttl is set to '', the associated resource never expires. + A duration in seconds with up to nine fractional digits, terminated by 's'. + Example - '3.5s'." + required: true + diff_suppress_func: 'comparePubsubSubscriptionExpirationPolicy' + - name: 'filter' + type: String + description: "The subscription only delivers the messages that match the filter. +Pub/Sub automatically acknowledges the messages that don't match the filter. You can filter messages +by their attributes. The maximum length of a filter is 256 bytes. After creating the subscription, +you can't modify the filter." + required: false + immutable: true + - name: 'deadLetterPolicy' + type: NestedObject + description: "A policy that specifies the conditions for dead lettering messages in +this subscription. If dead_letter_policy is not set, dead lettering +is disabled. + +The Cloud Pub/Sub service account associated with this subscription's +parent project (i.e., +service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com) must have +permission to Acknowledge() messages on this subscription." + send_empty_value: true + properties: + - name: 'deadLetterTopic' + type: String + description: "The name of the topic to which dead letter messages should be published. + Format is `projects/{project}/topics/{topic}`. + + The Cloud Pub/Sub service account associated with the enclosing subscription's + parent project (i.e., + service-{project_number}@gcp-sa-pubsub.iam.gserviceaccount.com) must have + permission to Publish() to this topic. + + The operation will fail if the topic does not exist. + Users should ensure that there is a subscription attached to this topic + since messages published to a topic with no subscriptions are lost." + - name: 'maxDeliveryAttempts' + type: Integer + description: "The maximum number of delivery attempts for any message. The value must be + between 5 and 100. + + The number of delivery attempts is defined as 1 + (the sum of number of + NACKs and number of times the acknowledgement deadline has been exceeded for the message). + + A NACK is any call to ModifyAckDeadline with a 0 deadline. Note that + client libraries may automatically extend ack_deadlines. + + This field will be honored on a best effort basis. + + If this parameter is 0, a default value of 5 is used." + - name: 'retryPolicy' + type: NestedObject + description: "A policy that specifies how Pub/Sub retries message delivery for this subscription. + +If not set, the default retry policy is applied. This generally implies that messages will be retried as soon as possible for healthy subscribers. +RetryPolicy will be triggered on NACKs or acknowledgement deadline exceeded events for a given message" + properties: + - name: 'minimumBackoff' + type: String + description: "The minimum delay between consecutive deliveries of a given message. Value should be between 0 and 600 seconds. Defaults to 10 seconds. + A duration in seconds with up to nine fractional digits, terminated by 's'. Example: '3.5s'." + default_from_api: true + diff_suppress_func: 'tpgresource.DurationDiffSuppress' + - name: 'maximumBackoff' + type: String + description: "The maximum delay between consecutive deliveries of a given message. Value should be between 0 and 600 seconds. Defaults to 600 seconds. + A duration in seconds with up to nine fractional digits, terminated by 's'. Example: '3.5s'." + default_from_api: true + diff_suppress_func: 'tpgresource.DurationDiffSuppress' + - name: 'enableMessageOrdering' + type: Boolean + description: "If `true`, messages published with the same orderingKey in PubsubMessage will be delivered to +the subscribers in the order in which they are received by the Pub/Sub system. Otherwise, they +may be delivered in any order." + immutable: true + - name: 'enableExactlyOnceDelivery' + type: Boolean + description: "If `true`, Pub/Sub provides the following guarantees for the delivery +of a message with a given value of messageId on this Subscriptions': + +- The message sent to a subscriber is guaranteed not to be resent before the message's acknowledgement deadline expires. + +- An acknowledged message will not be resent to a subscriber. + +Note that subscribers may still receive multiple copies of a message when `enable_exactly_once_delivery` +is true if the message was published multiple times by a publisher client. These copies are considered distinct by Pub/Sub and have distinct messageId values" diff --git a/mmv1/products/pubsub/go_Topic.yaml b/mmv1/products/pubsub/go_Topic.yaml new file mode 100644 index 000000000000..17cddf8c9ea7 --- /dev/null +++ b/mmv1/products/pubsub/go_Topic.yaml @@ -0,0 +1,150 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +name: 'Topic' +description: | + A named resource to which messages are sent by publishers. +references: + guides: + 'Managing Topics': 'https://cloud.google.com/pubsub/docs/admin#managing_topics' + api: 'https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics' +docs: + note: 'You can retrieve the email of the Google Managed Pub/Sub Service Account used for forwarding +by using the `google_project_service_identity` resource. +' +base_url: 'projects/{{project}}/topics' +create_verb: 'PUT' +update_url: 'projects/{{project}}/topics/{{name}}' +update_verb: 'PATCH' +update_mask: true +timeouts: + insert_minutes: 20 + update_minutes: 20 + delete_minutes: 20 +async: + check_response_func_existence: 'transport_tpg.PollCheckForExistence' + check_response_func_absence: 'transport_tpg.PollCheckForAbsence' + suppress_error: true + target_occurrences: 1 +iam_policy: + method_name_separator: ':' + parent_resource_attribute: 'topic' +custom_code: + encoder: 'templates/terraform/encoders/no_send_name.go.erb' + update_encoder: 'templates/terraform/update_encoder/pubsub_topic.erb' +error_retry_predicates: + + - 'transport_tpg.PubsubTopicProjectNotReady' +examples: + - name: 'pubsub_topic_basic' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + - name: 'pubsub_topic_cmek' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + key_name: 'example-key' + keyring_name: 'example-keyring' + skip_test: true + - name: 'pubsub_topic_geo_restricted' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + - name: 'pubsub_topic_schema_settings' + primary_resource_id: 'example' + primary_resource_name: 'example' + vars: + topic_name: 'example-topic' + schema_name: 'example' + test_env_vars: + project_name: 'PROJECT_NAME' +parameters: +properties: + - name: 'name' + type: String + description: "Name of the topic." + pattern: 'projects/{{project}}/topics/{{name}}' + required: true + immutable: true + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + custom_expand: 'templates/terraform/custom_expand/resource_from_self_link.go.erb' + - name: 'kmsKeyName' + type: String + description: "The resource name of the Cloud KMS CryptoKey to be used to protect access +to messages published on this topic. Your project's PubSub service account +(`service-{{PROJECT_NUMBER}}@gcp-sa-pubsub.iam.gserviceaccount.com`) must have +`roles/cloudkms.cryptoKeyEncrypterDecrypter` to use this feature. +The expected format is `projects/*/locations/*/keyRings/*/cryptoKeys/*`" + - name: 'labels' + type: KeyValueLabels + description: "A set of key/value label pairs to assign to this Topic. + + +**Note**: This field is non-authoritative, and will only manage the labels present in your configuration. +Please refer to the field `effective_labels` for all of the labels present on the resource." + immutable: false + - name: 'messageStoragePolicy' + type: NestedObject + description: "Policy constraining the set of Google Cloud Platform regions where +messages published to the topic may be stored. If not present, then no +constraints are in effect." + default_from_api: true + properties: + - name: 'allowedPersistenceRegions' + type: Array + description: "A list of IDs of GCP regions where messages that are published to + the topic may be persisted in storage. Messages published by + publishers running in non-allowed GCP regions (or running outside + of GCP altogether) will be routed for storage in one of the + allowed regions. An empty list means that no regions are allowed, + and is not a valid configuration." + required: true + item_type: Api::Type::String + - name: 'schemaSettings' + type: NestedObject + description: "Settings for validating messages published against a schema." + default_from_api: true + properties: + - name: 'schema' + type: String + description: "The name of the schema that messages published should be + validated against. Format is projects/{project}/schemas/{schema}. + The value of this field will be _deleted-schema_ + if the schema has been deleted." + required: true + - name: 'encoding' + type: Enum + description: "The encoding of messages validated against schema." + default_value: ENCODING_UNSPECIFIED + enum_values: + - 'ENCODING_UNSPECIFIED' + - 'JSON' + - 'BINARY' + - '' + - name: 'messageRetentionDuration' + type: String + description: "Indicates the minimum duration to retain a message after it is published +to the topic. If this field is set, messages published to the topic in +the last messageRetentionDuration are always available to subscribers. +For instance, it allows any attached subscription to seek to a timestamp +that is up to messageRetentionDuration in the past. If this field is not +set, message retention is controlled by settings on individual subscriptions. +The rotation period has the format of a decimal number, followed by the +letter `s` (seconds). Cannot be more than 31 days or less than 10 minutes." diff --git a/mmv1/products/pubsub/go_product.yaml b/mmv1/products/pubsub/go_product.yaml new file mode 100644 index 000000000000..f3f63389edd2 --- /dev/null +++ b/mmv1/products/pubsub/go_product.yaml @@ -0,0 +1,22 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +name: 'Pubsub' +display_name: 'Cloud Pub/Sub' +versions: + - name: 'ga' + base_url: 'https://pubsub.googleapis.com/v1/' +scopes: + - 'https://www.googleapis.com/auth/pubsub' diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 3edea972c351..37fd2de9f525 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -377,6 +377,8 @@ def generate_objects(output_folder, types, generate_code, generate_docs) generate_object object, output_folder, @target_version_name, generate_code, generate_docs end + # Uncomment for go YAML + # generate_object_modified object, output_folder, @target_version_name end end @@ -395,7 +397,6 @@ def generate_object(object, output_folder, version_name, generate_code, generate 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 @@ -406,6 +407,33 @@ def generate_object(object, output_folder, version_name, generate_code, generate Dir.chdir pwd end + def generate_object_modified(object, output_folder, version_name) + pwd = Dir.pwd + data = build_object_data(pwd, object, output_folder, version_name) + FileUtils.mkpath output_folder + Dir.chdir output_folder + Google::LOGGER.debug "Generating #{object.name} rewrite yaml" + generate_newyaml(pwd, data.clone) + Dir.chdir pwd + end + + def generate_newyaml(pwd, data) + # @api.api_name is the service folder name + product_name = @api.api_name + target_folder = File.join(folder_name(data.version), 'services', product_name) + FileUtils.mkpath target_folder + data.generate(pwd, + '/templates/terraform/yaml_conversion.erb', + "#{target_folder}/go_#{data.object.name}.yaml", + self) + return if File.exist?("#{target_folder}/go_product.yaml") + + data.generate(pwd, + '/templates/terraform/product_yaml_conversion.erb', + "#{target_folder}/go_product.yaml", + self) + end + def build_env { goformat_enabled: @go_format_enabled, diff --git a/mmv1/provider/terraform/custom_code.go b/mmv1/provider/terraform/custom_code.go new file mode 100644 index 000000000000..1213cf0b6572 --- /dev/null +++ b/mmv1/provider/terraform/custom_code.go @@ -0,0 +1,206 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package terraform + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// require 'uri' +// require 'api/object' +// require 'compile/core' +// require 'google/golang_utils' + +// Inserts custom code into terraform resources. +type CustomCode struct { + google.YamlValidator + + // Collection of fields allowed in the CustomCode section for + // Terraform. + + // All custom code attributes are string-typed. The string should + // be the name of a template file which will be compiled in the + // specified / described place. + // + // ====================== + // schema.Resource stuff + // ====================== + // Extra Schema Entries go below all other schema entries in the + // resource's Resource.Schema map. They should be formatted as + // entries in the map, e.g. `"foo": &schema.Schema{ ... },`. + + // attr_reader : + ExtraSchemaEntry string + + // ==================== + // Encoders & Decoders + // ==================== + // The encoders are functions which take the `obj` map after it + // has been assembled in either "Create" or "Update" and mutate it + // before it is sent to the server. There are lots of reasons you + // might want to use these - any differences between local schema + // and remote schema will be placed here. + // Because the call signature of this function cannot be changed, + // the template will place the function header and closing } for + // you, and your custom code template should *not* include them. + + // attr_reader : + Encoder string + + // The update encoder is the encoder used in Update - if one is + // not provided, the regular encoder is used. If neither is + // provided, of course, neither is used. Similarly, the custom + // code should *not* include the function header or closing }. + // Update encoders are only used if object.input is false, + // because when object.input is true, only individual fields + // can be updated - in that case, use a custom expander. + + // attr_reader : + UpdateEncoder string + + // The decoder is the opposite of the encoder - it's called + // after the Read succeeds, rather than before Create / Update + // are called. Like with encoders, the decoder should not + // include the function header or closing }. + + // attr_reader : + Decoder string + + // ===================== + // Simple customizations + // ===================== + // Constants go above everything else in the file, and include + // things like methods that will be referred to by name elsewhere + // (e.g. "fooBarDiffSuppress") and regexes that are necessarily + // exported (e.g. "fooBarValidationRegex"). + + // attr_reader : + Constants string + + // This code is run before the Create call happens. It's placed + // in the Create function, just before the Create call is made. + + // attr_reader : + PreCreate string + + // This code is run after the Create call succeeds. It's placed + // in the Create function directly without modification. + + // attr_reader : + PostCreate string + + // This code is run after the Create call fails before the error is + // returned. It's placed in the Create function directly without + // modification. + + // attr_reader : + PostCreateFailure string + + // This code replaces the entire contents of the Create call. It + // should be used for resources that don't have normal creation + // semantics that cannot be supported well by other MM features. + + // attr_reader : + CustomCreate string + + // This code is run before the Read call happens. It's placed + // in the Read function. + + // attr_reader : + PreRead string + + // This code is run before the Update call happens. It's placed + // in the Update function, just after the encoder call, before + // the Update call. Just like the encoder, it is only used if + // object.input is false. + + // attr_reader : + PreUpdate string + + // This code is run after the Update call happens. It's placed + // in the Update function, just after the call succeeds. + // Just like the encoder, it is only used if object.input is + // false. + + // attr_reader : + PostUpdate string + + // This code replaces the entire contents of the Update call. It + // should be used for resources that don't have normal update + // semantics that cannot be supported well by other MM features. + + // attr_reader : + CustomUpdate string + + // This code is run just before the Delete call happens. It's + // useful to prepare an object for deletion, e.g. by detaching + // a disk before deleting it. + + // attr_reader : + PreDelete string + + // This code is run just after the Delete call happens. + + // attr_reader : + PostDelete string + + // This code replaces the entire delete method. Since the delete + // method's function header can't be changed, the template + // inserts that for you - do not include it in your custom code. + + // attr_reader : + CustomDelete string + + // This code replaces the entire import method. Since the import + // method's function header can't be changed, the template + // inserts that for you - do not include it in your custom code. + + // attr_reader : + CustomImport string + + // This code is run just after the import method succeeds - it + // is useful for parsing attributes that are necessary for + // the Read() method to succeed. + + // attr_reader : + PostImport string + + // This code is run in the generated test file to check that the + // resource was successfully deleted. Use this if the API responds + // with a success HTTP code for deleted resources + + // attr_reader : + TestCheckDestroy string +} + +// def validate +// super + +// check :extra_schema_entry, type: String +// check :encoder, type: String +// check :update_encoder, type: String +// check :decoder, type: String +// check :constants, type: String +// check :pre_create, type: String +// check :post_create, type: String +// check :custom_create, type: String +// check :pre_read, type: String +// check :pre_update, type: String +// check :post_update, type: String +// check :custom_update, type: String +// check :pre_delete, type: String +// check :custom_import, type: String +// check :post_import, type: String +// check :test_check_destroy, type: String +// end diff --git a/mmv1/provider/terraform/docs.go b/mmv1/provider/terraform/docs.go new file mode 100644 index 000000000000..408cb8d9fac0 --- /dev/null +++ b/mmv1/provider/terraform/docs.go @@ -0,0 +1,61 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package terraform + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// require 'uri' +// require 'api/object' +// require 'compile/core' +// require 'google/golang_utils' + +// Inserts custom strings into terraform resource docs. +type Docs struct { + google.YamlValidator + + // All these values should be strings, which will be inserted + // directly into the terraform resource documentation. The + // strings should _not_ be the names of template files + // (This should be reconsidered if we find ourselves repeating + // any string more than ones), but rather the actual text + // (including markdown) which needs to be injected into the + // template. + // The text will be injected at the bottom of the specified + // section. + // attr_reader : + Warning string + + // attr_reader : + Note string + + // attr_reader : + RequiredProperties string + + // attr_reader : + OptionalProperties string + + // attr_reader : + Attributes string +} + +// def validate +// super +// check :warning, type: String +// check :note, type: String +// check :required_properties, type: String +// check :optional_properties, type: String +// check :attributes, type: String +// end diff --git a/mmv1/provider/terraform/examples.go b/mmv1/provider/terraform/examples.go new file mode 100644 index 000000000000..ff4ba716a24f --- /dev/null +++ b/mmv1/provider/terraform/examples.go @@ -0,0 +1,339 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package terraform + +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" +) + +// require 'uri' +// require 'api/object' +// require 'compile/core' +// require 'google/golang_utils' + +// Generates configs to be shown as examples in docs and outputted as tests +// from a shared template +type Examples struct { + google.YamlValidator + + // include Compile::Core + // include Google::GolangUtils + + // The name of the example in lower snake_case. + // Generally takes the form of the resource name followed by some detail + // about the specific test. For example, "address_with_subnetwork". + Name string + + // The id of the "primary" resource in an example. Used in import tests. + // This is the value that will appear in the Terraform config url. For + // example: + // resource "google_compute_address" {{primary_resource_id}} { + // ... + // } + PrimaryResourceId string + + // Optional resource type of the "primary" resource. Used in import tests. + // If set, this will override the default resource type implied from the + // object parent + PrimaryResourceType string + + // vars is a Hash from template variable names to output variable names. + // It will use the provided value as a prefix for generated tests, and + // insert it into the docs verbatim. + Vars map[string]string + + // Some variables need to hold special values during tests, and cannot + // be inferred by Open in Cloud Shell. For instance, org_id + // needs to be the correct value during integration tests, or else + // org tests cannot pass. Other examples include an existing project_id, + // a zone, a service account name, etc. + // + // test_env_vars is a Hash from template variable names to one of the + // following symbols: + // - :PROJECT_NAME + // - :FIRESTORE_PROJECT_NAME + // - :CREDENTIALS + // - :REGION + // - :ORG_ID + // - :ORG_TARGET + // - :BILLING_ACCT + // - :MASTER_BILLING_ACCT + // - :SERVICE_ACCT + // - :CUST_ID + // - :IDENTITY_USER + // This list corresponds to the `get*FromEnv` methods in provider_test.go. + TestEnvVars map[string]string + + // Hash to provider custom override values for generating test config + // If field my-var is set in this hash, it will replace vars[my-var] in + // tests. i.e. if vars["network"] = "my-vpc", without override: + // - doc config will have `network = "my-vpc"` + // - tests config will have `"network = my-vpc%{random_suffix}"` + // with context + // map[string]interface{}{ + // "random_suffix": acctest.RandString() + // } + // + // If test_vars_overrides["network"] = "nameOfVpc()" + // - doc config will have `network = "my-vpc"` + // - tests will replace with `"network = %{network}"` with context + // map[string]interface{}{ + // "network": nameOfVpc + // ... + // } + TestVarsOverrides map[string]string + + // Hash to provider custom override values for generating oics config + // See test_vars_overrides for more details + OicsVarsOverrides map[string]string + + // The version name of of the example's version if it's different than the + // resource version, eg. `beta` + // + // This should be the highest version of all the features used in the + // example; if there's a single beta field in an example, the example's + // min_version is beta. This is only needed if an example uses features + // with a different version than the resource; a beta resource's examples + // are all automatically versioned at beta. + // + // When an example has a version of beta, each resource must use the + // `google-beta` provider in the config. If the `google` provider is + // implicitly used, the test will fail. + // + // NOTE: Until Terraform 0.12 is released and is used in the OiCS tests, an + // explicit provider block should be defined. While the tests @ 0.12 will + // use `google-beta` automatically, past Terraform versions required an + // explicit block. + MinVersion string + + // Extra properties to ignore read on during import. + // These properties will likely be custom code. + IgnoreReadExtra []string + + // Whether to skip generating tests for this resource + SkipTest bool + + // Whether to skip generating docs for this example + SkipDocs bool + + // Whether to skip import tests for this example + SkipImportTest bool + + // The name of the primary resource for use in IAM tests. IAM tests need + // a reference to the primary resource to create IAM policies for + PrimaryResourceName string + + // The name of the location/region override for use in IAM tests. IAM + // tests may need this if the location is not inherited on the resource + // for one reason or another + RegionOverride string + + // The path to this example's Terraform config. + // Defaults to `templates/terraform/examples/{{name}}.tf.erb` + ConfigPath string + + // If the example should be skipped during VCR testing. + // This is the case when something about the resource or config causes VCR to fail for example + // a resource with a unique identifier generated within the resource via resource.UniqueId() + // Or a config with two fine grained resources that have a race condition during create + SkipVcr bool + + // Set for false by default. Set to true if you need to pull external provider for your + // testcase. Think before adding as there is latency and adds an external dependency to + // your test so avoid if you can. + PullExternal bool +} + +// func (e *Examples) config_documentation(pwd) { +// docs_defaults = { +// PROJECT_NAME: 'my-project-name', +// FIRESTORE_PROJECT_NAME: 'my-project-name', +// CREDENTIALS: 'my/credentials/filename.json', +// REGION: 'us-west1', +// ORG_ID: '123456789', +// ORG_DOMAIN: 'example.com', +// ORG_TARGET: '123456789', +// BILLING_ACCT: '000000-0000000-0000000-000000', +// MASTER_BILLING_ACCT: '000000-0000000-0000000-000000', +// SERVICE_ACCT: 'my@service-account.com', +// CUST_ID: 'A01b123xz', +// IDENTITY_USER: 'cloud_identity_user', +// PAP_DESCRIPTION: 'description' +// } +// @vars ||= {} +// @test_env_vars ||= {} +// body = lines(compile_file( +// { +// vars:, +// test_env_vars: test_env_vars.to_h { |k, v| [k, docs_defaults[v]] }, +// primary_resource_id: +// }, +// "//{pwd}///{config_path}" +// )) + +// // Remove region tags +// body = body.gsub(/// \[[a-zA-Z_ ]+\]\n/, '') +// body = body.gsub(/\n// \[[a-zA-Z_ ]+\]/, '') +// lines(compile_file( +// { content: body }, +// "//{pwd}/templates/terraform/examples/base_configs/documentation.tf.erb" +// )) +// } + +// func (e *Examples) config_test(pwd) { +// body = config_test_body(pwd) +// lines(compile_file( +// { +// content: body +// }, +// "//{pwd}/templates/terraform/examples/base_configs/test_body.go.erb" +// )) +// } + +// rubocop:disable Style/FormatStringToken +// func (e *Examples) config_test_body(pwd) { +// @vars ||= {} +// @test_env_vars ||= {} +// @test_vars_overrides ||= {} + +// // Construct map for vars to inject into config - will have +// // - "a-example-var-value%{random_suffix}"" +// // - "%{my_var}" for overrides that have custom Golang values +// rand_vars = vars.map do |k, v| +// // Some resources only allow underscores. +// testv = if v.include?('-') +// "tf-test-//{v}" +// elsif v.include?('_') +// "tf_test_//{v}" +// else +// // Some vars like descriptions shouldn't have prefix +// v +// end +// // Random suffix is 10 characters and standard name length <= 64 +// testv = "//{testv[0...54]}%{random_suffix}" +// [k, testv] +// end + +// rand_vars = rand_vars.to_h +// overrides = test_vars_overrides.to_h { |k, _| [k, "%{//{k}}"] } +// body = lines(compile_file( +// { +// vars: rand_vars.merge(overrides), +// test_env_vars: test_env_vars.to_h { |k, _| [k, "%{//{k}}"] }, +// primary_resource_id:, +// primary_resource_type: +// }, +// "//{pwd}///{config_path}" +// )) + +// // Remove region tags +// body = body.gsub(/// \[[a-zA-Z_ ]+\]\n/, '') +// body = body.gsub(/\n// \[[a-zA-Z_ ]+\]/, '') +// substitute_test_paths body +// } + +// func (e *Examples) config_oics(pwd) { +// @vars ||= [] +// @oics_vars_overrides ||= {} + +// rand_vars = vars.to_h { |k, str| [k, "//{str}-${local.name_suffix}"] } + +// // Examples with test_env_vars are skipped elsewhere +// body = lines(compile_file( +// { +// vars: rand_vars.merge(oics_vars_overrides), +// primary_resource_id: +// }, +// "//{pwd}///{config_path}" +// )) + +// // Remove region tags +// body = body.gsub(/// \[[a-zA-Z_ ]+\]\n/, '') +// body = body.gsub(/\n// \[[a-zA-Z_ ]+\]/, '') +// substitute_example_paths body +// } + +// func (e *Examples) oics_link() { +// hash = { +// cloudshell_git_repo: 'https://github.com/terraform-google-modules/docs-examples.git', +// cloudshell_working_dir: @name, +// cloudshell_image: 'gcr.io/cloudshell-images/cloudshell:latest', +// open_in_editor: 'main.tf', +// cloudshell_print: './motd', +// cloudshell_tutorial: './tutorial.md' +// } +// URI::HTTPS.build( +// host: 'console.cloud.google.com', +// path: '/cloudshell/open', +// query: URI.encode_www_form(hash) +// ) +// } + +// rubocop:disable Layout/LineLength +// func (e *Examples) substitute_test_paths(config) { +// config.gsub!('../static/img/header-logo.png', 'test-fixtures/header-logo.png') +// config.gsub!('path/to/private.key', 'test-fixtures/test.key') +// config.gsub!('path/to/certificate.crt', 'test-fixtures/test.crt') +// config.gsub!('path/to/index.zip', '%{zip_path}') +// config.gsub!('verified-domain.com', 'tf-test-domain%{random_suffix}.gcp.tfacc.hashicorptest.com') +// config.gsub!('path/to/id_rsa.pub', 'test-fixtures/ssh_rsa.pub') +// config +// } + +// func (e *Examples) substitute_example_paths(config) { +// config.gsub!('../static/img/header-logo.png', '../static/header-logo.png') +// config.gsub!('path/to/private.key', '../static/ssl_cert/test.key') +// config.gsub!('path/to/id_rsa.pub', '../static/ssh_rsa.pub') +// config.gsub!('path/to/certificate.crt', '../static/ssl_cert/test.crt') +// config +// end +// // rubocop:enable Layout/LineLength +// // rubocop:enable Style/FormatStringToken +// } + +// func (e *Examples) validate() { +// super +// check :name, type: String, required: true +// check :primary_resource_id, type: String +// check :min_version, type: String +// check :vars, type: Hash +// check :test_env_vars, type: Hash +// check :test_vars_overrides, type: Hash +// check :ignore_read_extra, type: Array, item_type: String, default: [] +// check :primary_resource_name, type: String +// check :skip_test, type: TrueClass +// check :skip_import_test, type: TrueClass +// check :skip_docs, type: TrueClass +// check :config_path, type: String, default: "templates/terraform/examples///{name}.tf.erb" +// check :skip_vcr, type: TrueClass +// check :pull_external, type: :boolean, default: false +// } + +// func (e *Examples) merge(other) { +// result = self.class.new +// instance_variables.each do |v| +// result.instance_variable_set(v, instance_variable_get(v)) +// end + +// other.instance_variables.each do |v| +// if other.instance_variable_get(v).instance_of?(Array) +// result.instance_variable_set(v, deep_merge(result.instance_variable_get(v), +// other.instance_variable_get(v))) +// else +// result.instance_variable_set(v, other.instance_variable_get(v)) +// end +// end + +// result +// } diff --git a/mmv1/provider/terraform/sub_template.rb b/mmv1/provider/terraform/sub_template.rb index e74d2ebce971..2dc16f7274f0 100644 --- a/mmv1/provider/terraform/sub_template.rb +++ b/mmv1/provider/terraform/sub_template.rb @@ -15,6 +15,13 @@ module Provider class Terraform # Functions to compile sub-templates. module SubTemplate + def build_newyaml_field(property, object, pwd) + compile_template "#{pwd}/templates/terraform/yaml_conversion_field.erb", + property:, + object:, + pwd: + end + def build_schema_property(property, object, pwd) compile_template "#{pwd}/templates/terraform/schema_property.erb", property:, diff --git a/mmv1/templates/terraform/product_yaml_conversion.erb b/mmv1/templates/terraform/product_yaml_conversion.erb new file mode 100644 index 000000000000..cade809c4334 --- /dev/null +++ b/mmv1/templates/terraform/product_yaml_conversion.erb @@ -0,0 +1,135 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +<% +#names +-%> +name: '<%= object.__product.name %>' +<% unless object.__product.legacy_name.nil? -%> +legacy_name: '<%= object.__product.legacy_name %>' +<% end -%> +<% unless object.__product.display_name.nil? -%> +display_name: '<%= object.__product.display_name %>' +<% end -%> +<% unless object.__product.client_name.nil? -%> +client_name: '<%= object.__product.client_name %>' +<% end -%> +<% +#versions +-%> +<% unless object.__product.versions.empty? -%> +versions: +<% object.__product.versions.each do |version| -%> + - name: '<%= version.name %>' +<% unless version.base_url.nil? -%> + base_url: '<%= version.base_url %>' +<% end -%> +<% unless version.cai_base_url.nil? -%> + cai_base_url: '<%= version.cai_base_url %>' +<% end -%> +<% end -%> +<% end -%> +<% +#scopes +-%> +<% unless object.__product.scopes.nil? -%> +scopes: +<% object.__product.scopes.each do |scope| -%> + - '<%= scope -%>' +<% end -%> +<% end -%> +<% +#async +-%> +<% unless object.__product.async.nil? -%> +async: +<% if object.__product.async.is_a? Provider::Terraform::PollAsync -%> +<% unless object.__product.async.check_response_func_existence.nil? -%> + check_response_func_existence: '<%= object.__product.async.check_response_func_existence %>' +<% end -%> +<% unless object.__product.async.check_response_func_absence.nil? -%> + check_response_func_absence: '<%= object.__product.async.check_response_func_absence %>' +<% end -%> +<% unless object.__product.async.custom_poll_read.nil? -%> + custom_poll_read: '<%= object.__product.async.custom_poll_read %>' +<% end -%> +<% unless object.__product.async.suppress_error.nil? -%> + suppress_error: <%= object.__product.async.suppress_error %> +<% end -%> +<% unless object.__product.async.target_occurrences.nil? -%> + target_occurrences: <%= object.__product.async.target_occurrences %> +<% end -%> +<% end -%> +<% if object.__product.async.is_a? Api::OpAsync -%> +<% #async.operation -%> +<% unless object.__product.async.operation.nil? -%> + operation: +<% unless object.__product.async.operation.base_url.nil? -%> + base_url: '<%= object.__product.async.operation.base_url %>' +<% end -%> +<% unless object.__product.async.operation.full_url.nil? -%> + full_url: '<%= object.__product.async.operation.full_url %>' +<% end -%> +<% unless object.__product.async.operation.kind.nil? -%> + kind: '<%= object.__product.async.operation.kind %>' +<% end -%> +<% unless object.__product.async.operation.path.nil? -%> + path: '<%= object.__product.async.operation.path %>' +<% end -%> +<% unless object.__product.async.operation.wait_ms.nil? -%> + wait_ms: <%= object.__product.async.operation.wait_ms %> +<% end -%> +<% #async.operation.timeouts -%> +<% unless object.__product.async.operation.timeouts.nil? -%> + timeouts: +<% unless object.__product.async.operation.timeouts.insert_minutes.nil? -%> + insert_minutes: <%= object.__product.async.operation.timeouts.insert_minutes %> +<% end -%> +<% unless object.__product.async.operation.timeouts.update_minutes.nil? -%> + update_minutes: <%= object.__product.async.operation.timeouts.update_minutes %> +<% end -%> +<% unless object.__product.async.operation.timeouts.delete_minutes.nil? -%> + delete_minutes: <%= object.__product.async.operation.timeouts.delete_minutes %> +<% end -%> +<% end -%> +<% end -%> +<% #async.result -%> +<% unless object.__product.async.result.nil? -%> + result: +<% unless object.__product.async.result.path.nil? -%> + path: '<%= object.__product.async.result.path %>' +<% end -%> +<% unless object.__product.async.result.resource_inside_response.nil? -%> + resource_inside_response: <%= object.__product.async.result.resource_inside_response %> +<% end -%> +<% end -%> +<% #async.error -%> +<% unless object.__product.async.error.nil? -%> + error: +<% unless object.__product.async.error.path.nil? -%> + path: '<%= object.__product.async.error.path %>' +<% end -%> +<% unless object.__product.async.error.message.nil? -%> + message: '<%= object.__product.async.error.message %>' +<% end -%> +<% end -%> +<% end -%> +<% end -%> +<% +#misc +-%> +<% unless object.__product.operation_retry.nil? -%> +operation_retry: '<%= object.__product.operation_retry %>' +<% end -%> diff --git a/mmv1/templates/terraform/yaml_conversion.erb b/mmv1/templates/terraform/yaml_conversion.erb new file mode 100644 index 000000000000..e89df4397fd9 --- /dev/null +++ b/mmv1/templates/terraform/yaml_conversion.erb @@ -0,0 +1,550 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Warning: This is a temporary file, and should not be edited directly +--- +<% +#common attrs +-%> +name: '<%= object.name %>' +<% unless object.kind.nil? -%> +kind: '<%= object.kind %>' +<% end -%> +<% unless object.legacy_name.nil? -%> +legacy_name: '<%= object.legacy_name %>' +<% end -%> +description: | + <%= object.description.gsub(/\n/, "\n ") %> +<% unless object.min_version.nil? -%> +<% unless object.min_version.name == 'ga' -%> +min_version: '<%= object.min_version.name %>' +<% end -%> +<% end -%> +<% unless !object.exclude_resource -%> +exclude_resource: <%= object.exclude_resource %> +<% end -%> +<% unless !object.exclude -%> +exclude: <%= object.exclude %> +<% end -%> +<% unless object.readonly.nil? -%> +readonly: <%= object.readonly %> +<% end -%> +<% +#references blocks +-%> +<% unless object.references.nil? -%> +references: +<% unless object.references.guides.nil? -%> + guides: +<% object.references.guides.each do |title, link| -%> + '<%= title -%>': '<%= link %>' +<% end -%> +<% end -%> +<% unless object.references.api.nil? -%> + api: '<%= object.references.api %>' +<% end -%> +<% end -%> +<% +#docs blocks +-%> +<% unless object.docs.nil? -%> +docs: +<% unless object.docs.warning.nil? -%> + warning: '<%= object.docs.warning %>' +<% end -%> +<% unless object.docs.note.nil? -%> + note: '<%= object.docs.note %>' +<% end -%> +<% unless object.docs.required_properties.nil? -%> + required_properties: '<%= object.docs.required_properties %>' +<% end -%> +<% unless object.docs.optional_properties.nil? -%> + optional_properties: '<%= object.docs.optional_properties %>' +<% end -%> +<% unless object.docs.attributes.nil? -%> + attributes: '<%= object.docs.attributes %>' +<% end -%> +<% end -%> +<% +#url/http attrs +-%> +<% unless object.id_format.nil? -%> +id_format: '<%= object.id_format %>' +<% end -%> +<% unless object.base_url.nil? -%> +base_url: '<%= object.base_url %>' +<% end -%> +<% unless object.cai_base_url.nil? -%> +cai_base_url: '<%= object.cai_base_url %>' +<% end -%> +<% unless object.self_link.nil? -%> +self_link: '<%= object.self_link %>' +<% end -%> +<% unless !object.has_self_link -%> +has_self_link: <%= object.has_self_link %> +<% end -%> +<% unless object.create_url.nil? -%> +create_url: '<%= object.create_url %>' +<% end -%> +<% unless object.create_verb.to_s == 'POST' -%> +create_verb: '<%= object.create_verb.to_s %>' +<% end -%> +<% unless object.update_url.nil? -%> +update_url: '<%= object.update_url %>' +<% end -%> +<% unless object.update_verb.to_s == 'PUT' -%> +update_verb: '<%= object.update_verb.to_s %>' +<% end -%> +<% unless object.update_mask.nil? -%> +update_mask: <%= object.update_mask %> +<% end -%> +<% unless object.read_verb.to_s == 'GET' -%> +read_verb: '<%= object.read_verb.to_s %>' +<% end -%> +<% unless object.read_query_params.nil? %> +read_query_params: '<%= object.read_query_params %>' +<% end -%> +<% unless !object.skip_read -%> +skip_read: <%= object.skip_read %> +<% end -%> +<% unless object.delete_url.nil? -%> +delete_url: '<%= object.delete_url %>' +<% end -%> +<% unless object.delete_verb.to_s == 'DELETE' -%> +delete_verb: '<%= object.delete_verb.to_s %>' +<% end -%> +<% unless !object.skip_delete -%> +skip_delete: <%= object.skip_delete %> +<% end -%> +<% unless object.immutable.nil? -%> +immutable: <%= object.immutable %> +<% end -%> +<% unless object.mutex.nil? -%> +mutex: <%= object.mutex %> +<% end -%> +<% +#import +-%> +<% unless object.import_format.empty? -%> +import_format: +<% object.import_format.each do |iformat| -%> + - '<%= iformat %>' +<% end -%> +<% end -%> +<% unless !object.exclude_import -%> +exclude_import: <%= object.exclude_import %> +<% end -%> +<% +#timeouts +-%> +<% unless object.timeouts.nil? -%> +timeouts: +<% unless object.timeouts.insert_minutes.nil? -%> + insert_minutes: <%= object.timeouts.insert_minutes %> +<% end -%> +<% unless object.timeouts.update_minutes.nil? -%> + update_minutes: <%= object.timeouts.update_minutes %> +<% end -%> +<% unless object.timeouts.delete_minutes.nil? -%> + delete_minutes: <%= object.timeouts.delete_minutes %> +<% end -%> +<% end -%> +<% +#async +-%> +<% unless !object.autogen_async -%> +autogen_async: <%= object.autogen_async %> +<% end -%> +<% unless object.async.nil? -%> +async: +<% if object.async.is_a? Provider::Terraform::PollAsync -%> +<% unless object.async.check_response_func_existence.nil? -%> + check_response_func_existence: '<%= object.async.check_response_func_existence %>' +<% end -%> +<% unless object.async.check_response_func_absence.nil? -%> + check_response_func_absence: '<%= object.async.check_response_func_absence %>' +<% end -%> +<% unless object.async.custom_poll_read.nil? -%> + custom_poll_read: '<%= object.async.custom_poll_read %>' +<% end -%> +<% unless object.async.suppress_error.nil? -%> + suppress_error: <%= object.async.suppress_error %> +<% end -%> +<% unless object.async.target_occurrences.nil? -%> + target_occurrences: <%= object.async.target_occurrences %> +<% end -%> +<% end -%> +<% if object.async.is_a? Api::OpAsync -%> +<% #async.operation %> +<% unless object.async.operation.nil? -%> + operation: +<% unless object.async.operation.base_url.nil? -%> + base_url: '<%= object.async.operation.base_url %>' +<% end -%> +<% unless object.async.operation.full_url.nil? -%> + full_url: '<%= object.async.operation.full_url %>' +<% end -%> +<% unless object.async.operation.kind.nil? -%> + kind: '<%= object.async.operation.kind %>' +<% end -%> +<% unless object.async.operation.path.nil? -%> + path: '<%= object.async.operation.path %>' +<% end -%> +<% unless object.async.operation.wait_ms.nil? -%> + wait_ms: <%= object.async.operation.wait_ms %> +<% end -%> +<% #async.operation.timeouts %> +<% unless object.async.operation.timeouts.nil? -%> + timeouts: +<% unless object.async.operation.timeouts.insert_minutes.nil? -%> + insert_minutes: <%= object.async.operation.timeouts.insert_minutes %> +<% end -%> +<% unless object.async.operation.timeouts.update_minutes.nil? -%> + update_minutes: <%= object.async.operation.timeouts.update_minutes %> +<% end -%> +<% unless object.async.operation.timeouts.delete_minutes.nil? -%> + delete_minutes: <%= object.async.operation.timeouts.delete_minutes %> +<% end -%> +<% end -%> +<% end -%> +<% #async.result %> +<% unless object.async.result.nil? -%> + result: +<% unless object.async.result.path.nil? -%> + path: '<%= object.async.result.path %>' +<% end -%> +<% unless object.async.result.resource_inside_response.nil? -%> + resource_inside_response: <%= object.async.result.resource_inside_response %> +<% end -%> +<% end -%> +<% #async.error %> +<% unless object.async.error.nil? -%> + error: +<% unless object.async.error.path.nil? -%> + path: '<%= object.async.error.path %>' +<% end -%> +<% unless object.async.error.message.nil? -%> + message: '<%= object.async.error.message %>' +<% end -%> +<% end -%> +<% end -%> +<% end -%> +<% +#collection/identity url +-%> +<% unless object.collection_url_key == object.name.plural.camelize(:lower) -%> +collection_url_key: '<%= object.collection_url_key %>' +<% end -%> +<% unless object.nested_query.nil? -%> +nested_query: +<% unless object.nested_query.keys.nil? -%> + keys: +<% object.nested_query.keys.each do |key| %> + - <%= key -%> +<% end -%> +<% end -%> +<% unless object.nested_query.is_list_of_ids.nil? -%> + is_list_of_ids: <%= object.nested_query.is_list_of_ids %> +<% end -%> +<% unless object.nested_query.modify_by_patch.nil? -%> + modify_by_patch: <%= object.nested_query.modify_by_patch %> +<% end -%> +<% end -%> +<% +#IAM +-%> +<% unless object.iam_policy.nil? -%> +iam_policy: +<% unless !object.iam_policy.exclude -%> + exclude: <%= object.iam_policy.exclude %> +<% end -%> +<% unless !object.iam_policy.exclude_tgc -%> + exclude_tgc: <%= object.iam_policy.exclude_tgc %> +<% end -%> +<% unless !object.iam_policy.skip_import_test -%> + skip_import_test: <%= object.iam_policy.skip_import_test %> +<% end -%> +<% unless object.iam_policy.method_name_separator == '/' -%> + method_name_separator: '<%= object.iam_policy.method_name_separator %>' +<% end -%> +<% unless object.iam_policy.parent_resource_type.nil? -%> + parent_resource_type: '<%= object.iam_policy.parent_resource_type %>' +<% end -%> +<% unless object.iam_policy.fetch_iam_policy_verb.to_s == 'GET' -%> + fetch_iam_policy_verb: '<%= object.iam_policy.fetch_iam_policy_verb.to_s %>' +<% end -%> +<% unless object.iam_policy.fetch_iam_policy_method == 'getIamPolicy' -%> + fetch_iam_policy_method: '<%= object.iam_policy.fetch_iam_policy_method %>' +<% end -%> +<% unless object.iam_policy.set_iam_policy_verb.to_s == 'POST' -%> + set_iam_policy_verb: '<%= object.iam_policy.set_iam_policy_verb.to_s %>' +<% end -%> +<% unless object.iam_policy.set_iam_policy_method == 'setIamPolicy' -%> + set_iam_policy_method: '<%= object.iam_policy.set_iam_policy_method %>' +<% end -%> +<% unless object.iam_policy.wrapped_policy_obj -%> + wrapped_policy_obj: <%= object.iam_policy.wrapped_policy_obj %> +<% end -%> +<% unless object.iam_policy.allowed_iam_role == 'roles/viewer' -%> + allowed_iam_role: '<%= object.iam_policy.allowed_iam_role %>' +<% end -%> +<% unless object.iam_policy.admin_iam_role.nil? -%> + admin_iam_role: '<%= object.iam_policy.admin_iam_role %>' +<% end -%> +<% unless object.iam_policy.parent_resource_attribute == 'id' -%> + parent_resource_attribute: '<%= object.iam_policy.parent_resource_attribute %>' +<% end -%> +<% unless object.iam_policy.test_project_name.nil? -%> + test_project_name: '<%= object.iam_policy.test_project_name %>' +<% end -%> +<% unless object.iam_policy.iam_conditions_request_type.nil? -%> + iam_conditions_request_type: '<%= object.iam_policy.iam_conditions_request_type %>' +<% end -%> +<% unless object.iam_policy.base_url.nil? -%> + base_url: '<%= object.iam_policy.base_url %>' +<% end -%> +<% unless object.iam_policy.self_link.nil? -%> + self_link: '<%= object.iam_policy.self_link %>' +<% end -%> +<% unless object.iam_policy.import_format.nil? -%> + import_format: +<% object.iam_policy.import_format.each do |iformat| -%> + - '<%= iformat %>' +<% end -%> +<% end -%> +<% unless object.iam_policy.iam_policy_version.nil? -%> + iam_policy_version: '<%= object.iam_policy.iam_policy_version %>' +<% end -%> +<% unless object.iam_policy.min_version.nil? -%> + min_version: '<%= object.iam_policy.min_version %>' +<% end -%> +<% unless object.iam_policy.substitute_zone_value -%> + substitute_zone_value: <%= object.iam_policy.substitute_zone_value %> +<% end -%> +<% end -%> +<% +#custom code +-%> +<% unless object.custom_code.nil? -%> +custom_code: +<% unless object.custom_code.extra_schema_entry.nil? -%> + extra_schema_entry: '<%= object.custom_code.extra_schema_entry %>' +<% end -%> +<% unless object.custom_code.constants.nil? -%> + constants: '<%= object.custom_code.constants %>' +<% end -%> +<% unless object.custom_code.encoder.nil? -%> + encoder: '<%= object.custom_code.encoder %>' +<% end -%> +<% unless object.custom_code.update_encoder.nil? -%> + update_encoder: '<%= object.custom_code.update_encoder %>' +<% end -%> +<% unless object.custom_code.decoder.nil? -%> + decoder: '<%= object.custom_code.decoder %>' +<% end -%> +<% unless object.custom_code.pre_create.nil? -%> + pre_create: '<%= object.custom_code.pre_create %>' +<% end -%> +<% unless object.custom_code.post_create.nil? -%> + post_create: '<%= object.custom_code.post_create %>' +<% end -%> +<% unless object.custom_code.custom_create.nil? -%> + custom_create: '<%= object.custom_code.custom_create %>' +<% end -%> +<% unless object.custom_code.pre_read.nil? -%> + pre_read: '<%= object.custom_code.pre_read %>' +<% end -%> +<% unless object.custom_code.pre_update.nil? -%> + pre_update: '<%= object.custom_code.pre_update %>' +<% end -%> +<% unless object.custom_code.post_update.nil? -%> + post_update: '<%= object.custom_code.post_update %>' +<% end -%> +<% unless object.custom_code.custom_update.nil? -%> + custom_update: '<%= object.custom_code.custom_update %>' +<% end -%> +<% unless object.custom_code.pre_delete.nil? -%> + pre_delete: '<%= object.custom_code.pre_delete %>' +<% end -%> +<% unless object.custom_code.custom_import.nil? -%> + custom_import: '<%= object.custom_code.custom_import %>' +<% end -%> +<% unless object.custom_code.post_import.nil? -%> + post_import: '<%= object.custom_code.post_import %>' +<% end -%> +<% unless object.custom_code.test_check_destroy.nil? -%> + test_check_destroy: '<%= object.custom_code.test_check_destroy %>' +<% end -%> +<% end -%> +<% unless object.custom_diff.empty? || (object.custom_diff.size == 1 && object.custom_diff.include?("tpgresource.SetLabelsDiff")) -%> +custom_diff: +<% object.custom_diff.each do |cdiff| -%> + - '<%= cdiff %>' +<% end -%> +<% end -%> +<% unless !object.skip_default_cdiff -%> +skip_default_cdiff: <%= object.skip_default_cdiff %> +<% end -%> +<% +#terraform overrides +-%> +<% unless object.filename_override.nil? -%> +filename_override: '<%= object.filename_override %>' +<% end -%> +<% unless object.exclude_tgc.nil? -%> +exclude_tgc: <%= object.exclude_tgc %> +<% end -%> +<% unless !object.skip_sweeper -%> +skip_sweeper: <%= object.skip_sweeper %> +<% end -%> +<% unless object.error_retry_predicates.nil? -%> +error_retry_predicates: +<% object.error_retry_predicates.each do |erpred| %> + - '<%= erpred -%>' +<% end -%> +<% end -%> +<% unless object.error_abort_predicates.nil? -%> +error_abort_predicates: +<% object.error_abort_predicates.each do |eapred| %> + - '<%= eapred -%>' +<% end -%> +<% end -%> +<% unless object.schema_version.nil? -%> +schema_version: <%= object.schema_version %> +<% end -%> +<% unless object.state_upgrade_base_schema_version == 0 -%> +state_upgrade_base_schema_version: <%= object.state_upgrade_base_schema_version %> +<% end -%> +<% unless !object.state_upgraders -%> +state_upgraders: <%= object.state_upgraders %> +<% end -%> +<% unless object.migrate_state.nil? -%> +migrate_state: '<%= object.migrate_state %>' +<% end -%> +<% unless !object.legacy_long_form_project -%> +legacy_long_form_project: <%= object.legacy_long_form_project %> +<% end -%> +<% unless !object.supports_indirect_user_project_override -%> +supports_indirect_user_project_override: <%= object.supports_indirect_user_project_override %> +<% end -%> +<% unless object.read_error_transform.nil? -%> +read_error_transform: '<%= object.read_error_transform %>' +<% end -%> +<% unless !object.taint_resource_on_failed_create -%> +taint_resource_on_failed_create: <%= object.taint_resource_on_failed_create %> +<% end -%> +<% unless object.deprecation_message.nil? -%> +deprecation_message: '<%= object.deprecation_message %>' +<% end -%> +<% +#examples +-%> +<% unless object.examples.empty? -%> +examples: +<% object.examples.each do |example| -%> + - name: '<%= example.name %>' +<% unless example.config_path == "templates/terraform/examples/#{example.name}.tf.erb" -%> + config_path: '<%= example.config_path %>' +<% end -%> +<% unless example.primary_resource_id.nil? -%> + primary_resource_id: '<%= example.primary_resource_id %>' +<% end -%> +<% unless example.primary_resource_id.nil? -%> + primary_resource_name: '<%= example.primary_resource_id %>' +<% end -%> +<% unless example.min_version.nil? -%> + min_version: '<%= example.min_version %>' +<% end -%> +<% unless example.vars.nil? -%> +<% unless example.vars.empty? -%> + vars: +<% example.vars.each do |vname, val| -%> + <%= vname -%>: '<%= val %>' +<% end -%> +<% end -%> +<% end -%> +<% unless example.test_env_vars.nil? -%> +<% unless example.test_env_vars.empty? -%> + test_env_vars: +<% example.test_env_vars.each do |vname, val| -%> + <%= vname -%>: '<%= val %>' +<% end -%> +<% end -%> +<% end -%> +<% unless example.test_vars_overrides.nil? -%> +<% unless example.test_vars_overrides.empty? -%> + test_vars_overrides: +<% example.test_vars_overrides.each do |vname, val| -%> + '<%= vname -%>': '<%= val %>' +<% end -%> +<% end -%> +<% end -%> +<% unless example.ignore_read_extra.empty? -%> + ignore_read_extra: +<% example.ignore_read_extra.each do |irextra| -%> + '<%= irextra %>' +<% end -%> +<% end -%> +<% unless !example.pull_external -%> + pull_external: <%= example.pull_external %> +<% end -%> +<% unless example.skip_test.nil? -%> + skip_test: <%= example.skip_test %> +<% end -%> +<% unless example.skip_import_test.nil? -%> + skip_import_test: <%= example.skip_import_test %> +<% end -%> +<% unless example.skip_docs.nil? -%> + skip_docs: <%= example.skip_docs %> +<% end -%> +<% unless example.skip_vcr.nil? -%> + skip_vcr: <%= example.skip_vcr %> +<% end -%> +<% end -%> +<% end -%> +<% +#virtual fields +-%> +<% unless object.virtual_fields.empty? -%> +virtual_fields: +<% object.virtual_fields.each do |vfield| -%> + - name: '<%= vfield.name %>' + description: '<%= vfield.description %>' +<% unless vfield.type.nil? -%> + type: <%= tf_type(vfield.type) %> +<% end -%> +<% unless vfield.default_value.nil? -%> + default_value: <%= go_literal(vfield.default_value) %> +<% end -%> +<% unless vfield.immutable.nil? -%> + immutable: <%= vfield.immutable %> +<% end -%> +<% end -%> +<% end -%> +<% +#fields +-%> +<% unless object.parameters.nil? -%> +parameters: +<% object.parameters.each do |prop| -%> +<%= lines(build_newyaml_field(prop, object, pwd)) -%> +<% end -%> +<% end -%> +<% unless object.properties.nil? -%> +properties: +<% object.properties.each do |prop| -%> +<%= lines(build_newyaml_field(prop, object, pwd)) -%> +<% end -%> +<% end -%> +<%# end -%> + diff --git a/mmv1/templates/terraform/yaml_conversion_field.erb b/mmv1/templates/terraform/yaml_conversion_field.erb new file mode 100644 index 000000000000..0ce6832e4fd7 --- /dev/null +++ b/mmv1/templates/terraform/yaml_conversion_field.erb @@ -0,0 +1,210 @@ +<% indent_spaces = 2 -%> +<% unless property.class.to_s == 'Api::Type::KeyValueTerraformLabels' || property.class.to_s == 'Api::Type::KeyValueEffectiveLabels' -%> + - name: '<%= property.name -%>' + type: <%= property.class.to_s.gsub("Api::Type::", "") %> +<% unless property.description.nil? -%> + description: "<%= property.description.strip.gsub('"', '\'') -%>" +<% end -%> +<% unless !property.unordered_list -%> + unordered_list: <%= property.unordered_list %> +<% end -%> +<% unless !property.is_set -%> + is_set: <%= property.is_set %> +<% end -%> +<% unless !property.schema_config_mode_attr -%> + schema_config_mode_attr: <%= property.schema_config_mode_attr %> +<% end -%> +<% unless property.pattern.nil? -%> + pattern: '<%= property.pattern %>' +<% end -%> +<% unless !property.exclude -%> + exclude: <%= property.exclude %> +<% end -%> +<% unless property.__resource.nil? -%> +<% unless property.min_version.name == 'ga'-%> + min_version: '<%= property.min_version.name %>' +<% end -%> +<% end -%> +<% unless property.exact_version.nil? -%> + exact_version: '<%= property.exact_version %>' +<% end -%> +<% unless property.url_param_only.nil? -%> + url_param_only: <%= property.url_param_only %> +<% end -%> +<% unless property.required.nil? -%> + required: <%= property.required %> +<% end -%> +<% unless property.immutable.nil? -%> + immutable: <%= property.immutable %> +<% end -%> +<% unless property.ignore_read.nil? -%> + ignore_read: <%= property.ignore_read %> +<% end -%> +<% unless !property.sensitive -%> + sensitive: <%= property.sensitive %> +<% end -%> +<% unless !property.default_from_api -%> + default_from_api: <%= property.default_from_api %> +<% end -%> +<% unless !property.output -%> + output: <%= property.output %> +<% end -%> +<% unless property.send_empty_value.nil? -%> + send_empty_value: <%= property.send_empty_value %> +<% end -%> +<% unless property.allow_empty_object.nil? -%> + allow_empty_object: <%= property.allow_empty_object %> +<% end -%> +<% unless property.read_query_params.nil? -%> + read_query_params: '<%= property.read_query_params %>' +<% end -%> +<% unless property.update_url.nil? -%> + update_url: '<%= property.update_url %>' +<% end -%> +<% unless property.update_verb == property.__resource&.update_verb -%> + update_verb: '<%= property.update_verb.to_s %>' +<% end -%> +<% unless property.update_id.nil? -%> + update_id: '<%= property.update_id %>' +<% end -%> +<% unless property.update_mask_fields.nil? -%> + update_mask_fields: +<% property.update_mask_fields.each do |fname| -%> + - '<%= fname %>' +<% end -%> +<% end -%> +<% unless property.fingerprint_name.nil? -%> + fingerprint_name: '<%= property.fingerprint_name %>' +<% end -%> +<% unless property.conflicts.nil? -%> +<% unless property.conflicts.empty? -%> + conflicts: +<% property.conflicts.each do |fname| -%> + - <%= fname %> +<% end -%> +<% end -%> +<% end -%> +<% unless property.at_least_one_of.nil? -%> +<% unless property.at_least_one_of.empty? -%> + at_least_one_of: +<% property.at_least_one_of.each do |fname| -%> + - '<%= fname %>' +<% end -%> +<% end -%> +<% end -%> +<% unless property.exactly_one_of.nil? -%> +<% unless property.exactly_one_of.empty? -%> + exactly_one_of: +<% property.exactly_one_of.each do |fname| -%> + - '<%= fname %>' +<% end -%> +<% end -%> +<% end -%> +<% unless property.required_with.nil? -%> +<% unless property.required_with.empty? -%> + required_with: +<% property.required_with.each do |fname| -%> + - '<%= fname %>' +<% end -%> +<% end -%> +<% end -%> +<% unless property.key_expander == 'tpgresource.ExpandString' -%> + key_expander: '<%= property.key_expander %>' +<% end -%> +<% unless property.key_diff_suppress_func.nil? -%> + key_diff_suppress_func: '<%= property.key_diff_suppress_func %>' +<% end -%> +<% unless property.diff_suppress_func.nil? -%> + diff_suppress_func: '<%= property.diff_suppress_func %>' +<% end -%> +<% unless property.state_func.nil? -%> + state_func: '<%= property.state_func %>' +<% end -%> +<% unless property.set_hash_func.nil? -%> + set_hash_func: '<%= property.set_hash_func %>' +<% end -%> +<% unless property.custom_flatten.nil? -%> + custom_flatten: '<%= property.custom_flatten %>' +<% end -%> +<% unless property.custom_expand.nil? -%> + custom_expand: '<%= property.custom_expand %>' +<% end -%> +<% unless property.flatten_object.nil? -%> + flatten_object: '<%= property.flatten_object %>' +<% end -%> +<% unless property.validation.nil? -%> + validation: +<% unless property.validation.regex.nil? -%> + regex: '<%= property.validation.regex %>' +<% end -%> +<% unless property.validation.function.nil? -%> + function: '<%= property.validation.function %>' +<% end -%> +<% end -%> +<% unless property.default_value.nil? -%> + default_value: <%= property.default_value %> +<% end -%> +<% unless property.deprecation_message.nil? -%> + deprecation_message: '<%= property.deprecation_message %>' +<% end -%> +<% unless property.removed_message.nil? -%> + removed_message: '<%= property.removed_message %>' +<% end -%> +<% if property.is_a?(Api::Type::Array) -%> +<% if property.item_type.is_a?(Api::Type::NestedObject) -%> + item_type: <%= property.item_type.type.to_s %> +<% unless property.item_type.properties.nil? -%> + properties: +<% property.item_type.properties.each do |prop| -%> +<%= lines(indent(build_newyaml_field(prop, object, pwd), 4)) -%> +<% end -%> +<% end -%> +<% else -%> + item_type: <%= property.item_type.to_s %> +<% end -%> +<% unless property.min_size.nil? -%> + min_size: <%= property.min_size %> +<% end -%> +<% unless property.max_size.nil? -%> + max_size: <%= property.max_size %> +<% end -%> +<% end -%> +<% if property.is_a?(Api::Type::ResourceRef) -%> +<% unless property.resource.nil? -%> + resource: '<%= property.resource %>' +<% end -%> +<% unless property.imports.nil? -%> + imports: '<%= property.imports.to_s %>' +<% end -%> +<% end -%> +<% if property.is_a?(Api::Type::Enum) -%> +<% unless property.values.nil? -%> + enum_values: +<% property.values.each do |enumval| -%> + - '<%= enumval %>' +<% end -%> +<% end -%> +<% unless property.skip_docs_values.nil? -%> + skip_docs_values: <%= property.skip_docs_values %> +<% end -%> +<% end -%> +<% if property.is_a?(Api::Type::Map) -%> +<% unless property.value_type.nil? -%> + value_type: '<%= property.value_type.to_s %>' +<% end -%> +<% unless property.key_name.nil? -%> + key_name: '<%= property.key_name %>' +<% end -%> +<% unless property.key_description.nil? -%> + key_description: '<%= property.key_description %>' +<% end -%> +<% end -%> +<% if property.is_a?(Api::Type::NestedObject) -%> +<% unless property.properties.nil? -%> + properties: +<% property.properties.each do |prop| -%> +<%= lines(indent(build_newyaml_field(prop, object, pwd), 4)) -%> +<% end -%> +<% end -%> +<% end -%> +<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/go.mod b/mmv1/third_party/go.mod new file mode 100644 index 000000000000..8b4fa24a554a --- /dev/null +++ b/mmv1/third_party/go.mod @@ -0,0 +1,2 @@ +// This is an empty go.mod to ensure packages required +// in this folder are not considered part of tpgtools modules. \ No newline at end of file From 5d86b613cda684877c2f0ad98b4d4e524e6aa89a Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Thu, 29 Feb 2024 16:02:05 -0800 Subject: [PATCH 056/200] Revert "Promote metric settings in compute region autoscaler to GA" (#10095) This reverts commit c3ce700765fbc4b3dc9896da767194b8eda9a13d. --- mmv1/products/compute/RegionAutoscaler.yaml | 3 +++ .../compute/resource_compute_region_autoscaler_test.go.erb | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/mmv1/products/compute/RegionAutoscaler.yaml b/mmv1/products/compute/RegionAutoscaler.yaml index 7ef41e624626..931e07443408 100644 --- a/mmv1/products/compute/RegionAutoscaler.yaml +++ b/mmv1/products/compute/RegionAutoscaler.yaml @@ -140,6 +140,7 @@ properties: Defines operating mode for this policy. - !ruby/object:Api::Type::NestedObject name: 'scaleDownControl' + min_version: beta description: | Defines scale down controls to reduce the risk of response latency and outages due to abrupt scale-in events @@ -264,6 +265,7 @@ properties: required: true - !ruby/object:Api::Type::Double name: 'singleInstanceAssignment' + min_version: beta description: | If scaling is based on a per-group metric value that represents the total amount of work to be done or resource usage, set this value to @@ -339,6 +341,7 @@ properties: (if you are using gce_instance resource type). If multiple TimeSeries are returned upon the query execution, the autoscaler will sum their respective values to obtain its scaling value. + min_version: beta - !ruby/object:Api::Type::NestedObject name: 'loadBalancingUtilization' description: | diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_autoscaler_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_autoscaler_test.go.erb index 64f15c2fb80e..1d6f65491513 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_autoscaler_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_autoscaler_test.go.erb @@ -217,12 +217,14 @@ resource "google_compute_region_autoscaler" "foobar" { target = 0.5 predictive_method = "OPTIMIZE_AVAILABILITY" } +<% unless version == 'ga' -%> scale_down_control { max_scaled_down_replicas { percent = 80 } time_window_sec = 300 } +<% end -%> } } `, autoscalerName) @@ -267,12 +269,14 @@ resource "google_compute_region_autoscaler" "foobar" { cpu_utilization { target = 0.5 } +<% unless version == 'ga' -%> scale_down_control { max_scaled_down_replicas { percent = 80 } time_window_sec = 300 } +<% end -%> scaling_schedules { name = "every-weekday-morning" description = "Increase to 2 every weekday at 7AM for 6 hours." From 0ac8f5283f99aca69ac1821ecbc67200d45b0390 Mon Sep 17 00:00:00 2001 From: Hamzawy63 <43001514+Hamzawy63@users.noreply.github.com> Date: Fri, 1 Mar 2024 10:42:44 +0100 Subject: [PATCH 057/200] Add type field to DNS authorization reosurce (#10030) * Add type field to DNS authorization reosurce * Add an example for regional DNS authorization * Add an example for regional certs using regional DNS auth * Fix lint errors * Fix typo in the enum values * Add type field in regional dns auth example --------- Co-authored-by: Hamza Hassan --- .../certificatemanager/Certificate.yaml | 7 ++++++ .../certificatemanager/DnsAuthorization.yaml | 23 +++++++++++++++++++ ..._manager_dns_authorization_regional.tf.erb | 7 ++++++ ...naged_regional_certificate_dns_auth.tf.erb | 19 +++++++++++++++ 4 files changed, 56 insertions(+) create mode 100644 mmv1/templates/terraform/examples/certificate_manager_dns_authorization_regional.tf.erb create mode 100644 mmv1/templates/terraform/examples/certificate_manager_google_managed_regional_certificate_dns_auth.tf.erb diff --git a/mmv1/products/certificatemanager/Certificate.yaml b/mmv1/products/certificatemanager/Certificate.yaml index d6cc703156cb..119379747fd0 100644 --- a/mmv1/products/certificatemanager/Certificate.yaml +++ b/mmv1/products/certificatemanager/Certificate.yaml @@ -88,6 +88,13 @@ examples: dns_auth_name2: 'dns-auth2' dns_auth_subdomain2: 'subdomain2' cert_name: 'dns-cert' + - !ruby/object:Provider::Terraform::Examples + name: 'certificate_manager_google_managed_regional_certificate_dns_auth' + primary_resource_id: 'default' + vars: + dns_auth_name: 'dns-auth' + dns_auth_subdomain: 'subdomain' + cert_name: 'dns-cert' custom_code: !ruby/object:Provider::Terraform::CustomCode constants: templates/terraform/constants/cert_manager.erb parameters: diff --git a/mmv1/products/certificatemanager/DnsAuthorization.yaml b/mmv1/products/certificatemanager/DnsAuthorization.yaml index 33cd7604ed80..92e1acdd3494 100644 --- a/mmv1/products/certificatemanager/DnsAuthorization.yaml +++ b/mmv1/products/certificatemanager/DnsAuthorization.yaml @@ -50,6 +50,13 @@ examples: dns_auth_name: 'dns-auth' zone_name: 'my-zone' subdomain: 'subdomain' + - !ruby/object:Provider::Terraform::Examples + name: 'certificate_manager_dns_authorization_regional' + primary_resource_id: 'default' + vars: + dns_auth_name: 'dns-auth' + zone_name: 'my-zone' + subdomain: 'subdomain' parameters: - !ruby/object:Api::Type::String name: 'name' @@ -84,6 +91,22 @@ properties: A domain which is being authorized. A DnsAuthorization resource covers a single domain and its wildcard, e.g. authorization for "example.com" can be used to issue certificates for "example.com" and "*.example.com". + - !ruby/object:Api::Type::Enum + name: type + description: | + type of DNS authorization. If unset during the resource creation, FIXED_RECORD will + be used for global resources, and PER_PROJECT_RECORD will be used for other locations. + + FIXED_RECORD DNS authorization uses DNS-01 validation method + + PER_PROJECT_RECORD DNS authorization allows for independent management + of Google-managed certificates with DNS authorization across multiple + projects. + immutable: true + values: + - :FIXED_RECORD + - :PER_PROJECT_RECORD + default_from_api: true - !ruby/object:Api::Type::NestedObject name: 'dnsResourceRecord' output: true diff --git a/mmv1/templates/terraform/examples/certificate_manager_dns_authorization_regional.tf.erb b/mmv1/templates/terraform/examples/certificate_manager_dns_authorization_regional.tf.erb new file mode 100644 index 000000000000..21df9b21c914 --- /dev/null +++ b/mmv1/templates/terraform/examples/certificate_manager_dns_authorization_regional.tf.erb @@ -0,0 +1,7 @@ +resource "google_certificate_manager_dns_authorization" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['dns_auth_name'] %>" + location = "us-central1" + description = "reginal dns" + type = "PER_PROJECT_RECORD" + domain = "<%= ctx[:vars]['subdomain'] %>.hashicorptest.com" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/certificate_manager_google_managed_regional_certificate_dns_auth.tf.erb b/mmv1/templates/terraform/examples/certificate_manager_google_managed_regional_certificate_dns_auth.tf.erb new file mode 100644 index 000000000000..f49a6cf70d8f --- /dev/null +++ b/mmv1/templates/terraform/examples/certificate_manager_google_managed_regional_certificate_dns_auth.tf.erb @@ -0,0 +1,19 @@ +resource "google_certificate_manager_certificate" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['cert_name'] %>" + description = "regional managed certs" + location = "us-central1" + managed { + domains = [ + google_certificate_manager_dns_authorization.instance.domain, + ] + dns_authorizations = [ + google_certificate_manager_dns_authorization.instance.id, + ] + } +} +resource "google_certificate_manager_dns_authorization" "instance" { + name = "<%= ctx[:vars]['dns_auth_name'] %>" + location = "us-central1" + description = "The default dnss" + domain = "<%= ctx[:vars]['dns_auth_subdomain'] %>.hashicorptest.com" +} \ No newline at end of file From 59e75bc22744a97d6d7bdaaba2d6e0e4d4a6d9cc Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 1 Mar 2024 11:35:47 +0000 Subject: [PATCH 058/200] TeamCity: Refactor config tests (#9956) * Add test util for locating a subproject 2 layers deep * Refactor tests to use new helper function * Consolidate testing of service sweeper builds, refactor `getSubProject` to return non-nullable value * Refactor new sweeper tests --- .../.teamcity/tests/nightly_tests_project.kt | 21 +---- .../terraform/.teamcity/tests/sweepers.kt | 89 ++++++------------- .../terraform/.teamcity/tests/test_utils.kt | 18 ++++ 3 files changed, 48 insertions(+), 80 deletions(-) diff --git a/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt b/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt index 57764788a5ac..af3d7b8a9b24 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt @@ -19,26 +19,13 @@ class NightlyTestProjectsTests { val project = googleCloudRootProject(testContextParameters()) // Find GA nightly test project - var gaProject: Project? = project.subProjects.find { p-> p.name == gaProjectName} - if (gaProject == null) { - Assert.fail("Could not find the Google (GA) project") - } - var gaNightlyTestProject: Project? = gaProject!!.subProjects.find { p-> p.name == nightlyTestsProjectName} - if (gaNightlyTestProject == null) { - Assert.fail("Could not find the Google (GA) Nightly Test project") - } + var gaNightlyTestProject = getSubProject(project, gaProjectName, nightlyTestsProjectName) // Find Beta nightly test project - var betaProject: Project? = project.subProjects.find { p-> p.name == betaProjectName} - if (betaProject == null) { - Assert.fail("Could not find the Google (Beta) project") - } - var betaNightlyTestProject: Project? = betaProject!!.subProjects.find { p-> p.name == nightlyTestsProjectName} - if (betaNightlyTestProject == null) { - Assert.fail("Could not find the Google (GA) Nightly Test project") - } + var betaNightlyTestProject = getSubProject(project, betaProjectName, nightlyTestsProjectName) - (gaNightlyTestProject!!.buildTypes + betaNightlyTestProject!!.buildTypes).forEach{bt -> + // Make assertions about builds in both nightly test projects + (gaNightlyTestProject.buildTypes + betaNightlyTestProject.buildTypes).forEach{bt -> assertTrue("Build configuration `${bt.name}` contains at least one trigger", bt.triggers.items.isNotEmpty()) // Look for at least one CRON trigger var found: Boolean = false diff --git a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt index 1603aaeda776..b05e38573e96 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt @@ -18,7 +18,7 @@ import projects.googleCloudRootProject class SweeperTests { @Test - fun projectSweeperProjectDoesNotSkipProjectSweep() { + fun projectSweeperDoesNotSkipProjectSweep() { val project = googleCloudRootProject(testContextParameters()) // Find Project sweeper project @@ -37,30 +37,33 @@ class SweeperTests { } @Test - fun gaNightlyProjectServiceSweeperSkipsProjectSweep() { + fun serviceSweepersSkipProjectSweeper() { val project = googleCloudRootProject(testContextParameters()) // Find GA nightly test project - val gaProject: Project? = project.subProjects.find { p-> p.name == gaProjectName} - if (gaProject == null) { - Assert.fail("Could not find the Google (GA) project") - } - val gaNightlyTestProject: Project? = gaProject!!.subProjects.find { p-> p.name == nightlyTestsProjectName} - if (gaNightlyTestProject == null) { - Assert.fail("Could not find the Google (GA) Nightly Test project") - } + val gaNightlyTestProject = getSubProject(project, gaProjectName, nightlyTestsProjectName) + // Find GA MM Upstream project + val gaMmUpstreamProject = getSubProject(project, gaProjectName, mmUpstreamProjectName) - // Find sweeper inside - val sweeper: BuildType? = gaNightlyTestProject!!.buildTypes.find { p-> p.name == ServiceSweeperName} - if (sweeper == null) { - Assert.fail("Could not find the sweeper build in the Google (GA) Nightly Test project") + // Find Beta nightly test project + val betaNightlyTestProject = getSubProject(project, betaProjectName, nightlyTestsProjectName) + // Find Beta MM Upstream project + val betaMmUpstreamProject = getSubProject(project, betaProjectName, mmUpstreamProjectName) + + val allProjects: ArrayList = arrayListOf(gaNightlyTestProject, gaMmUpstreamProject, betaNightlyTestProject, betaMmUpstreamProject) + allProjects.forEach{ project -> + // Find sweeper inside + val sweeper: BuildType? = project.buildTypes.find { p-> p.name == ServiceSweeperName} + if (sweeper == null) { + Assert.fail("Could not find the sweeper build in the ${project.name} project") + } + + // For the project sweeper to be skipped, SKIP_PROJECT_SWEEPER needs a value + // See https://github.com/GoogleCloudPlatform/magic-modules/blob/501429790939717ca6dce76dbf4b1b82aef4e9d9/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_sweeper.go#L18-L26 + + val value = sweeper!!.params.findRawParam("env.SKIP_PROJECT_SWEEPER")!!.value + assertTrue("env.SKIP_PROJECT_SWEEPER is set to a non-empty string in the sweeper build in the ${project.name} project. This means project sweepers are skipped. Value = `${value}` ", value != "") } - - // For the project sweeper to be skipped, SKIP_PROJECT_SWEEPER needs a value - // See https://github.com/GoogleCloudPlatform/magic-modules/blob/501429790939717ca6dce76dbf4b1b82aef4e9d9/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_sweeper.go#L18-L26 - - val value = sweeper!!.params.findRawParam("env.SKIP_PROJECT_SWEEPER")!!.value - assertTrue("env.SKIP_PROJECT_SWEEPER is set to a non-empty string, so project sweepers are skipped. Value = `${value}` ", value != "") } @Test @@ -68,14 +71,8 @@ class SweeperTests { val project = googleCloudRootProject(testContextParameters()) // Find GA nightly test project - val gaProject: Project? = project.subProjects.find { p-> p.name == gaProjectName} - if (gaProject == null) { - Assert.fail("Could not find the Google (GA) project") - } - val gaNightlyTestProject: Project? = gaProject!!.subProjects.find { p-> p.name == nightlyTestsProjectName} - if (gaNightlyTestProject == null) { - Assert.fail("Could not find the Google (GA) Nightly Test project") - } + val gaNightlyTestProject = getSubProject(project, gaProjectName, nightlyTestsProjectName) + // Find sweeper inside val sweeper: BuildType? = gaNightlyTestProject!!.buildTypes.find { p-> p.name == ServiceSweeperName} @@ -88,46 +85,12 @@ class SweeperTests { assertEquals("./google/sweeper", value) } - @Test - fun betaNightlyProjectServiceSweeperSkipsProjectSweep() { - val project = googleCloudRootProject(testContextParameters()) - - // Find Beta nightly test project - val betaProject: Project? = project.subProjects.find { p-> p.name == betaProjectName} - if (betaProject == null) { - Assert.fail("Could not find the Google (GA) project") - } - val betaNightlyTestProject: Project? = betaProject!!.subProjects.find { p-> p.name == nightlyTestsProjectName} - if (betaNightlyTestProject == null) { - Assert.fail("Could not find the Google (GA) Nightly Test project") - } - - // Find sweeper inside - val sweeper: BuildType? = betaNightlyTestProject!!.buildTypes.find { p-> p.name == ServiceSweeperName} - if (sweeper == null) { - Assert.fail("Could not find the sweeper build in the Google (GA) Nightly Test project") - } - - // For the project sweeper to be skipped, SKIP_PROJECT_SWEEPER needs a value - // See https://github.com/GoogleCloudPlatform/magic-modules/blob/501429790939717ca6dce76dbf4b1b82aef4e9d9/mmv1/third_party/terraform/services/resourcemanager/resource_google_project_sweeper.go#L18-L26 - - val value = sweeper!!.params.findRawParam("env.SKIP_PROJECT_SWEEPER")!!.value - assertTrue("env.SKIP_PROJECT_SWEEPER is set to a non-empty string, so project sweepers are skipped. Value = `${value}` ", value != "") - } - @Test fun betaNightlyProjectServiceSweeperRunsInGoogleBeta() { val project = googleCloudRootProject(testContextParameters()) // Find Beta nightly test project - val betaProject: Project? = project.subProjects.find { p-> p.name == betaProjectName} - if (betaProject == null) { - Assert.fail("Could not find the Google (GA) project") - } - val betaNightlyTestProject: Project? = betaProject!!.subProjects.find { p-> p.name == nightlyTestsProjectName} - if (betaNightlyTestProject == null) { - Assert.fail("Could not find the Google (GA) Nightly Test project") - } + val betaNightlyTestProject = getSubProject(project, betaProjectName, nightlyTestsProjectName) // Find sweeper inside val sweeper: BuildType? = betaNightlyTestProject!!.buildTypes.find { p-> p.name == ServiceSweeperName} diff --git a/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt b/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt index 747384496441..576e4b735c02 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt @@ -8,10 +8,13 @@ package tests import builds.AllContextParameters +import jetbrains.buildServer.configs.kotlin.Project +import org.junit.Assert const val gaProjectName = "Google" const val betaProjectName = "Google Beta" const val nightlyTestsProjectName = "Nightly Tests" +const val mmUpstreamProjectName = "MM Upstream Testing" const val projectSweeperProjectName = "Project Sweeper" fun testContextParameters(): AllContextParameters { @@ -49,4 +52,19 @@ fun testContextParameters(): AllContextParameters { "zone", "infraProject", "vcrBucketName") +} + +fun getSubProject(rootProject: Project, parentProjectName: String, subProjectName: String): Project { + // Find parent project within root + var parentProject: Project? = rootProject.subProjects.find { p-> p.name == parentProjectName} + if (parentProject == null) { + Assert.fail("Could not find the $parentProjectName project") + } + // Find subproject within parent identified above + var subProject: Project? = parentProject!!.subProjects.find { p-> p.name == subProjectName} + if (subProject == null) { + Assert.fail("Could not find the $subProjectName project") + } + + return subProject!! } \ No newline at end of file From 8a908339e6147aceec22c429faf7d6b23a3ca52a Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 1 Mar 2024 17:27:04 +0000 Subject: [PATCH 059/200] Update `teamcity-diff-check` script and GHAs to have more explicit calls to action (#10098) --- .../workflows/teamcity-services-diff-check-weekly.yml | 2 +- .github/workflows/teamcity-services-diff-check.yml | 2 +- tools/teamcity-diff-check/main.go | 9 +++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 577924f7cdaf..9626b3c9aa45 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -51,7 +51,7 @@ jobs: unzip -o artifacts/output.zip -d ./provider rm artifacts/output.zip - - name: Diff Check + - name: Check that new services have been added to the TeamCity configuration code run: | # Create lists of service packages in providers ls provider/google/services > tools/teamcity-diff-check/services_ga.txt diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml index 8034d6f87b43..a54137bd48b2 100644 --- a/.github/workflows/teamcity-services-diff-check.yml +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -75,7 +75,7 @@ jobs: unzip -o artifacts/output.zip -d ./provider rm artifacts/output.zip - - name: Diff Check + - name: Check that new services have been added to the TeamCity configuration code run: | # Create lists of service packages in providers ls provider/google/services > tools/teamcity-diff-check/services_ga.txt diff --git a/tools/teamcity-diff-check/main.go b/tools/teamcity-diff-check/main.go index b3a71436e8fa..577bdda526ca 100644 --- a/tools/teamcity-diff-check/main.go +++ b/tools/teamcity-diff-check/main.go @@ -45,7 +45,8 @@ func main() { //////////////////////////////////////////////////////////////////////////////// - f, err := os.Open(fmt.Sprintf("../../mmv1/third_party/terraform/.teamcity/components/inputs/%s", *serviceFile+".kt")) + filePath := fmt.Sprintf("mmv1/third_party/terraform/.teamcity/components/inputs/%s.kt", *serviceFile) + f, err := os.Open(fmt.Sprintf("../../%s", filePath)) // Need to make path relative to where the script is called if err != nil { panic(err) } @@ -79,13 +80,13 @@ func main() { teamcityServices = append(teamcityServices, string(service)) } if len(teamcityServices) == 0 { - fmt.Fprintf(os.Stderr, "teamcityServices error: regex produced no matches.\n") + fmt.Fprintf(os.Stderr, "error: script could not find any services listed in the file %s.kt .\n", filePath) os.Exit(1) } if diff := serviceDifference(googleServices, teamcityServices); len(diff) != 0 { - fmt.Fprintf(os.Stderr, "error: diff in %s\n", *serviceFile) - fmt.Fprintf(os.Stderr, "Missing Services: %s\n", diff) + fmt.Fprintf(os.Stderr, "error: missing services detected in %s\n", filePath) + fmt.Fprintf(os.Stderr, "Please update file to include these new services: %s\n", diff) os.Exit(1) } From 072343e86e659fed72711b63be269250b4526f7f Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 1 Mar 2024 17:27:47 +0000 Subject: [PATCH 060/200] TeamCity: enable ad hoc triggers of teamcity-diff-check GHA (#10099) --- .github/workflows/teamcity-services-diff-check-weekly.yml | 6 +++++- .github/workflows/teamcity-services-diff-check.yml | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 9626b3c9aa45..874fd3145913 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -2,8 +2,12 @@ name: TeamCity Services Weekly Diff Check permissions: read-all on: + # Enable ad hoc checks + workflow_dispatch: + + # Scheduled checks to catch edge cases schedule: - # Runs every tuesday morning + # Every Tuesday morning - cron: '0 4 * * 2' jobs: diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml index a54137bd48b2..f425a6e009f4 100644 --- a/.github/workflows/teamcity-services-diff-check.yml +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -2,7 +2,6 @@ name: TeamCity Services Diff Check permissions: read-all on: - workflow_dispatch: pull_request: paths: - '.github/workflows/teamcity-services-diff-check.yml' From c28bd3fa1805ea1a55e1bc3af9b691b0f84f90d4 Mon Sep 17 00:00:00 2001 From: "Francis (Feng) Liu" Date: Mon, 4 Mar 2024 06:34:41 -0800 Subject: [PATCH 061/200] Revert "fix forceNew on master_ipv4_cidr_block and private_endpoint_subnetwork (#10089)" (#10096) --- .../services/container/resource_container_cluster.go.erb | 2 ++ 1 file changed, 2 insertions(+) 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 b3471ce17ca3..00a3f3aaab84 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 @@ -1664,6 +1664,7 @@ func ResourceContainerCluster() *schema.Resource { Type: schema.TypeString, Computed: true, Optional: true, + ForceNew: true, AtLeastOneOf: privateClusterConfigKeys, ValidateFunc: verify.OrEmpty(validation.IsCIDRNetwork(28, 28)), Description: `The IP range in CIDR notation to use for the hosted master network. This range will be used for assigning private IP addresses to the cluster master(s) and the ILB VIP. This range must not overlap with any other ranges in use within the cluster's network, and it must be a /28 subnet. See Private Cluster Limitations for more details. This field only applies to private clusters, when enable_private_nodes is true.`, @@ -1681,6 +1682,7 @@ func ResourceContainerCluster() *schema.Resource { "private_endpoint_subnetwork": { Type: schema.TypeString, Optional: true, + ForceNew: true, AtLeastOneOf: privateClusterConfigKeys, DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, Description: `Subnetwork in cluster's network where master's endpoint will be provisioned.`, From f024ad5ee955f6140ea060e684fb7818f92a6c36 Mon Sep 17 00:00:00 2001 From: makuing <71718183+makuing@users.noreply.github.com> Date: Mon, 4 Mar 2024 17:03:01 +0100 Subject: [PATCH 062/200] subnetwork and service_account_email params described (17211) (#10102) * subnetwork and service_account_email params described (17211) * Doc adjustment --- .../website/docs/r/dataflow_flex_template_job.html.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown index d592b3fdb39c..992c142e8e5d 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataflow_flex_template_job.html.markdown @@ -118,6 +118,10 @@ provided, the provider project is used. * `region` - (Optional) The region in which the created job should run. +* `service_account_email` - (Optional) Service account email to run the workers as. + +* `subnetwork` - (Optional) Compute Engine subnetwork for launching instances to run your pipeline. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: From 9f98cde4b2e5946ec446d572c08d0ea15dfb6a57 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Mon, 4 Mar 2024 09:38:25 -0800 Subject: [PATCH 063/200] Update provider name in various spots (#10092) --- README.md | 4 +-- docs/content/best-practices/_index.md | 6 ++-- .../make-a-breaking-change.md | 12 ++++---- .../get-started/how-magic-modules-works.md | 2 +- .../terraform/META.d/_summary.yaml | 4 +-- .../docs/guides/getting_started.html.markdown | 6 ++-- .../guides/provider_reference.html.markdown | 4 +-- .../guides/version_2_upgrade.html.markdown | 8 ++--- .../guides/version_3_upgrade.html.markdown | 8 ++--- .../guides/version_4_upgrade.html.markdown | 8 ++--- .../guides/version_5_upgrade.html.markdown | 14 ++++----- .../website/docs/index.html.markdown | 30 +++++++++---------- tools/go-changelog/README.md | 3 +- tpgtools/README.md | 4 +-- 14 files changed, 56 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 1035baf6e4a7..5e40471b5628 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ # Magic Modules -Magic Modules is a code generator and CI system that's used to develop the Terraform providers -for Google Cloud Platform, [`google`](https://github.com/hashicorp/terraform-provider-google) (or TPG) and +Magic Modules is a code generator and CI system that's used to develop the Terraform provider +for Google Cloud, [`google`](https://github.com/hashicorp/terraform-provider-google) (or TPG) and [`google-beta`](https://github.com/hashicorp/terraform-provider-google-beta) (or TPGB). Magic Modules allows contributors to make changes against a single codebase and develop both diff --git a/docs/content/best-practices/_index.md b/docs/content/best-practices/_index.md index 81eebff07ebb..0942e110bf34 100644 --- a/docs/content/best-practices/_index.md +++ b/docs/content/best-practices/_index.md @@ -7,7 +7,7 @@ aliases: # Best practices -The following is a list of best practices that contributions are expected to follow in order to ensure a consistent UX for the Google Terraform provider internally and also compared to other Terraform providers. +The following is a list of best practices that contributions are expected to follow in order to ensure a consistent UX for the Terraform provider for Google Cloud internally and also compared to other Terraform providers. ## ForceNew @@ -44,7 +44,7 @@ See [magic-modules#13107](https://github.com/hashicorp/terraform-provider-google ## Add labels and annotations support -The new labels model and the new annotations model are introduced in [Terraform Google Provider 5.0.0](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_5_upgrade#provider). +The new labels model and the new annotations model are introduced in [Terraform provider for Google Cloud 5.0.0](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_5_upgrade#provider). There are now three label-related fields with the new labels model: * The `labels` field is now non-authoritative and only manages the label keys defined in your configuration for the resource. @@ -189,4 +189,4 @@ if err := tpgresource.SetDataSourceAnnotations(d); err != nil { 6. In the read mehtod, set `annotations`, and `effective_annotations` to state. 7. In the handwritten acceptance tests, add `annotations` to `ImportStateVerifyIgnore`. 8. In the corresponding data source, after the resource read method, call the function `tpgresource.SetDataSourceAnnotations(d)` to make `annotations` have all of the labels on the resource. -9. Add the documentation for these annotation-related fields. \ No newline at end of file +9. Add the documentation for these annotation-related fields. diff --git a/docs/content/develop/breaking-changes/make-a-breaking-change.md b/docs/content/develop/breaking-changes/make-a-breaking-change.md index d278a429d4dd..b9f28f9f860c 100644 --- a/docs/content/develop/breaking-changes/make-a-breaking-change.md +++ b/docs/content/develop/breaking-changes/make-a-breaking-change.md @@ -18,11 +18,11 @@ The `google` and `google-beta` providers are both considered "stable surfaces" for the purpose of releases, which means that neither provider allows breaking changes except during major releases, which are typically yearly. -Terraform users rely on the stability of Terraform providers (including the GCP -provider and other major providers.) Even as part of a major release, breaking -changes that are overly broad and/or have little benefit to users can cause -deeply negative reactions and significantly delay customers upgrading to the -new major version. +Terraform users rely on the stability of Terraform providers (including the +Google Cloud provider and other major providers.) Even as part of a major +release, breaking changes that are overly broad and/or have little benefit to +users can cause deeply negative reactions and significantly delay customers +upgrading to the new major version. Breaking changes may cause significant churn for users by forcing them to update their configurations. It also causes churn in tooling built on top of @@ -177,7 +177,7 @@ Entries should focus on the changes that users need to make when upgrading to `{{% param "majorVersion" %}}`, rather than how to write configurations after upgrading. -See [Terraform Google Provider 4.0.0 Upgrade Guide](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_4_upgrade) +See [Terraform provider for Google Cloud 4.0.0 Upgrade Guide](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_4_upgrade) and other upgrade guides for examples. The upgrade guide and the actual breaking change will be merged only after both are completed. diff --git a/docs/content/get-started/how-magic-modules-works.md b/docs/content/get-started/how-magic-modules-works.md index 6fc15e1549be..e11d54bccda9 100644 --- a/docs/content/get-started/how-magic-modules-works.md +++ b/docs/content/get-started/how-magic-modules-works.md @@ -8,7 +8,7 @@ aliases: # How Magic Modules works -Magic Modules can be thought of as a source of truth for how to map a GCP API resource representation to a Terraform resource (or datasource) representation. Magic Modules uses that mapping (and additional handwritten code where necessary) to generate "downstream" repositories - in particular, the Terraform providers for Google Platform: [`google`](https://github.com/hashicorp/terraform-provider-google) (or TPG) and [`google-beta`](https://github.com/hashicorp/terraform-provider-google-beta) (or TPGB). +Magic Modules can be thought of as a source of truth for how to map a GCP API resource representation to a Terraform resource (or datasource) representation. Magic Modules uses that mapping (and additional handwritten code where necessary) to generate "downstream" repositories - in particular, the Terraform providers for Google Cloud: [`google`](https://github.com/hashicorp/terraform-provider-google) (or TPG) and [`google-beta`](https://github.com/hashicorp/terraform-provider-google-beta) (or TPGB). Generation of the downstream repositories happens for every new commit in a PR (to a temporary branch owned by the [`modular-magician`](https://github.com/modular-magician/) robot user) and on every merge into the main branch (to the main branch of downstreams). Generation for PR commits allows contributors to manually examine the changes, as well as allowing automatic running of unit tests, acceptance tests, and automated checks such as breaking change detection. diff --git a/mmv1/third_party/terraform/META.d/_summary.yaml b/mmv1/third_party/terraform/META.d/_summary.yaml index c3dc9c1febb3..cef4b73691f1 100644 --- a/mmv1/third_party/terraform/META.d/_summary.yaml +++ b/mmv1/third_party/terraform/META.d/_summary.yaml @@ -7,6 +7,6 @@ partition: tf-ecosystem summary: owner: team-tf-hybrid-cloud description: | - The Terraform Google provider is a plugin that allows Terraform to manage resources on Google Cloud Platform. + The Terraform provider for Google Cloud is a plugin that allows Terraform to manage resources on Google Cloud. - visibility: external \ No newline at end of file + visibility: external diff --git a/mmv1/third_party/terraform/website/docs/guides/getting_started.html.markdown b/mmv1/third_party/terraform/website/docs/guides/getting_started.html.markdown index a329a71258e7..8ecb74a85217 100644 --- a/mmv1/third_party/terraform/website/docs/guides/getting_started.html.markdown +++ b/mmv1/third_party/terraform/website/docs/guides/getting_started.html.markdown @@ -1,10 +1,10 @@ --- -page_title: "Getting Started with the Google provider" +page_title: "Getting Started with the Google Cloud provider" description: |- - Getting started with the Google Cloud Platform provider + Getting started with the Google Cloud provider --- -# Getting Started with the Google Provider +# Getting Started with the Google Cloud provider ## Before you begin diff --git a/mmv1/third_party/terraform/website/docs/guides/provider_reference.html.markdown b/mmv1/third_party/terraform/website/docs/guides/provider_reference.html.markdown index 56642c7a8675..8b03ef435035 100644 --- a/mmv1/third_party/terraform/website/docs/guides/provider_reference.html.markdown +++ b/mmv1/third_party/terraform/website/docs/guides/provider_reference.html.markdown @@ -1,7 +1,7 @@ --- -page_title: "Google Provider Configuration Reference" +page_title: "Google Cloud Provider Configuration Reference" description: |- - Configuration reference for the Google provider for Terraform. + Configuration reference for the Terraform provider for Google Cloud. --- # Google Provider Configuration Reference diff --git a/mmv1/third_party/terraform/website/docs/guides/version_2_upgrade.html.markdown b/mmv1/third_party/terraform/website/docs/guides/version_2_upgrade.html.markdown index e3eb664de0e6..f7a3fafb7a67 100644 --- a/mmv1/third_party/terraform/website/docs/guides/version_2_upgrade.html.markdown +++ b/mmv1/third_party/terraform/website/docs/guides/version_2_upgrade.html.markdown @@ -1,12 +1,12 @@ --- -page_title: "Terraform Google Provider 2.0.0 Upgrade Guide" +page_title: "Terraform provider for Google Cloud 2.0.0 Upgrade Guide" description: |- - Terraform Google Provider 2.0.0 Upgrade Guide + Terraform provider for Google Cloud 2.0.0 Upgrade Guide --- -# Terraform Google Provider 2.0.0 Upgrade Guide +# Terraform provider for Google Cloud 2.0.0 Upgrade Guide -Version `2.0.0` of the Google provider for Terraform is a major release and +Version `2.0.0` of the Terraform provider for Google Cloud is a major release and includes some changes that you will need to consider when upgrading. This guide is intended to help with that process and focuses only on the changes necessary to upgrade from version `1.20.0` to `2.0.0`. diff --git a/mmv1/third_party/terraform/website/docs/guides/version_3_upgrade.html.markdown b/mmv1/third_party/terraform/website/docs/guides/version_3_upgrade.html.markdown index 06e5e64b36b4..305989cfae75 100644 --- a/mmv1/third_party/terraform/website/docs/guides/version_3_upgrade.html.markdown +++ b/mmv1/third_party/terraform/website/docs/guides/version_3_upgrade.html.markdown @@ -1,12 +1,12 @@ --- -page_title: "Terraform Google Provider 3.0.0 Upgrade Guide" +page_title: "Terraform provider for Google Cloud 3.0.0 Upgrade Guide" description: |- - Terraform Google Provider 3.0.0 Upgrade Guide + Terraform provider for Google Cloud 3.0.0 Upgrade Guide --- -# Terraform Google Provider 3.0.0 Upgrade Guide +# Terraform provider for Google Cloud 3.0.0 Upgrade Guide -The `3.0.0` release of the Google provider for Terraform is a major version and +The `3.0.0` release of the Terraform provider for Google Cloud is a major version and includes some changes that you will need to consider when upgrading. This guide is intended to help with that process and focuses only on the changes necessary to upgrade from the final `2.X` series release to `3.0.0`. diff --git a/mmv1/third_party/terraform/website/docs/guides/version_4_upgrade.html.markdown b/mmv1/third_party/terraform/website/docs/guides/version_4_upgrade.html.markdown index bad7cca87838..b34c133d1062 100644 --- a/mmv1/third_party/terraform/website/docs/guides/version_4_upgrade.html.markdown +++ b/mmv1/third_party/terraform/website/docs/guides/version_4_upgrade.html.markdown @@ -1,12 +1,12 @@ --- -page_title: "Terraform Google Provider 4.0.0 Upgrade Guide" +page_title: "Terraform provider for Google Cloud 4.0.0 Upgrade Guide" description: |- - Terraform Google Provider 4.0.0 Upgrade Guide + Terraform provider for Google Cloud 4.0.0 Upgrade Guide --- -# Terraform Google Provider 4.0.0 Upgrade Guide +# Terraform provider for Google Cloud 4.0.0 Upgrade Guide -The `4.0.0` release of the Google provider for Terraform is a major version and +The `4.0.0` release of the Terraform provider for Google Cloud is a major version and includes some changes that you will need to consider when upgrading. This guide is intended to help with that process and focuses only on the changes necessary to upgrade from the final `3.X` series release to `4.0.0`. diff --git a/mmv1/third_party/terraform/website/docs/guides/version_5_upgrade.html.markdown b/mmv1/third_party/terraform/website/docs/guides/version_5_upgrade.html.markdown index 1bd49e4d52c7..078ef0f0323a 100644 --- a/mmv1/third_party/terraform/website/docs/guides/version_5_upgrade.html.markdown +++ b/mmv1/third_party/terraform/website/docs/guides/version_5_upgrade.html.markdown @@ -1,12 +1,12 @@ --- -page_title: "Terraform Google Provider 5.0.0 Upgrade Guide" +page_title: "Terraform provider for Google Cloud 5.0.0 Upgrade Guide" description: |- - Terraform Google Provider 5.0.0 Upgrade Guide + Terraform provider for Google Cloud 5.0.0 Upgrade Guide --- -# Terraform Google Provider 5.0.0 Upgrade Guide +# Terraform provider for Google Cloud 5.0.0 Upgrade Guide -The `5.0.0` release of the Google provider for Terraform is a major version and +The `5.0.0` release of the Terraform provider for Google Cloud is a major version and includes some changes that you will need to consider when upgrading. This guide is intended to help with that process and focuses only on the changes necessary to upgrade from the final `4.X` series release to `5.0.0`. @@ -113,8 +113,8 @@ included in requests to the API. Replacing those labels' values with `_` or `true` are recommended. Not all of Google Cloud resources support labels and annotations. Please check -the Terraform Google provider resource documentation to figure out if a given -resource supports `labels` or `annotations` fields. +the resource documentation to figure out if a given resource supports `labels` +or `annotations` fields. #### Provider default labels @@ -188,7 +188,7 @@ Provider-level default annotations are not supported at this time. #### Resource labels -Previously, `labels` and `annotations` fields in the Terraform Google provider +Previously, `labels` and `annotations` fields in the Google Cloud provider were authoritative and Terraform thought it was the only owner of the fields. This model worked well initially, but with the introduction of system labels and other client-managed labels, Terraform would conflict with their labels and show diff --git a/mmv1/third_party/terraform/website/docs/index.html.markdown b/mmv1/third_party/terraform/website/docs/index.html.markdown index db9c0e41fbab..fee57ac9c426 100644 --- a/mmv1/third_party/terraform/website/docs/index.html.markdown +++ b/mmv1/third_party/terraform/website/docs/index.html.markdown @@ -1,12 +1,12 @@ --- -page_title: "Provider: Google Cloud Platform" +page_title: "Provider: Google Cloud" description: |- - The Google provider is used to configure your Google Cloud Platform infrastructure + The Terraform provider for Google Cloud is used to configure your Google Cloud infrastructure --- -# Google Cloud Platform Provider +# Terraform provider for Google Cloud -The Google provider is used to configure your [Google Cloud Platform](https://cloud.google.com/) infrastructure. +The Google Cloud provider is used to configure your [Google Cloud](https://cloud.google.com/) infrastructure. To learn the basics of Terraform using this provider, follow the hands-on [get started tutorials](https://developer.hashicorp.com/terraform/tutorials/gcp-get-started/infrastructure-as-code). @@ -14,7 +14,7 @@ For more involved examples, try [provisioning a GKE cluster](https://learn.hashi and deploying [Consul-backed Vault into it using Terraform Cloud](https://learn.hashicorp.com/tutorials/terraform/kubernetes-consul-vault-pipeline). Already experienced with Terraform? Check out the [Getting Started](/docs/providers/google/guides/getting_started.html) -page for a short introduction to using Terraform with Google Cloud Platform. +page for a short introduction to using Terraform with Google Cloud. ## Example Usage @@ -31,9 +31,9 @@ See the [provider reference](/docs/providers/google/guides/provider_reference.ht page for details on authentication and configuring the provider. Take advantage of [Modules](https://www.terraform.io/docs/modules/index.html) -to simplify your config by browsing the [Module Registry for GCP modules](https://registry.terraform.io/browse?provider=google). +to simplify your config by browsing the [Module Registry for Google Cloud modules](https://registry.terraform.io/browse?provider=google). -The Google provider is jointly maintained by: +The Google Cloud provider is jointly maintained by: * The [Terraform Team](https://cloud.google.com/docs/terraform) at Google * The Terraform team at [HashiCorp](https://www.hashicorp.com/) @@ -41,7 +41,7 @@ The Google provider is jointly maintained by: If you have configuration questions, or general questions about using the provider, try checking out: * [The Google category on discuss.hashicorp.com](https://discuss.hashicorp.com/c/terraform-providers/tf-google/32) -* The [Google Cloud Platform Community Slack](https://googlecloud-community.slack.com/) `#terraform` channel. If you are not registered with that Slack Workspace yet, the up-to-date **public sign-up link** can be found in the "Stay Connected" section of the [Google Developer Center](https://cloud.google.com/developers#stay-connected). +* The [Google Cloud Community Slack](https://googlecloud-community.slack.com/) `#terraform` channel. If you are not registered with that Slack Workspace yet, the up-to-date **public sign-up link** can be found in the "Stay Connected" section of the [Google Developer Center](https://cloud.google.com/developers#stay-connected). * [Terraform's community resources](https://www.terraform.io/docs/extend/community/index.html) * [HashiCorp support](https://support.hashicorp.com) for Terraform Enterprise customers @@ -53,22 +53,22 @@ and the [`google-beta` provider Releases](https://github.com/hashicorp/terraform for release notes and additional information. Per [Terraform Provider Versioning](https://www.hashicorp.com/blog/hashicorp-terraform-provider-versioning), -the Google provider follows [semantic versioning](https://semver.org/). +the Google Cloud provider follows [semantic versioning](https://semver.org/). In practice, patch / bugfix-only releases of the provider are infrequent. Most provider releases are either minor or major releases. ### Minor Releases -The Google provider currently aims to publish a minor release every week, +The Google Cloud provider currently aims to publish a minor release every week, although the timing of individual releases may differ if required by the provider team. ### Major Releases -The Google provider publishes major releases roughly yearly. An upgrade guide -will be published to help ease you through the transition between the prior -releases series and the new major release. +The Google Cloud provider publishes major releases roughly yearly. An upgrade +guide will be published to help ease you through the transition between the +prior releases series and the new major release. During major releases, all current deprecation warnings will be resolved, removing the field in question unless the deprecation warning message specifies @@ -80,7 +80,7 @@ lifecycle to give users plenty of time to safely update their configs. ## Features and Bug Requests -The Google provider's bugs and feature requests can be found in the [GitHub repo issues](https://github.com/hashicorp/terraform-provider-google/issues). +The Google Cloud provider's bugs and feature requests can be found in the [GitHub repo issues](https://github.com/hashicorp/terraform-provider-google/issues). Please avoid "me too" or "+1" comments. Instead, use a thumbs up [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) on enhancement requests. Provider maintainers will often prioritize work based on the number of thumbs on an issue. @@ -110,7 +110,7 @@ page for details on configuring the provider. ## Contributing -If you'd like to help extend the Google provider, we gladly accept community +If you'd like to help extend the Google Cloud provider, we gladly accept community contributions! Development on the providers is done through the [Magic Modules](https://github.com/GoogleCloudPlatform/magic-modules) repository. Our full contribution guide is available on the diff --git a/tools/go-changelog/README.md b/tools/go-changelog/README.md index 64967a73b685..5dcdaddf096b 100644 --- a/tools/go-changelog/README.md +++ b/tools/go-changelog/README.md @@ -156,8 +156,7 @@ formatting. ## Prior Art -This package is based on a bunch of experiments with the [Google Cloud Platform -Terraform provider](https://github.com/terraform-providers/terraform-provider-google) +This package is based on a bunch of experiments with the [Terraform provider for Google Cloud](https://github.com/terraform-providers/terraform-provider-google) and the lessons learned while generating it. It is also based on prior art in the community: diff --git a/tpgtools/README.md b/tpgtools/README.md index 3687768627a1..8ae74dddbfd9 100644 --- a/tpgtools/README.md +++ b/tpgtools/README.md @@ -1,7 +1,7 @@ # tpgtools `tpgtools` is the generator responsible for creating DCL-based resources in the -Terraform Google Provider (TPG). The DCL provides +Terraform provider for Google Cloud (TPG). The DCL provides [OpenAPI schema objects](https://swagger.io/specification/#schema-object) to describe the available types, and `tpgtools` uses those to construct Terraform resource schemas. @@ -55,7 +55,7 @@ go run . --path "api" --overrides "overrides" --output ~/some/dir --mode "serial ## New Resource Guide This guide is written to document the process for adding a resource to the -Google Terraform Provider (TPG) after it has been added to the +Terraform provider for Google Cloud (TPG) after it has been added to the [DCL](https://github.com/GoogleCloudPlatform/declarative-resource-client-library). ### Adding Resource Overrides From 49710e1ecf890aa538b8044aa261c1eed041e03e Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Mon, 4 Mar 2024 11:49:45 -0600 Subject: [PATCH 064/200] Go compiler skeleton and early terraform.rb provider code (#10104) --- mmv1/api/product.go | 24 + mmv1/api/product/version.go | 2 +- mmv1/go.mod | 5 +- mmv1/go.sum | 2 + mmv1/main.go | 111 +++-- mmv1/provider/terraform.go | 892 ++++++++++++++++++++++++++++++++++++ 6 files changed, 1000 insertions(+), 36 deletions(-) create mode 100644 mmv1/provider/terraform.go diff --git a/mmv1/api/product.go b/mmv1/api/product.go index f7b7b4235804..cf3bd9d33a48 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -15,6 +15,7 @@ package api import ( "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "golang.org/x/exp/slices" ) // require 'api/object' @@ -158,6 +159,29 @@ type Product struct { // false // end +func (p *Product) ExistsAtVersionOrLower(name string) bool { + if !slices.Contains(product.ORDER, name) { + return false + } + + for i := 0; i <= slices.Index(product.ORDER, name); i++ { + if p.ExistsAtVersion(product.ORDER[i]) { + return true + } + } + + return false +} + +func (p *Product) ExistsAtVersion(name string) bool { + for _, v := range p.Versions { + if v.Name == name { + return true + } + } + return false +} + // def exists_at_version(name) // // Versions aren't normally going to be empty since products need a // // base_url. This nil check exists for atypical products, like _bundle. diff --git a/mmv1/api/product/version.go b/mmv1/api/product/version.go index 16027fa61035..3c2ef6a670c0 100644 --- a/mmv1/api/product/version.go +++ b/mmv1/api/product/version.go @@ -15,7 +15,7 @@ package product // require 'api/object' -var ORDER = [...]string{"ga", "beta", "alpha", "private"} +var ORDER = []string{"ga", "beta", "alpha", "private"} // A version of the API for a given product / API group // In GCP, different product versions are generally ordered where alpha is diff --git a/mmv1/go.mod b/mmv1/go.mod index e9a5cebeee40..e1751dddea23 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -2,4 +2,7 @@ module github.com/GoogleCloudPlatform/magic-modules/mmv1 go 1.20 -require gopkg.in/yaml.v2 v2.4.0 // indirect +require ( + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/mmv1/go.sum b/mmv1/go.sum index 75346616b19b..0423d8d040b3 100644 --- a/mmv1/go.sum +++ b/mmv1/go.sum @@ -1,3 +1,5 @@ +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/mmv1/main.go b/mmv1/main.go index a7726a9a22f1..e969a8f8d02e 100644 --- a/mmv1/main.go +++ b/mmv1/main.go @@ -1,46 +1,62 @@ package main import ( - "encoding/json" "fmt" "log" "os" "path" "path/filepath" + "slices" "sort" "strings" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider" ) func main() { - var products_to_generate []string - var all_products = true + // TODO Q2: parse flags + var version = "beta" + var outputPath = "." + var generateCode = true + var generateDocs = true - var all_product_files []string = make([]string, 0) + log.Printf("Initiating go MM compiler") + + // TODO Q1: allow specifying one product (flag or hardcoded) + // var productsToGenerate []string + // var allProducts = true + var productsToGenerate = []string{"products/datafusion"} + var allProducts = false + + var allProductFiles []string = make([]string, 0) files, err := filepath.Glob("products/**/product.yaml") if err != nil { return } - for _, file_path := range files { - dir := filepath.Dir(file_path) - all_product_files = append(all_product_files, fmt.Sprintf("products/%s", filepath.Base(dir))) + for _, filePath := range files { + dir := filepath.Dir(filePath) + allProductFiles = append(allProductFiles, fmt.Sprintf("products/%s", filepath.Base(dir))) } + // TODO Q2: override directory - if all_products { - products_to_generate = all_product_files + if allProducts { + productsToGenerate = allProductFiles } - if products_to_generate == nil || len(products_to_generate) == 0 { + if productsToGenerate == nil || len(productsToGenerate) == 0 { log.Fatalf("No product.yaml file found.") } + log.Printf("Generating MM output to '%s'", outputPath) + log.Printf("Using %s version", version) + // Building compute takes a long time and can't be parallelized within the product // so lets build it first - sort.Slice(all_product_files, func(i int, j int) bool { - if all_product_files[i] == "compute" { + sort.Slice(allProductFiles, func(i int, j int) bool { + if allProductFiles[i] == "compute" { return true } return false @@ -48,31 +64,40 @@ func main() { yamlValidator := google.YamlValidator{} - for _, product_name := range all_product_files { - product_yaml_path := path.Join(product_name, "go_product.yaml") + for _, productName := range allProductFiles { + productYamlPath := path.Join(productName, "go_product.yaml") - // TODO: uncomment the error check that if the product.yaml exists for each product + // TODO Q2: uncomment the error check that if the product.yaml exists for each product // after Go-converted product.yaml files are complete for all products - - // if _, err := os.Stat(product_yaml_path); errors.Is(err, os.ErrNotExist) { - // log.Fatalf("%s does not contain a product.yaml file", product_name) + // if _, err := os.Stat(productYamlPath); errors.Is(err, os.ErrNotExist) { + // log.Fatalf("%s does not contain a product.yaml file", productName) // } - if _, err := os.Stat(product_yaml_path); err == nil { - log.Printf("product_yaml_path %#v", product_yaml_path) + // TODO Q2: product overrides + + if _, err := os.Stat(productYamlPath); err == nil { + // TODO Q1: remove these lines, which are for debugging + // log.Printf("productYamlPath %#v", productYamlPath) - productYaml, err := os.ReadFile(product_yaml_path) + var resources []api.Resource + + productYaml, err := os.ReadFile(productYamlPath) if err != nil { log.Fatalf("Cannot open the file: %v", productYaml) } productApi := api.Product{} yamlValidator.Parse(productYaml, &productApi) - // TODO: remove these lines, which are for debugging - prod, _ := json.Marshal(&productApi) - log.Printf("prod %s", string(prod)) + // TODO Q1: remove these lines, which are for debugging + // prod, _ := json.Marshal(&productApi) + // log.Printf("prod %s", string(prod)) + + if !productApi.ExistsAtVersionOrLower(version) { + log.Printf("%s does not have a '%s' version, skipping", productName, version) + continue + } - resourceFiles, err := filepath.Glob(fmt.Sprintf("%s/*", product_name)) + resourceFiles, err := filepath.Glob(fmt.Sprintf("%s/*", productName)) if err != nil { log.Fatalf("Cannot get resources files: %v", err) } @@ -81,17 +106,13 @@ func main() { continue } - // TODO REMOVE: limiting test block - // if !strings.Contains(resourceYamlPath, "datafusion") { - // continue - // } - // Prepend "go_" to the Go yaml files' name to distinguish with the ruby yaml files if filepath.Base(resourceYamlPath) == "go_product.yaml" || !strings.HasPrefix(filepath.Base(resourceYamlPath), "go_") { continue } - log.Printf(" resourceYamlPath %s", resourceYamlPath) + // TODO Q1: remove these lines, which are for debugging + // log.Printf(" resourceYamlPath %s", resourceYamlPath) resourceYaml, err := os.ReadFile(resourceYamlPath) if err != nil { log.Fatalf("Cannot open the file: %v", resourceYamlPath) @@ -99,10 +120,32 @@ func main() { resource := api.Resource{} yamlValidator.Parse(resourceYaml, &resource) - // TODO: remove these lines, which are for debugging - res, _ := json.Marshal(&resource) - log.Printf("resource %s", string(res)) + // TODO Q1: remove these lines, which are for debugging + // res, _ := json.Marshal(&resource) + // log.Printf("resource %s", string(res)) + + // TODO Q1: add labels related fields + + resources = append(resources, resource) } + + // TODO Q2: override resources + + // TODO Q1: sort resources by name and set in product + + // TODO Q2: set other providers via flag + providerToGenerate := provider.NewTerraform(productApi) + + if !slices.Contains(productsToGenerate, productName) { + log.Printf("%s not specified, skipping generation", productName) + continue + } + + // TODO Q1: generate templates + log.Printf("%s: Generating files", productName) + providerToGenerate.Generate(outputPath, productName, generateCode, generateDocs) } + + // TODO Q2: copy common files } } diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go new file mode 100644 index 000000000000..154e89c12736 --- /dev/null +++ b/mmv1/provider/terraform.go @@ -0,0 +1,892 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package provider + +import ( + "log" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" +) + +const TERRAFORM_PROVIDER_GA = "github.com/hashicorp/terraform-provider-google" +const TERRAFORM_PROVIDER_BETA = "github.com/hashicorp/terraform-provider-google-beta" +const TERRAFORM_PROVIDER_PRIVATE = "internal/terraform-next" +const RESOURCE_DIRECTORY_GA = "google" +const RESOURCE_DIRECTORY_BETA = "google-beta" +const RESOURCE_DIRECTORY_PRIVATE = "google-private" + +type Terraform struct { + ResourceCount int + + IAMResourceCount int + + ResourcesForVersion []api.Resource +} + +func NewTerraform(product api.Product) *Terraform { + t := Terraform{ResourceCount: 0, IAMResourceCount: 0} + + // TODO Q1 + // @target_version_name = version_name + // + // @version = @api.version_obj_or_closest(version_name) + // @api.set_properties_based_on_version(@version) + + return &t +} + +// +// # Main entry point for generation. +// def generate(output_folder, types, product_path, dump_yaml, generate_code, generate_docs) + +// end + +func (t *Terraform) Generate(outputFolder, productPath string, generateCode, generateDocs bool) { + log.Printf("Generate function called with %s %s %t %t", outputFolder, productPath, generateCode, generateDocs) + + // TODO Q1 + // generate_objects(output_folder, types, generate_code, generate_docs) + // + // 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 +} + +// +// # 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 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) +// +// generate_resources_for_version(products, @target_version_name) +// +// 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 +// +// # Gets the list of services dependent on the version ga, beta, and private +// # If there are some resources of a servcie is in GA, +// # then this service is in GA. Otherwise, the service is in BETA +// def get_mmv1_services_in_version(products, version) +// services = [] +// products.map do |product| +// product_definition = product[:definitions] +// if version == 'ga' +// some_resource_in_ga = false +// product_definition.objects.each do |object| +// break if some_resource_in_ga +// +// if !object.exclude && +// !object.not_in_version?(product_definition.version_obj_or_closest(version)) +// some_resource_in_ga = true +// end +// end +// +// services << product[:definitions].name.downcase if some_resource_in_ga +// else +// services << product[:definitions].name.downcase +// end +// end +// services +// 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 +// # Uncomment for go YAML +// # generate_object_modified object, output_folder, @target_version_name +// 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 generate_object_modified(object, output_folder, version_name) +// pwd = Dir.pwd +// data = build_object_data(pwd, object, output_folder, version_name) +// FileUtils.mkpath output_folder +// Dir.chdir output_folder +// Google::LOGGER.debug "Generating #{object.name} rewrite yaml" +// generate_newyaml(pwd, data.clone) +// Dir.chdir pwd +// end +// +// def generate_newyaml(pwd, data) +// # @api.api_name is the service folder name +// product_name = @api.api_name +// target_folder = File.join(folder_name(data.version), 'services', product_name) +// FileUtils.mkpath target_folder +// data.generate(pwd, +// '/templates/terraform/yaml_conversion.erb', +// "#{target_folder}/go_#{data.object.name}.yaml", +// self) +// return if File.exist?("#{target_folder}/go_product.yaml") +// +// data.generate(pwd, +// '/templates/terraform/product_yaml_conversion.erb', +// "#{target_folder}/go_product.yaml", +// self) +// 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 +// # non-HashiCorp downstreams. +// true +// end +// +// # ProductFileTemplate with Terraform specific fields +// class TerraformProductFileTemplate < Provider::ProductFileTemplate +// # The async object used for making operations. +// # We assume that all resources share the same async properties. +// attr_accessor :async +// +// # When generating OiCS examples, we attach the example we're +// # generating to the data object. +// attr_accessor :example +// +// attr_accessor :resource_name +// end +// +// # Sorts properties in the order they should appear in the TF schema: +// # Required, Optional, Computed +// def order_properties(properties) +// properties.select(&:required).sort_by(&:name) + +// properties.reject(&:required).reject(&:output).sort_by(&:name) + +// properties.select(&:output).sort_by(&:name) +// end +// +// def tf_type(property) +// tf_types[property.class] +// end +// +// # "Namespace" - prefix with product and resource - a property with +// # information from the "object" variable +// def namespace_property_from_object(property, object) +// name = property.name.camelize +// until property.parent.nil? +// property = property.parent +// name = property.name.camelize + name +// end +// +// "#{property.__resource.__product.api_name.camelize(:lower)}#{object.name}#{name}" +// end +// +// # Converts between the Magic Modules type of an object and its type in the +// # TF schema +// def tf_types +// { +// Api::Type::Boolean => 'schema.TypeBool', +// Api::Type::Double => 'schema.TypeFloat', +// Api::Type::Integer => 'schema.TypeInt', +// Api::Type::String => 'schema.TypeString', +// # Anonymous string property used in array of strings. +// 'Api::Type::String' => 'schema.TypeString', +// Api::Type::Time => 'schema.TypeString', +// Api::Type::Enum => 'schema.TypeString', +// Api::Type::ResourceRef => 'schema.TypeString', +// Api::Type::NestedObject => 'schema.TypeList', +// Api::Type::Array => 'schema.TypeList', +// Api::Type::KeyValuePairs => 'schema.TypeMap', +// Api::Type::KeyValueLabels => 'schema.TypeMap', +// Api::Type::KeyValueTerraformLabels => 'schema.TypeMap', +// Api::Type::KeyValueEffectiveLabels => 'schema.TypeMap', +// Api::Type::KeyValueAnnotations => 'schema.TypeMap', +// Api::Type::Map => 'schema.TypeSet', +// Api::Type::Fingerprint => 'schema.TypeString' +// } +// end +// +// def updatable?(resource, properties) +// !resource.immutable || !properties.reject { |p| p.update_url.nil? }.empty? +// end +// +// def force_new?(property, resource) +// ( +// (!property.output || property.is_a?(Api::Type::KeyValueEffectiveLabels)) && +// (property.immutable || +// (resource.immutable && property.update_url.nil? && property.immutable.nil? && +// (property.parent.nil? || +// (force_new?(property.parent, resource) && +// !(property.parent.flatten_object && property.is_a?(Api::Type::KeyValueLabels)) +// ) +// ) +// ) +// ) +// ) || +// (property.is_a?(Api::Type::KeyValueTerraformLabels) && +// !updatable?(resource, resource.all_user_properties) && !resource.root_labels? +// ) +// end +// +// # Returns tuples of (fieldName, list of update masks) for +// # top-level updatable fields. Schema path refers to a given Terraform +// # field name (e.g. d.GetChange('fieldName)') +// def get_property_update_masks_groups(properties, mask_prefix: '') +// mask_groups = [] +// properties.each do |prop| +// if prop.flatten_object +// mask_groups += get_property_update_masks_groups( +// prop.properties, mask_prefix: "#{prop.api_name}." +// ) +// elsif prop.update_mask_fields +// mask_groups << [prop.name.underscore, prop.update_mask_fields] +// else +// mask_groups << [prop.name.underscore, [mask_prefix + prop.api_name]] +// end +// end +// mask_groups +// end +// +// # Returns an updated path for a given Terraform field path (e.g. +// # 'a_field', 'parent_field.0.child_name'). Returns nil if the property +// # is not included in the resource's properties and removes keys that have +// # been flattened +// # FYI: Fields that have been renamed should use the new name, however, flattened +// # fields still need to be included, ie: +// # flattenedField > newParent > renameMe should be passed to this function as +// # flattened_field.0.new_parent.0.im_renamed +// # TODO(emilymye): Change format of input for +// # exactly_one_of/at_least_one_of/etc to use camelcase, MM properities and +// # convert to snake in this method +// def get_property_schema_path(schema_path, resource) +// nested_props = resource.properties +// prop = nil +// path_tkns = schema_path.split('.0.').map do |pname| +// camel_pname = pname.camelize(:lower) +// prop = nested_props.find { |p| p.name == camel_pname } +// # if we couldn't find it, see if it was renamed at the top level +// prop = nested_props.find { |p| p.name == schema_path } if prop.nil? +// return nil if prop.nil? +// +// nested_props = prop.nested_properties || [] +// prop.flatten_object ? nil : pname.underscore +// end +// if path_tkns.empty? || path_tkns[-1].nil? +// nil +// else +// path_tkns.compact.join('.0.') +// end +// end +// +// # Transforms a format string with field markers to a regex string with +// # capture groups. +// # +// # For instance, +// # projects/{{project}}/global/networks/{{name}} +// # is transformed to +// # projects/(?P[^/]+)/global/networks/(?P[^/]+) +// # +// # Values marked with % are URL-encoded, and will match any number of /'s. +// # +// # Note: ?P indicates a Python-compatible named capture group. Named groups +// # aren't common in JS-based regex flavours, but are in Perl-based ones +// def format2regex(format) +// format +// .gsub(/\{\{%([[:word:]]+)\}\}/, '(?P<\1>.+)') +// .gsub(/\{\{([[:word:]]+)\}\}/, '(?P<\1>[^/]+)') +// end +// +// # Capitalize the first letter of a property name. +// # E.g. "creationTimestamp" becomes "CreationTimestamp". +// def titlelize_property(property) +// property.name.camelize(:upper) +// end +// +// # Generates the list of resources, and gets the count of resources and iam resources +// # dependent on the version ga, beta or private. +// # The resource object has the format +// # { +// # terraform_name: +// # resource_name: +// # iam_class_name: +// # } +// # The variable resources_for_version is used to generate resources in file +// # mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +// def generate_resources_for_version(products, version) +// products.each do |product| +// product_definition = product[:definitions] +// service = product_definition.name.downcase +// product_definition.objects.each do |object| +// if object.exclude || +// object.not_in_version?(product_definition.version_obj_or_closest(version)) +// next +// end +// +// @resource_count += 1 unless object&.exclude_resource +// +// tf_product = (object.__product.legacy_name || product_definition.name).underscore +// terraform_name = object.legacy_name || "google_#{tf_product}_#{object.name.underscore}" +// +// unless object&.exclude_resource +// resource_name = "#{service}.Resource#{product_definition.name}#{object.name}" +// end +// +// iam_policy = object&.iam_policy +// +// @iam_resource_count += 3 unless iam_policy.nil? || iam_policy.exclude +// +// unless iam_policy.nil? || iam_policy.exclude || +// (iam_policy.min_version && iam_policy.min_version < version) +// iam_class_name = "#{service}.#{product_definition.name}#{object.name}" +// end +// +// @resources_for_version << { terraform_name:, resource_name:, iam_class_name: } +// end +// end +// +// @resources_for_version = @resources_for_version.compact +// end +// +// # TODO(nelsonjr): Review all object interfaces and move to private methods +// # that should not be exposed outside the object hierarchy. +// private +// +// def provider_name +// self.class.name.split('::').last.downcase +// 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}" +// end +// +// # This function uses the resource.erb template to create one file +// # per resource. The resource.erb template forms the basis of a single +// # GCP Resource on Terraform. +// def generate_resource(pwd, data, generate_code, generate_docs) +// if generate_code +// # @api.api_name is the service folder name +// product_name = @api.api_name +// target_folder = File.join(folder_name(data.version), 'services', product_name) +// FileUtils.mkpath target_folder +// data.generate(pwd, +// '/templates/terraform/resource.erb', +// "#{target_folder}/resource_#{full_resource_name(data)}.go", +// self) +// end +// +// return unless generate_docs +// +// generate_documentation(pwd, data) +// end +// +// def generate_documentation(pwd, data) +// target_folder = data.output_folder +// target_folder = File.join(target_folder, 'website', 'docs', 'r') +// FileUtils.mkpath target_folder +// filepath = File.join(target_folder, "#{full_resource_name(data)}.html.markdown") +// data.generate(pwd, 'templates/terraform/resource.html.markdown.erb', filepath, self) +// end +// +// def generate_resource_tests(pwd, data) +// return if data.object.examples +// .reject(&:skip_test) +// .reject do |e| +// @api.version_obj_or_closest(data.version) \ +// < @api.version_obj_or_closest(e.min_version) +// end +// .empty? +// +// product_name = @api.api_name +// target_folder = File.join(folder_name(data.version), 'services', product_name) +// FileUtils.mkpath folder_name(data.version) +// data.generate( +// pwd, +// 'templates/terraform/examples/base_configs/test_file.go.erb', +// "#{target_folder}/resource_#{full_resource_name(data)}_generated_test.go", +// self +// ) +// end +// +// def generate_resource_sweepers(pwd, data) +// return if data.object.skip_sweeper || +// data.object.custom_code.custom_delete || +// data.object.custom_code.pre_delete || +// data.object.custom_code.post_delete || +// data.object.skip_delete +// +// product_name = @api.api_name +// target_folder = File.join(folder_name(data.version), 'services', product_name) +// file_name = +// "#{target_folder}/resource_#{full_resource_name(data)}_sweeper.go" +// FileUtils.mkpath folder_name(data.version) +// data.generate(pwd, +// 'templates/terraform/sweeper_file.go.erb', +// file_name, +// self) +// end +// +// def generate_operation(pwd, output_folder, _types) +// return if @api.objects.select(&:autogen_async).empty? +// +// product_name = @api.api_name +// product_name_underscore = @api.name.underscore +// data = build_object_data(pwd, @api.objects.first, output_folder, @target_version_name) +// +// data.object = @api.objects.select(&:autogen_async).first +// +// data.async = data.object.async +// target_folder = File.join(folder_name(data.version), 'services', product_name) +// FileUtils.mkpath target_folder +// data.generate(pwd, +// 'templates/terraform/operation.go.erb', +// "#{target_folder}/#{product_name_underscore}_operation.go", +// self) +// end +// +// # Generate the IAM policy for this object. This is used to query and test +// # IAM policies separately from the resource itself +// def generate_iam_policy(pwd, data, generate_code, generate_docs) +// if generate_code \ +// && (!data.object.iam_policy.min_version \ +// || data.object.iam_policy.min_version >= data.version) +// product_name = @api.api_name +// target_folder = File.join(folder_name(data.version), 'services', product_name) +// FileUtils.mkpath target_folder +// data.generate(pwd, +// 'templates/terraform/iam_policy.go.erb', +// "#{target_folder}/iam_#{full_resource_name(data)}.go", +// self) +// +// # Only generate test if testable examples exist. +// unless data.object.examples.reject(&:skip_test).empty? +// data.generate( +// pwd, +// 'templates/terraform/examples/base_configs/iam_test_file.go.erb', +// "#{target_folder}/iam_#{full_resource_name(data)}_generated_test.go", +// self +// ) +// end +// end +// +// return unless generate_docs +// +// generate_iam_documentation(pwd, data) +// end +// +// def generate_iam_documentation(pwd, data) +// target_folder = data.output_folder +// resource_doc_folder = File.join(target_folder, 'website', 'docs', 'r') +// datasource_doc_folder = File.join(target_folder, 'website', 'docs', 'd') +// FileUtils.mkpath resource_doc_folder +// filepath = +// File.join(resource_doc_folder, "#{full_resource_name(data)}_iam.html.markdown") +// +// data.generate(pwd, 'templates/terraform/resource_iam.html.markdown.erb', filepath, self) +// FileUtils.mkpath datasource_doc_folder +// filepath = +// File.join(datasource_doc_folder, "#{full_resource_name(data)}_iam_policy.html.markdown") +// +// data.generate(pwd, 'templates/terraform/datasource_iam.html.markdown.erb', filepath, self) +// end +// +// def build_object_data(_pwd, object, output_folder, version) +// TerraformProductFileTemplate.file_for_resource( +// output_folder, +// object, +// version, +// build_env +// ) +// end +// +// def extract_identifiers(url) +// url.scan(/\{\{%?(\w+)\}\}/).flatten +// end +// +// # Returns the id format of an object, or self_link_uri if none is explicitly defined +// # We prefer the long name of a resource as the id so that users can reference +// # resources in a standard way, and most APIs accept short name, long name or self_link +// def id_format(object) +// object.id_format || object.self_link_uri +// end +// +// def full_resource_name(data) +// if data.object.legacy_name +// data.object.legacy_name.sub(/^google_/, '') +// else +// name = data.object.filename_override || data.object.name.underscore +// product_name = data.product.legacy_name || data.product.name.underscore +// "#{product_name}_#{name}" +// end +// end +// +// # Returns the extension for DCL packages for the given version. This is needed +// # as the DCL uses "alpha" for preview resources, while we use "private" +// def dcl_version(version) +// return '' if version == 'ga' +// return '/beta' if version == 'beta' +// return '/alpha' if version == 'private' +// end +// end +//end +// From 7d29d87449a4eb85dffc4d9bf5a4924c659cdb02 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Mon, 4 Mar 2024 18:08:55 +0000 Subject: [PATCH 065/200] Remove provider-related caches to address cache issues (#10097) We keep exceeding the 10GB cache limit for the repo, resulting in workflows stalling for 30min on caching steps and then timing out. --- .github/workflows/test-tpg.yml | 10 ---------- .github/workflows/unit-test-tpg.yml | 11 ----------- 2 files changed, 21 deletions(-) diff --git a/.github/workflows/test-tpg.yml b/.github/workflows/test-tpg.yml index 0b5148f7d1e2..dd05cecf003a 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -41,16 +41,6 @@ jobs: repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} ref: ${{ github.event.inputs.branch }} fetch-depth: 2 - - name: Cache Go modules and build cache - uses: actions/cache@v3 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-test-${{ github.event.inputs.repo }}-${{hashFiles('go.sum','google-*/transport/**','google-*/tpgresource/**','google-*/acctest/**','google-*/envvar/**','google-*/sweeper/**','google-*/verify/**') }} - restore-keys: | - ${{ runner.os }}-test-${{ github.event.inputs.repo }}-${{ hashFiles('go.sum') }} - ${{ runner.os }}-test-${{ github.event.inputs.repo }}- - name: Check for Code Changes id: pull_request run: | diff --git a/.github/workflows/unit-test-tpg.yml b/.github/workflows/unit-test-tpg.yml index ddb48186ff43..23aa27e848ed 100644 --- a/.github/workflows/unit-test-tpg.yml +++ b/.github/workflows/unit-test-tpg.yml @@ -30,17 +30,6 @@ jobs: with: go-version: '^1.20' - - name: Cache Go modules and build cache - uses: actions/cache@v3 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ${{ runner.os }}-test-${{ inputs.repo }}-${{hashFiles('go.sum','google-*/transport/**','google-*/tpgresource/**','google-*/acctest/**','google-*/envvar/**','google-*/sweeper/**','google-*/verify/**') }} - restore-keys: | - ${{ runner.os }}-test-${{ inputs.repo }}-${{ hashFiles('go.sum') }} - ${{ runner.os }}-test-${{ inputs.repo }}- - - name: Build Provider run: | go build From ae819d0619edd36414af1c5dc5f9e68a6b999174 Mon Sep 17 00:00:00 2001 From: Lingkai Shen Date: Mon, 4 Mar 2024 13:10:25 -0500 Subject: [PATCH 066/200] Fix hashicorp/terraform-provider-google#17388 (only run tests in beta) (#10093) --- mmv1/products/firebaseappcheck/AppAttestConfig.yaml | 2 ++ mmv1/products/firebaseappcheck/DebugToken.yaml | 1 + mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml | 2 ++ .../firebaseappcheck/RecaptchaEnterpriseConfig.yaml | 1 + mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml | 1 + .../firebase_app_check_app_attest_config_full.tf.erb | 4 ++++ .../firebase_app_check_app_attest_config_minimal.tf.erb | 4 ++++ .../examples/firebase_app_check_debug_token_basic.tf.erb | 8 ++++++-- .../firebase_app_check_play_integrity_config_full.tf.erb | 4 ++++ ...irebase_app_check_play_integrity_config_minimal.tf.erb | 4 ++++ ...ase_app_check_recaptcha_enterprise_config_basic.tf.erb | 4 ++++ .../firebase_app_check_recaptcha_v3_config_basic.tf.erb | 4 ++++ .../resource_firebase_app_check_app_attest_config_test.go | 2 +- .../resource_firebase_app_check_debug_token_test.go | 6 +++++- ...ource_firebase_app_check_play_integrity_config_test.go | 2 +- ...firebase_app_check_recaptcha_enterprise_config_test.go | 2 +- ...esource_firebase_app_check_recaptcha_v3_config_test.go | 2 +- 17 files changed, 46 insertions(+), 7 deletions(-) diff --git a/mmv1/products/firebaseappcheck/AppAttestConfig.yaml b/mmv1/products/firebaseappcheck/AppAttestConfig.yaml index 025e59fbcca9..9a92b7ed0c6e 100644 --- a/mmv1/products/firebaseappcheck/AppAttestConfig.yaml +++ b/mmv1/products/firebaseappcheck/AppAttestConfig.yaml @@ -37,6 +37,7 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_app_attest_config_minimal" + min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" @@ -50,6 +51,7 @@ examples: project_id: :PROJECT_NAME - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_app_attest_config_full" + min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/products/firebaseappcheck/DebugToken.yaml b/mmv1/products/firebaseappcheck/DebugToken.yaml index 4a6867760d36..e555a2ecd794 100644 --- a/mmv1/products/firebaseappcheck/DebugToken.yaml +++ b/mmv1/products/firebaseappcheck/DebugToken.yaml @@ -38,6 +38,7 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_debug_token_basic" + min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml b/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml index 7631e64d1a4b..8081a0c91f47 100644 --- a/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml +++ b/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml @@ -37,6 +37,7 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_play_integrity_config_minimal" + min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" @@ -46,6 +47,7 @@ examples: project_id: :PROJECT_NAME - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_play_integrity_config_full" + min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/products/firebaseappcheck/RecaptchaEnterpriseConfig.yaml b/mmv1/products/firebaseappcheck/RecaptchaEnterpriseConfig.yaml index a103c5dfb226..7d0dd0fb6b08 100644 --- a/mmv1/products/firebaseappcheck/RecaptchaEnterpriseConfig.yaml +++ b/mmv1/products/firebaseappcheck/RecaptchaEnterpriseConfig.yaml @@ -36,6 +36,7 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_recaptcha_enterprise_config_basic" + min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml b/mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml index 1e42c4796246..c259d076ee9e 100644 --- a/mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml +++ b/mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml @@ -36,6 +36,7 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_recaptcha_v3_config_basic" + min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_full.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_full.tf.erb index 134ecacfc5f8..4ef023c54153 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_full.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_full.tf.erb @@ -1,4 +1,6 @@ resource "google_firebase_apple_app" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Apple app" bundle_id = "<%= ctx[:vars]['bundle_id'] %>" @@ -13,6 +15,8 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_app_attest_config" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_apple_app.default.app_id token_ttl = "<%= ctx[:vars]['token_ttl'] %>" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_minimal.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_minimal.tf.erb index a25a7f2d698f..4ecb2eb56a87 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_minimal.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_minimal.tf.erb @@ -1,4 +1,6 @@ resource "google_firebase_apple_app" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Apple app" bundle_id = "<%= ctx[:vars]['bundle_id'] %>" @@ -13,6 +15,8 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_app_attest_config" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_apple_app.default.app_id diff --git a/mmv1/templates/terraform/examples/firebase_app_check_debug_token_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_debug_token_basic.tf.erb index 2434f163f5c0..4b27b397b226 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_debug_token_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_debug_token_basic.tf.erb @@ -1,16 +1,20 @@ resource "google_firebase_web_app" "default" { - project = "<%= ctx[:test_env_vars]['project_id'] %>" + provider = google-beta + + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Web App for debug token" } # It takes a while for App Check to recognize the new app # If your app already exists, you don't have to wait 30 seconds. resource "time_sleep" "wait_30s" { - depends_on = [google_firebase_web_app.default] + depends_on = [google_firebase_web_app.default] create_duration = "30s" } resource "google_firebase_app_check_debug_token" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_web_app.default.app_id display_name = "<%= ctx[:vars]['display_name'] %>" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_full.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_full.tf.erb index 78559763e319..5ec82cf383bb 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_full.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_full.tf.erb @@ -1,4 +1,6 @@ resource "google_firebase_android_app" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Play Integrity app" package_name = "<%= ctx[:vars]['package_name'] %>" @@ -14,6 +16,8 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_play_integrity_config" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_android_app.default.app_id token_ttl = "<%= ctx[:vars]['token_ttl'] %>" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_minimal.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_minimal.tf.erb index 4aacde367414..e360e1e07d08 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_minimal.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_minimal.tf.erb @@ -1,4 +1,6 @@ resource "google_firebase_android_app" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Play Integrity app" package_name = "<%= ctx[:vars]['package_name'] %>" @@ -14,6 +16,8 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_play_integrity_config" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_android_app.default.app_id diff --git a/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_enterprise_config_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_enterprise_config_basic.tf.erb index 806dfe37a16d..88435881cd40 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_enterprise_config_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_enterprise_config_basic.tf.erb @@ -1,4 +1,6 @@ resource "google_firebase_web_app" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Web App for reCAPTCHA Enterprise" } @@ -11,6 +13,8 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_recaptcha_enterprise_config" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_web_app.default.app_id site_key = "<%= ctx[:vars]['site_key'] %>" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_v3_config_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_v3_config_basic.tf.erb index 4b4c88b7ddd7..18b6a671ea72 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_v3_config_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_v3_config_basic.tf.erb @@ -1,4 +1,6 @@ resource "google_firebase_web_app" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Web App for reCAPTCHA V3" } @@ -11,6 +13,8 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_recaptcha_v3_config" "default" { + provider = google-beta + project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_web_app.default.app_id site_secret = "<%= ctx[:vars]['site_secret'] %>" diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_app_attest_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_app_attest_config_test.go index a1b05b852feb..2e3627bb5448 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_app_attest_config_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_app_attest_config_test.go @@ -21,7 +21,7 @@ func TestAccFirebaseAppCheckAppAttestConfig_firebaseAppCheckAppAttestConfigUpdat acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_debug_token_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_debug_token_test.go index e0e205580be9..1016785e0fe5 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_debug_token_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_debug_token_test.go @@ -26,7 +26,7 @@ func TestAccFirebaseAppCheckDebugToken_firebaseAppCheckDebugTokenUpdate(t *testi acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, @@ -58,6 +58,8 @@ func TestAccFirebaseAppCheckDebugToken_firebaseAppCheckDebugTokenUpdate(t *testi func testAccFirebaseAppCheckDebugToken_firebaseAppCheckDebugTokenTemplate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_firebase_web_app" "default" { + provider = google-beta + project = "%{project_id}" display_name = "Web App for debug token" } @@ -70,6 +72,8 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_debug_token" "default" { + provider = google-beta + project = "%{project_id}" app_id = google_firebase_web_app.default.app_id display_name = "%{display_name}" diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_play_integrity_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_play_integrity_config_test.go index c97df9fd1fab..a29a25a005a3 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_play_integrity_config_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_play_integrity_config_test.go @@ -20,7 +20,7 @@ func TestAccFirebaseAppCheckPlayIntegrityConfig_firebaseAppCheckPlayIntegrityCon acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_enterprise_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_enterprise_config_test.go index 6d0a91601ea7..77d3bb140a33 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_enterprise_config_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_enterprise_config_test.go @@ -28,7 +28,7 @@ func TestAccFirebaseAppCheckRecaptchaEnterpriseConfig_firebaseAppCheckRecaptchaE acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_v3_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_v3_config_test.go index 961215b8f63e..83d741a71c6c 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_v3_config_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_v3_config_test.go @@ -28,7 +28,7 @@ func TestAccFirebaseAppCheckRecaptchaV3Config_firebaseAppCheckRecaptchaV3ConfigU acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, From 712cce7da0b4d17e9ee5295c2df2ae67df9d4118 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Mon, 4 Mar 2024 13:32:26 -0800 Subject: [PATCH 067/200] Revert "Fix hashicorp/terraform-provider-google#17388 (only run tests in beta)" (#10111) This reverts commit ae819d0619edd36414af1c5dc5f9e68a6b999174. --- mmv1/products/firebaseappcheck/AppAttestConfig.yaml | 2 -- mmv1/products/firebaseappcheck/DebugToken.yaml | 1 - mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml | 2 -- .../firebaseappcheck/RecaptchaEnterpriseConfig.yaml | 1 - mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml | 1 - .../firebase_app_check_app_attest_config_full.tf.erb | 4 ---- .../firebase_app_check_app_attest_config_minimal.tf.erb | 4 ---- .../examples/firebase_app_check_debug_token_basic.tf.erb | 8 ++------ .../firebase_app_check_play_integrity_config_full.tf.erb | 4 ---- ...irebase_app_check_play_integrity_config_minimal.tf.erb | 4 ---- ...ase_app_check_recaptcha_enterprise_config_basic.tf.erb | 4 ---- .../firebase_app_check_recaptcha_v3_config_basic.tf.erb | 4 ---- .../resource_firebase_app_check_app_attest_config_test.go | 2 +- .../resource_firebase_app_check_debug_token_test.go | 6 +----- ...ource_firebase_app_check_play_integrity_config_test.go | 2 +- ...firebase_app_check_recaptcha_enterprise_config_test.go | 2 +- ...esource_firebase_app_check_recaptcha_v3_config_test.go | 2 +- 17 files changed, 7 insertions(+), 46 deletions(-) diff --git a/mmv1/products/firebaseappcheck/AppAttestConfig.yaml b/mmv1/products/firebaseappcheck/AppAttestConfig.yaml index 9a92b7ed0c6e..025e59fbcca9 100644 --- a/mmv1/products/firebaseappcheck/AppAttestConfig.yaml +++ b/mmv1/products/firebaseappcheck/AppAttestConfig.yaml @@ -37,7 +37,6 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_app_attest_config_minimal" - min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" @@ -51,7 +50,6 @@ examples: project_id: :PROJECT_NAME - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_app_attest_config_full" - min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/products/firebaseappcheck/DebugToken.yaml b/mmv1/products/firebaseappcheck/DebugToken.yaml index e555a2ecd794..4a6867760d36 100644 --- a/mmv1/products/firebaseappcheck/DebugToken.yaml +++ b/mmv1/products/firebaseappcheck/DebugToken.yaml @@ -38,7 +38,6 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_debug_token_basic" - min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml b/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml index 8081a0c91f47..7631e64d1a4b 100644 --- a/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml +++ b/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml @@ -37,7 +37,6 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_play_integrity_config_minimal" - min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" @@ -47,7 +46,6 @@ examples: project_id: :PROJECT_NAME - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_play_integrity_config_full" - min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/products/firebaseappcheck/RecaptchaEnterpriseConfig.yaml b/mmv1/products/firebaseappcheck/RecaptchaEnterpriseConfig.yaml index 7d0dd0fb6b08..a103c5dfb226 100644 --- a/mmv1/products/firebaseappcheck/RecaptchaEnterpriseConfig.yaml +++ b/mmv1/products/firebaseappcheck/RecaptchaEnterpriseConfig.yaml @@ -36,7 +36,6 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_recaptcha_enterprise_config_basic" - min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml b/mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml index c259d076ee9e..1e42c4796246 100644 --- a/mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml +++ b/mmv1/products/firebaseappcheck/RecaptchaV3Config.yaml @@ -36,7 +36,6 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: "firebase_app_check_recaptcha_v3_config_basic" - min_version: 'beta' # Need the time_sleep resource pull_external: true primary_resource_id: "default" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_full.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_full.tf.erb index 4ef023c54153..134ecacfc5f8 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_full.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_full.tf.erb @@ -1,6 +1,4 @@ resource "google_firebase_apple_app" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Apple app" bundle_id = "<%= ctx[:vars]['bundle_id'] %>" @@ -15,8 +13,6 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_app_attest_config" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_apple_app.default.app_id token_ttl = "<%= ctx[:vars]['token_ttl'] %>" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_minimal.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_minimal.tf.erb index 4ecb2eb56a87..a25a7f2d698f 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_minimal.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_app_attest_config_minimal.tf.erb @@ -1,6 +1,4 @@ resource "google_firebase_apple_app" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Apple app" bundle_id = "<%= ctx[:vars]['bundle_id'] %>" @@ -15,8 +13,6 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_app_attest_config" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_apple_app.default.app_id diff --git a/mmv1/templates/terraform/examples/firebase_app_check_debug_token_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_debug_token_basic.tf.erb index 4b27b397b226..2434f163f5c0 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_debug_token_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_debug_token_basic.tf.erb @@ -1,20 +1,16 @@ resource "google_firebase_web_app" "default" { - provider = google-beta - - project = "<%= ctx[:test_env_vars]['project_id'] %>" + project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Web App for debug token" } # It takes a while for App Check to recognize the new app # If your app already exists, you don't have to wait 30 seconds. resource "time_sleep" "wait_30s" { - depends_on = [google_firebase_web_app.default] + depends_on = [google_firebase_web_app.default] create_duration = "30s" } resource "google_firebase_app_check_debug_token" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_web_app.default.app_id display_name = "<%= ctx[:vars]['display_name'] %>" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_full.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_full.tf.erb index 5ec82cf383bb..78559763e319 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_full.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_full.tf.erb @@ -1,6 +1,4 @@ resource "google_firebase_android_app" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Play Integrity app" package_name = "<%= ctx[:vars]['package_name'] %>" @@ -16,8 +14,6 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_play_integrity_config" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_android_app.default.app_id token_ttl = "<%= ctx[:vars]['token_ttl'] %>" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_minimal.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_minimal.tf.erb index e360e1e07d08..4aacde367414 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_minimal.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_play_integrity_config_minimal.tf.erb @@ -1,6 +1,4 @@ resource "google_firebase_android_app" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Play Integrity app" package_name = "<%= ctx[:vars]['package_name'] %>" @@ -16,8 +14,6 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_play_integrity_config" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_android_app.default.app_id diff --git a/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_enterprise_config_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_enterprise_config_basic.tf.erb index 88435881cd40..806dfe37a16d 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_enterprise_config_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_enterprise_config_basic.tf.erb @@ -1,6 +1,4 @@ resource "google_firebase_web_app" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Web App for reCAPTCHA Enterprise" } @@ -13,8 +11,6 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_recaptcha_enterprise_config" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_web_app.default.app_id site_key = "<%= ctx[:vars]['site_key'] %>" diff --git a/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_v3_config_basic.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_v3_config_basic.tf.erb index 18b6a671ea72..4b4c88b7ddd7 100644 --- a/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_v3_config_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firebase_app_check_recaptcha_v3_config_basic.tf.erb @@ -1,6 +1,4 @@ resource "google_firebase_web_app" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" display_name = "Web App for reCAPTCHA V3" } @@ -13,8 +11,6 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_recaptcha_v3_config" "default" { - provider = google-beta - project = "<%= ctx[:test_env_vars]['project_id'] %>" app_id = google_firebase_web_app.default.app_id site_secret = "<%= ctx[:vars]['site_secret'] %>" diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_app_attest_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_app_attest_config_test.go index 2e3627bb5448..a1b05b852feb 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_app_attest_config_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_app_attest_config_test.go @@ -21,7 +21,7 @@ func TestAccFirebaseAppCheckAppAttestConfig_firebaseAppCheckAppAttestConfigUpdat acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_debug_token_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_debug_token_test.go index 1016785e0fe5..e0e205580be9 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_debug_token_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_debug_token_test.go @@ -26,7 +26,7 @@ func TestAccFirebaseAppCheckDebugToken_firebaseAppCheckDebugTokenUpdate(t *testi acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, @@ -58,8 +58,6 @@ func TestAccFirebaseAppCheckDebugToken_firebaseAppCheckDebugTokenUpdate(t *testi func testAccFirebaseAppCheckDebugToken_firebaseAppCheckDebugTokenTemplate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_firebase_web_app" "default" { - provider = google-beta - project = "%{project_id}" display_name = "Web App for debug token" } @@ -72,8 +70,6 @@ resource "time_sleep" "wait_30s" { } resource "google_firebase_app_check_debug_token" "default" { - provider = google-beta - project = "%{project_id}" app_id = google_firebase_web_app.default.app_id display_name = "%{display_name}" diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_play_integrity_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_play_integrity_config_test.go index a29a25a005a3..c97df9fd1fab 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_play_integrity_config_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_play_integrity_config_test.go @@ -20,7 +20,7 @@ func TestAccFirebaseAppCheckPlayIntegrityConfig_firebaseAppCheckPlayIntegrityCon acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_enterprise_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_enterprise_config_test.go index 77d3bb140a33..6d0a91601ea7 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_enterprise_config_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_enterprise_config_test.go @@ -28,7 +28,7 @@ func TestAccFirebaseAppCheckRecaptchaEnterpriseConfig_firebaseAppCheckRecaptchaE acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_v3_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_v3_config_test.go index 83d741a71c6c..961215b8f63e 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_v3_config_test.go +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_recaptcha_v3_config_test.go @@ -28,7 +28,7 @@ func TestAccFirebaseAppCheckRecaptchaV3Config_firebaseAppCheckRecaptchaV3ConfigU acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), ExternalProviders: map[string]resource.ExternalProvider{ "random": {}, "time": {}, From 3ccc673c9b2202948591b546ae21658ea4f19d8a Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Mon, 4 Mar 2024 16:36:27 -0500 Subject: [PATCH 068/200] Add support for string --> object map for DCL resources (#10039) * Add support for string --> object map for DCL resources * Fix whitespace in template * Add test, need updated DCL to work * Add override for key name * Both overrides * Update docs, prepend key for maps * Update bundle descriptions * Comment update --- mmv1/third_party/terraform/go.mod.erb | 2 +- mmv1/third_party/terraform/go.sum | 2 + ...rce_gke_hub_feature_membership_test.go.erb | 96 ++++++++++++++++++- .../gke_hub_feature_membership.html.markdown | 89 +++++++++++++++++ tpgtools/go.mod | 2 +- tpgtools/go.sum | 8 +- tpgtools/override.go | 1 + tpgtools/override_details.go | 5 + .../gkehub/beta/feature_membership.yaml | 8 ++ .../overrides/gkehub/feature_membership.yaml | 10 +- tpgtools/property.go | 61 +++++++++++- tpgtools/templates/resource.go.tmpl | 60 +++++++++++- tpgtools/type.go | 7 +- 13 files changed, 330 insertions(+), 21 deletions(-) diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index b5d4fd065d93..fa30a092113d 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -5,7 +5,7 @@ go 1.20 require ( cloud.google.com/go/bigtable v1.19.0 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.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 6837513a22df..63d8188cf48c 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -413,3 +413,5 @@ 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.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= diff --git a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb index d231ea19e62c..a7ab46c640a6 100644 --- a/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb +++ b/mmv1/third_party/terraform/services/gkehub/resource_gke_hub_feature_membership_test.go.erb @@ -1008,6 +1008,17 @@ func TestAccGKEHubFeatureMembership_gkehubFeaturePolicyController(t *testing.T) ImportState: true, ImportStateVerify: true, }, + { + Config: testAccGKEHubFeatureMembership_policycontrollerUpdateMaps(context), + Check: resource.ComposeTestCheckFunc( + testAccCheckGkeHubFeatureMembershipPresent(t, fmt.Sprintf("tf-test-gkehub%s", context["random_suffix"]), "global", "policycontroller", fmt.Sprintf("tf-test1%s", context["random_suffix"])), + ), + }, + { + ResourceName: "google_gke_hub_feature_membership.feature_member", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -1064,9 +1075,92 @@ resource "google_gke_hub_feature_membership" "feature_member" { "PROMETHEUS" ] } + deployment_configs { + component_name = "admission" + replica_count = 3 + pod_affinity = "ANTI_AFFINITY" + container_resources { + limits { + memory = "1Gi" + cpu = "1.5" + } + requests { + memory = "500Mi" + cpu = "150m" + } + } + pod_tolerations { + key = "key1" + operator = "Equal" + value = "value1" + effect = "NoSchedule" + } + } + deployment_configs { + component_name = "mutation" + replica_count = 3 + pod_affinity = "ANTI_AFFINITY" + } policy_content { template_library { - installation = "NOT_INSTALLED" + installation = "ALL" + } + bundles { + bundle_name = "pci-dss-v3.2.1" + exempted_namespaces = ["sample-namespace"] + } + bundles { + bundle_name = "nist-sp-800-190" + } + } + } + version = "1.17.0" + } +} +`, context) +} + +func testAccGKEHubFeatureMembership_policycontrollerUpdateMaps(context map[string]interface{}) string { + return gkeHubFeatureProjectSetup(context) + gkeHubClusterMembershipSetup(context) + acctest.Nprintf(` +resource "google_gke_hub_feature" "feature" { + project = google_project.project.project_id + name = "policycontroller" + location = "global" + depends_on = [google_project_service.container, google_project_service.gkehub, google_project_service.poco] +} + +resource "google_gke_hub_feature_membership" "feature_member" { + project = google_project.project.project_id + location = "global" + feature = google_gke_hub_feature.feature.name + membership = google_gke_hub_membership.membership.membership_id + policycontroller { + policy_controller_hub_config { + install_spec = "INSTALL_SPEC_SUSPENDED" + constraint_violation_limit = 50 + referential_rules_enabled = true + log_denies_enabled = true + mutation_enabled = true + monitoring { + backends = [ + "PROMETHEUS" + ] + } + deployment_configs { + component_name = "admission" + pod_affinity = "NO_AFFINITY" + } + deployment_configs { + component_name = "audit" + container_resources { + limits { + memory = "1Gi" + cpu = "1.5" + } + requests { + memory = "500Mi" + cpu = "150m" + } } } } 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 ed571b6d7bdd..bd79aaa35da8 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 @@ -504,6 +504,10 @@ The following arguments are supported: (Optional) The maximum number of audit violations to be stored in a constraint. If not set, the default of 20 will be used. + * `deployment_configs` - + (Optional) + Map of deployment configs to deployments ("admission", "audit", "mutation"). + * `policy_content` - (Optional) Specifies the desired policy content on the cluster. Structure is [documented below](#nested_policy_content). @@ -514,12 +518,97 @@ The following arguments are supported: (Optional) Specifies the list of backends Policy Controller will export to. Must be one of `CLOUD_MONITORING` or `PROMETHEUS`. Defaults to [`CLOUD_MONITORING`, `PROMETHEUS`]. Specifying an empty value `[]` disables metrics export. +The `deployment_configs` block supports: + +* `component_name` - + (Required) + The name of the component. One of `admission` `audit` or `mutation` + +* `container_resources` - + (Optional) + Container resource requirements. + +* `pod_affinity` - + (Optional) + Pod affinity configuration. Possible values: AFFINITY_UNSPECIFIED, NO_AFFINITY, ANTI_AFFINITY + +* `pod_tolerations` - + (Optional) + Pod tolerations of node taints. + +* `replica_count` - + (Optional) + Pod replica count. + +The `container_resources` block supports: + +* `limits` - + (Optional) + Limits describes the maximum amount of compute resources allowed for use by the running container. + +* `requests` - + (Optional) + Requests describes the amount of compute resources reserved for the container by the kube-scheduler. + +The `limits` block supports: + +* `cpu` - + (Optional) + CPU requirement expressed in Kubernetes resource units. + +* `memory` - + (Optional) + Memory requirement expressed in Kubernetes resource units. + +The `requests` block supports: + +* `cpu` - + (Optional) + CPU requirement expressed in Kubernetes resource units. + +* `memory` - + (Optional) + Memory requirement expressed in Kubernetes resource units. + +The `pod_tolerations` block supports: + +* `effect` - + (Optional) + Matches a taint effect. + +* `key` - + (Optional) + Matches a taint key (not necessarily unique). + +* `operator` - + (Optional) + Matches a taint operator. + +* `value` - + (Optional) + Matches a taint value. + The `policy_content` block supports: +* `bundles` - + (Optional) + map of bundle name to BundleInstallSpec. The bundle name maps to the `bundleName` key in the `policycontroller.gke.io/constraintData` annotation on a constraint. + * `template_library` (Optional) Configures the installation of the Template Library. Structure is [documented below](#nested_template_library). +The `template_library` block supports: +The `bundles` block supports: + +* `bundle_name` - + (Required) + The name of the bundle. + +* `exempted_namespaces` - + (Optional) + The set of namespaces to be exempted from the bundle. + The `template_library` block supports: * `installation` diff --git a/tpgtools/go.mod b/tpgtools/go.mod index 14c13f11e191..90f55b270e1e 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.62.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.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 86a5ac602ab9..30d683a7cf40 100644 --- a/tpgtools/go.sum +++ b/tpgtools/go.sum @@ -6,12 +6,8 @@ cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdi cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.60.0 h1:RFZs9I3tXewC7cJf8RKbUMpQZO6jWZ9SHSnNd+auxsQ= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.60.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.61.0 h1:IAr9UlYbxURIYABRMagXXo8pDlkFNFFXWz5J2+srrnc= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.61.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0 h1:s4Y6r6RrYLBnqosGXLwR0h1Gqr0VT3wgd6rqvHsD9OE= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.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/override.go b/tpgtools/override.go index a190f8026e7e..5ce55962733c 100644 --- a/tpgtools/override.go +++ b/tpgtools/override.go @@ -79,6 +79,7 @@ const ( CustomListSize = "CUSTOM_LIST_SIZE_CONSTRAINT" CustomDefault = "CUSTOM_DEFAULT" CustomSchemaValues = "CUSTOM_SCHEMA_VALUES" + ComplexMapKey = "COMPLEX_MAP_KEY_NAME" ) // Overrides represents the type a resource's override file can be marshalled diff --git a/tpgtools/override_details.go b/tpgtools/override_details.go index 12ee16832a59..963c23656e92 100644 --- a/tpgtools/override_details.go +++ b/tpgtools/override_details.go @@ -230,3 +230,8 @@ type StateUpgradeDetails struct { // The current schema version SchemaVersion int } + +type ComplexMapKeyDetails struct { + // The name of the key as exposed by Terraform + KeyName string +} diff --git a/tpgtools/overrides/gkehub/beta/feature_membership.yaml b/tpgtools/overrides/gkehub/beta/feature_membership.yaml index 3eac7364e119..8acee09e053a 100644 --- a/tpgtools/overrides/gkehub/beta/feature_membership.yaml +++ b/tpgtools/overrides/gkehub/beta/feature_membership.yaml @@ -29,3 +29,11 @@ details: functions: - tpgresource.DefaultProviderProject +- type: COMPLEX_MAP_KEY_NAME + field: policycontroller.policy_controller_hub_config.policy_content.bundles + details: + keyname: bundle_name +- type: COMPLEX_MAP_KEY_NAME + field: policycontroller.policy_controller_hub_config.deployment_configs + details: + keyname: component_name \ No newline at end of file diff --git a/tpgtools/overrides/gkehub/feature_membership.yaml b/tpgtools/overrides/gkehub/feature_membership.yaml index 2e8b8f32503c..cd6cf1876fcc 100644 --- a/tpgtools/overrides/gkehub/feature_membership.yaml +++ b/tpgtools/overrides/gkehub/feature_membership.yaml @@ -24,4 +24,12 @@ field: mesh.control_plane details: message: >- - Deprecated in favor of the `management` field \ No newline at end of file + Deprecated in favor of the `management` field +- type: COMPLEX_MAP_KEY_NAME + field: policycontroller.policy_controller_hub_config.policy_content.bundles + details: + keyname: bundle_name +- type: COMPLEX_MAP_KEY_NAME + field: policycontroller.policy_controller_hub_config.deployment_configs + details: + keyname: component_name \ No newline at end of file diff --git a/tpgtools/property.go b/tpgtools/property.go index f7939be2a3d9..62e5aa4fa51c 100644 --- a/tpgtools/property.go +++ b/tpgtools/property.go @@ -107,6 +107,10 @@ type Property struct { // Sub-properties of nested objects or arrays with nested objects Properties []Property + // If this is a complex map type, this string represents the name of the + // field that the key to the map can be set with + ComplexMapKeyName string + // Reference to the parent resource. // note: "Properties" will not be available. resource *Resource @@ -198,13 +202,24 @@ func (p Property) ObjectType() string { } func (p Property) IsArray() bool { - return (p.Type.String() == SchemaTypeList || p.Type.String() == SchemaTypeSet) && !p.Type.IsObject() + return (p.Type.String() == SchemaTypeList || p.Type.String() == SchemaTypeSet) && !p.Type.IsObject() && !p.IsComplexMap() } func (t Type) IsSet() bool { return t.String() == SchemaTypeSet } +// Complex map is for maps of string --> object that are supported in DCL but +// not in Terraform. We handle this by adding a field in the Terraform schema +// for the key in the map. This must be added via a COMPLEX_MAP_KEY_NAME +// override +func (t Type) IsComplexMap() bool { + if t.typ.AdditionalProperties != nil { + return t.typ.AdditionalProperties.Type != "string" + } + return false +} + // ShouldGenerateNestedSchema returns true if an object's nested schema function should be generated. func (p Property) ShouldGenerateNestedSchema() bool { return len(p.Properties) > 0 && !p.Collapsed @@ -278,6 +293,9 @@ func buildGetter(p Property, rawGetter string) string { if p.Type.IsEnumArray() { return fmt.Sprintf("expand%s%sArray(%s)", p.resource.PathType(), p.PackagePath(), rawGetter) } + if p.Type.IsComplexMap() { + return fmt.Sprintf("expand%s%sMap(%s)", p.resource.PathType(), p.PackagePath(), rawGetter) + } if p.Type.typ.Items != nil && p.Type.typ.Items.Type == "string" { return fmt.Sprintf("tpgdclresource.ExpandStringArray(%s)", rawGetter) } @@ -317,6 +335,9 @@ func (p Property) DefaultStateSetter() string { return fmt.Sprintf("d.Set(%q, res.%s)", p.Name(), p.PackageName) case SchemaTypeList, SchemaTypeSet: + if p.IsComplexMap() { + return fmt.Sprintf("d.Set(%q, flatten%s%sMap(res.%s))", p.Name(), p.resource.PathType(), p.PackagePath(), p.PackageName) + } if p.typ.Items != nil && ((p.typ.Items.Type == "string" && len(p.typ.Items.Enum) == 0) || p.typ.Items.Type == "integer") { return fmt.Sprintf("d.Set(%q, res.%s)", p.Name(), p.PackageName) } @@ -365,6 +386,9 @@ func (p Property) flattenGetterWithParent(parent string) string { if p.Type.IsEnumArray() { return fmt.Sprintf("flatten%s%sArray(obj.%s)", p.resource.PathType(), p.PackagePath(), p.PackageName) } + if p.Type.IsComplexMap() { + return fmt.Sprintf("flatten%s%sMap(%s.%s)", p.resource.PathType(), p.PackagePath(), parent, p.PackageName) + } if p.Type.typ.Items != nil && p.Type.typ.Items.Type == "integer" { return fmt.Sprintf("%s.%s", parent, p.PackageName) } @@ -376,7 +400,6 @@ func (p Property) flattenGetterWithParent(parent string) string { return fmt.Sprintf("flatten%s%sArray(%s.%s)", p.resource.PathType(), p.PackagePath(), parent, p.PackageName) } } - if p.typ.Type == "object" { return fmt.Sprintf("flatten%s%s(%s.%s)", p.resource.PathType(), p.PackagePath(), parent, p.PackageName) } @@ -651,6 +674,38 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher p.ElemIsBasicType = true } } + // Complex maps are represented as TypeSet but don't have v.Items set. + // Use AdditionalProperties instead, and add an additional `name` field + // that represents the key in the map + if p.Type.IsComplexMap() { + props, err := createPropertiesFromSchema(p.Type.typ.AdditionalProperties, typeFetcher, overrides, resource, &p, location) + if err != nil { + return nil, err + } + cm := ComplexMapKeyDetails{} + cmOk, err := overrides.PropertyOverrideWithDetails(ComplexMapKey, p, &cm, location) + if err != nil { + return nil, fmt.Errorf("failed to decode complex map key name details") + } + if !cmOk { + return nil, fmt.Errorf("failed to find complex map key name for map named: %s", p.Name()) + } + keyProp := Property{ + title: cm.KeyName, + Type: Type{&openapi.Schema{Type: "string"}}, + resource: resource, + parent: &p, + Required: true, + Description: "The name for the key in the map for which this object is mapped to in the API", + } + props = append([]Property{keyProp}, props...) + + p.Properties = props + e := fmt.Sprintf("%s%sSchema()", resource.PathType(), p.PackagePath()) + p.Elem = &e + p.ElemIsBasicType = false + p.ComplexMapKeyName = cm.KeyName + } if !p.Computed { if stringInSlice(v.Title, schema.Required) { @@ -779,7 +834,7 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher p.ValidateFunc = &vf.Function } - if p.Type.String() == SchemaTypeSet { + if p.Type.IsSet() { shf := SetHashFuncDetails{} shfOk, err := overrides.PropertyOverrideWithDetails(SetHashFunc, p, &shf, location) if err != nil { diff --git a/tpgtools/templates/resource.go.tmpl b/tpgtools/templates/resource.go.tmpl index 8de8fa398c60..b65085ba771f 100644 --- a/tpgtools/templates/resource.go.tmpl +++ b/tpgtools/templates/resource.go.tmpl @@ -661,6 +661,39 @@ func expand{{$.PathType}}{{$v.PackagePath}}Array(o interface{}) []{{$.Package}}. items = append(items, *i) } + return items +} + {{- end }} + + {{ if $v.IsComplexMap -}} +func expand{{$.PathType}}{{$v.PackagePath}}Map(o interface{}) map[string]{{$.Package}}.{{$v.ObjectType}} { + if o == nil { + {{- if $v.Computed }} + return nil + {{- else }} + return make(map[string]{{$.Package}}.{{$v.ObjectType}}) + {{- end }} + } + + o = o.(*schema.Set).List() + + objs := o.([]interface{}) + if len(objs) == 0 || objs[0] == nil { + {{- if $v.Computed }} + return nil + {{- else }} + return make(map[string]{{$.Package}}.{{$v.ObjectType}}) + {{- end }} + } + + items := make(map[string]{{$.Package}}.{{$v.ObjectType}}) + for _, item := range objs { + i := expand{{$.PathType}}{{$v.PackagePath}}(item) + if item != nil { + items[item.(map[string]interface{})["{{$v.ComplexMapKeyName}}"].(string)] = *i + } + } + return items } {{- end }} @@ -688,7 +721,7 @@ func expand{{$.PathType}}{{$v.PackagePath}}(o interface{}) *{{$.Package}}.{{$v.O {{- end }} return &{{$.Package}}.{{$v.ObjectType}}{ {{- range $p := $v.Properties }} - {{- if and ($p.Settable) ($p.ExpandGetter) }} + {{- if and ($p.Settable) ($p.ExpandGetter) (or (not $v.IsComplexMap) (ne $p.Name $v.ComplexMapKeyName)) }} {{$p.PackageName}}: {{$p.ExpandGetter}}, {{- end -}} {{ end }} @@ -713,17 +746,36 @@ func flatten{{$.PathType}}{{$v.PackagePath}}Array(objs []{{$.Package}}.{{$v.Obje } {{- end }} -func flatten{{$.PathType}}{{$v.PackagePath}}(obj *{{$.Package}}.{{$v.ObjectType}}) interface{} { - if obj == nil || obj.Empty(){ + {{ if $v.IsComplexMap -}} +func flatten{{$.PathType}}{{$v.PackagePath}}Map(objs map[string]{{$.Package}}.{{$v.ObjectType}}) []interface{} { + if objs == nil { + return nil + } + + items := []interface{}{} + for name, item := range objs { + i := flatten{{$.PathType}}{{$v.PackagePath}}(&item, name) + items = append(items, i) + } + + return items +} + {{- end }} + +func flatten{{$.PathType}}{{$v.PackagePath}}(obj *{{$.Package}}.{{$v.ObjectType}}{{- if $v.IsComplexMap -}}, name string{{- end -}}) interface{} { + if obj == nil {{- if not $v.IsComplexMap -}}|| obj.Empty(){{- end -}}{ return nil } transformed := map[string]interface{}{ {{- range $p := $v.Properties }} - {{- if ($p.FlattenGetter) }} + {{- if or (not $v.IsComplexMap) (ne $p.Name $v.ComplexMapKeyName) }} "{{$p.Name}}": {{$p.FlattenGetter}}, {{- end -}} {{ end }} } +{{ if $v.IsComplexMap }} + transformed["{{$v.ComplexMapKeyName}}"] = name +{{ end }} {{ if $v.IsObject }} return []interface{}{transformed} {{ else }} diff --git a/tpgtools/type.go b/tpgtools/type.go index 47adedaa30c9..cb31f0a7c562 100644 --- a/tpgtools/type.go +++ b/tpgtools/type.go @@ -67,14 +67,13 @@ func (t Type) String() string { } return "unknown number type" case "object": - // assume if this is set, it's a string -> string map for now. - // https://swagger.io/docs/specification/data-models/dictionaries/ - // describes the behaviour of AdditionalProperties for type: object if t.typ.AdditionalProperties != nil { if v := t.typ.AdditionalProperties.Type; v == "string" { return SchemaTypeMap } else { - return fmt.Sprintf("unknown AdditionalProperties: %q", v) + // Complex maps are handled as sets with an extra value for the + // name of the object + return SchemaTypeSet } } return SchemaTypeList From c4d1efa32fa9aec82c1951a596f115b2ac443d88 Mon Sep 17 00:00:00 2001 From: Jared Date: Mon, 4 Mar 2024 13:55:57 -0800 Subject: [PATCH 069/200] fix permadiff by reading empty docker_config field (#10113) --- mmv1/products/artifactregistry/Repository.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/artifactregistry/Repository.yaml b/mmv1/products/artifactregistry/Repository.yaml index 6e0c73eb468f..965a3fab1923 100644 --- a/mmv1/products/artifactregistry/Repository.yaml +++ b/mmv1/products/artifactregistry/Repository.yaml @@ -181,6 +181,7 @@ properties: name: 'dockerConfig' description: |- Docker repository config contains repository level configuration for the repositories of docker type. + allow_empty_object: true properties: - !ruby/object:Api::Type::Boolean name: 'immutableTags' From d62a06fc45213066de668f6a8dab4814ae382ec0 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 4 Mar 2024 14:07:53 -0800 Subject: [PATCH 070/200] Import package golang.org/x/exp/slices in MMv1 go compiler (#10108) --- mmv1/go.mod | 4 ++-- mmv1/go.sum | 1 + mmv1/main.go | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mmv1/go.mod b/mmv1/go.mod index e1751dddea23..24d9a6c630d1 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -3,6 +3,6 @@ module github.com/GoogleCloudPlatform/magic-modules/mmv1 go 1.20 require ( - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 + gopkg.in/yaml.v2 v2.4.0 ) diff --git a/mmv1/go.sum b/mmv1/go.sum index 0423d8d040b3..b8ec4cc09d5a 100644 --- a/mmv1/go.sum +++ b/mmv1/go.sum @@ -1,5 +1,6 @@ golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/mmv1/main.go b/mmv1/main.go index e969a8f8d02e..b23108ac117a 100644 --- a/mmv1/main.go +++ b/mmv1/main.go @@ -6,10 +6,11 @@ import ( "os" "path" "path/filepath" - "slices" "sort" "strings" + "golang.org/x/exp/slices" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider" From 216fffd274b08af2e3f718d3d8aeb8cb6410b420 Mon Sep 17 00:00:00 2001 From: Joakim Tangnes <10198932+Zarux@users.noreply.github.com> Date: Mon, 4 Mar 2024 23:49:48 +0100 Subject: [PATCH 071/200] fix(kms): certificate chain type to array of strings (#9582) --- mmv1/products/kms/CryptoKeyVersion.yaml | 9 ++- .../kms/resource_kms_crypto_key_test.go | 67 +++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/mmv1/products/kms/CryptoKeyVersion.yaml b/mmv1/products/kms/CryptoKeyVersion.yaml index b193fee87c02..4fc87f93a051 100644 --- a/mmv1/products/kms/CryptoKeyVersion.yaml +++ b/mmv1/products/kms/CryptoKeyVersion.yaml @@ -104,15 +104,18 @@ properties: description: | The certificate chains needed to validate the attestation properties: - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Array + item_type: Api::Type::String name: 'caviumCerts' description: | Cavium certificate chain corresponding to the attestation. - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Array + item_type: Api::Type::String name: 'googleCardCerts' description: | Google card certificate chain corresponding to the attestation. - - !ruby/object:Api::Type::String + - !ruby/object:Api::Type::Array + item_type: Api::Type::String name: 'googlePartitionCerts' description: | Google partition certificate chain corresponding to the attestation. diff --git a/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go b/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go index 328fc50734d7..29c650fa0ecb 100644 --- a/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go +++ b/mmv1/third_party/terraform/services/kms/resource_kms_crypto_key_test.go @@ -444,6 +444,35 @@ func TestAccKmsCryptoKeyVersion_basic(t *testing.T) { }) } +func TestAccKmsCryptoKeyVersionWithSymmetricHSM(t *testing.T) { + t.Parallel() + + projectId := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + projectOrg := envvar.GetTestOrgFromEnv(t) + projectBillingAccount := envvar.GetTestBillingAccountFromEnv(t) + keyRingName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + cryptoKeyName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testGoogleKmsCryptoKeyVersionWithSymmetricHSM(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), + }, + { + ResourceName: "google_kms_crypto_key_version.crypto_key_version", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testGoogleKmsCryptoKeyVersion_removed(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName), + }, + }, + }) +} + func TestAccKmsCryptoKeyVersion_skipInitialVersion(t *testing.T) { t.Parallel() @@ -747,6 +776,44 @@ resource "google_kms_crypto_key_version" "crypto_key_version" { `, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName) } +func testGoogleKmsCryptoKeyVersionWithSymmetricHSM(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string { + return fmt.Sprintf(` +resource "google_project" "acceptance" { + name = "%s" + project_id = "%s" + org_id = "%s" + billing_account = "%s" +} + +resource "google_project_service" "acceptance" { + project = google_project.acceptance.project_id + service = "cloudkms.googleapis.com" +} + +resource "google_kms_key_ring" "key_ring" { + project = google_project_service.acceptance.project + name = "%s" + location = "us-central1" +} + +resource "google_kms_crypto_key" "crypto_key" { + name = "%s" + key_ring = google_kms_key_ring.key_ring.id + labels = { + key = "value" + } + version_template { + algorithm = "GOOGLE_SYMMETRIC_ENCRYPTION" + protection_level = "HSM" + } +} + +resource "google_kms_crypto_key_version" "crypto_key_version" { + crypto_key = google_kms_crypto_key.crypto_key.id +} +`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName) +} + func testGoogleKmsCryptoKeyVersion_removed(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string { return fmt.Sprintf(` resource "google_project" "acceptance" { From 2c6c6a10d96b6489c88445b5c55f70a306fede5a Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 5 Mar 2024 10:53:25 +0000 Subject: [PATCH 072/200] Bump GHA actions to navigate deprecations of NodeJS 12 and 16 (#10110) * Update all uses of `actions/cache` to v3 * Update all uses of `actions/checkout` to v4 * Update all uses of `actions/upload-artifact` to v3.1.0 * Update all uses of `actions/setup-go` to v4.0.0 * Update all uses of `ruby/setup-ruby` to v1.160.0 from v1.144.2 [v1.160.0](https://github.com/ruby/setup-ruby/releases/tag/v1.160.0) is the version after they upgraded to NodeJS 20 where they fixed some issues from the upgrade from nodejs 16->20 The previous version, ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1, is v1.144.2 --- .github/workflows/build-downstream.yml | 12 ++++++------ .github/workflows/changelog-checker.yml | 2 +- .github/workflows/magic-modules.yml | 6 +++--- .github/workflows/membership-checker.yml | 2 +- .github/workflows/repository-documentation.yml | 2 +- .../teamcity-services-diff-check-weekly.yml | 4 ++-- .github/workflows/teamcity-services-diff-check.yml | 6 +++--- .github/workflows/test-tgc.yml | 4 ++-- .github/workflows/test-tpg.yml | 4 ++-- .github/workflows/unit-test-tgc.yml | 2 +- .github/workflows/unit-test-tpg.yml | 2 +- .github/workflows/unit-tests-diff-processor.yml | 2 +- 12 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build-downstream.yml b/.github/workflows/build-downstream.yml index f8446388ee65..91f33499bd10 100644 --- a/.github/workflows/build-downstream.yml +++ b/.github/workflows/build-downstream.yml @@ -21,17 +21,17 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Ruby - uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1 + uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 with: ruby-version: '3.1' - name: Cache Bundler gems - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: mmv1/vendor/bundle key: ${{ runner.os }}-gems-${{ hashFiles('mmv1/**/Gemfile.lock') }} @@ -45,13 +45,13 @@ jobs: working-directory: mmv1 - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '^1.20' # Cache Go modules - name: Cache Go modules - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} @@ -108,7 +108,7 @@ jobs: (current_dir=$(pwd) && cd $OUTPUT_PATH && zip -r "$current_dir/output.zip" .) - name: Upload built artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 with: name: artifact-${{ inputs.repo }} path: output.zip \ No newline at end of file diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index 3158329b9c84..4e546f0e05e5 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: repo - name: Check Changelog diff --git a/.github/workflows/magic-modules.yml b/.github/workflows/magic-modules.yml index 1a2c88510fa2..d92e666e2b60 100644 --- a/.github/workflows/magic-modules.yml +++ b/.github/workflows/magic-modules.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: repo fetch-depth: 0 @@ -36,7 +36,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: repo fetch-depth: 2 @@ -49,7 +49,7 @@ jobs: git fetch origin ${{ github.base_ref }} # Fetch the base branch git merge --no-ff origin/${{ github.base_ref }} # Merge with the base branch - name: Set up Ruby - uses: ruby/setup-ruby@ec02537da5712d66d4d50a0f33b7eb52773b5ed1 + uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 with: ruby-version: '3.1' - name: Install dependencies diff --git a/.github/workflows/membership-checker.yml b/.github/workflows/membership-checker.yml index 2612f2c61679..7a206b519eaa 100644 --- a/.github/workflows/membership-checker.yml +++ b/.github/workflows/membership-checker.yml @@ -11,7 +11,7 @@ jobs: build-and-unit-tests: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 with: diff --git a/.github/workflows/repository-documentation.yml b/.github/workflows/repository-documentation.yml index 6ff5b1bbf966..531673c5788f 100644 --- a/.github/workflows/repository-documentation.yml +++ b/.github/workflows/repository-documentation.yml @@ -12,7 +12,7 @@ jobs: deploy: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true # Fetch Hugo themes (true OR recursive) fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 874fd3145913..5d857f0eda90 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -26,10 +26,10 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '^1.20' diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml index f425a6e009f4..37dd8e218554 100644 --- a/.github/workflows/teamcity-services-diff-check.yml +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -15,7 +15,7 @@ jobs: services: ${{steps.services.outputs.services}} steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: "Check for New Services" @@ -45,10 +45,10 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '^1.20' diff --git a/.github/workflows/test-tgc.yml b/.github/workflows/test-tgc.yml index 1546a5c856ee..32e290364067 100644 --- a/.github/workflows/test-tgc.yml +++ b/.github/workflows/test-tgc.yml @@ -36,7 +36,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} ref: ${{ github.event.inputs.branch }} @@ -79,7 +79,7 @@ jobs: }' - name: Set up Go if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '^1.20' - name: Build Terraform Google Conversion diff --git a/.github/workflows/test-tpg.yml b/.github/workflows/test-tpg.yml index dd05cecf003a..eff5cdc3755e 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -36,7 +36,7 @@ jobs: timeout-minutes: 30 steps: - name: Checkout Repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} ref: ${{ github.event.inputs.branch }} @@ -70,7 +70,7 @@ jobs: }' - name: Set up Go if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '^1.20' - name: Build Provider diff --git a/.github/workflows/unit-test-tgc.yml b/.github/workflows/unit-test-tgc.yml index e1c983d92ba8..f254f91240db 100644 --- a/.github/workflows/unit-test-tgc.yml +++ b/.github/workflows/unit-test-tgc.yml @@ -28,7 +28,7 @@ jobs: rm artifacts-tpgb/output.zip - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '^1.20' diff --git a/.github/workflows/unit-test-tpg.yml b/.github/workflows/unit-test-tpg.yml index 23aa27e848ed..ac925a0fe621 100644 --- a/.github/workflows/unit-test-tpg.yml +++ b/.github/workflows/unit-test-tpg.yml @@ -26,7 +26,7 @@ jobs: rm artifacts/output.zip - name: Set up Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: '^1.20' diff --git a/.github/workflows/unit-tests-diff-processor.yml b/.github/workflows/unit-tests-diff-processor.yml index 638fb42c60c5..91d081716ab3 100644 --- a/.github/workflows/unit-tests-diff-processor.yml +++ b/.github/workflows/unit-tests-diff-processor.yml @@ -11,7 +11,7 @@ jobs: test: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 From 3791c34c28ff987929f1e1869c9eba723c80a095 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:14:28 +0000 Subject: [PATCH 073/200] Address dependency issues in TestAccFirestoreField_* tests (#9957) * Add additional wait in TestAccFirestoreField_* tests * Boost wait in test to 6 minutes * Add dependency between database and service to control delete order * Update dependency to explicitly include project * Make firestore fields be removed from state when they're 'deleted' * Add `destroy_duration` * Remove from state after log line that uses id value * Update destory check to accept a 403 as valid * Remove unneeded changes in PR * Remove call to SetId --- .../custom_check_destroy/firestore_field.go.erb | 11 ++++++++++- .../firestore/resource_firestore_field_test.go | 8 ++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/mmv1/templates/terraform/custom_check_destroy/firestore_field.go.erb b/mmv1/templates/terraform/custom_check_destroy/firestore_field.go.erb index f3caa9775cca..7b5fe9d1fffc 100644 --- a/mmv1/templates/terraform/custom_check_destroy/firestore_field.go.erb +++ b/mmv1/templates/terraform/custom_check_destroy/firestore_field.go.erb @@ -16,7 +16,16 @@ res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ UserAgent: config.UserAgent, }) if err != nil { - return err + e := err.(*googleapi.Error) + if e.Code == 403 && strings.Contains(e.Message, "Cloud Firestore API has not been used in project") { + // The acceptance test has provisioned the resources under test in a new project, and the destory check is seeing the + // effects of the project not existing. This means the service isn't enabled, and that the resource is definitely destroyed. + // We do not return the error in this case - destroy was successful + return nil + } + + // Return err in all other cases + return err } if v := res["indexConfig"]; v != nil { diff --git a/mmv1/third_party/terraform/services/firestore/resource_firestore_field_test.go b/mmv1/third_party/terraform/services/firestore/resource_firestore_field_test.go index 794b5f8369a5..8be524c6e99a 100644 --- a/mmv1/third_party/terraform/services/firestore/resource_firestore_field_test.go +++ b/mmv1/third_party/terraform/services/firestore/resource_firestore_field_test.go @@ -103,7 +103,11 @@ resource "google_firestore_database" "database" { location_id = "nam5" type = "FIRESTORE_NATIVE" - depends_on = [google_project_service.firestore] + # used to control delete order + depends_on = [ + google_project_service.firestore, + google_project.project + ] } `, context) } else { @@ -115,7 +119,7 @@ resource "google_firestore_database" "database" { type = "FIRESTORE_NATIVE" delete_protection_state = "DELETE_PROTECTION_DISABLED" - deletion_policy = "DELETE" + deletion_policy = "DELETE" } `, context) } From 0249d74bdb046afe63b6562f40b7cfa315eeb8b2 Mon Sep 17 00:00:00 2001 From: Laurens Knoll <3205006+laurensknoll@users.noreply.github.com> Date: Tue, 5 Mar 2024 15:45:55 +0100 Subject: [PATCH 074/200] add network_url attribute in consumer_accept_list block of google_compute_service_attachment resource (#9895) * add network_url attribute in consumer_accept_list block of google_compute_service_attachment resource * Bugfix: Use SelfLinkRelativePath check to prevent false positive resource changes --- mmv1/products/compute/ServiceAttachment.yaml | 26 ++++- .../compute_service_attachment.go.erb | 50 ++++++++++ ...ervice_attachment_explicit_networks.tf.erb | 97 +++++++++++++++++++ 3 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 mmv1/templates/terraform/constants/compute_service_attachment.go.erb create mode 100644 mmv1/templates/terraform/examples/service_attachment_explicit_networks.tf.erb diff --git a/mmv1/products/compute/ServiceAttachment.yaml b/mmv1/products/compute/ServiceAttachment.yaml index f913840817a1..a7609767f815 100644 --- a/mmv1/products/compute/ServiceAttachment.yaml +++ b/mmv1/products/compute/ServiceAttachment.yaml @@ -68,6 +68,20 @@ examples: producer_forwarding_rule_name: 'producer-forwarding-rule' consumer_address_name: 'psc-ilb-consumer-address' consumer_forwarding_rule_name: 'psc-ilb-consumer-forwarding-rule' + - !ruby/object:Provider::Terraform::Examples + name: 'service_attachment_explicit_networks' + primary_resource_id: 'psc_ilb_service_attachment' + vars: + service_attachment_name: 'my-psc-ilb' + network_name: 'psc-ilb-network' + nat_subnetwork_name: 'psc-ilb-nat' + producer_subnetwork_name: 'psc-ilb-producer-subnetwork' + producer_health_check_name: 'producer-service-health-check' + producer_service_name: 'producer-service' + producer_forwarding_rule_name: 'producer-forwarding-rule' + consumer_network_name: 'psc-ilb-consumer-network' + consumer_address_name: 'psc-ilb-consumer-address' + consumer_forwarding_rule_name: 'psc-ilb-consumer-forwarding-rule' - !ruby/object:Provider::Terraform::Examples name: 'service_attachment_reconcile_connections' primary_resource_id: 'psc_ilb_service_attachment' @@ -82,6 +96,7 @@ examples: consumer_address_name: 'psc-ilb-consumer-address' consumer_forwarding_rule_name: 'psc-ilb-consumer-forwarding-rule' custom_code: !ruby/object:Provider::Terraform::CustomCode + constants: templates/terraform/constants/compute_service_attachment.go.erb update_encoder: 'templates/terraform/update_encoder/compute_service_attachment.go.erb' parameters: - !ruby/object:Api::Type::ResourceRef @@ -194,13 +209,22 @@ properties: attachment. send_empty_value: true is_set: true + set_hash_func: computeServiceAttachmentConsumerAcceptListsHash item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::String name: 'projectIdOrNum' - required: true + # TODO (laurensknoll): add exactly_one_of when it can be applied to lists (https://github.com/hashicorp/terraform-plugin-sdk/issues/470) description: | A project that is allowed to connect to this service attachment. + Only one of project_id_or_num and network_url may be set. + - !ruby/object:Api::Type::String + name: 'networkUrl' + # TODO (laurensknoll): add exactly_one_of when it can be applied to lists (https://github.com/hashicorp/terraform-plugin-sdk/issues/470) + description: | + The network that is allowed to connect to this service attachment. + Only one of project_id_or_num and network_url may be set. + diff_suppress_func: 'tpgresource.CompareSelfLinkRelativePaths' - !ruby/object:Api::Type::Integer name: 'connectionLimit' required: true diff --git a/mmv1/templates/terraform/constants/compute_service_attachment.go.erb b/mmv1/templates/terraform/constants/compute_service_attachment.go.erb new file mode 100644 index 000000000000..ee6a557b2f22 --- /dev/null +++ b/mmv1/templates/terraform/constants/compute_service_attachment.go.erb @@ -0,0 +1,50 @@ +<%# The license inside this block applies to this file. + # Copyright 2020 Google Inc. + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. +-%> + +// Hash based on key, which is either project_id_or_num or network_url. +func computeServiceAttachmentConsumerAcceptListsHash(v interface{}) int { + if v == nil { + return 0 + } + + var buf bytes.Buffer + m := v.(map[string]interface{}) + log.Printf("[DEBUG] hashing %v", m) + + if v, ok := m["project_id_or_num"]; ok { + if v == nil { + v = "" + } + + buf.WriteString(fmt.Sprintf("%v-", v)) + } + + if v, ok := m["network_url"]; ok { + if v == nil { + v = "" + } else { + if networkUrl, err := tpgresource.GetRelativePath(v.(string)); err != nil { + log.Printf("[WARN] Error on retrieving relative path of network url: %s", err) + } else { + v = networkUrl + } + } + + buf.WriteString(fmt.Sprintf("%v-", v)) + } + + log.Printf("[DEBUG] computed hash value of %v from %v", tpgresource.Hashcode(buf.String()), buf.String()) + return tpgresource.Hashcode(buf.String()) +} diff --git a/mmv1/templates/terraform/examples/service_attachment_explicit_networks.tf.erb b/mmv1/templates/terraform/examples/service_attachment_explicit_networks.tf.erb new file mode 100644 index 000000000000..a66f689582af --- /dev/null +++ b/mmv1/templates/terraform/examples/service_attachment_explicit_networks.tf.erb @@ -0,0 +1,97 @@ +resource "google_compute_service_attachment" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['service_attachment_name'] %>" + region = "us-west2" + description = "A service attachment configured with Terraform" + + enable_proxy_protocol = false + + connection_preference = "ACCEPT_MANUAL" + nat_subnets = [google_compute_subnetwork.psc_ilb_nat.id] + target_service = google_compute_forwarding_rule.psc_ilb_target_service.id + + consumer_accept_lists { + network_url = google_compute_network.psc_ilb_consumer_network.self_link + connection_limit = 1 + } +} + +resource "google_compute_network" "psc_ilb_consumer_network" { + name = "<%= ctx[:vars]['consumer_network_name'] %>" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "psc_ilb_consumer_subnetwork" { + name = "<%= ctx[:vars]['consumer_network_name'] %>" + ip_cidr_range = "10.0.0.0/16" + region = "us-west2" + network = google_compute_network.psc_ilb_consumer_network.id +} + +resource "google_compute_address" "psc_ilb_consumer_address" { + name = "<%= ctx[:vars]['consumer_address_name'] %>" + region = "us-west2" + + subnetwork = google_compute_subnetwork.psc_ilb_consumer_subnetwork.id + address_type = "INTERNAL" +} + +resource "google_compute_forwarding_rule" "psc_ilb_consumer" { + name = "<%= ctx[:vars]['consumer_forwarding_rule_name'] %>" + region = "us-west2" + + target = google_compute_service_attachment.psc_ilb_service_attachment.id + load_balancing_scheme = "" # need to override EXTERNAL default when target is a service attachment + network = google_compute_network.psc_ilb_consumer_network.id + subnetwork = google_compute_subnetwork.psc_ilb_consumer_subnetwork.id + ip_address = google_compute_address.psc_ilb_consumer_address.id +} + +resource "google_compute_forwarding_rule" "psc_ilb_target_service" { + name = "<%= ctx[:vars]['producer_forwarding_rule_name'] %>" + region = "us-west2" + + load_balancing_scheme = "INTERNAL" + backend_service = google_compute_region_backend_service.producer_service_backend.id + all_ports = true + network = google_compute_network.psc_ilb_network.name + subnetwork = google_compute_subnetwork.psc_ilb_producer_subnetwork.name +} + +resource "google_compute_region_backend_service" "producer_service_backend" { + name = "<%= ctx[:vars]['producer_service_name'] %>" + region = "us-west2" + + health_checks = [google_compute_health_check.producer_service_health_check.id] +} + +resource "google_compute_health_check" "producer_service_health_check" { + name = "<%= ctx[:vars]['producer_health_check_name'] %>" + + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } +} + +resource "google_compute_network" "psc_ilb_network" { + name = "<%= ctx[:vars]['network_name'] %>" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "psc_ilb_producer_subnetwork" { + name = "<%= ctx[:vars]['producer_subnetwork_name'] %>" + region = "us-west2" + + network = google_compute_network.psc_ilb_network.id + ip_cidr_range = "10.0.0.0/16" +} + +resource "google_compute_subnetwork" "psc_ilb_nat" { + name = "<%= ctx[:vars]['nat_subnetwork_name'] %>" + region = "us-west2" + + network = google_compute_network.psc_ilb_network.id + purpose = "PRIVATE_SERVICE_CONNECT" + ip_cidr_range = "10.1.0.0/16" +} From d9a016547e57b25a192bfb628f30d78b5a464ad8 Mon Sep 17 00:00:00 2001 From: Rustem Bekmukhametov Date: Tue, 5 Mar 2024 08:38:53 -0800 Subject: [PATCH 075/200] Update the GCF resource to reflect transition from Container Registry to Artifact Registry (#10058) --- .../cloudfunctions/resource_cloudfunctions_function.go | 2 +- .../resource_cloudfunctions_function_test.go.erb | 6 +++--- .../website/docs/r/cloudfunctions_function.html.markdown | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go index b6d3d77906e2..4c3c1489dd66 100644 --- a/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go +++ b/mmv1/third_party/terraform/services/cloudfunctions/resource_cloudfunctions_function.go @@ -201,7 +201,7 @@ func ResourceCloudFunctionsFunction() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - Description: `Docker Registry to use for storing the function's Docker images. Allowed values are CONTAINER_REGISTRY (default) and ARTIFACT_REGISTRY.`, + Description: `Docker Registry to use for storing the function's Docker images. Allowed values are ARTIFACT_REGISTRY (default) and CONTAINER_REGISTRY.`, }, "docker_repository": { 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 61a267c0fcd8..6288ae43d97b 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 @@ -52,7 +52,7 @@ func TestAccCloudFunctionsFunction_basic(t *testing.T) { resource.TestCheckResourceAttr(funcResourceName, "description", "test function"), resource.TestCheckResourceAttr(funcResourceName, - "docker_registry", "CONTAINER_REGISTRY"), + "docker_registry", "ARTIFACT_REGISTRY"), resource.TestCheckResourceAttr(funcResourceName, "available_memory_mb", "128"), resource.TestCheckResourceAttr(funcResourceName, @@ -659,7 +659,7 @@ resource "google_cloudfunctions_function" "function" { name = "%s" runtime = "nodejs10" description = "test function" - docker_registry = "CONTAINER_REGISTRY" + docker_registry = "ARTIFACT_REGISTRY" available_memory_mb = 128 source_archive_bucket = google_storage_bucket.bucket.name source_archive_object = google_storage_bucket_object.archive.name @@ -762,7 +762,7 @@ resource "google_cloudfunctions_function" "function" { name = "%[3]s" runtime = "nodejs10" description = "test function" - docker_registry = "CONTAINER_REGISTRY" + docker_registry = "ARTIFACT_REGISTRY" available_memory_mb = 128 source_archive_bucket = google_storage_bucket.bucket.name source_archive_object = google_storage_bucket_object.archive.name diff --git a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown index 5cfb46f700fe..b24afb988530 100644 --- a/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/cloudfunctions_function.html.markdown @@ -162,9 +162,9 @@ Please refer to the field 'effective_labels' for all of the labels present on th * `source_repository` - (Optional) Represents parameters related to source repository where a function is hosted. Cannot be set alongside `source_archive_bucket` or `source_archive_object`. Structure is [documented below](#nested_source_repository). It must match the pattern `projects/{project}/locations/{location}/repositories/{repository}`.* -* `docker_registry` - (Optional) Docker Registry to use for storing the function's Docker images. Allowed values are CONTAINER_REGISTRY (default) and ARTIFACT_REGISTRY. +* `docker_registry` - (Optional) Docker Registry to use for storing the function's Docker images. Allowed values are ARTIFACT_REGISTRY (default) and CONTAINER_REGISTRY. -* `docker_repository` - (Optional) User managed repository created in Artifact Registry optionally with a customer managed encryption key. If specified, deployments will use Artifact Registry. This is the repository to which the function docker image will be pushed after it is built by Cloud Build. If unspecified, Container Registry will be used by default, unless specified otherwise by other means. +* `docker_repository` - (Optional) User-managed repository created in Artifact Registry to which the function's Docker image will be pushed after it is built by Cloud Build. May optionally be encrypted with a customer-managed encryption key (CMEK). If unspecified and `docker_registry` is not explicitly set to `CONTAINER_REGISTRY`, GCF will create and use a default Artifact Registry repository named 'gcf-artifacts' in the region. * `kms_key_name` - (Optional) Resource name of a KMS crypto key (managed by the user) used to encrypt/decrypt function resources. It must match the pattern `projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}`. If specified, you must also provide an artifact registry repository using the `docker_repository` field that was created with the same KMS crypto key. Before deploying, please complete all pre-requisites described in https://cloud.google.com/functions/docs/securing/cmek#granting_service_accounts_access_to_the_key From 1bc4aceace723ea0536f33b50c0230d86436dac2 Mon Sep 17 00:00:00 2001 From: hao-nan-li <100219545+hao-nan-li@users.noreply.github.com> Date: Tue, 5 Mar 2024 08:59:53 -0800 Subject: [PATCH 076/200] Handwrite sweepers for networkConnectivity hubs and spokes (#10069) --- ...ce_network_connectivity_hub_sweeper.go.erb | 127 ++++++++++++++++++ ..._network_connectivity_spoke_sweeper.go.erb | 127 ++++++++++++++++++ .../networkconnectivity/beta/hub.yaml | 1 + .../networkconnectivity/beta/spoke.yaml | 1 + 4 files changed, 256 insertions(+) create mode 100644 mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_hub_sweeper.go.erb create mode 100644 mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_spoke_sweeper.go.erb diff --git a/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_hub_sweeper.go.erb b/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_hub_sweeper.go.erb new file mode 100644 index 000000000000..573e4e0838fa --- /dev/null +++ b/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_hub_sweeper.go.erb @@ -0,0 +1,127 @@ +<% autogen_exception -%> +package networkconnectivity + +<% unless version == "ga" -%> + +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("NetworkConnectivityHub", testSweepNetworkConnectivityHub) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkConnectivityHub(region string) error { + resourceName := "NetworkConnectivityHub" + 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://networkconnectivity.googleapis.com/v1/projects/{{project}}/locations/global/hubs", "?")[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["hubs"] + 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://networkconnectivity.googleapis.com/v1/projects/{{project}}/locations/global/hubs/{{name}}" + 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 +} + +<% end -%> \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_spoke_sweeper.go.erb b/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_spoke_sweeper.go.erb new file mode 100644 index 000000000000..f1f1e49cb9a3 --- /dev/null +++ b/mmv1/third_party/terraform/services/networkconnectivity/resource_network_connectivity_spoke_sweeper.go.erb @@ -0,0 +1,127 @@ +<% autogen_exception -%> +package networkconnectivity + +<% unless version == "ga" -%> + +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("NetworkConnectivitySpoke", testSweepNetworkConnectivitySpoke) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepNetworkConnectivitySpoke(region string) error { + resourceName := "NetworkConnectivitySpoke" + 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://networkconnectivity.googleapis.com/v1/projects/{{project}}/locations/global/spokes", "?")[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["spokes"] + 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://networkconnectivity.googleapis.com/v1/projects/{{project}}/locations/global/spokes/{{name}}" + 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 +} + +<% end -%> \ No newline at end of file diff --git a/tpgtools/overrides/networkconnectivity/beta/hub.yaml b/tpgtools/overrides/networkconnectivity/beta/hub.yaml index af851d79a0c9..282feed97e5f 100644 --- a/tpgtools/overrides/networkconnectivity/beta/hub.yaml +++ b/tpgtools/overrides/networkconnectivity/beta/hub.yaml @@ -1,3 +1,4 @@ +- type: NO_SWEEPER - type: CUSTOMIZE_DIFF details: functions: diff --git a/tpgtools/overrides/networkconnectivity/beta/spoke.yaml b/tpgtools/overrides/networkconnectivity/beta/spoke.yaml index af851d79a0c9..282feed97e5f 100644 --- a/tpgtools/overrides/networkconnectivity/beta/spoke.yaml +++ b/tpgtools/overrides/networkconnectivity/beta/spoke.yaml @@ -1,3 +1,4 @@ +- type: NO_SWEEPER - type: CUSTOMIZE_DIFF details: functions: From 10450a2aaf2f01d2c84d93cefaac5fa5011b4fac Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Tue, 5 Mar 2024 13:29:41 -0600 Subject: [PATCH 077/200] Fix wrong variable in override logic (#10125) --- mmv1/compiler.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 9b2160026bc4..2e4bc8b5b3ce 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -199,7 +199,7 @@ Dir["#{ovr_prod_dir}/*"].each do |override_path| next if File.basename(override_path) == 'product.yaml' \ || File.extname(override_path) != '.yaml' \ - || File.basename(file_path).include?('go_') + || File.basename(override_path).include?('go_') file_path = File.join(product_name, File.basename(override_path)) res_yaml = if File.exist?(file_path) From 5ad9866e045ce0a1e675760f19773f81534b7210 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Tue, 5 Mar 2024 13:14:39 -0800 Subject: [PATCH 078/200] Make missing test detector reader into a separate module (#10115) --- tools/missing-test-detector/detector.go | 7 ++++--- tools/missing-test-detector/detector_test.go | 4 +++- tools/missing-test-detector/go.mod | 2 +- tools/missing-test-detector/main.go | 3 ++- .../{ => reader}/reader.go | 8 ++++---- .../{ => reader}/reader_test.go | 18 +++++++++--------- .../testdata/service/config_variable_test.go | 0 .../testdata/service/covered_resource_test.go | 0 .../testdata/service/cross_file_1_test.go | 0 .../testdata/service/cross_file_2_test.go | 0 .../testdata/service/function_call_test.go | 0 .../testdata/service/multiple_resource_test.go | 0 .../testdata/service/serial_resource_test.go | 0 .../service/uncovered_resource_test.go | 0 14 files changed, 23 insertions(+), 19 deletions(-) rename tools/missing-test-detector/{ => reader}/reader.go (98%) rename tools/missing-test-detector/{ => reader}/reader_test.go (92%) rename tools/missing-test-detector/{ => reader}/testdata/service/config_variable_test.go (100%) rename tools/missing-test-detector/{ => reader}/testdata/service/covered_resource_test.go (100%) rename tools/missing-test-detector/{ => reader}/testdata/service/cross_file_1_test.go (100%) rename tools/missing-test-detector/{ => reader}/testdata/service/cross_file_2_test.go (100%) rename tools/missing-test-detector/{ => reader}/testdata/service/function_call_test.go (100%) rename tools/missing-test-detector/{ => reader}/testdata/service/multiple_resource_test.go (100%) rename tools/missing-test-detector/{ => reader}/testdata/service/serial_resource_test.go (100%) rename tools/missing-test-detector/{ => reader}/testdata/service/uncovered_resource_test.go (100%) diff --git a/tools/missing-test-detector/detector.go b/tools/missing-test-detector/detector.go index 72de96216d5f..2af06c169781 100644 --- a/tools/missing-test-detector/detector.go +++ b/tools/missing-test-detector/detector.go @@ -5,6 +5,7 @@ import ( "sort" "strings" + "github.com/GoogleCloudPlatform/magic-modules/tools/missing-test-detector/reader" "github.com/hashicorp/hcl/v2/hclwrite" "github.com/zclconf/go-cty/cty" ) @@ -19,7 +20,7 @@ type FieldSet map[string]struct{} // Detect missing tests for the given resource changes map in the given slice of tests. // Return a map of resource names to missing test info about that resource. -func detectMissingTests(changedFields map[string]ResourceChanges, allTests []*Test) (map[string]*MissingTestInfo, error) { +func detectMissingTests(changedFields map[string]ResourceChanges, allTests []*reader.Test) (map[string]*MissingTestInfo, error) { resourceNamesToTests := make(map[string][]string) for _, test := range allTests { for _, step := range test.Steps { @@ -51,13 +52,13 @@ func detectMissingTests(changedFields map[string]ResourceChanges, allTests []*Te return missingTests, nil } -func markCoverage(fieldCoverage ResourceChanges, config Resource) error { +func markCoverage(fieldCoverage ResourceChanges, config reader.Resource) error { for fieldName, fieldValue := range config { if coverage, ok := fieldCoverage[fieldName]; ok { if field, ok := coverage.(*Field); ok { field.Tested = true } else if objectCoverage, ok := coverage.(ResourceChanges); ok { - if fieldValueConfig, ok := fieldValue.(Resource); ok { + if fieldValueConfig, ok := fieldValue.(reader.Resource); ok { if err := markCoverage(objectCoverage, fieldValueConfig); err != nil { return fmt.Errorf("error parsing %q: %s", fieldName, err) } diff --git a/tools/missing-test-detector/detector_test.go b/tools/missing-test-detector/detector_test.go index 67855a3d44b7..69b6b1ec7a7c 100644 --- a/tools/missing-test-detector/detector_test.go +++ b/tools/missing-test-detector/detector_test.go @@ -3,10 +3,12 @@ package main import ( "reflect" "testing" + + "github.com/GoogleCloudPlatform/magic-modules/tools/missing-test-detector/reader" ) func TestDetectMissingTests(t *testing.T) { - allTests, errs := readAllTests("testdata") + allTests, errs := reader.ReadAllTests("reader/testdata") if len(errs) > 0 { t.Errorf("errors reading tests before testing detect missing tests: %v", errs) } diff --git a/tools/missing-test-detector/go.mod b/tools/missing-test-detector/go.mod index 3e25a00ea6e2..a074a5d1b471 100644 --- a/tools/missing-test-detector/go.mod +++ b/tools/missing-test-detector/go.mod @@ -1,4 +1,4 @@ -module github.com/trodge/magic-modules/tools/missing-test-detector +module github.com/GoogleCloudPlatform/magic-modules/tools/missing-test-detector go 1.20 diff --git a/tools/missing-test-detector/main.go b/tools/missing-test-detector/main.go index 16b6fdeba104..c8ba0672b02a 100644 --- a/tools/missing-test-detector/main.go +++ b/tools/missing-test-detector/main.go @@ -7,6 +7,7 @@ import ( "strings" "text/template" + "github.com/GoogleCloudPlatform/magic-modules/tools/missing-test-detector/reader" "github.com/golang/glog" ) @@ -15,7 +16,7 @@ var flagServicesDir = flag.String("services-dir", "", "directory where service d func main() { flag.Parse() - allTests, errs := readAllTests(*flagServicesDir) + allTests, errs := reader.ReadAllTests(*flagServicesDir) for path, err := range errs { glog.Infof("error reading path: %s, err: %v", path, err) } diff --git a/tools/missing-test-detector/reader.go b/tools/missing-test-detector/reader/reader.go similarity index 98% rename from tools/missing-test-detector/reader.go rename to tools/missing-test-detector/reader/reader.go index 7ef732636da6..0fa96586cb2b 100644 --- a/tools/missing-test-detector/reader.go +++ b/tools/missing-test-detector/reader/reader.go @@ -1,4 +1,4 @@ -package main +package reader import ( "fmt" @@ -33,7 +33,7 @@ func (t *Test) String() string { } // Return a slice of tests as well as a map of file or test names to errors encountered. -func readAllTests(servicesDir string) ([]*Test, map[string]error) { +func ReadAllTests(servicesDir string) ([]*Test, map[string]error) { dirs, err := os.ReadDir(servicesDir) if err != nil { return nil, map[string]error{servicesDir: err} @@ -52,7 +52,7 @@ func readAllTests(servicesDir string) ([]*Test, map[string]error) { testFileNames = append(testFileNames, filepath.Join(servicePath, file.Name())) } } - serviceTests, serviceErrs := readTestFiles(testFileNames) + serviceTests, serviceErrs := ReadTestFiles(testFileNames) for fileName, err := range serviceErrs { allErrs[fileName] = err } @@ -65,7 +65,7 @@ func readAllTests(servicesDir string) ([]*Test, map[string]error) { } // Read all the test files in a service directory together to capture cross-file function usage. -func readTestFiles(filenames []string) ([]*Test, map[string]error) { +func ReadTestFiles(filenames []string) ([]*Test, map[string]error) { funcDecls := make(map[string]*ast.FuncDecl) // map of function names to function declarations varDecls := make(map[string]*ast.BasicLit) // map of variable names to value expressions errs := make(map[string]error) // map of file or test names to errors encountered parsing diff --git a/tools/missing-test-detector/reader_test.go b/tools/missing-test-detector/reader/reader_test.go similarity index 92% rename from tools/missing-test-detector/reader_test.go rename to tools/missing-test-detector/reader/reader_test.go index b210c469a502..59a04c03c606 100644 --- a/tools/missing-test-detector/reader_test.go +++ b/tools/missing-test-detector/reader/reader_test.go @@ -1,4 +1,4 @@ -package main +package reader import ( "os" @@ -9,7 +9,7 @@ import ( // This test only ensures there isn't a panic reading tests in the provider. func TestReadAllTests(t *testing.T) { if servicesDir := os.Getenv("SERVICES_DIR"); servicesDir != "" { - _, errs := readAllTests(servicesDir) + _, errs := ReadAllTests(servicesDir) for path, err := range errs { t.Logf("path: %s, err: %v", path, err) } @@ -19,7 +19,7 @@ func TestReadAllTests(t *testing.T) { } func TestReadCoveredResourceTestFile(t *testing.T) { - tests, err := readTestFiles([]string{"testdata/service/covered_resource_test.go"}) + tests, err := ReadTestFiles([]string{"testdata/service/covered_resource_test.go"}) if err != nil { t.Fatalf("error reading covered resource test file: %v", err) } @@ -47,7 +47,7 @@ func TestReadCoveredResourceTestFile(t *testing.T) { } func TestReadConfigVariableTestFile(t *testing.T) { - tests, err := readTestFiles([]string{"testdata/service/config_variable_test.go"}) + tests, err := ReadTestFiles([]string{"testdata/service/config_variable_test.go"}) if err != nil { t.Fatalf("error reading config variable test file: %v", err) } @@ -67,7 +67,7 @@ func TestReadConfigVariableTestFile(t *testing.T) { } func TestReadMultipleResourcesTestFile(t *testing.T) { - tests, err := readTestFiles([]string{"testdata/service/multiple_resource_test.go"}) + tests, err := ReadTestFiles([]string{"testdata/service/multiple_resource_test.go"}) if err != nil { t.Fatalf("error reading multiple resources test file: %v", err) } @@ -101,7 +101,7 @@ func TestReadMultipleResourcesTestFile(t *testing.T) { } func TestReadSerialResourceTestFile(t *testing.T) { - tests, err := readTestFiles([]string{"testdata/service/serial_resource_test.go"}) + tests, err := ReadTestFiles([]string{"testdata/service/serial_resource_test.go"}) if err != nil { t.Fatalf("error reading serial resource test file: %v", err) } @@ -140,7 +140,7 @@ func TestReadSerialResourceTestFile(t *testing.T) { } func TestReadCrossFileTests(t *testing.T) { - tests, err := readTestFiles([]string{"testdata/service/cross_file_1_test.go", "testdata/service/cross_file_2_test.go"}) + tests, err := ReadTestFiles([]string{"testdata/service/cross_file_1_test.go", "testdata/service/cross_file_2_test.go"}) if err != nil { t.Fatalf("error reading cross file tests: %v", err) } @@ -183,7 +183,7 @@ func TestReadCrossFileTests(t *testing.T) { } func TestReadHelperFunctionCall(t *testing.T) { - tests, err := readTestFiles([]string{"testdata/service/function_call_test.go"}) + tests, err := ReadTestFiles([]string{"testdata/service/function_call_test.go"}) if err != nil { t.Fatalf("error reading function call test: %v", err) } @@ -193,7 +193,7 @@ func TestReadHelperFunctionCall(t *testing.T) { expectedTest := &Test{ Name: "TestAccFunctionCallResource", Steps: []Step{ - Step{ + { "helped_resource": Resources{ "primary": Resource{ "field_one": "\"value-one\"", diff --git a/tools/missing-test-detector/testdata/service/config_variable_test.go b/tools/missing-test-detector/reader/testdata/service/config_variable_test.go similarity index 100% rename from tools/missing-test-detector/testdata/service/config_variable_test.go rename to tools/missing-test-detector/reader/testdata/service/config_variable_test.go diff --git a/tools/missing-test-detector/testdata/service/covered_resource_test.go b/tools/missing-test-detector/reader/testdata/service/covered_resource_test.go similarity index 100% rename from tools/missing-test-detector/testdata/service/covered_resource_test.go rename to tools/missing-test-detector/reader/testdata/service/covered_resource_test.go diff --git a/tools/missing-test-detector/testdata/service/cross_file_1_test.go b/tools/missing-test-detector/reader/testdata/service/cross_file_1_test.go similarity index 100% rename from tools/missing-test-detector/testdata/service/cross_file_1_test.go rename to tools/missing-test-detector/reader/testdata/service/cross_file_1_test.go diff --git a/tools/missing-test-detector/testdata/service/cross_file_2_test.go b/tools/missing-test-detector/reader/testdata/service/cross_file_2_test.go similarity index 100% rename from tools/missing-test-detector/testdata/service/cross_file_2_test.go rename to tools/missing-test-detector/reader/testdata/service/cross_file_2_test.go diff --git a/tools/missing-test-detector/testdata/service/function_call_test.go b/tools/missing-test-detector/reader/testdata/service/function_call_test.go similarity index 100% rename from tools/missing-test-detector/testdata/service/function_call_test.go rename to tools/missing-test-detector/reader/testdata/service/function_call_test.go diff --git a/tools/missing-test-detector/testdata/service/multiple_resource_test.go b/tools/missing-test-detector/reader/testdata/service/multiple_resource_test.go similarity index 100% rename from tools/missing-test-detector/testdata/service/multiple_resource_test.go rename to tools/missing-test-detector/reader/testdata/service/multiple_resource_test.go diff --git a/tools/missing-test-detector/testdata/service/serial_resource_test.go b/tools/missing-test-detector/reader/testdata/service/serial_resource_test.go similarity index 100% rename from tools/missing-test-detector/testdata/service/serial_resource_test.go rename to tools/missing-test-detector/reader/testdata/service/serial_resource_test.go diff --git a/tools/missing-test-detector/testdata/service/uncovered_resource_test.go b/tools/missing-test-detector/reader/testdata/service/uncovered_resource_test.go similarity index 100% rename from tools/missing-test-detector/testdata/service/uncovered_resource_test.go rename to tools/missing-test-detector/reader/testdata/service/uncovered_resource_test.go From 978c66d4722b13f15b72ac0253666b5713814e85 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Tue, 5 Mar 2024 14:30:09 -0800 Subject: [PATCH 079/200] Use old github token if new tokens are not available (#10114) * Use old github token if new tokens are not available * Add lookup function for github token or fallback * Add fall back * Add fallback --- .ci/magician/cmd/check_cassettes.go | 17 +++++++++++++++-- .ci/magician/cmd/community_checker.go | 4 ++-- .ci/magician/cmd/generate_comment.go | 10 ++++++++-- .ci/magician/cmd/generate_downstream.go | 1 + .ci/magician/cmd/membership_checker.go | 4 ++-- .ci/magician/cmd/request_service_reviewers.go | 4 ++-- .ci/magician/cmd/test_terraform_vcr.go | 11 +++++++++-- .ci/magician/cmd/test_tgc.go | 4 ++-- .ci/magician/cmd/test_tpg.go | 4 ++-- .../test_tgc_integration.sh | 5 +++++ 10 files changed, 48 insertions(+), 16 deletions(-) diff --git a/.ci/magician/cmd/check_cassettes.go b/.ci/magician/cmd/check_cassettes.go index f5977ec0be29..d31cebe44ddd 100644 --- a/.ci/magician/cmd/check_cassettes.go +++ b/.ci/magician/cmd/check_cassettes.go @@ -13,7 +13,6 @@ import ( var ccEnvironmentVariables = [...]string{ "COMMIT_SHA", - "GITHUB_TOKEN_DOWNSTREAMS", "GOCACHE", "GOPATH", "GOOGLE_BILLING_ACCOUNT", @@ -56,13 +55,19 @@ var checkCassettesCmd = &cobra.Command{ env[ev] = val } + githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_DOWNSTREAMS") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN_DOWNSTREAMS or GITHUB_TOKEN environment variables") + os.Exit(1) + } + rnr, err := exec.NewRunner() if err != nil { fmt.Println("Error creating Runner: ", err) os.Exit(1) } - ctlr := source.NewController(env["GOPATH"], "modular-magician", env["GITHUB_TOKEN_DOWNSTREAMS"], rnr) + ctlr := source.NewController(env["GOPATH"], "modular-magician", githubToken, rnr) vt, err := vcr.NewTester(env, rnr) if err != nil { @@ -73,6 +78,14 @@ var checkCassettesCmd = &cobra.Command{ }, } +func lookupGithubTokenOrFallback(tokenName string) (string, bool) { + val, ok := os.LookupEnv(tokenName) + if !ok { + return os.LookupEnv("GITHUB_TOKEN") + } + return val, ok +} + func listCCEnvironmentVariables() string { var result string for i, ev := range ccEnvironmentVariables { diff --git a/.ci/magician/cmd/community_checker.go b/.ci/magician/cmd/community_checker.go index 2ec024952520..9eb82a5e3e2e 100644 --- a/.ci/magician/cmd/community_checker.go +++ b/.ci/magician/cmd/community_checker.go @@ -64,9 +64,9 @@ var communityApprovalCmd = &cobra.Command{ baseBranch := args[5] fmt.Println("Base Branch: ", baseBranch) - githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_MAGIC_MODULES") if !ok { - fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES or GITHUB_TOKEN environment variables") os.Exit(1) } gh := github.NewClient(githubToken) diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index b00ab9986d6e..b78bbf35fd3c 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -35,8 +35,6 @@ var gcEnvironmentVariables = [...]string{ "BUILD_ID", "BUILD_STEP", "COMMIT_SHA", - "GITHUB_TOKEN_DOWNSTREAMS", - "GITHUB_TOKEN_MAGIC_MODULES", "GOPATH", "HOME", "PATH", @@ -71,6 +69,14 @@ var generateCommentCmd = &cobra.Command{ env[ev] = val } + for _, tokenName := range []string{"GITHUB_TOKEN_DOWNSTREAMS", "GITHUB_TOKEN_MAGIC_MODULES"} { + val, ok := lookupGithubTokenOrFallback(tokenName) + if !ok { + fmt.Printf("Did not provide %s or GITHUB_TOKEN environment variable\n", tokenName) + os.Exit(1) + } + env[tokenName] = val + } gh := github.NewClient(env["GITHUB_TOKEN_MAGIC_MODULES"]) rnr, err := exec.NewRunner() if err != nil { diff --git a/.ci/magician/cmd/generate_downstream.go b/.ci/magician/cmd/generate_downstream.go index b8605905f242..2e812d482069 100644 --- a/.ci/magician/cmd/generate_downstream.go +++ b/.ci/magician/cmd/generate_downstream.go @@ -25,6 +25,7 @@ var gdEnvironmentVariables = [...]string{ var gdTokenEnvironmentVariables = [...]string{ "GITHUB_TOKEN_CLASSIC", "GITHUB_TOKEN_DOWNSTREAMS", + "GITHUB_TOKEN", } var generateDownstreamCmd = &cobra.Command{ diff --git a/.ci/magician/cmd/membership_checker.go b/.ci/magician/cmd/membership_checker.go index 71ffda29a253..97210105dd08 100644 --- a/.ci/magician/cmd/membership_checker.go +++ b/.ci/magician/cmd/membership_checker.go @@ -72,9 +72,9 @@ var membershipCheckerCmd = &cobra.Command{ baseBranch := args[5] fmt.Println("Base Branch: ", baseBranch) - githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_MAGIC_MODULES") if !ok { - fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES or GITHUB_TOKEN environment variables") os.Exit(1) } gh := github.NewClient(githubToken) diff --git a/.ci/magician/cmd/request_service_reviewers.go b/.ci/magician/cmd/request_service_reviewers.go index 33abd8d1ca1f..6ef80c5283c0 100644 --- a/.ci/magician/cmd/request_service_reviewers.go +++ b/.ci/magician/cmd/request_service_reviewers.go @@ -40,9 +40,9 @@ var requestServiceReviewersCmd = &cobra.Command{ prNumber := args[0] fmt.Println("PR Number: ", prNumber) - githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_MAGIC_MODULES") if !ok { - fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES or GITHUB_TOKEN environment variable") os.Exit(1) } gh := github.NewClient(githubToken) diff --git a/.ci/magician/cmd/test_terraform_vcr.go b/.ci/magician/cmd/test_terraform_vcr.go index 3c979ef3ab84..60fda5577d82 100644 --- a/.ci/magician/cmd/test_terraform_vcr.go +++ b/.ci/magician/cmd/test_terraform_vcr.go @@ -15,8 +15,6 @@ import ( ) var ttvEnvironmentVariables = [...]string{ - "GITHUB_TOKEN_DOWNSTREAMS", - "GITHUB_TOKEN_MAGIC_MODULES", "GOCACHE", "GOPATH", "GOOGLE_BILLING_ACCOUNT", @@ -55,6 +53,15 @@ var testTerraformVCRCmd = &cobra.Command{ env[ev] = val } + for _, tokenName := range []string{"GITHUB_TOKEN_DOWNSTREAMS", "GITHUB_TOKEN_MAGIC_MODULES"} { + val, ok := lookupGithubTokenOrFallback(tokenName) + if !ok { + fmt.Printf("Did not provide %s or GITHUB_TOKEN environment variable\n", tokenName) + os.Exit(1) + } + env[tokenName] = val + } + baseBranch := os.Getenv("BASE_BRANCH") if baseBranch == "" { baseBranch = "main" diff --git a/.ci/magician/cmd/test_tgc.go b/.ci/magician/cmd/test_tgc.go index 54fd97394612..5f000d731b15 100644 --- a/.ci/magician/cmd/test_tgc.go +++ b/.ci/magician/cmd/test_tgc.go @@ -36,9 +36,9 @@ var testTGCCmd = &cobra.Command{ commit := os.Getenv("COMMIT_SHA") pr := os.Getenv("PR_NUMBER") - githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_MAGIC_MODULES") if !ok { - fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES or GITHUB_TOKEN environment variables") os.Exit(1) } gh := github.NewClient(githubToken) diff --git a/.ci/magician/cmd/test_tpg.go b/.ci/magician/cmd/test_tpg.go index 58d216d512ff..260b5b2a7466 100644 --- a/.ci/magician/cmd/test_tpg.go +++ b/.ci/magician/cmd/test_tpg.go @@ -42,9 +42,9 @@ var testTPGCmd = &cobra.Command{ commit := os.Getenv("COMMIT_SHA") pr := os.Getenv("PR_NUMBER") - githubToken, ok := os.LookupEnv("GITHUB_TOKEN_MAGIC_MODULES") + githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_MAGIC_MODULES") if !ok { - fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES environment variable") + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES or GITHUB_TOKEN environment variables") os.Exit(1) } gh := github.NewClient(githubToken) diff --git a/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh b/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh index 8f4ead70dc18..be80ee454f1d 100755 --- a/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh +++ b/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh @@ -36,6 +36,11 @@ post_body=$( jq -n \ --arg state "pending" \ '{context: $context, target_url: $target_url, state: $state}') +# Fall back to old github token if new token is unavailable. +if [[ -z $GITHUB_TOKEN_MAGIC_MODULES ]]; then + GITHUB_TOKEN_MAGIC_MODULES=$GITHUB_TOKEN +fi + curl \ -X POST \ -u "$github_username:$GITHUB_TOKEN_MAGIC_MODULES" \ From 8373cea715cdb25197b639f8b8d340cf09b4fa83 Mon Sep 17 00:00:00 2001 From: xuchenma <67921399+xuchenma@users.noreply.github.com> Date: Wed, 6 Mar 2024 06:52:06 -0800 Subject: [PATCH 080/200] Add test for PATCH environment type (#10131) --- ...source_apigee_environment_type_test.go.erb | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 mmv1/third_party/terraform/services/apigee/resource_apigee_environment_type_test.go.erb diff --git a/mmv1/third_party/terraform/services/apigee/resource_apigee_environment_type_test.go.erb b/mmv1/third_party/terraform/services/apigee/resource_apigee_environment_type_test.go.erb new file mode 100644 index 000000000000..bef24217d444 --- /dev/null +++ b/mmv1/third_party/terraform/services/apigee/resource_apigee_environment_type_test.go.erb @@ -0,0 +1,179 @@ +<% autogen_exception -%> +package apigee_test +<% unless version == 'ga' -%> + +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 TestAccApigeeEnvironment_apigeeEnvironmentTypeTestExampleUpdate(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckApigeeEnvironmentDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApigeeEnvironment_apigeeEnvironmentTypeTestExample(context), + }, + { + ResourceName: "google_apigee_environment.apigee_environment", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"org_id"}, + }, + { + Config: testAccApigeeEnvironment_apigeeEnvironmentTypeTestExampleUpdate(context), + }, + { + ResourceName: "google_apigee_environment.apigee_environment", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"org_id"}, + }, + }, + }) +} + +func testAccApigeeEnvironment_apigeeEnvironmentTypeTestExampleUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_project" "project" { + provider = google-beta + + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +resource "google_project_service" "apigee" { + provider = google-beta + + project = google_project.project.project_id + service = "apigee.googleapis.com" +} + +resource "google_project_service" "compute" { + provider = google-beta + + project = google_project.project.project_id + service = "compute.googleapis.com" +} + +resource "google_project_service" "servicenetworking" { + provider = google-beta + + project = google_project.project.project_id + service = "servicenetworking.googleapis.com" +} + +resource "google_project_service" "kms" { + provider = google-beta + + project = google_project.project.project_id + service = "cloudkms.googleapis.com" +} + +resource "google_compute_network" "apigee_network" { + provider = google-beta + + name = "apigee-network" + project = google_project.project.project_id + depends_on = [google_project_service.compute] +} + +resource "google_compute_global_address" "apigee_range" { + provider = google-beta + + name = "tf-test-apigee-range%{random_suffix}" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = google_compute_network.apigee_network.id + project = google_project.project.project_id +} + +resource "google_service_networking_connection" "apigee_vpc_connection" { + provider = google-beta + + network = google_compute_network.apigee_network.id + service = "servicenetworking.googleapis.com" + reserved_peering_ranges = [google_compute_global_address.apigee_range.name] + depends_on = [google_project_service.servicenetworking] +} + +resource "google_kms_key_ring" "apigee_keyring" { + provider = google-beta + + name = "apigee-keyring" + location = "us-central1" + project = google_project.project.project_id + depends_on = [google_project_service.kms] +} + +resource "google_kms_crypto_key" "apigee_key" { + provider = google-beta + + name = "apigee-key" + key_ring = google_kms_key_ring.apigee_keyring.id +} + +resource "google_project_service_identity" "apigee_sa" { + provider = google-beta + + project = google_project.project.project_id + service = google_project_service.apigee.service +} + +resource "google_kms_crypto_key_iam_binding" "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}", + ] +} + +resource "google_apigee_organization" "apigee_org" { + provider = google-beta + + analytics_region = "us-central1" + project_id = google_project.project.project_id + authorized_network = google_compute_network.apigee_network.id + billing_type = "PAYG" + runtime_database_encryption_key_name = google_kms_crypto_key.apigee_key.id + + depends_on = [ + google_service_networking_connection.apigee_vpc_connection, + google_project_service.apigee, + google_kms_crypto_key_iam_binding.apigee_sa_keyuser, + ] +} + +resource "google_apigee_environment" "apigee_environment" { + provider = google-beta + + org_id = google_apigee_organization.apigee_org.id + name = "tf-test%{random_suffix}" + description = "Apigee Environment" + display_name = "tf-test%{random_suffix}" + type = "INTERMEDIATE" +} +`, context) +} + +<% end -%> From 55a1fa855d07e03b0ad43d070f3dc996fd6f2922 Mon Sep 17 00:00:00 2001 From: Esha Goel Date: Wed, 6 Mar 2024 15:16:57 +0000 Subject: [PATCH 081/200] Add new resource for Application for Apphub (#10079) * Add new resource for Application for Apphub * Add new resource for Application for Apphub * Enable Apphub API in test cases * Fix precheck error * Fix precheck error * Resolve comments * Fix lint error * Fix examples * Remove apphub from teamcity config This causes PR build failures, I'll add it later --------- Co-authored-by: Sam Levenick --- mmv1/products/apphub/Application.yaml | 189 ++++++++++++++++ mmv1/products/apphub/product.yaml | 23 ++ .../examples/apphub_application_basic.tf.erb | 7 + .../examples/apphub_application_full.tf.erb | 29 +++ .../components/inputs/services_beta.kt | 5 + .../components/inputs/services_ga.kt | 5 + .../resource_apphub_application_test.go | 210 ++++++++++++++++++ 7 files changed, 468 insertions(+) create mode 100644 mmv1/products/apphub/Application.yaml create mode 100644 mmv1/products/apphub/product.yaml create mode 100644 mmv1/templates/terraform/examples/apphub_application_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/apphub_application_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/apphub/resource_apphub_application_test.go diff --git a/mmv1/products/apphub/Application.yaml b/mmv1/products/apphub/Application.yaml new file mode 100644 index 000000000000..fbac56d6ba63 --- /dev/null +++ b/mmv1/products/apphub/Application.yaml @@ -0,0 +1,189 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +base_url: projects/{{project}}/locations/{{location}}/applications +create_url: projects/{{project}}/locations/{{location}}/applications?applicationId={{application_id}} +self_link: projects/{{project}}/locations/{{location}}/applications/{{application_id}} +id_format: projects/{{project}}/locations/{{location}}/applications/{{application_id}} +import_format: + - projects/{{project}}/locations/{{location}}/applications/{{application_id}} +name: Application +description: 'Application is a functional grouping of Services and Workloads that helps achieve a desired end-to-end business functionality. + Services and Workloads are owned by the Application.' +autogen_async: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "application_basic" + primary_resource_id: "example" + config_path: "templates/terraform/examples/apphub_application_basic.tf.erb" + vars: + application_id: "example-application" + - !ruby/object:Provider::Terraform::Examples + name: "application_full" + primary_resource_id: "example2" + config_path: "templates/terraform/examples/apphub_application_full.tf.erb" + vars: + application_id: "example-application" + display_name: "Application Full" + description: "Application for testing" + business_name: "Alice" + business_email: "alice@google.com" + developer_name: "Bob" + developer_email: "bob@google.com" + operator_name: "Charlie" + operator_email: "charlie@google.com" +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: "Identifier. The resource name of an Application. Format:\n\"projects/{host-project-id}/locations/{location}/applications/{application-id}\" " + - !ruby/object:Api::Type::String + name: displayName + description: 'Optional. User-defined name for the Application. ' + - !ruby/object:Api::Type::String + name: description + description: 'Optional. User-defined description of an Application. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Criticality type. ' + required: true + values: + - :MISSION_CRITICAL + - :HIGH + - :MEDIUM + - :LOW + name: criticality + description: 'Criticality of the Application, Service, or Workload ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Environment type. ' + required: true + values: + - :PRODUCTION + - :STAGING + - :TEST + - :DEVELOPMENT + name: environment + description: 'Environment of the Application, Service, or Workload ' + - !ruby/object:Api::Type::Array + name: developerOwners + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Optional. Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + required: true + description: 'Required. Email address of the contacts. ' + description: 'Optional. Developer team that owns development and coding. ' + - !ruby/object:Api::Type::Array + name: operatorOwners + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Optional. Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + required: true + description: 'Required. Email address of the contacts. ' + description: 'Optional. Operator team that ensures runtime and operations. ' + - !ruby/object:Api::Type::Array + name: businessOwners + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Optional. Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + required: true + description: 'Required. Email address of the contacts. ' + description: 'Optional. Business team that ensures user needs are met and value + is delivered ' + name: attributes + description: 'Consumer provided attributes. ' + - !ruby/object:Api::Type::String + name: createTime + description: 'Output only. Create time. ' + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: 'Output only. Update time. ' + output: true + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::Enum + name: type + description: "Required. Scope Type. \n Possible values:\nREGIONAL" + required: true + values: + - :REGIONAL + name: scope + description: 'Scope of an application. ' + required: true + - !ruby/object:Api::Type::String + name: uid + description: 'Output only. A universally unique identifier (in UUID4 format) for + the `Application`. ' + output: true + - !ruby/object:Api::Type::Enum + name: state + description: "Output only. Application state. \n Possible values:\n STATE_UNSPECIFIED\nCREATING\nACTIVE\nDELETING" + output: true + values: + - :STATE_UNSPECIFIED + - :CREATING + - :ACTIVE + - :DELETING +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: applicationId + description: 'Required. The Application identifier. ' + url_param_only: true + required: 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 +update_verb: :PATCH +update_mask: true diff --git a/mmv1/products/apphub/product.yaml b/mmv1/products/apphub/product.yaml new file mode 100644 index 000000000000..4df439355736 --- /dev/null +++ b/mmv1/products/apphub/product.yaml @@ -0,0 +1,23 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +--- !ruby/object:Api::Product +name: Apphub +display_name: App Hub +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://apphub.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform diff --git a/mmv1/templates/terraform/examples/apphub_application_basic.tf.erb b/mmv1/templates/terraform/examples/apphub_application_basic.tf.erb new file mode 100644 index 000000000000..7b7c50231dca --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_application_basic.tf.erb @@ -0,0 +1,7 @@ +resource "google_apphub_application" "<%= ctx[:primary_resource_id] %>" { + location = "us-east1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} diff --git a/mmv1/templates/terraform/examples/apphub_application_full.tf.erb b/mmv1/templates/terraform/examples/apphub_application_full.tf.erb new file mode 100644 index 000000000000..42d9de520464 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_application_full.tf.erb @@ -0,0 +1,29 @@ +resource "google_apphub_application" "<%= ctx[:primary_resource_id] %>" { + location = "us-east1" + application_id = "<%= ctx[:vars]['application_id'] %>" + display_name = "<%= ctx[:vars]['display_name'] %>" + scope { + type = "REGIONAL" + } + description = "<%= ctx[:vars]['description'] %>" + attributes { + environment { + type = "STAGING" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "<%= ctx[:vars]['business_name'] %>" + email = "<%= ctx[:vars]['business_email'] %>" + } + developer_owners { + display_name = "<%= ctx[:vars]['developer_name'] %>" + email = "<%= ctx[:vars]['developer_email'] %>" + } + operator_owners { + display_name = "<%= ctx[:vars]['operator_name'] %>" + email = "<%= ctx[:vars]['operator_email'] %>" + } + } +} diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index 27550dabce13..443987885a6f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -48,6 +48,11 @@ var ServicesListBeta = mapOf( "displayName" to "Appengine", "path" to "./google-beta/services/appengine" ), + "apphub" to mapOf( + "name" to "apphub", + "displayName" to "Apphub", + "path" to "./google-beta/services/apphub" + ), "artifactregistry" to mapOf( "name" to "artifactregistry", "displayName" to "Artifactregistry", diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index 51f98ed08a05..08ce6c2ee82f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -48,6 +48,11 @@ var ServicesListGa = mapOf( "displayName" to "Appengine", "path" to "./google/services/appengine" ), + "apphub" to mapOf( + "name" to "apphub", + "displayName" to "Apphub", + "path" to "./google/services/apphub" + ), "artifactregistry" to mapOf( "name" to "artifactregistry", "displayName" to "Artifactregistry", diff --git a/mmv1/third_party/terraform/services/apphub/resource_apphub_application_test.go b/mmv1/third_party/terraform/services/apphub/resource_apphub_application_test.go new file mode 100644 index 000000000000..3e68916cc73e --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/resource_apphub_application_test.go @@ -0,0 +1,210 @@ +package apphub_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccApphubApplication_applicationUpdateFull(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: testAccCheckApphubApplicationDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApphubApplication_applicationFullExample(context), + }, + { + ResourceName: "google_apphub_application.example2", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id"}, + }, + { + Config: testAccApphubApplication_applicationUpdateDisplayName(context), + }, + { + ResourceName: "google_apphub_application.example2", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id"}, + }, + { + Config: testAccApphubApplication_applicationUpdateEnvironment(context), + }, + { + ResourceName: "google_apphub_application.example2", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id"}, + }, + { + Config: testAccApphubApplication_applicationUpdateCriticality(context), + }, + { + ResourceName: "google_apphub_application.example2", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id"}, + }, + { + Config: testAccApphubApplication_applicationUpdateOwners(context), + }, + { + ResourceName: "google_apphub_application.example2", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id"}, + }, + }, + }) +} + +func testAccApphubApplication_applicationUpdateDisplayName(context map[string]interface{}) string { + return acctest.Nprintf(` + +resource "google_apphub_application" "example2" { + location = "us-east1" + application_id = "tf-test-example-application%{random_suffix}" + display_name = "Application Full New%{random_suffix}" + scope { + type = "REGIONAL" + } + attributes { + environment { + type = "STAGING" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "Alice%{random_suffix}" + email = "alice@google.com%{random_suffix}" + } + developer_owners { + display_name = "Bob%{random_suffix}" + email = "bob@google.com%{random_suffix}" + } + operator_owners { + display_name = "Charlie%{random_suffix}" + email = "charlie@google.com%{random_suffix}" + } + } +} +`, context) +} + +func testAccApphubApplication_applicationUpdateEnvironment(context map[string]interface{}) string { + return acctest.Nprintf(` + +resource "google_apphub_application" "example2" { + location = "us-east1" + application_id = "tf-test-example-application%{random_suffix}" + display_name = "Application Full New%{random_suffix}" + scope { + type = "REGIONAL" + } + attributes { + environment { + type = "TEST" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "Alice%{random_suffix}" + email = "alice@google.com%{random_suffix}" + } + developer_owners { + display_name = "Bob%{random_suffix}" + email = "bob@google.com%{random_suffix}" + } + operator_owners { + display_name = "Charlie%{random_suffix}" + email = "charlie@google.com%{random_suffix}" + } + } +} +`, context) +} + +func testAccApphubApplication_applicationUpdateCriticality(context map[string]interface{}) string { + return acctest.Nprintf(` + +resource "google_apphub_application" "example2" { + location = "us-east1" + application_id = "tf-test-example-application%{random_suffix}" + display_name = "Application Full New%{random_suffix}" + scope { + type = "REGIONAL" + } + attributes { + environment { + type = "TEST" + } + criticality { + type = "MEDIUM" + } + business_owners { + display_name = "Alice%{random_suffix}" + email = "alice@google.com%{random_suffix}" + } + developer_owners { + display_name = "Bob%{random_suffix}" + email = "bob@google.com%{random_suffix}" + } + operator_owners { + display_name = "Charlie%{random_suffix}" + email = "charlie@google.com%{random_suffix}" + } + } +} +`, context) +} + +func testAccApphubApplication_applicationUpdateOwners(context map[string]interface{}) string { + return acctest.Nprintf(` + +resource "google_apphub_application" "example2" { + location = "us-east1" + application_id = "tf-test-example-application%{random_suffix}" + display_name = "Application Full New%{random_suffix}" + scope { + type = "REGIONAL" + } + attributes { + environment { + type = "TEST" + } + criticality { + type = "MEDIUM" + } + business_owners { + display_name = "Alice%{random_suffix}" + email = "alice@google.com%{random_suffix}" + } + developer_owners { + display_name = "Bob%{random_suffix}" + email = "bob@google.com%{random_suffix}" + } + developer_owners { + display_name = "Derek%{random_suffix}" + email = "derek@google.com%{random_suffix}" + } + operator_owners { + display_name = "Charlie%{random_suffix}" + email = "charlie@google.com%{random_suffix}" + } + } +} +`, context) +} From 17300fa53535dabccabb6ec869d43f378b27780e Mon Sep 17 00:00:00 2001 From: Sam Levenick Date: Wed, 6 Mar 2024 10:37:19 -0500 Subject: [PATCH 082/200] Add apphub (#10133) Adds AppHub to APIs to activate --- .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 a6f8c58a5f69..439d37f5e8b3 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -168,6 +168,7 @@ module "project-services" { "apikeys.googleapis.com", "appengine.googleapis.com", "appengineflex.googleapis.com", + "apphub.googleapis.com", "artifactregistry.googleapis.com", "assuredworkloads.googleapis.com", "autoscaling.googleapis.com", From 1b12d6c903c6ef15fe8395918f47c9f476195cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20=27Cherit=27=20Sz=C3=B3stak?= Date: Wed, 6 Mar 2024 17:20:01 +0100 Subject: [PATCH 083/200] Allow sending empty app_engine and serverless google_compute_region_network_endpoint_group (#10031) --- mmv1/products/compute/RegionNetworkEndpointGroup.yaml | 7 +++++++ .../region_network_endpoint_group_appengine_empty.tf.erb | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 mmv1/templates/terraform/examples/region_network_endpoint_group_appengine_empty.tf.erb diff --git a/mmv1/products/compute/RegionNetworkEndpointGroup.yaml b/mmv1/products/compute/RegionNetworkEndpointGroup.yaml index 2dc6d82c64cc..177ce9001bf1 100644 --- a/mmv1/products/compute/RegionNetworkEndpointGroup.yaml +++ b/mmv1/products/compute/RegionNetworkEndpointGroup.yaml @@ -68,6 +68,11 @@ examples: primary_resource_id: 'appengine_neg' vars: neg_name: 'appengine-neg' + - !ruby/object:Provider::Terraform::Examples + name: 'region_network_endpoint_group_appengine_empty' + primary_resource_id: 'appengine_neg' + vars: + neg_name: 'appengine-neg' - !ruby/object:Provider::Terraform::Examples name: 'region_network_endpoint_group_psc' primary_resource_id: 'psc_neg' @@ -209,6 +214,7 @@ properties: - cloud_function - serverless_deployment allow_empty_object: true + send_empty_value: true description: | This field is only used for SERVERLESS NEGs. @@ -278,6 +284,7 @@ properties: - cloud_function - app_engine allow_empty_object: true + send_empty_value: true description: | This field is only used for SERVERLESS NEGs. diff --git a/mmv1/templates/terraform/examples/region_network_endpoint_group_appengine_empty.tf.erb b/mmv1/templates/terraform/examples/region_network_endpoint_group_appengine_empty.tf.erb new file mode 100644 index 000000000000..fe794ed86e7b --- /dev/null +++ b/mmv1/templates/terraform/examples/region_network_endpoint_group_appengine_empty.tf.erb @@ -0,0 +1,8 @@ +// App Engine Example +resource "google_compute_region_network_endpoint_group" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['neg_name'] %>" + network_endpoint_type = "SERVERLESS" + region = "us-central1" + app_engine { + } +} From ffd2cf300a8b5652a4638c772880bb5eeee24b34 Mon Sep 17 00:00:00 2001 From: Benjamin Kaplan <58792807+bskaplan@users.noreply.github.com> Date: Wed, 6 Mar 2024 09:13:14 -0800 Subject: [PATCH 084/200] Support service-level min instances in Cloud Run v2 services. (#10083) --- mmv1/products/cloudrunv2/Service.yaml | 10 ++ .../resource_cloud_run_v2_service_test.go.erb | 101 ++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index 4c7198049bfe..bbedcc2cf10c 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -256,6 +256,16 @@ properties: One or more custom audiences that you want this service to support. Specify each custom audience as the full URL in a string. The custom audiences are encoded in the token and used to authenticate requests. For more information, see https://cloud.google.com/run/docs/configuring/custom-audiences. item_type: Api::Type::String + - !ruby/object:Api::Type::NestedObject + name: 'scaling' + min_version: beta + description: | + Scaling settings that apply to the whole service + properties: + - !ruby/object:Api::Type::Integer + name: 'minInstanceCount' + description: | + Minimum number of instances for the service, to be divided among all revisions receiving traffic. - !ruby/object:Api::Type::NestedObject name: 'template' required: true diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb index f74b09be0e2f..bacaa401b2d6 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb @@ -794,6 +794,107 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceAttributionLabel(t *testing.T) { }) } +<% unless version == 'ga' -%> +func TestAccCloudRunV2Service_cloudrunv2ServiceWithServiceMinInstances(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: testAccCheckCloudRunV2ServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Service_cloudrunv2ServiceWithMinInstances(context), + }, + { + ResourceName: "google_cloud_run_v2_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "launch_stage"}, + }, + { + Config: testAccCloudRunV2Service_cloudrunv2ServiceWithNoMinInstances(context), + }, + { + ResourceName: "google_cloud_run_v2_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "launch_stage"}, + }, + + }, + }) +} + +func testAccCloudRunV2Service_cloudrunv2ServiceWithNoMinInstances(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_service" "default" { + name = "tf-test-cloudrun-service%{random_suffix}" + description = "description creating" + location = "us-central1" + launch_stage = "BETA" + annotations = { + generated-by = "magic-modules" + } + ingress = "INGRESS_TRAFFIC_ALL" + labels = { + label-1 = "value-1" + } + client = "client-1" + client_version = "client-version-1" + template { + containers { + name = "container-1" + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + lifecycle { + ignore_changes = [ + launch_stage, + ] + } +} + +`, context) +} +func testAccCloudRunV2Service_cloudrunv2ServiceWithMinInstances(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_service" "default" { + name = "tf-test-cloudrun-service%{random_suffix}" + description = "description creating" + location = "us-central1" + launch_stage = "BETA" + annotations = { + generated-by = "magic-modules" + } + ingress = "INGRESS_TRAFFIC_ALL" + labels = { + label-1 = "value-1" + } + client = "client-1" + client_version = "client-version-1" + scaling { + min_instance_count = 1 + } + template { + containers { + name = "container-1" + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + } + lifecycle { + ignore_changes = [ + launch_stage, + ] + } +} + +`, context) +} +<% end -%> + func testAccCloudRunV2Service_cloudrunv2ServiceWithAttributionLabel(context map[string]interface{}) string { return acctest.Nprintf(` provider "google" { From 787da35afeb5c4fa51a73001a2c0de59bb366ba8 Mon Sep 17 00:00:00 2001 From: jinyangtang <147192056+jinyangtang@users.noreply.github.com> Date: Wed, 6 Mar 2024 15:00:27 -0800 Subject: [PATCH 085/200] feat: Add CMEK support for Firestore database in Beta provider (#10044) * Modify database.yaml to add cmek related fields * Add two examples for firestore CMEK databases for testing * Resolve trailing space * Update documentation for kmsKeyName field * Resolve trailing space * Make field immutable * Update field documentation * Update field description --- mmv1/products/firestore/Database.yaml | 72 +++++++++++++++++++ .../examples/firestore_cmek_database.tf.erb | 50 +++++++++++++ ...ore_cmek_database_in_datastore_mode.tf.erb | 50 +++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 mmv1/templates/terraform/examples/firestore_cmek_database.tf.erb create mode 100644 mmv1/templates/terraform/examples/firestore_cmek_database_in_datastore_mode.tf.erb diff --git a/mmv1/products/firestore/Database.yaml b/mmv1/products/firestore/Database.yaml index 051872d7bc1a..d294f94c147a 100644 --- a/mmv1/products/firestore/Database.yaml +++ b/mmv1/products/firestore/Database.yaml @@ -78,6 +78,23 @@ examples: - project - etag - deletion_policy + - !ruby/object:Provider::Terraform::Examples + name: 'firestore_cmek_database' + min_version: beta + primary_resource_id: 'database' + vars: + database_id: "cmek-database-id" + delete_protection_state: "DELETE_PROTECTION_ENABLED" + kms_key_ring_name: "kms-key-ring" + kms_key_name: "kms-key" + 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' @@ -102,6 +119,23 @@ examples: - project - etag - deletion_policy + - !ruby/object:Provider::Terraform::Examples + name: 'firestore_cmek_database_in_datastore_mode' + min_version: beta + primary_resource_id: 'database' + vars: + database_id: "cmek-database-id" + delete_protection_state: "DELETE_PROTECTION_ENABLED" + kms_key_ring_name: "kms-key-ring" + kms_key_name: "kms-key" + test_env_vars: + project_id: :PROJECT_NAME + test_vars_overrides: + delete_protection_state: '"DELETE_PROTECTION_DISABLED"' + ignore_read_extra: + - project + - etag + - deletion_policy virtual_fields: - !ruby/object:Api::Type::Enum name: 'deletion_policy' @@ -234,3 +268,41 @@ properties: This value is continuously updated, and becomes stale the moment it is queried. If you are using this value to recover data, make sure to account for the time from the moment when the value is queried to the moment when you initiate the recovery. A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". output: true + - !ruby/object:Api::Type::NestedObject + name: cmekConfig + min_version: beta + immutable: true + description: | + The CMEK (Customer Managed Encryption Key) configuration for a Firestore + database. If not present, the database is secured by the default Google + encryption key. + properties: + - !ruby/object:Api::Type::String + name: kmsKeyName + required: true + immutable: true + description: | + The resource ID of a Cloud KMS key. If set, the database created will + be a Customer-managed Encryption Key (CMEK) database encrypted with + this key. This feature is allowlist only in initial launch. + + Only keys in the same location as this database are allowed to be used + for encryption. For Firestore's nam5 multi-region, this corresponds to Cloud KMS + multi-region us. For Firestore's eur3 multi-region, this corresponds to + Cloud KMS multi-region europe. See https://cloud.google.com/kms/docs/locations. + + This value should be the KMS key resource ID in the format of + `projects/{project_id}/locations/{kms_location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}`. + How to retrive this resource ID is listed at + https://cloud.google.com/kms/docs/getting-resource-ids#getting_the_id_for_a_key_and_version. + - !ruby/object:Api::Type::Array + name: activeKeyVersion + output: true + description: | + Currently in-use KMS key versions (https://cloud.google.com/kms/docs/resource-hierarchy#key_versions). + During key rotation (https://cloud.google.com/kms/docs/key-rotation), there can be + multiple in-use key versions. + + The expected format is + `projects/{project_id}/locations/{kms_location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}/cryptoKeyVersions/{key_version}`. + item_type: Api::Type::String diff --git a/mmv1/templates/terraform/examples/firestore_cmek_database.tf.erb b/mmv1/templates/terraform/examples/firestore_cmek_database.tf.erb new file mode 100644 index 000000000000..330b16d32eab --- /dev/null +++ b/mmv1/templates/terraform/examples/firestore_cmek_database.tf.erb @@ -0,0 +1,50 @@ +data "google_project" "project" { + provider = google-beta +} + +resource "google_firestore_database" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "<%= ctx[:vars]['database_id']%>" + location_id = "nam5" + type = "FIRESTORE_NATIVE" + 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" + cmek_config { + kms_key_name = google_kms_crypto_key.crypto_key.id + } + + depends_on = [ + google_kms_crypto_key_iam_binding.firestore_cmek_keyuser + ] +} + +resource "google_kms_crypto_key" "crypto_key" { + provider = google-beta + + name = "<%= ctx[:vars]['kms_key_name'] %>" + key_ring = google_kms_key_ring.key_ring.id + purpose = "ENCRYPT_DECRYPT" +} + +resource "google_kms_key_ring" "key_ring" { + provider = google-beta + + name = "<%= ctx[:vars]['kms_key_ring_name'] %>" + location = "us" +} + +resource "google_kms_crypto_key_iam_binding" "firestore_cmek_keyuser" { + provider = google-beta + + crypto_key_id = google_kms_crypto_key.crypto_key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-firestore.iam.gserviceaccount.com", + ] +} diff --git a/mmv1/templates/terraform/examples/firestore_cmek_database_in_datastore_mode.tf.erb b/mmv1/templates/terraform/examples/firestore_cmek_database_in_datastore_mode.tf.erb new file mode 100644 index 000000000000..ac2a33a8ce06 --- /dev/null +++ b/mmv1/templates/terraform/examples/firestore_cmek_database_in_datastore_mode.tf.erb @@ -0,0 +1,50 @@ +data "google_project" "project" { + provider = google-beta +} + +resource "google_firestore_database" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "<%= ctx[:vars]['database_id']%>" + location_id = "nam5" + type = "DATASTORE_MODE" + 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" + cmek_config { + kms_key_name = google_kms_crypto_key.crypto_key.id + } + + depends_on = [ + google_kms_crypto_key_iam_binding.firestore_cmek_keyuser + ] +} + +resource "google_kms_crypto_key" "crypto_key" { + provider = google-beta + + name = "<%= ctx[:vars]['kms_key_name'] %>" + key_ring = google_kms_key_ring.key_ring.id + purpose = "ENCRYPT_DECRYPT" +} + +resource "google_kms_key_ring" "key_ring" { + provider = google-beta + + name = "<%= ctx[:vars]['kms_key_ring_name'] %>" + location = "us" +} + +resource "google_kms_crypto_key_iam_binding" "firestore_cmek_keyuser" { + provider = google-beta + + crypto_key_id = google_kms_crypto_key.crypto_key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-firestore.iam.gserviceaccount.com", + ] +} From bbb072140e12dd22cfc72dd5dfe2c182337cb497 Mon Sep 17 00:00:00 2001 From: Naitian Liu <83430653+naitianliu-google@users.noreply.github.com> Date: Wed, 6 Mar 2024 16:28:02 -0800 Subject: [PATCH 086/200] Allow vcenter_network to be set (#9946) * Allow vcenter_network to be set * set default from api --- mmv1/products/gkeonprem/VmwareCluster.yaml | 3 ++- .../terraform/examples/gkeonprem_vmware_cluster_f5lb.tf.erb | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mmv1/products/gkeonprem/VmwareCluster.yaml b/mmv1/products/gkeonprem/VmwareCluster.yaml index 26a32312ce27..0e2e265fac87 100644 --- a/mmv1/products/gkeonprem/VmwareCluster.yaml +++ b/mmv1/products/gkeonprem/VmwareCluster.yaml @@ -252,7 +252,8 @@ properties: description: vcenter_network specifies vCenter network name. Inherited from the admin cluster. - output: true + immutable: true + default_from_api: true - !ruby/object:Api::Type::NestedObject name: 'hostConfig' description: diff --git a/mmv1/templates/terraform/examples/gkeonprem_vmware_cluster_f5lb.tf.erb b/mmv1/templates/terraform/examples/gkeonprem_vmware_cluster_f5lb.tf.erb index 3f9f6a15c69b..dbab108ee6bf 100644 --- a/mmv1/templates/terraform/examples/gkeonprem_vmware_cluster_f5lb.tf.erb +++ b/mmv1/templates/terraform/examples/gkeonprem_vmware_cluster_f5lb.tf.erb @@ -21,6 +21,7 @@ resource "google_gkeonprem_vmware_cluster" "<%= ctx[:primary_resource_id] %>" { gateway="test-gateway" } } + vcenter_network = "test-vcenter-network" } control_plane_node { cpus = 4 From 5780286152c4dcfa0d1b7caa6f9214dc6ffc73c4 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 6 Mar 2024 16:43:27 -0800 Subject: [PATCH 087/200] Sort resources and set in product in go compiler (#10135) --- mmv1/api/product.go | 10 +++++++++- mmv1/api/resource.go | 23 +++++++++++++++++++++-- mmv1/api/type.go | 5 ++--- mmv1/main.go | 25 ++++++++++++++++--------- mmv1/provider/terraform.go | 2 +- 5 files changed, 49 insertions(+), 16 deletions(-) diff --git a/mmv1/api/product.go b/mmv1/api/product.go index cf3bd9d33a48..d56edeefb9be 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -39,7 +39,7 @@ type Product struct { // Display Name: The full name of the GCP product; eg "Cloud Bigtable" - Objects []interface{} + Objects []*Resource // The list of permission scopes available for the service // For example: `https://www.googleapis.com/auth/compute` @@ -69,6 +69,14 @@ type Product struct { ClientName string `yaml:"client_name"` } +func (p *Product) Validate() { + // TODO Q1 Rewrite super + // super + for _, o := range p.Objects { + o.ProductMetadata = p + } +} + // def validate // super // set_variables @objects, :__product diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 75557aaee73b..894850e765c1 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -267,9 +267,28 @@ type Resource struct { // Add a deprecation message for a resource that's been deprecated in the API. DeprecationMessage string `yaml:"deprecation_message"` - Properties []Type + Properties []*Type - Parameters []Type + Parameters []*Type + + ProductMetadata *Product } // TODO: rewrite functions +func (r *Resource) Validate() { + // TODO Q1 Rewrite super + // super + + r.setResourceMetada(r.Parameters) + r.setResourceMetada(r.Properties) +} + +func (r *Resource) setResourceMetada(properties []*Type) { + if properties == nil { + return + } + + for _, property := range properties { + property.ResourceMetadata = r + } +} diff --git a/mmv1/api/type.go b/mmv1/api/type.go index b65547f1c9f3..0fe6f165e6dd 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -231,10 +231,9 @@ type Type struct { // just as they are in the standard flattener template. CustomFlatten string `yaml:"custom_flatten"` - __resource Resource + ResourceMetadata *Resource - // TODO: set a specific type intead of interface{} - __parent interface{} // is nil for top-level properties + ParentMetadata *Type // is nil for top-level properties } const MAX_NAME = 20 diff --git a/mmv1/main.go b/mmv1/main.go index b23108ac117a..b01aad864eaf 100644 --- a/mmv1/main.go +++ b/mmv1/main.go @@ -80,17 +80,17 @@ func main() { // TODO Q1: remove these lines, which are for debugging // log.Printf("productYamlPath %#v", productYamlPath) - var resources []api.Resource + var resources []*api.Resource = make([]*api.Resource, 0) productYaml, err := os.ReadFile(productYamlPath) if err != nil { log.Fatalf("Cannot open the file: %v", productYaml) } - productApi := api.Product{} - yamlValidator.Parse(productYaml, &productApi) + productApi := &api.Product{} + yamlValidator.Parse(productYaml, productApi) // TODO Q1: remove these lines, which are for debugging - // prod, _ := json.Marshal(&productApi) + // prod, _ := json.Marshal(productApi) // log.Printf("prod %s", string(prod)) if !productApi.ExistsAtVersionOrLower(version) { @@ -118,21 +118,29 @@ func main() { if err != nil { log.Fatalf("Cannot open the file: %v", resourceYamlPath) } - resource := api.Resource{} - yamlValidator.Parse(resourceYaml, &resource) + resource := &api.Resource{} + yamlValidator.Parse(resourceYaml, resource) // TODO Q1: remove these lines, which are for debugging - // res, _ := json.Marshal(&resource) + // res, _ := json.Marshal(resource) // log.Printf("resource %s", string(res)) // TODO Q1: add labels related fields + resource.Validate() resources = append(resources, resource) } // TODO Q2: override resources + log.Printf("resources before sorting %#v", resources) - // TODO Q1: sort resources by name and set in product + // Sort resources by name + sort.Slice(resources, func(i, j int) bool { + return resources[i].Name < resources[j].Name + }) + + productApi.Objects = resources + productApi.Validate() // TODO Q2: set other providers via flag providerToGenerate := provider.NewTerraform(productApi) @@ -142,7 +150,6 @@ func main() { continue } - // TODO Q1: generate templates log.Printf("%s: Generating files", productName) providerToGenerate.Generate(outputPath, productName, generateCode, generateDocs) } diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 154e89c12736..fb620c1ddce5 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -34,7 +34,7 @@ type Terraform struct { ResourcesForVersion []api.Resource } -func NewTerraform(product api.Product) *Terraform { +func NewTerraform(product *api.Product) *Terraform { t := Terraform{ResourceCount: 0, IAMResourceCount: 0} // TODO Q1 From a68867619922a8f947e59c9246281f4c6c741f34 Mon Sep 17 00:00:00 2001 From: Sneha Prasad <32434989+snpd25@users.noreply.github.com> Date: Thu, 7 Mar 2024 20:19:17 +0530 Subject: [PATCH 088/200] fix failing posture test (#10086) * fix failing posture test * modify posture name --------- Co-authored-by: Sneha Prasad --- .../terraform/examples/securityposture_posture_basic.tf.erb | 2 +- .../securityposture_posture_deployment_basic.tf.erb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mmv1/templates/terraform/examples/securityposture_posture_basic.tf.erb b/mmv1/templates/terraform/examples/securityposture_posture_basic.tf.erb index 9101034c48c2..32205bb0ae71 100644 --- a/mmv1/templates/terraform/examples/securityposture_posture_basic.tf.erb +++ b/mmv1/templates/terraform/examples/securityposture_posture_basic.tf.erb @@ -1,5 +1,5 @@ resource "google_securityposture_posture" "<%= ctx[:primary_resource_id] %>"{ - posture_id = "posture_1" + posture_id = "posture_example" parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" location = "global" state = "ACTIVE" diff --git a/mmv1/templates/terraform/examples/securityposture_posture_deployment_basic.tf.erb b/mmv1/templates/terraform/examples/securityposture_posture_deployment_basic.tf.erb index 8a514eb735e2..45cd4d886073 100644 --- a/mmv1/templates/terraform/examples/securityposture_posture_deployment_basic.tf.erb +++ b/mmv1/templates/terraform/examples/securityposture_posture_deployment_basic.tf.erb @@ -1,4 +1,4 @@ -resource "google_securityposture_posture" "posture1" { +resource "google_securityposture_posture" "posture_1" { posture_id = "posture_1" parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" location = "global" @@ -27,6 +27,6 @@ resource "google_securityposture_posture_deployment" "<%= ctx[:primary_resource_ location = "global" description = "a new posture deployment" target_resource = "projects/<%= ctx[:test_env_vars]['project_number'] %>" - posture_id = google_securityposture_posture.posture1.name - posture_revision_id = google_securityposture_posture.posture1.revision_id + posture_id = google_securityposture_posture.posture_1.name + posture_revision_id = google_securityposture_posture.posture_1.revision_id } \ No newline at end of file From 5c5b415c6c20bb760b511e8589d270dcc3728a50 Mon Sep 17 00:00:00 2001 From: rishamchokshi <44479344+rishamchokshi@users.noreply.github.com> Date: Thu, 7 Mar 2024 09:19:13 -0700 Subject: [PATCH 089/200] Create support for KMS Ekmconnection resource (#10094) --- mmv1/products/kms/EkmConnection.yaml | 166 ++++++++++++++++++ .../examples/kms_ekm_connection_basic.tf.erb | 12 ++ .../kms/resource_kms_ekm_connection_test.go | 139 +++++++++++++++ 3 files changed, 317 insertions(+) create mode 100644 mmv1/products/kms/EkmConnection.yaml create mode 100644 mmv1/templates/terraform/examples/kms_ekm_connection_basic.tf.erb create mode 100644 mmv1/third_party/terraform/services/kms/resource_kms_ekm_connection_test.go diff --git a/mmv1/products/kms/EkmConnection.yaml b/mmv1/products/kms/EkmConnection.yaml new file mode 100644 index 000000000000..191bf70d852d --- /dev/null +++ b/mmv1/products/kms/EkmConnection.yaml @@ -0,0 +1,166 @@ +# 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: 'EkmConnection' +base_url: 'projects/{{project}}/locations/{{location}}/ekmConnections' +create_url: 'projects/{{project}}/locations/{{location}}/ekmConnections?ekmConnectionId={{name}}' +self_link: 'projects/{{project}}/locations/{{location}}/ekmConnections/{{name}}' +update_verb: :PATCH +update_mask: true +description: | + `Ekm Connections` are used to control the connection settings for an `EXTERNAL_VPC` CryptoKey. + It is used to connect customer's external key manager to Google Cloud EKM. + + + ~> **Note:** Ekm Connections cannot be deleted from Google Cloud Platform. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Creating a Ekm Connection': 'https://cloud.google.com/kms/docs/create-ekm-connection' + api: 'https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.ekmConnections' +id_format: 'projects/{{project}}/locations/{{location}}/ekmConnections/{{name}}' +import_format: ['projects/{{project}}/locations/{{location}}/ekmConnections/{{name}}'] +skip_delete: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'kms_ekm_connection_basic' + primary_resource_id: + 'example-ekmconnection' + skip_test: true + vars: + ekmconnection_name: 'ekmconnection_example' +parameters: + - !ruby/object:Api::Type::String + name: 'location' + description: | + The location for the EkmConnection. + A full list of valid locations can be found by running `gcloud kms locations list`. + required: true + ignore_read: true + url_param_only: true + immutable: true +properties: + - !ruby/object:Api::Type::String + name: 'name' + description: | + The resource name for the EkmConnection. + required: true + immutable: true + diff_suppress_func: 'tpgresource.CompareResourceNames' + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + - !ruby/object:Api::Type::Array + name: 'serviceResolvers' + description: | + A list of ServiceResolvers where the EKM can be reached. There should be one ServiceResolver per EKM replica. Currently, only a single ServiceResolver is supported + required: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'serviceDirectoryService' + description: | + Required. The resource name of the Service Directory service pointing to an EKM replica, in the format projects/*/locations/*/namespaces/*/services/* + required: true + - !ruby/object:Api::Type::String + name: 'hostname' + description: | + Required. The hostname of the EKM replica used at TLS and HTTP layers. + required: true + - !ruby/object:Api::Type::Array + name: 'serverCertificates' + description: | + Required. A list of leaf server certificates used to authenticate HTTPS connections to the EKM replica. Currently, a maximum of 10 Certificate is supported. + required: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'rawDer' + description: | + Required. The raw certificate bytes in DER format. A base64-encoded string. + required: true + - !ruby/object:Api::Type::Boolean + name: 'parsed' + description: | + Output only. True if the certificate was parsed successfully. + output: true + - !ruby/object:Api::Type::String + name: 'issuer' + description: | + Output only. The issuer distinguished name in RFC 2253 format. Only present if parsed is true. + output: true + - !ruby/object:Api::Type::String + name: 'subject' + description: | + Output only. The subject distinguished name in RFC 2253 format. Only present if parsed is true. + output: true + - !ruby/object:Api::Type::String + name: 'notBeforeTime' + description: | + Output only. The certificate is not valid before this time. Only present if parsed is true. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + output: true + - !ruby/object:Api::Type::String + name: 'notAfterTime' + description: | + Output only. The certificate is not valid after this time. Only present if parsed is true. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + output: true + - !ruby/object:Api::Type::String + name: 'sha256Fingerprint' + description: | + Output only. The SHA-256 certificate fingerprint as a hex string. Only present if parsed is true. + output: true + - !ruby/object:Api::Type::String + name: 'serialNumber' + description: | + Output only. The certificate serial number as a hex string. Only present if parsed is true. + output: true + - !ruby/object:Api::Type::Array + name: 'subjectAlternativeDnsNames' + description: | + Output only. The subject Alternative DNS names. Only present if parsed is true. + output: true + default_from_api: true + item_type: Api::Type::String + - !ruby/object:Api::Type::String + name: 'endpointFilter' + description: | + Optional. The filter applied to the endpoints of the resolved service. If no filter is specified, all endpoints will be considered. An endpoint will be chosen arbitrarily from the filtered list for each request. For endpoint filter syntax and examples, see https://cloud.google.com/service-directory/docs/reference/rpc/google.cloud.servicedirectory.v1#resolveservicerequest. + required: false + default_from_api: true + - !ruby/object:Api::Type::Enum + name: 'keyManagementMode' + description: | + Optional. Describes who can perform control plane operations on the EKM. If unset, this defaults to MANUAL + required: false + default_value: :MANUAL + values: + - :MANUAL + - :CLOUD_KMS + - !ruby/object:Api::Type::String + name: 'etag' + required: false + default_from_api: true + description: | + Optional. Etag of the currently stored EkmConnection. + - !ruby/object:Api::Type::String + name: 'cryptoSpacePath' + description: | + Optional. Identifies the EKM Crypto Space that this EkmConnection maps to. Note: This field is required if KeyManagementMode is CLOUD_KMS. + required: false + default_from_api: true + - !ruby/object:Api::Type::String + name: 'createTime' + description: | + Output only. The time at which the EkmConnection was created. + A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z". + output: true diff --git a/mmv1/templates/terraform/examples/kms_ekm_connection_basic.tf.erb b/mmv1/templates/terraform/examples/kms_ekm_connection_basic.tf.erb new file mode 100644 index 000000000000..49fcd7f8769c --- /dev/null +++ b/mmv1/templates/terraform/examples/kms_ekm_connection_basic.tf.erb @@ -0,0 +1,12 @@ +resource "google_kms_ekm_connection" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['ekmconnection_name'] %>" + location = "us-central1" + key_management_mode = "MANUAL" + service_resolvers { + service_directory_service = "projects/project_id/locations/us-central1/namespaces/namespace_name/services/service_name" + hostname = "example-ekm.goog" + server_certificates { + raw_der = "==HAwIBCCAr6gAwIBAgIUWR+EV4lqiV7Ql12VY==" + } + } +} diff --git a/mmv1/third_party/terraform/services/kms/resource_kms_ekm_connection_test.go b/mmv1/third_party/terraform/services/kms/resource_kms_ekm_connection_test.go new file mode 100644 index 000000000000..38d9b6c39fd5 --- /dev/null +++ b/mmv1/third_party/terraform/services/kms/resource_kms_ekm_connection_test.go @@ -0,0 +1,139 @@ +package kms_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccKMSEkmConnection_kmsEkmConnectionBasicExample_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: testAccKMSEkmConnection_kmsEkmConnectionBasicExample_full(context), + }, + { + ResourceName: "google_kms_ekm_connection.example-ekmconnection", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name"}, + }, + { + Config: testAccKMSEkmConnection_kmsEkmConnectionBasicExample_update(context), + }, + { + ResourceName: "google_kms_ekm_connection.example-ekmconnection", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "name"}, + }, + }, + }) +} + +func testAccKMSEkmConnection_kmsEkmConnectionBasicExample_full(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_secret_manager_secret_version" "raw_der" { + secret = "playground-cert" + project = "315636579862" +} +data "google_secret_manager_secret_version" "hostname" { + secret = "external-uri" + project = "315636579862" +} +data "google_secret_manager_secret_version" "servicedirectoryservice" { + secret = "external-servicedirectoryservice" + project = "315636579862" +} +data "google_project" "vpc-project" { + project_id = "cloud-ekm-refekm-playground" +} +data "google_project" "project" { +} +resource "google_project_iam_member" "add_sdviewer" { + project = data.google_project.vpc-project.number + role = "roles/servicedirectory.viewer" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-ekms.iam.gserviceaccount.com" +} +resource "google_project_iam_member" "add_pscAuthorizedService" { + project = data.google_project.vpc-project.number + role = "roles/servicedirectory.pscAuthorizedService" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-ekms.iam.gserviceaccount.com" +} +resource "google_kms_ekm_connection" "example-ekmconnection" { + name = "tf_test_ekmconnection_example%{random_suffix}" + location = "us-central1" + key_management_mode = "MANUAL" + service_resolvers { + service_directory_service = data.google_secret_manager_secret_version.servicedirectoryservice.secret_data + hostname = data.google_secret_manager_secret_version.hostname.secret_data + server_certificates { + raw_der = data.google_secret_manager_secret_version.raw_der.secret_data + } + } + depends_on = [ + google_project_iam_member.add_pscAuthorizedService, + google_project_iam_member.add_sdviewer + ] +} +`, context) +} + +func testAccKMSEkmConnection_kmsEkmConnectionBasicExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_project" "vpc-project" { + project_id = "cloud-ekm-refekm-playground" +} +data "google_project" "project" { +} +data "google_secret_manager_secret_version" "raw_der" { + secret = "playground-cert" + project = "315636579862" +} +data "google_secret_manager_secret_version" "hostname" { + secret = "external-uri" + project = "315636579862" +} +data "google_secret_manager_secret_version" "servicedirectoryservice" { + secret = "external-servicedirectoryservice" + project = "315636579862" +} +resource "google_project_iam_member" "add_sdviewer_updateekmconnection" { + project = data.google_project.vpc-project.number + role = "roles/servicedirectory.viewer" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-ekms.iam.gserviceaccount.com" +} +resource "google_project_iam_member" "add_pscAuthorizedService_updateekmconnection" { + project = data.google_project.vpc-project.number + role = "roles/servicedirectory.pscAuthorizedService" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-ekms.iam.gserviceaccount.com" +} +resource "google_kms_ekm_connection" "example-ekmconnection" { + name = "tf_test_ekmconnection_example%{random_suffix}" + location = "us-central1" + key_management_mode = "CLOUD_KMS" + crypto_space_path = "v0/longlived/crypto-space-placeholder" + service_resolvers { + service_directory_service = data.google_secret_manager_secret_version.servicedirectoryservice.secret_data + hostname = data.google_secret_manager_secret_version.hostname.secret_data + server_certificates { + raw_der = data.google_secret_manager_secret_version.raw_der.secret_data + } + } + depends_on = [ + google_project_iam_member.add_pscAuthorizedService_updateekmconnection, + google_project_iam_member.add_sdviewer_updateekmconnection + ] +} +`, context) +} From 12b3ce1062029cd144b66e51d511c12532df9363 Mon Sep 17 00:00:00 2001 From: kautikdk <144651627+kautikdk@users.noreply.github.com> Date: Thu, 7 Mar 2024 17:54:07 +0000 Subject: [PATCH 090/200] Fixes two lifecycle rules with different no_age value always generates change. (#10137) --- .../storage/resource_storage_bucket.go.erb | 8 +++--- .../resource_storage_bucket_test.go.erb | 26 ++++++++++++++++--- 2 files changed, 26 insertions(+), 8 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 8f9d429e3408..ed7422389d82 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 @@ -1237,10 +1237,10 @@ func flattenBucketLifecycle(d *schema.ResourceData, lifecycle *storage.BucketLif rules := make([]map[string]interface{}, 0, len(lifecycle.Rule)) - for _, rule := range lifecycle.Rule { + for index, rule := range lifecycle.Rule { rules = append(rules, map[string]interface{}{ "action": schema.NewSet(resourceGCSBucketLifecycleRuleActionHash, []interface{}{flattenBucketLifecycleRuleAction(rule.Action)}), - "condition": schema.NewSet(resourceGCSBucketLifecycleRuleConditionHash, []interface{}{flattenBucketLifecycleRuleCondition(d, rule.Condition)}), + "condition": schema.NewSet(resourceGCSBucketLifecycleRuleConditionHash, []interface{}{flattenBucketLifecycleRuleCondition(index, d, rule.Condition)}), }) } @@ -1254,7 +1254,7 @@ func flattenBucketLifecycleRuleAction(action *storage.BucketLifecycleRuleAction) } } -func flattenBucketLifecycleRuleCondition(d *schema.ResourceData, condition *storage.BucketLifecycleRuleCondition) map[string]interface{} { +func flattenBucketLifecycleRuleCondition(index int, d *schema.ResourceData, condition *storage.BucketLifecycleRuleCondition) map[string]interface{} { ruleCondition := map[string]interface{}{ "created_before": condition.CreatedBefore, "matches_storage_class": tpgresource.ConvertStringArrToInterface(condition.MatchesStorageClass), @@ -1279,7 +1279,7 @@ func flattenBucketLifecycleRuleCondition(d *schema.ResourceData, condition *stor } } // 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{ + if v, ok := d.GetOk(fmt.Sprintf("lifecycle_rule.%d.condition",index)); ok{ state_condition := v.(*schema.Set).List()[0].(map[string]interface{}) ruleCondition["no_age"] = state_condition["no_age"].(bool) } 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 7c686a2878cd..f62447cb399e 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 @@ -508,7 +508,7 @@ func TestAccStorageBucket_lifecycleRulesNoAge(t *testing.T) { ResourceName: "google_storage_bucket.bucket", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"force_destroy","lifecycle_rule.0.condition.0.no_age"}, + ImportStateVerifyIgnore: []string{"force_destroy","lifecycle_rule.1.condition.0.no_age"}, }, { Config: testAccStorageBucket_customAttributes_withLifecycleNoAgeAndAge(bucketName), @@ -522,7 +522,7 @@ func TestAccStorageBucket_lifecycleRulesNoAge(t *testing.T) { ResourceName: "google_storage_bucket.bucket", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"force_destroy","lifecycle_rule.0.condition.0.no_age"}, + ImportStateVerifyIgnore: []string{"force_destroy","lifecycle_rule.1.condition.0.no_age"}, }, { Config: testAccStorageBucket_customAttributes_withLifecycle1(bucketName), @@ -1477,8 +1477,8 @@ 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 { + actual := b.Lifecycle.Rule[1].Condition.Age + if expected == nil && b.Lifecycle.Rule[1].Condition.Age == nil { return nil } if expected == nil { @@ -1688,6 +1688,15 @@ resource "google_storage_bucket" "bucket" { name = "%s" location = "EU" force_destroy = "true" + lifecycle_rule { + action { + type = "Delete" + } + condition { + age = 10 + no_age = false + } + } lifecycle_rule { action { type = "Delete" @@ -1707,6 +1716,15 @@ resource "google_storage_bucket" "bucket" { name = "%s" location = "EU" force_destroy = "true" + lifecycle_rule { + action { + type = "Delete" + } + condition { + age = 10 + no_age = false + } + } lifecycle_rule { action { type = "Delete" From e75074de0ad046be7c842eb6fea56adb59b32bd8 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Thu, 7 Mar 2024 18:27:37 +0000 Subject: [PATCH 091/200] TeamCity: Add project for testing the provider functions feature branch (#10088) * Add ability to use non-default versions of Terraform in TeamCity builds * Add function to enable making build configs for single packages at a time * Add new sub project that contains 2 builds for testing provider functions the 2 builds: 1) only pulls code from the feature branch on the downstream hashicorp/terraform-provider-google repo 2) only pulls code from the feature branch on the downstream hashicorp/terraform-provider-google-beta repo These builds both use an alpha release of TF 1.8.0 * Add builds for testing auto generated branches in the MM upstream repos These re-use existing VCR Roots. * Make the builds that test the `FEATURE-BRANCH-provider-functions branches in the downstream repos run every night at the default time * Fix defect in 'Download Terraform' build step definition * Update build step to solve bug * Update build_configuration_per_package.kt --- .../builds/build_configuration_per_package.kt | 11 +- .../components/builds/build_parameters.kt | 14 ++- .../components/builds/build_steps.kt | 7 +- .../.teamcity/components/inputs/packages.kt | 10 ++ .../FEATURE-BRANCH-provider-functions.kt | 102 ++++++++++++++++++ .../components/projects/root_project.kt | 5 + 6 files changed, 142 insertions(+), 7 deletions(-) create mode 100644 mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt index 21d956030d68..395dc4da4a9c 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt @@ -15,6 +15,8 @@ import jetbrains.buildServer.configs.kotlin.sharedResources import jetbrains.buildServer.configs.kotlin.vcs.GitVcsRoot import replaceCharsId +// BuildConfigurationsForPackages accepts a map containing details of multiple packages in a provider and returns a list of build configurations for them all. +// Intended to be used in projects where we're testing all packages, e.g. the nightly test projects fun BuildConfigurationsForPackages(packages: Map>, providerName: String, parentProjectName: String, vcsRoot: GitVcsRoot, sharedResources: List, environmentVariables: AccTestConfiguration): List { val list = ArrayList() @@ -31,6 +33,13 @@ fun BuildConfigurationsForPackages(packages: Map>, p return list } +// BuildConfigurationForSinglePackage accepts details of a single package in a provider and returns a build configuration for it +// Intended to be used in short-lived projects where we're testing specific packages, e.g. feature branch testing +fun BuildConfigurationForSinglePackage(packageName: String, packagePath: String, packageDisplayName: String, providerName: String, parentProjectName: String, vcsRoot: GitVcsRoot, sharedResources: List, environmentVariables: AccTestConfiguration): BuildType{ + val pkg = PackageDetails(packageName, packageDisplayName, providerName, parentProjectName) + return pkg.buildConfiguration(packagePath, vcsRoot, sharedResources, environmentVariables) +} + class PackageDetails(private val packageName: String, private val displayName: String, private val providerName: String, private val parentProjectName: String) { // buildConfiguration returns a BuildType for a service package @@ -102,4 +111,4 @@ class PackageDetails(private val packageName: String, private val displayName: S var id = "%s_%s_PACKAGE_%s".format(this.parentProjectName, this.providerName, this.packageName) return replaceCharsId(id) } -} \ No newline at end of file +} diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt index 88928ed37a23..7641bc858592 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt @@ -252,12 +252,20 @@ fun ParametrizedWithType.readOnlySettings() { } // ParametrizedWithType.terraformCoreBinaryTesting sets environment variables that control what Terraform version is downloaded -// and ensures the testing framework uses that downloaded version -fun ParametrizedWithType.terraformCoreBinaryTesting() { - text("env.TERRAFORM_CORE_VERSION", DefaultTerraformCoreVersion, "The version of Terraform Core which should be used for testing") +// and ensures the testing framework uses that downloaded version. The default Terraform core version is used if no argument is supplied. +fun ParametrizedWithType.terraformCoreBinaryTesting(tfVersion: String = DefaultTerraformCoreVersion) { + text("env.TERRAFORM_CORE_VERSION", tfVersion, "The version of Terraform Core which should be used for testing") hiddenVariable("env.TF_ACC_TERRAFORM_PATH", "%system.teamcity.build.checkoutDir%/tools/terraform", "The path where the Terraform Binary is located. Used by the testing framework.") } +// BuildType.overrideTerraformCoreVersion is used to override the value of TERRAFORM_CORE_VERSION in special cases where we're testing new features +// that rely on a specific version of Terraform we might not want to be used for all our tests in TeamCity. +fun BuildType.overrideTerraformCoreVersion(tfVersion: String){ + params { + terraformCoreBinaryTesting(tfVersion) + } +} + fun ParametrizedWithType.terraformShouldPanicForSchemaErrors() { hiddenVariable("env.TF_SCHEMA_PANIC_ON_ERROR", "1", "Panic if unknown/unmatched fields are set into the state") } diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt index 78f942cf380d..4682f1240eb9 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt @@ -64,14 +64,15 @@ fun BuildSteps.downloadTerraformBinary() { // https://releases.hashicorp.com/terraform/0.12.28/terraform_0.12.28_linux_amd64.zip val terraformUrl = "https://releases.hashicorp.com/terraform/%env.TERRAFORM_CORE_VERSION%/terraform_%env.TERRAFORM_CORE_VERSION%_linux_amd64.zip" step(ScriptBuildStep { - name = "Download Terraform version %s".format(DefaultTerraformCoreVersion) + name = "Download Terraform" scriptContent = """ #!/bin/bash + echo "Downloading Terraform version %env.TERRAFORM_CORE_VERSION%" mkdir -p tools - wget -O tf.zip %s + wget -O tf.zip $terraformUrl unzip tf.zip mv terraform tools/ - """.format(terraformUrl).trimIndent() + """.trimIndent() }) } diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt index 5ea3d2a5d48a..2e4b11ffb516 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt @@ -13,6 +13,11 @@ var PackagesListGa = mapOf( "displayName" to "Environment Variables", "path" to "./google/envvar" ), + "functions" to mapOf( + "name" to "functions", + "displayName" to "Provider-Defined Functions", + "path" to "./google/functions" + ), "fwmodels" to mapOf( "name" to "fwmodels", "displayName" to "Framework Models", @@ -64,6 +69,11 @@ var PackagesListBeta = mapOf( "displayName" to "Environment Variables", "path" to "./google-beta/envvar" ), + "functions" to mapOf( + "name" to "functions", + "displayName" to "Provider-Defined Functions", + "path" to "./google-beta/functions" + ), "fwmodels" to mapOf( "name" to "fwmodels", "displayName" to "Framework Models", diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt new file mode 100644 index 000000000000..3c1752e227f7 --- /dev/null +++ b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt @@ -0,0 +1,102 @@ +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + +// This file is controlled by MMv1, any changes made here will be overwritten + +package projects.feature_branches + +import ProviderNameBeta +import ProviderNameGa +import builds.* +import generated.PackagesListBeta +import generated.PackagesListGa +import jetbrains.buildServer.configs.kotlin.Project +import jetbrains.buildServer.configs.kotlin.vcs.GitVcsRoot +import replaceCharsId +import vcs_roots.ModularMagicianVCSRootBeta +import vcs_roots.ModularMagicianVCSRootGa + +const val featureBranchProviderFunctionsName = "FEATURE-BRANCH-provider-functions" +const val providerFunctionsTfCoreVersion = "1.8.0-alpha20240228" + +// VCS Roots specifically for pulling code from the feature branches in the downstream and upstream repos +object HashicorpVCSRootGa_featureBranchProviderFunctions: GitVcsRoot({ + name = "VCS root for the hashicorp/terraform-provider-${ProviderNameGa} repo @ refs/heads/${featureBranchProviderFunctionsName}" + url = "https://github.com/hashicorp/terraform-provider-${ProviderNameGa}" + branch = "refs/heads/${featureBranchProviderFunctionsName}" + branchSpec = "" // empty as we'll access no other branches +}) + +object HashicorpVCSRootBeta_featureBranchProviderFunctions: GitVcsRoot({ + name = "VCS root for the hashicorp/terraform-provider-${ProviderNameBeta} repo @ refs/heads/${featureBranchProviderFunctionsName}" + url = "https://github.com/hashicorp/terraform-provider-${ProviderNameBeta}" + branch = "refs/heads/${featureBranchProviderFunctionsName}" + branchSpec = "" // empty as we'll access no other branches +}) + +fun featureBranchProviderFunctionSubProject(allConfig: AllContextParameters): Project { + + val projectId = replaceCharsId(featureBranchProviderFunctionsName) + + val packageName = "functions" // This project will contain only builds to test this single package + val sharedResourcesEmpty: List = listOf() // No locking when testing functions + val vcrConfig = getVcrAcceptanceTestConfig(allConfig) // Reused below for both MM testing build configs + val trigger = NightlyTriggerConfiguration() // Resued below for running tests against the downstream repos every night. + + var parentId: String // To be overwritten when each build config is generated below. + + // GA + val gaConfig = getGaAcceptanceTestConfig(allConfig) + // How to make only build configuration to the relevant package(s) + val functionPackageGa = PackagesListGa.getValue(packageName) + + // Enable testing using hashicorp/terraform-provider-google + parentId = "${projectId}_HC_GA" + val buildConfigHashiCorpGa = BuildConfigurationForSinglePackage(packageName, functionPackageGa.getValue("path"), "Provider-Defined Functions (GA provider, HashiCorp downstream)", ProviderNameGa, parentId, HashicorpVCSRootGa_featureBranchProviderFunctions, sharedResourcesEmpty, gaConfig) + buildConfigHashiCorpGa.addTrigger(trigger) + + // Enable testing using modular-magician/terraform-provider-google + parentId = "${projectId}_MM_GA" + val buildConfigModularMagicianGa = BuildConfigurationForSinglePackage(packageName, functionPackageGa.getValue("path"), "Provider-Defined Functions (GA provider, MM upstream)", ProviderNameGa, parentId, ModularMagicianVCSRootGa, sharedResourcesEmpty, vcrConfig) + + // Beta + val betaConfig = getBetaAcceptanceTestConfig(allConfig) + val functionPackageBeta = PackagesListBeta.getValue("functions") + + // Enable testing using hashicorp/terraform-provider-google-beta + parentId = "${projectId}_HC_BETA" + val buildConfigHashiCorpBeta = BuildConfigurationForSinglePackage(packageName, functionPackageBeta.getValue("path"), "Provider-Defined Functions (Beta provider, HashiCorp downstream)", ProviderNameBeta, parentId, HashicorpVCSRootBeta_featureBranchProviderFunctions, sharedResourcesEmpty, betaConfig) + buildConfigHashiCorpBeta.addTrigger(trigger) + + // Enable testing using modular-magician/terraform-provider-google-beta + parentId = "${projectId}_MM_BETA" + val buildConfigModularMagicianBeta = BuildConfigurationForSinglePackage(packageName, functionPackageBeta.getValue("path"), "Provider-Defined Functions (Beta provider, MM upstream)", ProviderNameBeta, parentId, ModularMagicianVCSRootBeta, sharedResourcesEmpty, vcrConfig) + + val allBuildConfigs = listOf(buildConfigHashiCorpGa, buildConfigModularMagicianGa, buildConfigHashiCorpBeta, buildConfigModularMagicianBeta) + + // Make these builds use a 1.8.0-ish version of TF core + allBuildConfigs.forEach{ b -> + b.overrideTerraformCoreVersion(providerFunctionsTfCoreVersion) + } + + return Project{ + id(projectId) + name = featureBranchProviderFunctionsName + description = "Subproject for testing feature branch $featureBranchProviderFunctionsName" + + // Register feature branch-specific VCS roots in the project + vcsRoot(HashicorpVCSRootGa_featureBranchProviderFunctions) + vcsRoot(HashicorpVCSRootBeta_featureBranchProviderFunctions) + + // Register all build configs in the project + allBuildConfigs.forEach{ b -> + buildType(b) + } + + params { + readOnlySettings() + } + } +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt index 0c130da8eca5..a78260dfe650 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt @@ -18,6 +18,7 @@ import generated.ServicesListBeta import generated.ServicesListGa import jetbrains.buildServer.configs.kotlin.Project import jetbrains.buildServer.configs.kotlin.sharedResource +import projects.feature_branches.featureBranchProviderFunctionSubProject // googleCloudRootProject returns a root project that contains a subprojects for the GA and Beta version of the // Google provider. There are also resources to help manage the test projects used for acceptance tests. @@ -57,10 +58,14 @@ fun googleCloudRootProject(allConfig: AllContextParameters): Project { } } + // Projects required for nightly testing, testing MM upstreams, and sweepers subProject(googleSubProjectGa(allConfig)) subProject(googleSubProjectBeta(allConfig)) subProject(projectSweeperSubProject(allConfig)) + // Feature branch-testing projects - these will be added and removed as needed + subProject(featureBranchProviderFunctionSubProject(allConfig)) + params { readOnlySettings() } From 7d69486c5abeca313d2ce35ae053b073e34ca03a Mon Sep 17 00:00:00 2001 From: kangy-google Date: Thu, 7 Mar 2024 10:53:09 -0800 Subject: [PATCH 092/200] Add `ephemeral_directories` to google_workstations_workstation_config (#10042) * Add `ephemeral_directories` to google_workstations_workstation_config * Remove trailing spaces * Add a test for ephemeral_directories * Fix test * Add a test for source_image * Fix typo in test * Remove unnecessary immutable field --- .../workstations/WorkstationConfig.yaml | 42 +++++ ...orkstations_workstation_config_test.go.erb | 178 ++++++++++++++++++ 2 files changed, 220 insertions(+) diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index 624e5593fd20..39fada27bca8 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -369,6 +369,48 @@ properties: description: | Name of the snapshot to use as the source for the disk. This can be the snapshot's `self_link`, `id`, or a string in the format of `projects/{project}/global/snapshots/{snapshot}`. If set, `sizeGb` and `fsType` must be empty. Can only be updated if it has an existing value. # TODO(esu): Add conflicting fields once complex lists are supported. + - !ruby/object:Api::Type::Array + name: 'ephemeralDirectories' + description: | + Ephemeral directories which won't persist across workstation sessions. + default_from_api: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'mountPath' + description: | + Location of this directory in the running workstation. + default_from_api: true + - !ruby/object:Api::Type::NestedObject + name: 'gcePd' + description: | + An EphemeralDirectory backed by a Compute Engine persistent disk. + default_from_api: true + properties: + - !ruby/object:Api::Type::String + name: 'diskType' + description: | + Type of the disk to use. Defaults to `"pd-standard"`. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'sourceSnapshot' + description: | + Name of the snapshot to use as the source for the disk. + + Must be empty if `sourceImage` is set. + Must be empty if `read_only` is false. + Updating `source_snapshot` will update content in the ephemeral directory after the workstation is restarted. + - !ruby/object:Api::Type::String + name: 'sourceImage' + description: | + Name of the disk image to use as the source for the disk. + + Must be empty `sourceSnapshot` is set. + Updating `sourceImage` will update content in the ephemeral directory after the workstation is restarted. + - !ruby/object:Api::Type::Boolean + name: 'readOnly' + description: | + Whether the disk is read only. If true, the disk may be shared by multiple VMs and `sourceSnapshot` must be set. - !ruby/object:Api::Type::NestedObject name: 'container' description: | diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb index 72565a7f5219..e29069d6ab11 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb @@ -223,6 +223,184 @@ resource "google_workstations_workstation_config" "default" { `, context) } +func TestAccWorkstationsWorkstationConfig_ephemeralDirectories(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationConfig_ephemeralDirectories(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkstationsWorkstationConfig_ephemeralDirectories(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_compute_disk" "test_source_disk" { + provider = google-beta + name = "tf-test-workstation-source-disk%{random_suffix}" + size = 10 + type = "pd-ssd" + zone = "us-central1-a" +} + +resource "google_compute_snapshot" "test_source_snapshot" { + provider = google-beta + name = "tf-test-workstation-source-snapshot%{random_suffix}" + source_disk = google_compute_disk.test_source_disk.name + zone = "us-central1-a" +} + +resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + foo = "bar" + } +} + +resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + + ephemeral_directories { + mount_path = "/cache" + gce_pd { + source_snapshot = google_compute_snapshot.test_source_snapshot.id + read_only = true + } + } + + labels = { + foo = "bar" + } +} +`, context) +} + +func TestAccWorkstationsWorkstationConfig_ephemeralDirectories_withSourceImage(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationConfig_ephemeralDirectories_withSourceImage(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag", "labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccWorkstationsWorkstationConfig_ephemeralDirectories_withSourceImage(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_compute_disk" "test_source_disk" { + provider = google-beta + name = "tf-test-workstation-source-disk%{random_suffix}" + size = 10 + type = "pd-ssd" + zone = "us-central1-a" +} + +resource "google_compute_image" "test_source_image" { + provider = google-beta + name = "tf-test-workstation-source-image%{random_suffix}" + source_disk = google_compute_disk.test_source_disk.name + storage_locations = ["us-central1"] +} + +resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + foo = "bar" + } +} + +resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + + ephemeral_directories { + mount_path = "/cache" + gce_pd { + disk_type = "pd-standard" + source_image = google_compute_image.test_source_image.id + read_only = true + } + } + + labels = { + foo = "bar" + } +} +`, context) +} func TestAccWorkstationsWorkstationConfig_serviceAccount(t *testing.T) { t.Parallel() From e285c09c0a21af2e5fe3721a23522331599c415e Mon Sep 17 00:00:00 2001 From: Lingkai Shen Date: Thu, 7 Mar 2024 14:57:08 -0500 Subject: [PATCH 093/200] App Check DeviceCheck provider (#9978) * App Check DeviceCheck provider * Remove minimal example & pattern field * Add real private keys that are not useful anywhere * Limit tests to beta --- .../firebaseappcheck/DeviceCheckConfig.yaml | 97 +++++++++++++++++++ ..._app_check_device_check_config_full.tf.erb | 34 +++++++ ..._app_check_device_check_config_test.go.erb | 63 ++++++++++++ .../test-fixtures/private-key-2.p8 | 15 +++ .../test-fixtures/private-key.p8 | 15 +++ 5 files changed, 224 insertions(+) create mode 100644 mmv1/products/firebaseappcheck/DeviceCheckConfig.yaml create mode 100644 mmv1/templates/terraform/examples/firebase_app_check_device_check_config_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_device_check_config_test.go.erb create mode 100644 mmv1/third_party/terraform/services/firebaseappcheck/test-fixtures/private-key-2.p8 create mode 100644 mmv1/third_party/terraform/services/firebaseappcheck/test-fixtures/private-key.p8 diff --git a/mmv1/products/firebaseappcheck/DeviceCheckConfig.yaml b/mmv1/products/firebaseappcheck/DeviceCheckConfig.yaml new file mode 100644 index 000000000000..3b708a93471d --- /dev/null +++ b/mmv1/products/firebaseappcheck/DeviceCheckConfig.yaml @@ -0,0 +1,97 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- +!ruby/object:Api::Resource +name: "DeviceCheckConfig" +base_url: projects/{{project}}/apps/{{app_id}}/deviceCheckConfig +self_link: projects/{{project}}/apps/{{app_id}}/deviceCheckConfig +create_url: projects/{{project}}/apps/{{app_id}}/deviceCheckConfig?updateMask=tokenTtl,keyId,privateKey +create_verb: :PATCH +update_verb: :PATCH +update_mask: true +skip_delete: true +description: | + An app's DeviceCheck configuration object. Note that the Team ID registered with your + app is used as part of the validation process. Make sure your `google_firebase_apple_app` has a team_id present. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + "Official Documentation": "https://firebase.google.com/docs/app-check" + api: "https://firebase.google.com/docs/reference/appcheck/rest/v1/projects.apps.deviceCheckConfig" +import_format: + [ + "projects/{{project}}/apps/{{app_id}}/deviceCheckConfig", + "{{project}}/{{app_id}}", + "{{app_id}}", + ] +examples: + - !ruby/object:Provider::Terraform::Examples + name: "firebase_app_check_device_check_config_full" + min_version: 'beta' + # Need the time_sleep resource + pull_external: true + primary_resource_id: "default" + vars: + bundle_id: "bundle.id.devicecheck" + key_id: "Key ID" + private_key_path: "path/to/private-key.p8" + team_id: "9987654321" + token_ttl: "7200s" + test_vars_overrides: + # Don't add random suffix + private_key_path: '"test-fixtures/private-key-2.p8"' + team_id: '"9987654321"' + token_ttl: '"7200s"' + test_env_vars: + project_id: :PROJECT_NAME +parameters: + - !ruby/object:Api::Type::String + name: app_id + description: | + The ID of an + [Apple App](https://firebase.google.com/docs/reference/firebase-management/rest/v1beta1/projects.iosApps#IosApp.FIELDS.app_id). + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: name + description: | + The relative resource name of the DeviceCheck configuration object + output: true + - !ruby/object:Api::Type::String + name: tokenTtl + description: | + Specifies the duration for which App Check tokens exchanged from DeviceCheck artifacts will be valid. + If unset, a default value of 1 hour is assumed. Must be between 30 minutes and 7 days, inclusive. + + A duration in seconds with up to nine fractional digits, ending with 's'. Example: "3.5s". + default_from_api: true + - !ruby/object:Api::Type::String + name: keyId + description: | + The key identifier of a private key enabled with DeviceCheck, created in your Apple Developer account. + required: true + - !ruby/object:Api::Type::String + name: privateKey + description: | + The contents of the private key (.p8) file associated with the key specified by keyId. + required: true + sensitive: true + ignore_read: true + - !ruby/object:Api::Type::Boolean + name: privateKeySet + description: | + Whether the privateKey field was previously set. Since App Check will never return the + privateKey field, this field is the only way to find out whether it was previously set. + output: true diff --git a/mmv1/templates/terraform/examples/firebase_app_check_device_check_config_full.tf.erb b/mmv1/templates/terraform/examples/firebase_app_check_device_check_config_full.tf.erb new file mode 100644 index 000000000000..72b6a96fbafb --- /dev/null +++ b/mmv1/templates/terraform/examples/firebase_app_check_device_check_config_full.tf.erb @@ -0,0 +1,34 @@ +resource "google_firebase_apple_app" "default" { + provider = google-beta + + project = "<%= ctx[:test_env_vars]['project_id'] %>" + display_name = "Apple app" + bundle_id = "<%= ctx[:vars]['bundle_id'] %>" + team_id = "<%= ctx[:vars]['team_id'] %>" +} + +# It takes a while for App Check to recognize the new app +# If your app already exists, you don't have to wait 30 seconds. +resource "time_sleep" "wait_30s" { + depends_on = [google_firebase_apple_app.default] + create_duration = "30s" +} + +resource "google_firebase_app_check_device_check_config" "default" { + provider = google-beta + + project = "<%= ctx[:test_env_vars]['project_id'] %>" + app_id = google_firebase_apple_app.default.app_id + token_ttl = "<%= ctx[:vars]['token_ttl'] %>" + key_id = "<%= ctx[:vars]['key_id'] %>" + private_key = file("<%= ctx[:vars]['private_key_path'] %>") + + depends_on = [time_sleep.wait_30s] + + lifecycle { + precondition { + condition = google_firebase_apple_app.default.team_id != "" + error_message = "Provide a Team ID on the Apple App to use App Check" + } + } +} diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_device_check_config_test.go.erb b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_device_check_config_test.go.erb new file mode 100644 index 000000000000..156a2cac1e59 --- /dev/null +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_device_check_config_test.go.erb @@ -0,0 +1,63 @@ +<% autogen_exception -%> +package firebaseappcheck_test +<% unless version == 'ga' -%> + +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 TestAccFirebaseAppCheckDeviceCheckConfig_firebaseAppCheckDeviceCheckConfigUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project_id": envvar.GetTestProjectFromEnv(), + "team_id": "9987654321", + "private_key_path": "test-fixtures/private-key.p8", + "token_ttl": "3900s", + "random_suffix": acctest.RandString(t, 10), + } + + contextUpdated := map[string]interface{}{ + "project_id": envvar.GetTestProjectFromEnv(), + "team_id": "9987654321", + "private_key_path": "test-fixtures/private-key-2.p8", + "token_ttl": "7200s", + // Bundle ID needs to be the same between updates but different between tests + "random_suffix": context["random_suffix"], + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testAccFirebaseAppCheckDeviceCheckConfig_firebaseAppCheckDeviceCheckConfigFullExample(context), + }, + { + ResourceName: "google_firebase_app_check_device_check_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"private_key", "app_id"}, + }, + { + Config: testAccFirebaseAppCheckDeviceCheckConfig_firebaseAppCheckDeviceCheckConfigFullExample(contextUpdated), + }, + { + ResourceName: "google_firebase_app_check_device_check_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"private_key", "app_id"}, + }, + }, + }) +} +<% end -%> diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/test-fixtures/private-key-2.p8 b/mmv1/third_party/terraform/services/firebaseappcheck/test-fixtures/private-key-2.p8 new file mode 100644 index 000000000000..f581bea0e054 --- /dev/null +++ b/mmv1/third_party/terraform/services/firebaseappcheck/test-fixtures/private-key-2.p8 @@ -0,0 +1,15 @@ +-----BEGIN PRIVATE KEY----- +MIICWwIBAAKBgQCVA/2LQtUYJI8KlNHWzNPzGzVv01qavSbmuW0QYjshxRnXDBk+ +fWZePJAmsyuhU4Y2SkM5Wqvgjo/rDPaRPdTiEtKQuNesRgQeOVmAWDkIXEiieTwb +RYuXbdpZhH86Vt6xOMt14tGPKE5VuuySvTqgQRCvRTylrF3koBc0d/8NVQIDAQAB +AoGAG7qBXH+ULYjoAR0OKv00V2FxwRxAGNknuvk4HTtaK3+Evmpm7CTjfpegb0MZ +1Ew5hjKtbae8oe2FRETGQOKTkS68I/D9PGP4aTzmSkf6PjwXwhlBYp09xxv4nmxV +BCbsoicNMvdk0F7SPblnZBO9i0DpZ8pT9wyPo8QzWBfi5IECQQD8gIOja3Zim4R9 +HVL7Blvhzhl2ibuITV2PKfQ11v0a+Om+rZKwdrhxKgWoguDvvP7ExWSPTZJKSm0J +bzhU+APhAkEAlxR3fY+zSpxHaxbOqZ6cea5cZtyHcX607nW8N037yBErIjcJKL65 +gHx9Vq1Xo24o4C6kyzmh00BnkyXul4439QJAPWvtmaUcaSQ3eE/XzaRgWW9PFlyu +t5tKNPcZprcjXppKEc4bLr3SZAS616DuoqKwvqDds1ZFTbkJCRB6/YBPQQJAeyGG +JYKJyKRIHMJw2pNXymBOFNNlXB29jp/ML3LSYwODGRar01ZmT46mhI8wXxV4IQZC +7xLgjhDumWIP69tQRQJAfuOy4TP2drxNI7fP7YenV1ks6CiLHcBN04f6NItWilTN +Cc+Mv/rio9xO56Yp9oePMaFT9QEzfO/cqX6QvyfblQ== +-----END PRIVATE KEY----- \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/test-fixtures/private-key.p8 b/mmv1/third_party/terraform/services/firebaseappcheck/test-fixtures/private-key.p8 new file mode 100644 index 000000000000..d48a562a97bd --- /dev/null +++ b/mmv1/third_party/terraform/services/firebaseappcheck/test-fixtures/private-key.p8 @@ -0,0 +1,15 @@ +-----BEGIN PRIVATE KEY----- +MIICXAIBAAKBgG3vDegwb8uUvns/Iuodo/cNK0eMHxqb+2n16dQnxL7az+ShNWKQ +jTSzXY5y4VexrTdPEU5ZiTPONZXyl4/iFvOnyFxnC6Zjyr+xeIU5X4TmjYq0yCuZ +xbovAWw+E4KUKt1V62avd+hGZHPtCKLfV/uYITG7I8R+GyEAdMoaXP8JAgMBAAEC +gYBsQFf7aabMWx3uks84phNNNOSHQY1nUG2Te5nTVY3BOgo44h2Ffz3sxSq9GJaZ +GdatfehWtIgMQWQ20Xk5L7LUzSxmndHbUIzYU17xZrAsgmjYTwvAQ13If2L6S+pz +EUbTLkMnlbAgvtJ2AqZZZ3LE41N9ey60gVB1cCu9fCXLuQJBANAeoDXXvh7nXdyN +Zd84zXpSk8SLmAmQn1JB7z3oPkrZ0dG42GMOzYw9MP8n2bATHV+OB0/gdUFJAYYp +kwz+bJ8CQQCHObHelAlkH3or+JVECpovNMHs2UGB6yF1ZX0Nep3iR90fhi3BsnVo +IQGdHlQC2NL+iaBF4Mv2/dfZTen1vMtXAkEAk7+KQW8+G7ZpXjBLyCMNTO/e08O+ +VdwEH2OLsslzn7PvTxIJHJnfttWiOSJTWrrXOYUdD8nrtENd/574NFtTRQJAaExD +uJ0NsT/mB0wwNM7IpWhXusrHD+G/aMDidyb/56vuDYZ8fE2c6LesevcNbTS3aMPV +7o+4QcUAWwcRUQxQ+QJBAJEAwwzFnLJtrFYEnz7YNufgjiMrX7CBJCwrXGZpZrHX +EdDDOGiLrm871hc3tNQWmzou9AFIwZFeIOXVdIHIQzk= +-----END PRIVATE KEY----- \ No newline at end of file From 6caf25d3237cf1a05160638ab1b9f6bdde6d074a Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Thu, 7 Mar 2024 22:17:45 +0100 Subject: [PATCH 094/200] Documentation (#10012) * duplicate Composer 2 argument reference * remove fields that are not supported in Composer 3 * move fields that are new in Composer 3 to Composer 3 section only * make suggested changes, add description if new versioning schema * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown, remove outdated info Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * add notice that composer 3 is not yet released. * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Stephen Lewis (Burrows) * specify composer version in section links. * specify composer version in composer 1 documentation links * add section links in composer 2 argument reference * add section links in composer 3 argument reference * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> * Update mmv1/third_party/terraform/website/docs/r/composer_environment.html.markdown Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> --------- Co-authored-by: Pavel Salnikov <90701144+pavel-salnikov@users.noreply.github.com> Co-authored-by: Stephen Lewis (Burrows) --- .../docs/r/composer_environment.html.markdown | 450 +++++++++++++++--- 1 file changed, 384 insertions(+), 66 deletions(-) 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 61e961b78b54..81865ec37908 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 @@ -229,7 +229,7 @@ The following arguments are supported: * `config` - (Optional) - Configuration parameters for this environment Structure is [documented below](#nested_config). + Configuration parameters for this environment Structure is [documented below](#nested_config_c1). * `labels` - (Optional) @@ -260,7 +260,7 @@ The following arguments are supported: (Optional) The ID of the project in which the resource belongs. If it is not provided, the provider project is used. -The `config` block supports: +The `config` block supports: * `node_count` - (Optional, Cloud Composer 1 only) @@ -268,28 +268,19 @@ The following arguments are supported: * `node_config` - (Optional) - The configuration used for the Kubernetes Engine cluster. Structure is [documented below](#nested_node_config). + The configuration used for the Kubernetes Engine cluster. Structure is [documented below](#nested_node_config_c1). * `recovery_config` - (Optional, Cloud Composer 2 only) - The configuration settings for recovery. Structure is [documented below](#nested_recovery_config). + The configuration settings for recovery. Structure is [documented below](#nested_recovery_config_c1). * `software_config` - (Optional) - The configuration settings for software inside the environment. Structure is [documented below](#nested_software_config). + The configuration settings for software inside the environment. Structure is [documented below](#nested_software_config_c1). * `private_environment_config` - (Optional) - The configuration used for the Private IP Cloud Composer environment. Structure is [documented below](#nested_private_environment_config). - -* `enable_private_environment` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) - If true, a private Composer environment will be created. - -* `enable_private_builds_only` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) - If true, builds performed during operations that install Python packages have only private connectivity to Google services. - If false, the builds also have access to the internet. + The configuration used for the Private IP Cloud Composer environment. Structure is [documented below](#nested_private_environment_config_c1). * `web_server_network_access_control` - The network-level access control policy for the Airflow web server. @@ -319,9 +310,9 @@ The following arguments are supported: master authorized networks will disallow all external traffic to access Kubernetes master through HTTPS except traffic from the given CIDR blocks, Google Compute Engine Public IPs and Google Prod IPs. Structure is - [documented below](#nested_master_authorized_networks_config). + [documented below](#nested_master_authorized_networks_config_c1). -The `node_config` block supports: +The `node_config` block supports: * `zone` - (Optional, Cloud Composer 1 only) @@ -382,7 +373,7 @@ The following arguments are supported: * `ip_allocation_policy` - (Optional) Configuration for controlling how IPs are allocated in the GKE cluster. - Structure is [documented below](#nested_ip_allocation_policy). + Structure is [documented below](#nested_ip_allocation_policy_c1). Cannot be updated. * `max_pods_per_node` - @@ -401,7 +392,7 @@ The following arguments are supported: all destination addresses, except between pods traffic. See the [documentation](https://cloud.google.com/composer/docs/enable-ip-masquerade-agent). -The `software_config` block supports: +The `software_config` block supports: * `airflow_config_overrides` - (Optional) Apache Airflow configuration properties to override. Property keys contain the section and property names, @@ -444,7 +435,7 @@ The following arguments are supported: ``` * `image_version` - - (Optional in Cloud Composer 1, required in Cloud Composer 2) +(Required) In Composer 1, use a specific Composer 1 version in this parameter. If omitted, the default is the latest version of Composer 2. The version of the software running in the environment. This encapsulates both the version of Cloud Composer functionality and the version of Apache Airflow. It must match the regular expression @@ -465,12 +456,8 @@ The following arguments are supported: (Optional, Cloud Composer 1 with Airflow 2 only) The number of schedulers for Airflow. -* `web_server_plugins_mode` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) - Web server plugins configuration. Should be either 'ENABLED' or 'DISABLED'. Defaults to 'ENABLED'. - -See [documentation](https://cloud.google.com/composer/docs/how-to/managing/configuring-private-ip) for setting up private environments. The `private_environment_config` block supports: +See [documentation](https://cloud.google.com/composer/docs/how-to/managing/configuring-private-ip) for setting up private environments. The `private_environment_config` block supports: * `connection_type` - (Optional, Cloud Composer 2 only) @@ -506,9 +493,9 @@ See [documentation](https://cloud.google.com/composer/docs/how-to/managing/confi The `web_server_network_access_control` supports: * `allowed_ip_range` - - A collection of allowed IP ranges with descriptions. Structure is [documented below](#nested_allowed_ip_range). + A collection of allowed IP ranges with descriptions. Structure is [documented below](#nested_allowed_ip_range_c1). -The `allowed_ip_range` supports: +The `allowed_ip_range` supports: * `value` - (Required) @@ -521,7 +508,7 @@ The `web_server_network_access_control` supports: (Optional) A description of this ip range. -The `ip_allocation_policy` block supports: +The `ip_allocation_policy` block supports: * `use_ip_aliases` - (Optional, Cloud Composer 1 only) @@ -560,7 +547,7 @@ The `web_server_network_access_control` supports: (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use. Specify either `services_secondary_range_name` or `services_ipv4_cidr_block` but not both. -The `database_config` block supports: +The `database_config` block supports: * `machine_type` - (Optional) @@ -571,7 +558,7 @@ The `web_server_network_access_control` supports: (Optional) Preferred Cloud SQL database zone. -The `web_server_config` block supports: +The `web_server_config` block supports: * `machine_type` - (Required) @@ -580,7 +567,7 @@ The `web_server_network_access_control` supports: Value custom is returned only in response, if Airflow web server parameters were manually changed to a non-standard values. -The `encryption_config` block supports: +The `encryption_config` block supports: * `kms_key_name` - (Required) @@ -588,7 +575,7 @@ The `web_server_network_access_control` supports: be the fully qualified resource name, i.e. projects/project-id/locations/location/keyRings/keyring/cryptoKeys/key. Cannot be updated. -The `maintenance_window` block supports: +The `maintenance_window` block supports: * `start_time` - (Required) Start time of the first recurrence of the maintenance window. @@ -604,15 +591,15 @@ The `web_server_network_access_control` supports: The only allowed values for 'FREQ' field are 'FREQ=DAILY' and 'FREQ=WEEKLY;BYDAY=...'. Example values: 'FREQ=WEEKLY;BYDAY=TU,WE', 'FREQ=DAILY'. -The `master_authorized_networks_config` block supports: +The `master_authorized_networks_config` block supports: * `enabled` - (Required) Whether or not master authorized networks is enabled. * `cidr_blocks` - - `cidr_blocks `define up to 50 external networks that could access Kubernetes master through HTTPS. Structure is [documented below](#nested_cidr_blocks). + `cidr_blocks `define up to 50 external networks that could access Kubernetes master through HTTPS. Structure is [documented below](#nested_cidr_blocks_c1). -The `cidr_blocks` supports: +The `cidr_blocks` supports: * `display_name` - (Optional) @@ -632,7 +619,7 @@ The following arguments are supported: * `config` - (Optional) - Configuration parameters for this environment. Structure is documented below. + Configuration parameters for this environment. Structure is [documented below](#nested_config_c2). * `labels` - (Optional) @@ -656,24 +643,23 @@ The following arguments are supported: * `storage_config` - (Optional) - Configuration options for storage used by Composer environment. Structure is documented below. + Configuration options for storage used by Composer environment. Structure is [documented below](#nested_storage_config_c2). -The `config` block supports: +The `config` block supports: * `node_config` - (Optional) - The configuration used for the Kubernetes Engine cluster. Structure is documented below. + The configuration used for the Kubernetes Engine cluster. Structure is [documented below](#nested_node_config_c2). * `software_config` - (Optional) The configuration settings for software (Airflow) inside the environment. Structure is - documented below. + [documented below](#nested_software_config_c2). * `private_environment_config` - (Optional) - The configuration used for the Private IP Cloud Composer environment. Structure is documented - below. + The configuration used for the Private IP Cloud Composer environment. Structure is [documented below](#nested_private_environment_config_c2). * `encryption_config` - (Optional) @@ -685,12 +671,12 @@ The `config` block supports: The configuration settings for Cloud Composer maintenance windows. * `workloads_config` - - (Optional, Cloud Composer 2 only) + (Optional) The Kubernetes workloads configuration for GKE cluster associated with the Cloud Composer environment. * `environment_size` - - (Optional, Cloud Composer 2 only) + (Optional) The environment size controls the performance parameters of the managed Cloud Composer infrastructure that includes the Airflow database. Values for environment size are `ENVIRONMENT_SIZE_SMALL`, `ENVIRONMENT_SIZE_MEDIUM`, @@ -709,20 +695,20 @@ The `config` block supports: master authorized networks will disallow all external traffic to access Kubernetes master through HTTPS except traffic from the given CIDR blocks, Google Compute Engine Public IPs and Google Prod IPs. Structure is - documented below. + [documented below](#nested_master_authorized_networks_config_c1). * `data_retention_config` - (Optional, Cloud Composer 2.0.23 or newer only) Configuration setting for airflow data rentention mechanism. Structure is - [documented below](#nested_data_retention_config). + [documented below](#nested_data_retention_config_c2). -The `data_retention_config` block supports: +The `data_retention_config` block supports: * `task_logs_retention_config` - (Optional) The configuration setting for Task Logs. Structure is - [documented below](#nested_task_logs_retention_config). + [documented below](#nested_task_logs_retention_config_c2). -The `task_logs_retention_config` block supports: +The `task_logs_retention_config` block supports: * `storage_mode` - (Optional) The mode of storage for Airflow workers task logs. Values for storage mode are @@ -730,14 +716,14 @@ The `config` block supports: `CLOUD_LOGGING_AND_CLOUD_STORAGE` to store logs in cloud logging and cloud storage. -The `storage_config` block supports: +The `storage_config` block supports: * `bucket` - (Required) Name of an existing Cloud Storage bucket to be used by the environment. -The `node_config` block supports: +The `node_config` block supports: * `network` - (Optional) @@ -773,7 +759,7 @@ The `node_config` block supports: * `ip_allocation_policy` - (Optional) Configuration for controlling how IPs are allocated in the GKE cluster. - Structure is documented below. + Structure is [documented below](#nested_ip_allocation_policy_c2). Cannot be updated. * `enable_ip_masq_agent` - @@ -783,12 +769,7 @@ The `node_config` block supports: packets from node IP addresses instead of Pod IP addresses See the [documentation](https://cloud.google.com/composer/docs/enable-ip-masquerade-agent). -* `composer_internal_ipv4_cidr_block` - - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) - At least /20 IPv4 cidr range that will be used by Composer internal components. - Cannot be updated. - -The `software_config` block supports: +The `software_config` block supports: * `airflow_config_overrides` - (Optional) Apache Airflow configuration properties to override. Property keys contain the section and property names, @@ -831,10 +812,8 @@ The `software_config` block supports: ``` * `image_version` - - (Required in Cloud Composer 2, optional in Cloud Composer 1) +(Optional) If omitted, the default is the latest version of Composer 2. - **In Cloud Composer 2, you must specify an image with Cloud Composer 2**. Otherwise, the default image for Cloud Composer 1 is used. For more information about Cloud Composer images, see - [Cloud Composer version list](https://cloud.google.com/composer/docs/concepts/versioning/composer-versions). The version of the software running in the environment. This encapsulates both the version of Cloud Composer functionality and the version of Apache Airflow. It must match the regular expression @@ -853,14 +832,14 @@ The `software_config` block supports: (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer environments in versions composer-2.1.2-airflow-*.*.* and newer) The configuration for Cloud Data Lineage integration. Structure is - [documented below](#nested_cloud_data_lineage_integration). + [documented below](#nested_cloud_data_lineage_integration_c2). -The `cloud_data_lineage_integration` block supports: +The `cloud_data_lineage_integration` block supports: * `enabled` - (Required) Whether or not Cloud Data Lineage integration is enabled. -See [documentation](https://cloud.google.com/composer/docs/how-to/managing/configuring-private-ip) for setting up private environments. The `private_environment_config` block supports: +See [documentation](https://cloud.google.com/composer/docs/how-to/managing/configuring-private-ip) for setting up private environments. The `private_environment_config` block supports: * `enable_private_endpoint` - If true, access to the public endpoint of the GKE cluster is denied. @@ -894,7 +873,7 @@ See [documentation](https://cloud.google.com/composer/docs/how-to/managing/confi versions `composer-2.*.*-airflow-*.*.*` and newer. -The `ip_allocation_policy` block supports: +The `ip_allocation_policy` block supports: * `cluster_secondary_range_name` - (Optional) @@ -951,7 +930,7 @@ The `ip_allocation_policy` block supports: The only allowed values for 'FREQ' field are 'FREQ=DAILY' and 'FREQ=WEEKLY;BYDAY=...'. Example values: 'FREQ=WEEKLY;BYDAY=TU,WE', 'FREQ=DAILY'. -The `recovery_config` block supports: +The `recovery_config` block supports: * `scheduled_snapshots_config` - (Optional) @@ -993,6 +972,345 @@ The `workloads_config` block supports: (Optional) Configuration for resources used by Airflow workers. +The `scheduler` block supports: + +* `cpu` - + (Optional) + The number of CPUs for a single Airflow scheduler. + +* `memory_gb` - + (Optional) + The amount of memory (GB) for a single Airflow scheduler. + +* `storage_gb` - + (Optional) + The amount of storage (GB) for a single Airflow scheduler. + +* `count` - + (Optional) + The number of schedulers. + +The `triggerer` block supports: + +* `cpu` - + (Required) + The number of CPUs for a single Airflow triggerer. + +* `memory_gb` - + (Required) + The amount of memory (GB) for a single Airflow triggerer. + +* `count` - + (Required) + The number of Airflow triggerers. + +The `web_server` block supports: + +* `cpu` - + (Optional) + The number of CPUs for the Airflow web server. + +* `memory_gb` - + (Optional) + The amount of memory (GB) for the Airflow web server. + +* `storage_gb` - + (Optional) + The amount of storage (GB) for the Airflow web server. + +The `worker` block supports: + +* `cpu` - + (Optional) + The number of CPUs for a single Airflow worker. + +* `memory_gb` - + (Optional) + The amount of memory (GB) for a single Airflow worker. + +* `storage_gb` + (Optional) + The amount of storage (GB) for a single Airflow worker. + +* `min_count` - + (Optional) + The minimum number of Airflow workers that the environment can run. The number of workers in the + environment does not go above this number, even if a lower number of workers can handle the load. + +* `max_count` - + (Optional) + The maximum number of Airflow workers that the environment can run. The number of workers in the + environment does not go above this number, even if a higher number of workers is required to + handle the load. + + +## Argument Reference - Cloud Composer 3 + +**Please note: This documentation corresponds to Composer 3, which is not yet released.** + +The following arguments are supported: + +* `name` - + (Required) + Name of the environment + +* `config` - + (Optional) + Configuration parameters for this environment. Structure is [documented below](#nested_config_c3). + +* `labels` - + (Optional) + User-defined labels for this environment. The labels map can contain + no more than 64 entries. Entries of the labels map are UTF8 strings + that comply with the following restrictions: + Label keys must be between 1 and 63 characters long and must conform + to the following regular expression: `[a-z]([-a-z0-9]*[a-z0-9])?`. + Label values must be between 0 and 63 characters long and must + conform to the regular expression `([a-z]([-a-z0-9]*[a-z0-9])?)?`. + No more than 64 labels can be associated with a given environment. + Both keys and values must be <= 128 bytes in size. + +* `region` - + (Optional) + The location or Compute Engine region for the environment. + +* `project` - + (Optional) The ID of the project in which the resource belongs. + If it is not provided, the provider project is used. + +* `storage_config` - + (Optional) + Configuration options for storage used by Composer environment. Structure is [documented below](#nested_storage_config_c3). + + +The `config` block supports: + +* `node_config` - + (Optional) + The configuration used for the Kubernetes Engine cluster. Structure is [documented below](#nested_node_config_c3). + +* `software_config` - + (Optional) + The configuration settings for software (Airflow) inside the environment. Structure is [documented below](#nested_software_config_c3). + +* `enable_private_environment` - + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + If true, a private Composer environment will be created. + +* `enable_private_builds_only` - + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + If true, builds performed during operations that install Python packages have only private connectivity to Google services. + If false, the builds also have access to the internet. + +* `encryption_config` - + (Optional) + The encryption options for the Cloud Composer environment and its + dependencies. + +* `maintenance_window` - + (Optional) + The configuration settings for Cloud Composer maintenance windows. + +* `workloads_config` - + (Optional) + The Kubernetes workloads configuration for GKE cluster associated with the + Cloud Composer environment. + +* `environment_size` - + (Optional) + The environment size controls the performance parameters of the managed + Cloud Composer infrastructure that includes the Airflow database. Values for + environment size are `ENVIRONMENT_SIZE_SMALL`, `ENVIRONMENT_SIZE_MEDIUM`, + and `ENVIRONMENT_SIZE_LARGE`. + +* `data_retention_config` - + (Optional, Cloud Composer 2.0.23 or later only) + Configuration setting for Airflow database retention mechanism. Structure is + [documented below](#nested_data_retention_config_c3). + +The `data_retention_config` block supports: +* `task_logs_retention_config` - + (Optional) + The configuration setting for Airflow task logs. Structure is + [documented below](#nested_task_logs_retention_config_c3). + +The `task_logs_retention_config` block supports: +* `storage_mode` - + (Optional) + The mode of storage for Airflow task logs. Values for storage mode are + `CLOUD_LOGGING_ONLY` to only store logs in cloud logging and + `CLOUD_LOGGING_AND_CLOUD_STORAGE` to store logs in cloud logging and cloud storage. + + +The `storage_config` block supports: + +* `bucket` - + (Required) + Name of an existing Cloud Storage bucket to be used by the environment. + + +The `node_config` block supports: + +* `network` - + (Optional) + The Compute Engine network to be used for machine + communications, specified as a self-link, relative resource name + (for example "projects/{project}/global/networks/{network}"), by name. + + The network must belong to the environment's project. If unspecified, the "default" network ID in the environment's + project is used. If a Custom Subnet Network is provided, subnetwork must also be provided. + +* `subnetwork` - + (Optional) + The Compute Engine subnetwork to be used for machine + communications, specified as a self-link, relative resource name (for example, + "projects/{project}/regions/{region}/subnetworks/{subnetwork}"), or by name. If subnetwork is provided, + network must also be provided and the subnetwork must belong to the enclosing environment's project and region. + +* `composer_network_attachment` - + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + PSC (Private Service Connect) Network entry point. Customers can pre-create the Network Attachment + and point Cloud Composer environment to use. It is possible to share network attachment among many environments, + provided enough IP addresses are available. + +* `service_account` - + (Optional) + The Google Cloud Platform Service Account to be used by the + node VMs. If a service account is not specified, the "default" + Compute Engine service account is used. Cannot be updated. If given, + note that the service account must have `roles/composer.worker` + for any GCP resources created under the Cloud Composer Environment. + +* `tags` - + (Optional) + The list of instance tags applied to all node VMs. Tags are + used to identify valid sources or targets for network + firewalls. Each tag within the list must comply with RFC1035. + Cannot be updated. + +* `composer_internal_ipv4_cidr_block` - + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + /20 IPv4 cidr range that will be used by Composer internal components. + Cannot be updated. + +The `software_config` block supports: + +* `airflow_config_overrides` - + (Optional) Apache Airflow configuration properties to override. Property keys contain the section and property names, + separated by a hyphen, for example "core-dags_are_paused_at_creation". + + Section names must not contain hyphens ("-"), opening square brackets ("["), or closing square brackets ("]"). + The property name must not be empty and cannot contain "=" or ";". Section and property names cannot contain + characters: "." Apache Airflow configuration property names must be written in snake_case. Property values can + contain any character, and can be written in any lower/upper case format. Certain Apache Airflow configuration + property values are [blacklisted](https://cloud.google.com/composer/docs/concepts/airflow-configurations#airflow_configuration_blacklists), + and cannot be overridden. + +* `pypi_packages` - + (Optional) + Custom Python Package Index (PyPI) packages to be installed + in the environment. Keys refer to the lowercase package name (e.g. "numpy"). Values are the lowercase extras and + version specifier (e.g. "==1.12.0", "[devel,gcp_api]", "[devel]>=1.8.2, <1.9.2"). To specify a package without + pinning it to a version specifier, use the empty string as the value. + +* `env_variables` - + (Optional) + Additional environment variables to provide to the Apache Airflow scheduler, worker, and webserver processes. + Environment variable names must match the regular expression `[a-zA-Z_][a-zA-Z0-9_]*`. + They cannot specify Apache Airflow software configuration overrides (they cannot match the regular expression + `AIRFLOW__[A-Z0-9_]+__[A-Z0-9_]+`), and they cannot match any of the following reserved names: + ``` + AIRFLOW_HOME + C_FORCE_ROOT + CONTAINER_NAME + DAGS_FOLDER + GCP_PROJECT + GCS_BUCKET + GKE_CLUSTER_NAME + SQL_DATABASE + SQL_INSTANCE + SQL_PASSWORD + SQL_PROJECT + SQL_REGION + SQL_USER + ``` + +* `image_version` - + (Required) If omitted, the default is the latest version of Composer 2. + + In Cloud Composer 3, you can only specify 3 in the Cloud Composer portion of the image version. Example: composer-3-airflow-x.y.z-build.t. + + The Apache Airflow portion of the image version is a full semantic version that points to one of the + supported Apache Airflow versions, or an alias in the form of only major, major.minor or major.minor.patch versions specified. + Like in Composer 1 and 2, a given Airflow version is released multiple times in Composer, with different patches + and versions of dependencies. To distinguish between these versions in Composer 3, you can optionally specify a + build number to pin to a specific Airflow release. + Example: composer-3-airflow-2.6.3-build.4. + + The image version in Composer 3 must match the regular expression: + `composer-(([0-9]+)(\.[0-9]+\.[0-9]+(-preview\.[0-9]+)?)?|latest)-airflow-(([0-9]+)((\.[0-9]+)(\.[0-9]+)?)?(-build\.[0-9]+)?)` + Example: composer-3-airflow-2.6.3-build.4 + + **Important**: In-place upgrade for Composer 3 is not yet supported. + +* `cloud_data_lineage_integration` - + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), + Cloud Composer environments in versions composer-2.1.2-airflow-*.*.* and later) + The configuration for Cloud Data Lineage integration. Structure is + [documented below](#nested_cloud_data_lineage_integration_c3). + +* `web_server_plugins_mode` - + (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) + Web server plugins configuration. Can be either 'ENABLED' or 'DISABLED'. Defaults to 'ENABLED'. + +The `cloud_data_lineage_integration` block supports: +* `enabled` - + (Required) + Whether or not Cloud Data Lineage integration is enabled. + +The `encryption_config` block supports: + +* `kms_key_name` - + (Required) + Customer-managed Encryption Key available through Google's Key Management Service. It must + be the fully qualified resource name, + i.e. projects/project-id/locations/location/keyRings/keyring/cryptoKeys/key. Cannot be updated. + +The `maintenance_window` block supports: + +* `start_time` - + (Required) + Start time of the first recurrence of the maintenance window. + +* `end_time` - + (Required) + Maintenance window end time. It is used only to calculate the duration of the maintenance window. + The value for end-time must be in the future, relative to 'start_time'. + +* `recurrence` - + (Required) + Maintenance window recurrence. Format is a subset of RFC-5545 (https://tools.ietf.org/html/rfc5545) 'RRULE'. + The only allowed values for 'FREQ' field are 'FREQ=DAILY' and 'FREQ=WEEKLY;BYDAY=...'. + Example values: 'FREQ=WEEKLY;BYDAY=TU,WE', 'FREQ=DAILY'. + +The `workloads_config` block supports: + +* `scheduler` - + (Optional) + Configuration for resources used by Airflow scheduler. + +* `triggerer` - + (Optional) + Configuration for resources used by Airflow triggerer. + +* `web_server` - + (Optional) + Configuration for resources used by Airflow web server. + +* `worker` - + (Optional) + Configuration for resources used by Airflow workers. + * `dag_processor` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html), Cloud Composer 3 only) Configuration for resources used by DAG processor. From 4940461a14c96e28bd3575efa0eef98bcbe3f47f Mon Sep 17 00:00:00 2001 From: Pavan Kumar Sunkara Date: Thu, 7 Mar 2024 21:45:14 +0000 Subject: [PATCH 095/200] Promote metric settings in compute region autoscaler to GA (#10103) --- mmv1/products/compute/RegionAutoscaler.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/mmv1/products/compute/RegionAutoscaler.yaml b/mmv1/products/compute/RegionAutoscaler.yaml index 931e07443408..fa9991ee61aa 100644 --- a/mmv1/products/compute/RegionAutoscaler.yaml +++ b/mmv1/products/compute/RegionAutoscaler.yaml @@ -265,7 +265,6 @@ properties: required: true - !ruby/object:Api::Type::Double name: 'singleInstanceAssignment' - min_version: beta description: | If scaling is based on a per-group metric value that represents the total amount of work to be done or resource usage, set this value to @@ -341,7 +340,6 @@ properties: (if you are using gce_instance resource type). If multiple TimeSeries are returned upon the query execution, the autoscaler will sum their respective values to obtain its scaling value. - min_version: beta - !ruby/object:Api::Type::NestedObject name: 'loadBalancingUtilization' description: | From 00f7bfb27208915fd7fb5c133bf9f4934c363c58 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 7 Mar 2024 14:14:10 -0800 Subject: [PATCH 096/200] Clarified permissions for a few workflows (#10124) * Clarified permissions for a few workflows * fixed conditions for running repository-documentation workflows * Bumped actions/checkout to v4 * force downstream generation * Revert "force downstream generation" This reverts commit d54857b4dc5767ab8f98543e6a84d25c8be1104a. --- ...ml => repository-documentation-deploy.yml} | 12 ++++----- .../repository-documentation-test.yml | 27 +++++++++++++++++++ .github/workflows/test-tgc.yml | 7 +++-- .github/workflows/test-tpg.yml | 7 +++-- 4 files changed, 39 insertions(+), 14 deletions(-) rename .github/workflows/{repository-documentation.yml => repository-documentation-deploy.yml} (82%) create mode 100644 .github/workflows/repository-documentation-test.yml diff --git a/.github/workflows/repository-documentation.yml b/.github/workflows/repository-documentation-deploy.yml similarity index 82% rename from .github/workflows/repository-documentation.yml rename to .github/workflows/repository-documentation-deploy.yml index 531673c5788f..f94df4ce4ffd 100644 --- a/.github/workflows/repository-documentation.yml +++ b/.github/workflows/repository-documentation-deploy.yml @@ -1,16 +1,17 @@ -name: repository-documentation +name: repository-documentation-deploy + +permissions: read-all on: push: branches: - - main # Set a branch to deploy - pull_request: - paths: - - 'docs/**' + - main jobs: deploy: runs-on: ubuntu-22.04 + permissions: + contents: write steps: - uses: actions/checkout@v4 with: @@ -29,7 +30,6 @@ jobs: - name: Deploy uses: peaceiris/actions-gh-pages@de7ea6f8efb354206b205ef54722213d99067935 # v3.9.0 - if: github.ref == 'refs/heads/main' with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs/public diff --git a/.github/workflows/repository-documentation-test.yml b/.github/workflows/repository-documentation-test.yml new file mode 100644 index 000000000000..f2952926ef2a --- /dev/null +++ b/.github/workflows/repository-documentation-test.yml @@ -0,0 +1,27 @@ +name: repository-documentation-test + +permissions: read-all + +on: + pull_request: + paths: + - 'docs/**' + +jobs: + deploy: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + submodules: true # Fetch Hugo themes (true OR recursive) + fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod + + - name: Setup Hugo + uses: peaceiris/actions-hugo@16361eb4acea8698b220b76c0d4e84e1fd22c61d # v2.6.0 + with: + hugo-version: '0.115.0' + extended: true + + - name: Build + working-directory: ./docs + run: hugo --minify diff --git a/.github/workflows/test-tgc.yml b/.github/workflows/test-tgc.yml index 32e290364067..3eb9aaad4121 100644 --- a/.github/workflows/test-tgc.yml +++ b/.github/workflows/test-tgc.yml @@ -1,9 +1,6 @@ name: TGC Build and Unit Test -permissions: - actions: read - contents: read - statuses: write +permissions: read-all env: status_suffix: "-build-and-unit-tests" @@ -32,6 +29,8 @@ concurrency: jobs: build-and-unit-test: + permissions: + statuses: write runs-on: ubuntu-latest timeout-minutes: 30 steps: diff --git a/.github/workflows/test-tpg.yml b/.github/workflows/test-tpg.yml index eff5cdc3755e..46d83b487def 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -1,9 +1,6 @@ name: Provider Build and Unit Test -permissions: - actions: read - contents: read - statuses: write +permissions: read-all env: status_suffix: "-build-and-unit-tests" @@ -32,6 +29,8 @@ concurrency: jobs: build-and-unit-test: + permissions: + statuses: write runs-on: ubuntu-latest timeout-minutes: 30 steps: From 3e97dde391dd776251199d68de1e696e4244c4b8 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 7 Mar 2024 14:14:26 -0800 Subject: [PATCH 097/200] Post statuses earlier (#10128) * Post initial statuses earlier so that we are resilient issues during cloning * force generation * Revert "force generation" This reverts commit 864ec92ec03b75dea021cdb617d86d31112d9140. --- .github/workflows/test-tgc.yml | 36 +++++++++++++++++----------------- .github/workflows/test-tpg.yml | 31 ++++++++++++++--------------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/.github/workflows/test-tgc.yml b/.github/workflows/test-tgc.yml index 3eb9aaad4121..190bb6ae68c0 100644 --- a/.github/workflows/test-tgc.yml +++ b/.github/workflows/test-tgc.yml @@ -34,6 +34,24 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: + - name: Get Job URL + if: ${{ !cancelled() }} + id: get_job + run: | + response=$(curl --get -Ss -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}/jobs") + html_url=$(echo "$response" | jq -r --arg job_name "${{ github.job }}" '.jobs | map(select(.name == $job_name)) | .[0].html_url') + echo "url=${html_url}" >> $GITHUB_OUTPUT + - name: Post Pending Status to Pull Request + if: ${{ !cancelled() }} + run: | + curl -X POST -H "Authorization: token ${{secrets.GITHUB_TOKEN}}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/${{github.event.inputs.sha}}" \ + -d '{ + "context": "${{ github.event.inputs.repo }}${{ env.status_suffix }}", + "target_url": "${{ steps.get_job.outputs.url }}", + "state": "pending" + }' - name: Checkout Repository uses: actions/checkout@v4 with: @@ -58,24 +76,6 @@ jobs: else echo "has_changes=true" >> $GITHUB_OUTPUT fi - - name: Get Job URL - if: ${{ !cancelled() }} - id: get_job - run: | - response=$(curl --get -Ss -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}/jobs") - html_url=$(echo "$response" | jq -r --arg job_name "${{ github.job }}" '.jobs | map(select(.name == $job_name)) | .[0].html_url') - echo "url=${html_url}" >> $GITHUB_OUTPUT - - name: Post Pending Status to Pull Request - if: ${{ !cancelled() }} - run: | - curl -X POST -H "Authorization: token ${{secrets.GITHUB_TOKEN}}" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/${{github.event.inputs.sha}}" \ - -d '{ - "context": "${{ github.event.inputs.repo }}${{ env.status_suffix }}", - "target_url": "${{ steps.get_job.outputs.url }}", - "state": "pending" - }' - name: Set up Go if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} uses: actions/setup-go@v4 diff --git a/.github/workflows/test-tpg.yml b/.github/workflows/test-tpg.yml index 46d83b487def..9edca790e1ec 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -34,23 +34,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - name: Checkout Repository - uses: actions/checkout@v4 - with: - repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} - ref: ${{ github.event.inputs.branch }} - fetch-depth: 2 - - name: Check for Code Changes - id: pull_request - run: | - gofiles=$(git diff --name-only HEAD~1 | { grep -e "\.go$" -e "go.mod$" -e "go.sum$" || test $? = 1; }) - if [ -z "$gofiles" ]; then - echo "has_changes=false" >> $GITHUB_OUTPUT - else - echo "has_changes=true" >> $GITHUB_OUTPUT - fi - name: Get Job URL - if: ${{ !cancelled() }} id: get_job run: | response=$(curl --get -Ss -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/attempts/${{ github.run_attempt }}/jobs") @@ -67,6 +51,21 @@ jobs: "target_url": "${{ steps.get_job.outputs.url }}", "state": "pending" }' + - name: Checkout Repository + uses: actions/checkout@v4 + with: + repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} + ref: ${{ github.event.inputs.branch }} + fetch-depth: 2 + - name: Check for Code Changes + id: pull_request + run: | + gofiles=$(git diff --name-only HEAD~1 | { grep -e "\.go$" -e "go.mod$" -e "go.sum$" || test $? = 1; }) + if [ -z "$gofiles" ]; then + echo "has_changes=false" >> $GITHUB_OUTPUT + else + echo "has_changes=true" >> $GITHUB_OUTPUT + fi - name: Set up Go if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} uses: actions/setup-go@v4 From 5989a16860b84d15ac84f0994cc31e27c0c59422 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Thu, 7 Mar 2024 17:52:14 -0600 Subject: [PATCH 098/200] Make TestAccDefaultUniverseDomain_doesNotMatchExplicit independent from test credentials (#10140) --- mmv1/third_party/terraform/provider/provider.go.erb | 6 +++--- .../provider/universe/universe_domain_compute_test.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mmv1/third_party/terraform/provider/provider.go.erb b/mmv1/third_party/terraform/provider/provider.go.erb index 4f7195a37355..c090b8c43096 100644 --- a/mmv1/third_party/terraform/provider/provider.go.erb +++ b/mmv1/third_party/terraform/provider/provider.go.erb @@ -299,12 +299,12 @@ func ProviderConfigure(ctx context.Context, d *schema.ResourceData, p *schema.Pr // Check if the user provided a value from the universe_domain field other than the default if v, ok := d.GetOk("universe_domain"); ok && v.(string) != "googleapis.com" { if config.UniverseDomain == "" { - return nil, diag.FromErr(fmt.Errorf("Universe domain '%s' supplied directly to Terraform with no matching universe domain in credentials. Credentials with no 'universe_domain' set are assumed to be in the default universe.", v)) + return nil, diag.FromErr(fmt.Errorf("Universe domain mismatch: '%s' supplied directly to Terraform with no matching universe domain in credentials. Credentials with no 'universe_domain' set are assumed to be in the default universe.", v)) } else if v.(string) != config.UniverseDomain { if _, err := os.Stat(config.Credentials); err == nil { - return nil, diag.FromErr(fmt.Errorf("'%s' does not match the universe domain '%s' already set in the credential file '%s'. The 'universe_domain' provider configuration can not be used to override the universe domain that is defined in the active credential. Set the 'universe_domain' provider configuration when universe domain information is not already available in the credential, e.g. when authenticating with a JWT token.", v, config.UniverseDomain, config.Credentials)) + return nil, diag.FromErr(fmt.Errorf("Universe domain mismatch: '%s' does not match the universe domain '%s' already set in the credential file '%s'. The 'universe_domain' provider configuration can not be used to override the universe domain that is defined in the active credential. Set the 'universe_domain' provider configuration when universe domain information is not already available in the credential, e.g. when authenticating with a JWT token.", v, config.UniverseDomain, config.Credentials)) } else { - return nil, diag.FromErr(fmt.Errorf("'%s' does not match the universe domain '%s' supplied directly to Terraform. The 'universe_domain' provider configuration can not be used to override the universe domain that is defined in the active credential. Set the 'universe_domain' provider configuration when universe domain information is not already available in the credential, e.g. when authenticating with a JWT token.", v, config.UniverseDomain)) + return nil, diag.FromErr(fmt.Errorf("Universe domain mismatch: '%s' does not match the universe domain '%s' supplied directly to Terraform. The 'universe_domain' provider configuration can not be used to override the universe domain that is defined in the active credential. Set the 'universe_domain' provider configuration when universe domain information is not already available in the credential, e.g. when authenticating with a JWT token.", v, config.UniverseDomain)) } } } diff --git a/mmv1/third_party/terraform/provider/universe/universe_domain_compute_test.go b/mmv1/third_party/terraform/provider/universe/universe_domain_compute_test.go index c895e952970e..f345ac3d1968 100644 --- a/mmv1/third_party/terraform/provider/universe/universe_domain_compute_test.go +++ b/mmv1/third_party/terraform/provider/universe/universe_domain_compute_test.go @@ -57,7 +57,7 @@ func TestAccDefaultUniverseDomain_doesNotMatchExplicit(t *testing.T) { Steps: []resource.TestStep{ resource.TestStep{ Config: testAccUniverseDomain_basic_disk(universeDomainFake), - ExpectError: regexp.MustCompile("supplied directly to Terraform with no matching universe domain in credentials"), + ExpectError: regexp.MustCompile("Universe domain mismatch"), }, }, }) From c6e3d15d06633b1f5c80f45495f891ab2ded6c4e Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 8 Mar 2024 09:15:24 -0800 Subject: [PATCH 099/200] Simplified / clarified approval flow for presubmits (#10142) * Simplified / clarified approval flow for presubmits * Force generation * Removed unused command args and cleaned up documentation for membership-checker * Revert "Force generation" This reverts commit db32066e198daf930006f72bae43602f22d8e3d9. --- .ci/gcb-contributor-membership-checker.yml | 4 -- .ci/magician/cmd/community_checker.go | 24 ++-------- .ci/magician/cmd/community_checker_test.go | 24 ++++++---- .ci/magician/cmd/membership_checker.go | 53 +++------------------ .ci/magician/cmd/membership_checker_test.go | 40 ++++------------ 5 files changed, 36 insertions(+), 109 deletions(-) diff --git a/.ci/gcb-contributor-membership-checker.yml b/.ci/gcb-contributor-membership-checker.yml index f40bc6d69c5b..68219b034e4d 100644 --- a/.ci/gcb-contributor-membership-checker.yml +++ b/.ci/gcb-contributor-membership-checker.yml @@ -68,10 +68,6 @@ steps: - "membership-checker" - $_PR_NUMBER - $COMMIT_SHA - - $BRANCH_NAME - - $_HEAD_REPO_URL - - $_HEAD_BRANCH - - $_BASE_BRANCH availableSecrets: secretManager: diff --git a/.ci/magician/cmd/community_checker.go b/.ci/magician/cmd/community_checker.go index 9eb82a5e3e2e..2834009a5ebb 100644 --- a/.ci/magician/cmd/community_checker.go +++ b/.ci/magician/cmd/community_checker.go @@ -39,11 +39,8 @@ var communityApprovalCmd = &cobra.Command{ 6. Base Branch The command performs the following steps: - 1. Retrieve and print the provided pull request details. - 2. Get the author of the pull request and determine their user type. - 3. If the author is not a trusted user (neither a Core Contributor nor a Googler): - a. Trigger cloud builds with specific substitutions for the PR. - 4. For all pull requests, the 'awaiting-approval' label is removed. + 1. Trigger cloud presubmits with specific substitutions for the PR. + 2. Remove the 'awaiting-approval' label from the PR. `, Run: func(cmd *cobra.Command, args []string) { prNumber := args[0] @@ -84,25 +81,14 @@ func execCommunityChecker(prNumber, commitSha, branchName, headRepoUrl, headBran "_BASE_BRANCH": baseBranch, } - pullRequest, err := gh.GetPullRequest(prNumber) + // trigger presubmit builds - community-checker requires approval + // (explicitly or via membership-checker) + err := cb.TriggerMMPresubmitRuns(commitSha, substitutions) if err != nil { fmt.Println(err) os.Exit(1) } - author := pullRequest.User.Login - authorUserType := gh.GetUserType(author) - trusted := authorUserType == github.CoreContributorUserType || authorUserType == github.GooglerUserType - - // only triggers build for untrusted users (because trusted users will be handled by membership-checker) - if !trusted { - err = cb.TriggerMMPresubmitRuns(commitSha, substitutions) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - } - // in community-checker job: // remove awaiting-approval label from external contributor PRs gh.RemoveLabel(prNumber, "awaiting-approval") diff --git a/.ci/magician/cmd/community_checker_test.go b/.ci/magician/cmd/community_checker_test.go index 2b02e28448f3..9880d83031a3 100644 --- a/.ci/magician/cmd/community_checker_test.go +++ b/.ci/magician/cmd/community_checker_test.go @@ -37,12 +37,16 @@ func TestExecCommunityChecker_CoreContributorFlow(t *testing.T) { execCommunityChecker("pr1", "sha1", "branch1", "url1", "head1", "base1", gh, cb) - if _, ok := cb.calledMethods["TriggerMMPresubmitRuns"]; ok { - t.Fatal("Presubmit runs redundantly triggered for core contributor") + method := "TriggerMMPresubmitRuns" + expected := [][]any{{"sha1", map[string]string{"BRANCH_NAME": "branch1", "_BASE_BRANCH": "base1", "_HEAD_BRANCH": "head1", "_HEAD_REPO_URL": "url1", "_PR_NUMBER": "pr1"}}} + if calls, ok := cb.calledMethods[method]; !ok { + t.Fatal("Presubmit runs not triggered for core contributor") + } else if !reflect.DeepEqual(calls, expected) { + t.Fatalf("Wrong calls for %s, got %v, expected %v", method, calls, expected) } - method := "RemoveLabel" - expected := [][]any{{"pr1", "awaiting-approval"}} + method = "RemoveLabel" + expected = [][]any{{"pr1", "awaiting-approval"}} if calls, ok := gh.calledMethods[method]; !ok { t.Fatal("awaiting-approval label not removed for PR ") } else if !reflect.DeepEqual(calls, expected) { @@ -69,12 +73,16 @@ func TestExecCommunityChecker_GooglerFlow(t *testing.T) { execCommunityChecker("pr1", "sha1", "branch1", "url1", "head1", "base1", gh, cb) - if _, ok := cb.calledMethods["TriggerMMPresubmitRuns"]; ok { - t.Fatal("Presubmit runs redundantly triggered for googler") + method := "TriggerMMPresubmitRuns" + expected := [][]any{{"sha1", map[string]string{"BRANCH_NAME": "branch1", "_BASE_BRANCH": "base1", "_HEAD_BRANCH": "head1", "_HEAD_REPO_URL": "url1", "_PR_NUMBER": "pr1"}}} + if calls, ok := cb.calledMethods[method]; !ok { + t.Fatal("Presubmit runs not triggered for googler") + } else if !reflect.DeepEqual(calls, expected) { + t.Fatalf("Wrong calls for %s, got %v, expected %v", method, calls, expected) } - method := "RemoveLabel" - expected := [][]any{{"pr1", "awaiting-approval"}} + method = "RemoveLabel" + expected = [][]any{{"pr1", "awaiting-approval"}} if calls, ok := gh.calledMethods[method]; !ok { t.Fatal("awaiting-approval label not removed for PR ") } else if !reflect.DeepEqual(calls, expected) { diff --git a/.ci/magician/cmd/membership_checker.go b/.ci/magician/cmd/membership_checker.go index 97210105dd08..a91ce77c5fca 100644 --- a/.ci/magician/cmd/membership_checker.go +++ b/.ci/magician/cmd/membership_checker.go @@ -33,26 +33,18 @@ var membershipCheckerCmd = &cobra.Command{ The command expects the following pull request details as arguments: 1. PR Number 2. Commit SHA - 3. Branch Name - 4. Head Repo URL - 5. Head Branch - 6. Base Branch It then performs the following operations: 1. Extracts and displays the pull request details. 2. Fetches the author of the pull request and determines their contribution type. - 3. If the author is not a core contributor: - a. Identifies the initially requested reviewer and those who previously reviewed this PR. - b. Determines and requests reviewers based on the above. - c. Posts comments tailored to the contribution type, the trust level of the contributor, and the primary reviewer. - 4. For trusted authors (Core Contributors and Googlers): - a. Triggers generate-diffs using the provided PR details. - b. Automatically approves the community-checker run. - 5. For external or untrusted contributors: + 3. For trusted authors (Core Contributors and Googlers): + a. Automatically approves the community-checker run. + 4. For external or untrusted contributors: a. Adds the 'awaiting-approval' label. b. Posts a link prompting approval for the build. `, - Args: cobra.ExactArgs(6), + // This can change to cobra.ExactArgs(2) after at least a 2-week soak + Args: cobra.RangeArgs(2, 6), Run: func(cmd *cobra.Command, args []string) { prNumber := args[0] fmt.Println("PR Number: ", prNumber) @@ -60,18 +52,6 @@ var membershipCheckerCmd = &cobra.Command{ commitSha := args[1] fmt.Println("Commit SHA: ", commitSha) - branchName := args[2] - fmt.Println("Branch Name: ", branchName) - - headRepoUrl := args[3] - fmt.Println("Head Repo URL: ", headRepoUrl) - - headBranch := args[4] - fmt.Println("Head Branch: ", headBranch) - - baseBranch := args[5] - fmt.Println("Base Branch: ", baseBranch) - githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_MAGIC_MODULES") if !ok { fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES or GITHUB_TOKEN environment variables") @@ -79,19 +59,11 @@ var membershipCheckerCmd = &cobra.Command{ } gh := github.NewClient(githubToken) cb := cloudbuild.NewClient() - execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch, gh, cb) + execMembershipChecker(prNumber, commitSha, gh, cb) }, } -func execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBranch, baseBranch string, gh GithubClient, cb CloudbuildClient) { - substitutions := map[string]string{ - "BRANCH_NAME": branchName, - "_PR_NUMBER": prNumber, - "_HEAD_REPO_URL": headRepoUrl, - "_HEAD_BRANCH": headBranch, - "_BASE_BRANCH": baseBranch, - } - +func execMembershipChecker(prNumber, commitSha string, gh GithubClient, cb CloudbuildClient) { pullRequest, err := gh.GetPullRequest(prNumber) if err != nil { fmt.Println(err) @@ -102,17 +74,6 @@ func execMembershipChecker(prNumber, commitSha, branchName, headRepoUrl, headBra authorUserType := gh.GetUserType(author) trusted := authorUserType == github.CoreContributorUserType || authorUserType == github.GooglerUserType - // auto_run(contributor-membership-checker) will be run on every commit or /gcbrun: - // only triggers builds for trusted users - if trusted { - err = cb.TriggerMMPresubmitRuns(commitSha, substitutions) - if err != nil { - fmt.Println(err) - os.Exit(1) - } - } - - // in contributor-membership-checker job: // 1. auto approve community-checker run for trusted users // 2. add awaiting-approval label to external contributor PRs if trusted { diff --git a/.ci/magician/cmd/membership_checker_test.go b/.ci/magician/cmd/membership_checker_test.go index a3a40b4b89bd..81074230ec56 100644 --- a/.ci/magician/cmd/membership_checker_test.go +++ b/.ci/magician/cmd/membership_checker_test.go @@ -35,22 +35,10 @@ func TestExecMembershipChecker_CoreContributorFlow(t *testing.T) { calledMethods: make(map[string][][]any), } - execMembershipChecker("pr1", "sha1", "branch1", "url1", "head1", "base1", gh, cb) + execMembershipChecker("pr1", "sha1", gh, cb) - if _, ok := gh.calledMethods["RequestPullRequestReviewer"]; ok { - t.Fatal("Incorrectly requested review for core contributor") - } - - method := "TriggerMMPresubmitRuns" - expected := [][]any{{"sha1", map[string]string{"BRANCH_NAME": "branch1", "_BASE_BRANCH": "base1", "_HEAD_BRANCH": "head1", "_HEAD_REPO_URL": "url1", "_PR_NUMBER": "pr1"}}} - if calls, ok := cb.calledMethods[method]; !ok { - t.Fatal("Presubmit runs not triggered for core author") - } else if !reflect.DeepEqual(calls, expected) { - t.Fatalf("Wrong calls for %s, got %v, expected %v", method, calls, expected) - } - - method = "ApproveCommunityChecker" - expected = [][]any{{"pr1", "sha1"}} + method := "ApproveCommunityChecker" + expected := [][]any{{"pr1", "sha1"}} if calls, ok := cb.calledMethods[method]; !ok { t.Fatal("Community checker not approved for core author") } else if !reflect.DeepEqual(calls, expected) { @@ -75,18 +63,10 @@ func TestExecMembershipChecker_GooglerFlow(t *testing.T) { calledMethods: make(map[string][][]any), } - execMembershipChecker("pr1", "sha1", "branch1", "url1", "head1", "base1", gh, cb) + execMembershipChecker("pr1", "sha1", gh, cb) - method := "TriggerMMPresubmitRuns" - expected := [][]any{{"sha1", map[string]string{"BRANCH_NAME": "branch1", "_BASE_BRANCH": "base1", "_HEAD_BRANCH": "head1", "_HEAD_REPO_URL": "url1", "_PR_NUMBER": "pr1"}}} - if calls, ok := cb.calledMethods[method]; !ok { - t.Fatal("Presubmit runs not triggered for googler") - } else if !reflect.DeepEqual(calls, expected) { - t.Fatalf("Wrong calls for %s, got %v, expected %v", method, calls, expected) - } - - method = "ApproveCommunityChecker" - expected = [][]any{{"pr1", "sha1"}} + method := "ApproveCommunityChecker" + expected := [][]any{{"pr1", "sha1"}} if calls, ok := cb.calledMethods[method]; !ok { t.Fatal("Community checker not approved for googler") } else if !reflect.DeepEqual(calls, expected) { @@ -110,7 +90,7 @@ func TestExecMembershipChecker_AmbiguousUserFlow(t *testing.T) { calledMethods: make(map[string][][]any), } - execMembershipChecker("pr1", "sha1", "branch1", "url1", "head1", "base1", gh, cb) + execMembershipChecker("pr1", "sha1", gh, cb) method := "AddLabel" expected := [][]any{{"pr1", "awaiting-approval"}} @@ -131,10 +111,6 @@ func TestExecMembershipChecker_AmbiguousUserFlow(t *testing.T) { if _, ok := gh.calledMethods["ApproveCommunityChecker"]; ok { t.Fatal("Incorrectly approved community checker for ambiguous user") } - - if _, ok := gh.calledMethods["TriggerMMPresubmitRuns"]; ok { - t.Fatal("Incorrectly triggered presubmit runs for ambiguous user") - } } func TestExecMembershipChecker_CommentForNewPrimaryReviewer(t *testing.T) { @@ -153,5 +129,5 @@ func TestExecMembershipChecker_CommentForNewPrimaryReviewer(t *testing.T) { calledMethods: make(map[string][][]any), } - execMembershipChecker("pr1", "sha1", "branch1", "url1", "head1", "base1", gh, cb) + execMembershipChecker("pr1", "sha1", gh, cb) } From eaded1dd2c3992e3d31fb4aaf16dffb47a7c4d40 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Fri, 8 Mar 2024 10:09:43 -0800 Subject: [PATCH 100/200] Clean up delete template (#10144) --- mmv1/templates/terraform/resource.erb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mmv1/templates/terraform/resource.erb b/mmv1/templates/terraform/resource.erb index 10254f2ae4b9..ce0764568b71 100644 --- a/mmv1/templates/terraform/resource.erb +++ b/mmv1/templates/terraform/resource.erb @@ -1047,19 +1047,17 @@ func resource<%= object.resource_name -%>Delete(d *schema.ResourceData, meta int <% end -%> <% end -%> <% if object.supports_indirect_user_project_override -%> - if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { billingProject = parts[1] } - <% end -%> - log.Printf("[DEBUG] Deleting <%= object.name -%> %q", d.Id()) // err == nil indicates that the billing_project value was found if bp, err := tpgresource.GetBillingProject(d, config); err == nil { billingProject = bp } + log.Printf("[DEBUG] Deleting <%= object.name -%> %q", d.Id()) res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ Config: config, Method: "<%= object.delete_verb.to_s.upcase -%>", From 331569fa7edb2a6501873846decb27c5e033abb6 Mon Sep 17 00:00:00 2001 From: askubis Date: Fri, 8 Mar 2024 19:33:36 +0100 Subject: [PATCH 101/200] added missing web documentation about create_timestamp for compute_(region_)instance_group_manager (#10148) --- .../website/docs/r/compute_instance_group_manager.html.markdown | 2 ++ .../docs/r/compute_region_instance_group_manager.html.markdown | 2 ++ 2 files changed, 4 insertions(+) diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown index 834633b6b6d9..04f576cb43cf 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown @@ -313,6 +313,8 @@ exported: * `id` - an identifier for the resource with format `projects/{{project}}/zones/{{zone}}/instanceGroupManagers/{{name}}` +* `creation_timestamp` - Creation timestamp in RFC3339 text format. + * `fingerprint` - The fingerprint of the instance group manager. * `instance_group` - The full URL of the instance group created by the manager. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown index 8dfbf3ee9a9f..eeab84344718 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown @@ -324,6 +324,8 @@ exported: * `id` - an identifier for the resource with format `projects/{{project}}/regions/{{region}}/instanceGroupManagers/{{name}}` +* `creation_timestamp` - Creation timestamp in RFC3339 text format. + * `fingerprint` - The fingerprint of the instance group manager. * `instance_group` - The full URL of the instance group created by the manager. From b3dd24768e1709f305efff76c197501e7f31ab44 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Fri, 8 Mar 2024 11:59:35 -0800 Subject: [PATCH 102/200] Move pre_delete code closer to the request (#10143) --- mmv1/templates/terraform/resource.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mmv1/templates/terraform/resource.erb b/mmv1/templates/terraform/resource.erb index ce0764568b71..ea2b7cb1e269 100644 --- a/mmv1/templates/terraform/resource.erb +++ b/mmv1/templates/terraform/resource.erb @@ -1032,7 +1032,6 @@ func resource<%= object.resource_name -%>Delete(d *schema.ResourceData, meta int <%# If the deletion of the object requires sending a request body, the custom code will set 'obj' -%> var obj map[string]interface{} -<%= lines(compile(pwd + '/' + object.custom_code.pre_delete)) if object.custom_code.pre_delete -%> <% if object.nested_query&.modify_by_patch -%> <%# Keep this after mutex - patch request data relies on current resource state %> obj, err = resource<%= object.resource_name -%>PatchDeleteEncoder(d, meta, obj) @@ -1057,6 +1056,8 @@ func resource<%= object.resource_name -%>Delete(d *schema.ResourceData, meta int billingProject = bp } +<%= lines(compile(pwd + '/' + object.custom_code.pre_delete)) if object.custom_code.pre_delete -%> + log.Printf("[DEBUG] Deleting <%= object.name -%> %q", d.Id()) res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ Config: config, From 030e79065affbdfc31f63b405ee004dedf253133 Mon Sep 17 00:00:00 2001 From: "Michael R. Torres" <6692889+micrictor@users.noreply.github.com> Date: Fri, 8 Mar 2024 14:02:54 -0800 Subject: [PATCH 103/200] Create resource definition for IAP Tunnel DestGroup (#10064) --- mmv1/products/iap/TunnelDestGroup.yaml | 78 +++++++++++++++ .../terraform/examples/iap_destgroup.tf.erb | 9 ++ .../resource_iap_tunnel_dest_group_test.go | 94 +++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 mmv1/products/iap/TunnelDestGroup.yaml create mode 100644 mmv1/templates/terraform/examples/iap_destgroup.tf.erb create mode 100644 mmv1/third_party/terraform/services/iap/resource_iap_tunnel_dest_group_test.go diff --git a/mmv1/products/iap/TunnelDestGroup.yaml b/mmv1/products/iap/TunnelDestGroup.yaml new file mode 100644 index 000000000000..2ebacbd5e9f8 --- /dev/null +++ b/mmv1/products/iap/TunnelDestGroup.yaml @@ -0,0 +1,78 @@ +# 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: 'TunnelDestGroup' +description: | + Tunnel destination groups represent resources that have the same tunnel access restrictions. +references: !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/iap/docs/reference/rest/v1/projects.iap_tunnel.locations.destGroups' + guides: + 'Set up IAP TCP forwarding with an IP address or hostname in a Google Cloud or non-Google Cloud environment': 'https://cloud.google.com/iap/docs/tcp-by-host' +base_url: 'projects/{{project}}/iap_tunnel/locations/{{region}}/destGroups' +create_url: 'projects/{{project}}/iap_tunnel/locations/{{region}}/destGroups?tunnelDestGroupId={{group_name}}' +update_verb: :PATCH +self_link: 'projects/{{project}}/iap_tunnel/locations/{{region}}/destGroups/{{group_name}}' +import_format: [ + 'projects/{{project}}/iap_tunnel/locations/{{region}}/destGroups/{{group_name}}', + '{{project}}/iap_tunnel/locations/{{region}}/destGroups/{{group_name}}', + '{{region}}/destGroups/{{group_name}}', +] +iam_policy: !ruby/object:Api::Resource::IamPolicy + skip_import_test: true + parent_resource_attribute: 'dest_group' + method_name_separator: ':' + fetch_iam_policy_verb: :POST + allowed_iam_role: 'roles/iap.tunnelResourceAccessor' + iam_conditions_request_type: :REQUEST_BODY + base_url: 'projects/{{project}}/iap_tunnel/locations/{{region}}/destGroups/{{dest_group}}' + import_format: [ + 'projects/{{project}}/iap_tunnel/locations/{{region}}/destGroups/{{dest_group}}', + '{{project}}/iap_tunnel/locations/{{region}}/destGroups/{{dest_group}}', + ] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'iap_destgroup' + pull_external: true + primary_resource_id: 'dest_group' + primary_resource_name: 'fmt.Sprintf("tf-test%s", context["random_suffix"])' +parameters: + - !ruby/object:Api::Type::String + name: 'region' + description: | + The region of the tunnel group. Must be the same as the network resources in the group. + immutable: true + url_param_only: true + default_from_api: true + - !ruby/object:Api::Type::String + name: 'group_name' + description: Unique tunnel destination group name. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'name' + description: Full resource name. + immutable: true + output: true + - !ruby/object:Api::Type::Array + name: 'cidrs' + description: | + List of CIDRs that this group applies to. + item_type: Api::Type::String + - !ruby/object:Api::Type::Array + name: 'fqdns' + description: | + List of FQDNs that this group applies to. + item_type: Api::Type::String diff --git a/mmv1/templates/terraform/examples/iap_destgroup.tf.erb b/mmv1/templates/terraform/examples/iap_destgroup.tf.erb new file mode 100644 index 000000000000..0ebfd16f5236 --- /dev/null +++ b/mmv1/templates/terraform/examples/iap_destgroup.tf.erb @@ -0,0 +1,9 @@ +resource "google_iap_tunnel_dest_group" "dest_group" { + region = "us-central1" + group_name = "testgroup%{random_suffix}" + cidrs = [ + "10.1.0.0/16", + "192.168.10.0/24", + ] +} + diff --git a/mmv1/third_party/terraform/services/iap/resource_iap_tunnel_dest_group_test.go b/mmv1/third_party/terraform/services/iap/resource_iap_tunnel_dest_group_test.go new file mode 100644 index 000000000000..c04063a75b71 --- /dev/null +++ b/mmv1/third_party/terraform/services/iap/resource_iap_tunnel_dest_group_test.go @@ -0,0 +1,94 @@ +package iap_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccIapTunnelDestGroup_updates(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), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + CheckDestroy: testAccCheckIapTunnelDestGroupDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccIapTunnelDestGroup_full(context), + }, + { + ResourceName: "google_iap_tunnel_dest_group.dest_group", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"region", "group_name"}, + }, + { + Config: testAccIapTunnelDestGroup_updated(context), + }, + { + ResourceName: "google_iap_tunnel_dest_group.dest_group", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"region", "group_name"}, + }, + { + Config: testAccIapTunnelDestGroup_updated_fqdns(context), + }, + { + ResourceName: "google_iap_tunnel_dest_group.dest_group", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"region", "group_name"}, + }, + }, + }) +} + +func testAccIapTunnelDestGroup_full(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_iap_tunnel_dest_group" "dest_group" { + region = "us-central1" + group_name = "testgroup%{random_suffix}" + cidrs = [ + "10.1.0.0/16", + "192.168.10.0/24", + ] +} +`, context) +} + +func testAccIapTunnelDestGroup_updated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_iap_tunnel_dest_group" "dest_group" { + region = "us-central1" + group_name = "testgroup%{random_suffix}" + cidrs = [ + "10.1.0.0/16", + ] +} +`, context) +} + +func testAccIapTunnelDestGroup_updated_fqdns(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_iap_tunnel_dest_group" "dest_group" { + region = "us-central1" + group_name = "testgroup%{random_suffix}" + cidrs = [ + "10.1.0.0/16", + ] + fqdns = ["proxied.lan"] +} +`, context) +} From ab2122202ab62d620cbbbc8928078b0782146994 Mon Sep 17 00:00:00 2001 From: Esha Goel Date: Fri, 8 Mar 2024 23:59:42 +0000 Subject: [PATCH 104/200] Add new resource for Service Project for Apphub (#10048) FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 --- .../apphub/ServiceProjectAttachment.yaml | 110 ++++++++++++++++++ .../constants/apphub_service_project.go.erb | 4 + .../apphub_service_project.go.erb | 6 + .../apphub_service_project.go.erb | 3 + ...ub_service_project_attachment_basic.tf.erb | 16 +++ ...hub_service_project_attachment_full.tf.erb | 17 +++ 6 files changed, 156 insertions(+) create mode 100644 mmv1/products/apphub/ServiceProjectAttachment.yaml create mode 100644 mmv1/templates/terraform/constants/apphub_service_project.go.erb create mode 100644 mmv1/templates/terraform/custom_expand/apphub_service_project.go.erb create mode 100644 mmv1/templates/terraform/custom_flatten/apphub_service_project.go.erb create mode 100644 mmv1/templates/terraform/examples/apphub_service_project_attachment_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/apphub_service_project_attachment_full.tf.erb diff --git a/mmv1/products/apphub/ServiceProjectAttachment.yaml b/mmv1/products/apphub/ServiceProjectAttachment.yaml new file mode 100644 index 000000000000..724f60dc7d0e --- /dev/null +++ b/mmv1/products/apphub/ServiceProjectAttachment.yaml @@ -0,0 +1,110 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +--- !ruby/object:Api::Resource +base_url: projects/{{project}}/locations/global/serviceProjectAttachments +create_url: projects/{{project}}/locations/global/serviceProjectAttachments?serviceProjectAttachmentId={{service_project_attachment_id}} +self_link: projects/{{project}}/locations/global/serviceProjectAttachments/{{service_project_attachment_id}} +id_format: projects/{{project}}/locations/global/serviceProjectAttachments/{{service_project_attachment_id}} +import_format: + - projects/{{project}}/locations/global/serviceProjectAttachments/{{service_project_attachment_id}} +name: ServiceProjectAttachment +description: | + Represents a Service project attachment to the Host Project. +immutable: true +autogen_async: true +custom_code: !ruby/object:Provider::Terraform::CustomCode + constants: 'templates/terraform/constants/apphub_service_project.go.erb' +examples: + - !ruby/object:Provider::Terraform::Examples + name: "service_project_attachment_basic" + pull_external: true + primary_resource_id: "example" + config_path: "templates/terraform/examples/apphub_service_project_attachment_basic.tf.erb" + vars: + service_project_attachment_id: "project-1" + test_env_vars: + org_id: :ORG_ID + host_project: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: "service_project_attachment_full" + pull_external: true + primary_resource_id: "example2" + config_path: "templates/terraform/examples/apphub_service_project_attachment_full.tf.erb" + vars: + service_project_attachment_id: "project-1" + test_env_vars: + org_id: :ORG_ID + host_project: :PROJECT_NAME +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: | + "Identifier. The resource name of a ServiceProjectAttachment. Format:\"projects/{host-project-id}/locations/global/serviceProjectAttachments/{service-project-id}.\" " + - !ruby/object:Api::Type::String + name: serviceProject + diff_suppress_func: 'ServiceProjectDiffSuppress' + custom_expand: 'templates/terraform/custom_expand/apphub_service_project.go.erb' + custom_flatten: 'templates/terraform/custom_flatten/apphub_service_project.go.erb' + description: | + "Immutable. Service project name in the format: \"projects/abc\" + or \"projects/123\". As input, project name with either project id or number + are accepted. As output, this field will contain project number. " + immutable: true + - !ruby/object:Api::Type::String + name: createTime + description: 'Output only. Create time. ' + output: true + - !ruby/object:Api::Type::String + name: uid + description: "Output only. A globally unique identifier (in UUID4 format) for the `ServiceProjectAttachment`. " + output: true + - !ruby/object:Api::Type::Enum + name: 'state' + description: | + ServiceProjectAttachment state. + output: true + values: + - :STATE_UNSPECIFIED + - :CREATING + - :ACTIVE + - :DELETING +parameters: + - !ruby/object:Api::Type::String + name: serviceProjectAttachmentId + description: "Required. The service project attachment identifier must contain the + project_id of the service project specified in the service_project_attachment.service_project + field. Hint: \"projects/{project_id}\" " + url_param_only: true + required: 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/templates/terraform/constants/apphub_service_project.go.erb b/mmv1/templates/terraform/constants/apphub_service_project.go.erb new file mode 100644 index 000000000000..55e38f6b1d44 --- /dev/null +++ b/mmv1/templates/terraform/constants/apphub_service_project.go.erb @@ -0,0 +1,4 @@ +// Suppress all diff for the field Service Project +func ServiceProjectDiffSuppress(_, _, _ string, _ *schema.ResourceData) bool { + return true +} \ No newline at end of file diff --git a/mmv1/templates/terraform/custom_expand/apphub_service_project.go.erb b/mmv1/templates/terraform/custom_expand/apphub_service_project.go.erb new file mode 100644 index 000000000000..716466f55f9b --- /dev/null +++ b/mmv1/templates/terraform/custom_expand/apphub_service_project.go.erb @@ -0,0 +1,6 @@ +func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + + service_project := "projects/" + d.Get("service_project_attachment_id").(string) + + return service_project, nil +} diff --git a/mmv1/templates/terraform/custom_flatten/apphub_service_project.go.erb b/mmv1/templates/terraform/custom_flatten/apphub_service_project.go.erb new file mode 100644 index 000000000000..05cb8d57c1d5 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/apphub_service_project.go.erb @@ -0,0 +1,3 @@ +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return nil +} diff --git a/mmv1/templates/terraform/examples/apphub_service_project_attachment_basic.tf.erb b/mmv1/templates/terraform/examples/apphub_service_project_attachment_basic.tf.erb new file mode 100644 index 000000000000..33d835bacc44 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_service_project_attachment_basic.tf.erb @@ -0,0 +1,16 @@ +resource "google_apphub_service_project_attachment" "<%= ctx[:primary_resource_id] %>" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project.service_project] + + create_duration = "120s" +} diff --git a/mmv1/templates/terraform/examples/apphub_service_project_attachment_full.tf.erb b/mmv1/templates/terraform/examples/apphub_service_project_attachment_full.tf.erb new file mode 100644 index 000000000000..f88c9b9ab7fa --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_service_project_attachment_full.tf.erb @@ -0,0 +1,17 @@ +resource "google_apphub_service_project_attachment" "<%= ctx[:primary_resource_id] %>" { + service_project_attachment_id = google_project.service_project_full.project_id + service_project = google_project.service_project_full.project_id + depends_on = [time_sleep.wait_120s] +} + +resource "google_project" "service_project_full" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project Full" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project.service_project_full] + + create_duration = "120s" +} From 124dd0e33a5d934bf27cd2764db835fa7791e4fd Mon Sep 17 00:00:00 2001 From: Luca Prete Date: Mon, 11 Mar 2024 18:32:13 +0100 Subject: [PATCH 105/200] [#15779] Add google_network_security_firewall_endpoint_association resource (#9815) * [#15779] Add google_network_security_firewall_endpoint_association resource * Fixing tests * Fixes * Add test for update --------- Co-authored-by: Luca Prete --- .../FirewallEndpointAssociation.yaml | 122 ++++++++++++++ ...firewall_endpoint_association_basic.tf.erb | 21 +++ ..._firewall_endpoint_association_test.go.erb | 154 ++++++++++++++++++ 3 files changed, 297 insertions(+) create mode 100644 mmv1/products/networksecurity/FirewallEndpointAssociation.yaml create mode 100644 mmv1/templates/terraform/examples/network_security_firewall_endpoint_association_basic.tf.erb create mode 100644 mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go.erb diff --git a/mmv1/products/networksecurity/FirewallEndpointAssociation.yaml b/mmv1/products/networksecurity/FirewallEndpointAssociation.yaml new file mode 100644 index 000000000000..9a49eb7496fb --- /dev/null +++ b/mmv1/products/networksecurity/FirewallEndpointAssociation.yaml @@ -0,0 +1,122 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the 'License'); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an 'AS IS' BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'FirewallEndpointAssociation' +base_url: '{{parent}}/locations/{{location}}/firewallEndpointAssociations' +create_url: '{{parent}}/locations/{{location}}/firewallEndpointAssociations?firewallEndpointId={{name}}' +self_link: '{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}' +min_version: beta +update_verb: :PATCH +update_mask: true +description: | + Firewall endpoint association links a firewall endpoint to a VPC network in + the same zone. After you define this association, Cloud Firewall forwards the + zonal workload traffic in your VPC network that requires layer 7 inspection to + the attached firewall endpoint. +references: + !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/projects.locations.firewallEndpointAssociations#FirewallEndpointAssociation' + guides: + 'Firewall endpoint overview': 'https://cloud.google.com/firewall/docs/about-firewall-endpoints' + 'Create and associate firewall endpoints': 'https://cloud.google.com/firewall/docs/configure-firewall-endpoints' +async: !ruby/object:Api::OpAsync + include_project: true + operation: !ruby/object:Api::OpAsync::Operation + base_url: '{{op_id}}' + result: !ruby/object:Api::OpAsync::Result + resource_inside_response: true +import_format: [ + '{{%parent}}/locations/{{location}}/firewallEndpointAssociations/{{name}}' +] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'network_security_firewall_endpoint_association_basic' + primary_resource_id: 'default' + # Handwritten test will take care of creates and updates. + # Firewall endpoint association creation is subjet to firewall endpoint creation which is long and expensive. + skip_test: true + min_version: beta + vars: + resource_name_prefix: 'my-firewall-endpoint' + test_env_vars: + org_id: :ORG_ID + project: :PROJECT_NAME +parameters: + - !ruby/object:Api::Type::String + name: 'name' + required: true + immutable: true + url_param_only: true + description: | + The name of the firewall endpoint association resource. + - !ruby/object:Api::Type::String + name: 'location' + required: true + immutable: true + description: | + The location (zone) of the firewall endpoint association. + url_param_only: true + - !ruby/object:Api::Type::String + name: 'parent' + description: | + The name of the parent this firewall endpoint association belongs to. + Format: projects/{project_id}. + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'firewallEndpoint' + required: true + description: | + The URL of the firewall endpoint that is being associated. + - !ruby/object:Api::Type::String + name: 'network' + required: true + description: | + The URL of the network that is being associated. + - !ruby/object:Api::Type::String + name: 'tlsInspectionPolicy' + description: | + The URL of the TlsInspectionPolicy that is being associated. + - !ruby/object:Api::Type::KeyValueLabels + name: 'labels' + description: | + A map of key/value label pairs to assign to the resource. + - !ruby/object:Api::Type::String + name: 'selfLink' + description: | + Server-defined URL of this resource. + output: true + - !ruby/object:Api::Type::Time + name: 'createTime' + description: Time the firewall endpoint was created in UTC. + output: true + - !ruby/object:Api::Type::Time + name: 'updateTime' + description: Time the firewall endpoint was updated in UTC. + output: true + - !ruby/object:Api::Type::Boolean + name: 'reconciling' + description: | + Whether reconciling is in progress, recommended per https://google.aip.dev/128. + output: true + - !ruby/object:Api::Type::Enum + name: 'state' + description: The current state of the endpoint. + output: true + values: + - :ACTIVE + - :CREATING + - :DELETING + - :INACTIVE diff --git a/mmv1/templates/terraform/examples/network_security_firewall_endpoint_association_basic.tf.erb b/mmv1/templates/terraform/examples/network_security_firewall_endpoint_association_basic.tf.erb new file mode 100644 index 000000000000..ce6b59347058 --- /dev/null +++ b/mmv1/templates/terraform/examples/network_security_firewall_endpoint_association_basic.tf.erb @@ -0,0 +1,21 @@ +resource "google_network_security_firewall_endpoint" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + name = "<%= ctx[:vars]['resource_name_prefix'] %>" + parent = "organizations/<%= ctx[:test_env_vars]['org_id'] %>" + location = "us-central1-a" + + labels = { + foo = "bar" + } +} + +resource "google_network_security_firewall_endpoint_association" "<%= ctx[:primary_resource_id] %>_association" { + provider = google-beta + name = "<%= ctx[:vars]['resource_name_prefix'] %>-association" + parent = "projects/<%= ctx[:test_env_vars]['project'] %>" + location = "us-central1-a" + + labels = { + foo = "bar" + } +} diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go.erb new file mode 100644 index 000000000000..e10e75113914 --- /dev/null +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_association_test.go.erb @@ -0,0 +1,154 @@ +<% autogen_exception -%> +package networksecurity_test +<% unless version == 'ga' -%> + +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" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" +) + +func TestAccNetworkSecurityFirewallEndpointAssociations_basic(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + orgId := envvar.GetTestOrgFromEnv(t) + randomSuffix := acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_basic(randomSuffix, orgId, ), + }, + { + ResourceName: "google_network_security_firewall_endpoint_association.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccNetworkSecurityFirewallEndpointAssociation_update(randomSuffix, orgId, ), + }, + { + ResourceName: "google_network_security_firewall_endpoint_association.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + +func testAccNetworkSecurityFirewallEndpointAssociation_basic(randomSuffix string, orgId string) string { + return fmt.Sprintf(` +resource "google_compute_network" "foobar" { + provider = google-beta + name = "tf-test-my-vpc%s" + auto_create_subnetworks = false +} + +resource "google_network_security_firewall_endpoint" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%s" + parent = "organizations/%s" + location = "us-central1-a" +} + +# TODO: add tlsInspectionPolicy once resource is ready +resource "google_network_security_firewall_endpoint_association" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%s" + parent = "organizations/%s" + location = "us-central1-a" + firewall_endpoint = google_network_security_firewall_endpoint.foobar.id + network = google_compute_network.foobar.id + + labels = { + foo = "bar" + } +} +`, randomSuffix, randomSuffix, orgId, randomSuffix, orgId) +} + +func testAccNetworkSecurityFirewallEndpointAssociation_update(randomSuffix string, orgId string) string { + return fmt.Sprintf(` +resource "google_compute_network" "foobar" { + provider = google-beta + name = "tf-test-my-vpc%s" + auto_create_subnetworks = false +} + +resource "google_network_security_firewall_endpoint" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%s" + parent = "organizations/%s" + location = "us-central1-a" +} + +# TODO: add tlsInspectionPolicy once resource is ready +resource "google_network_security_firewall_endpoint_association" "foobar" { + provider = google-beta + name = "tf-test-my-firewall-endpoint%s" + parent = "organizations/%s" + location = "us-central1-a" + firewall_endpoint = google_network_security_firewall_endpoint.foobar.id + network = google_compute_network.foobar.id + + labels = { + foo = "bar-updated" + } +} +`, randomSuffix, randomSuffix, orgId, randomSuffix, orgId) +} + +func testAccCheckNetworkSecurityFirewallEndpointAssociationDestroyProducer(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_network_security_firewall_endpoint_association" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{NetworkSecurityBasePath}}{{parent}}/locations/{{location}}/firewallEndpointAssociations/{{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("NetworkSecurityFirewallEndpointAssociation still exists at %s", url) + } + } + + return nil + } +} + +<% end -%> From b16ca4a132078fb83a5b7f74239bce06f8376d92 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Mon, 11 Mar 2024 10:48:34 -0700 Subject: [PATCH 106/200] update teamcity diff check to run every monday morning also (#10159) --- .github/workflows/teamcity-services-diff-check-weekly.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 5d857f0eda90..1d0bf90820c5 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -7,8 +7,8 @@ on: # Scheduled checks to catch edge cases schedule: - # Every Tuesday morning - - cron: '0 4 * * 2' + # Every Monday and Tuesday morning + - cron: '0 4 * * 1-2' jobs: terraform-provider-google: From 3907a64071e2aece0d26ef2e637e401a85ad1411 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 11 Mar 2024 12:47:19 -0700 Subject: [PATCH 107/200] Add DisplayName to Product struct (#10161) --- mmv1/api/async.go | 2 +- mmv1/api/product.go | 20 ++++--- mmv1/google/string_utils.go | 111 ++++++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 10 deletions(-) create mode 100644 mmv1/google/string_utils.go diff --git a/mmv1/api/async.go b/mmv1/api/async.go index 55d756fa8312..dc4090fe7663 100644 --- a/mmv1/api/async.go +++ b/mmv1/api/async.go @@ -66,7 +66,7 @@ type Result struct { // Contains information about the result of an Operation - ResourceInsideResponse bool + ResourceInsideResponse bool `yaml:"resource_inside_response"` } // def validate diff --git a/mmv1/api/product.go b/mmv1/api/product.go index d56edeefb9be..bfaed3a19869 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -15,6 +15,7 @@ package api import ( "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" "golang.org/x/exp/slices" ) @@ -38,6 +39,7 @@ type Product struct { // Name string // Display Name: The full name of the GCP product; eg "Cloud Bigtable" + DisplayName string `yaml:"display_name"` Objects []*Resource @@ -108,15 +110,15 @@ func (p *Product) Validate() { // name.downcase // end -// // The product full name is the "display name" in string form intended for -// // users to read in documentation; "Google Compute Engine", "Cloud Bigtable" -// def display_name -// if @display_name.nil? -// name.space_separated -// else -// @display_name -// end -// end +// The product full name is the "display name" in string form intended for +// users to read in documentation; "Google Compute Engine", "Cloud Bigtable" +func (p Product) GetDisplayName() string { + if p.DisplayName == "" { + return google.SpaceSeparated(p.Name) + } + + return p.DisplayName +} // // Most general version that exists for the product // // If GA is present, use that, else beta, else alpha diff --git a/mmv1/google/string_utils.go b/mmv1/google/string_utils.go new file mode 100644 index 000000000000..264f031893c6 --- /dev/null +++ b/mmv1/google/string_utils.go @@ -0,0 +1,111 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google + +import ( + "regexp" + "strings" +) + +// // Helper class to process and mutate strings. +// class StringUtils +// // Converts string from camel case to underscore +// def self.underscore(source) +// source.gsub(/::/, '/') +// .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') +// .gsub(/([a-z\d])([A-Z])/, '\1_\2') +// .tr('-', '_') +// .tr('.', '_') +// .downcase +// end + +// // Converts from PascalCase to Space Separated +// def self.space_separated(source) +// tmp = source.gsub(/([A-Z]+)([A-Z][a-z])/, '\1 \2') +// .gsub(/([a-z\d])([A-Z])/, '\1 \2') +// .downcase +// tmp[0].upcase.concat(tmp[1..]) +// end + +// Converts from PascalCase to Space Separated +// For example, converts "AccessApproval" to "Access Approval" +func SpaceSeparated(source string) string { + tmp := regexp.MustCompile(`([A-Z]+)([A-Z][a-z])`).ReplaceAllString(source, "${1} ${2}") + tmp = regexp.MustCompile(`([a-z\d])([A-Z])`).ReplaceAllString(tmp, "${1} ${2}") + tmp = strings.ToLower(tmp) + tmp = strings.Title(tmp) + return tmp +} + +// // Converts a string to space-separated capitalized words +// def self.title(source) +// ss = space_separated(source) +// ss.gsub(/\b(? policies +// // indices -> indices +// return source if source.end_with?('ies') || source.end_with?('es') + +// // index -> indices +// return "//{source.gsub(/ex$/, '')}ices" if source.end_with?('ex') + +// // mesh -> meshes +// return "//{source}es" if source.end_with?('esh') + +// // key -> keys +// // gateway -> gateways +// return "//{source}s" if source.end_with?('ey') || source.end_with?('ay') + +// // policy -> policies +// return "//{source.gsub(/y$/, '')}ies" if source.end_with?('y') + +// "//{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 From 922cc703a5cc9d371a1396bec930869be9d890e9 Mon Sep 17 00:00:00 2001 From: gurankitt <161278508+gurankitt@users.noreply.github.com> Date: Tue, 12 Mar 2024 19:46:38 +0530 Subject: [PATCH 108/200] Add data source for apphub discovered service (#10105) * Add data source for apphub discovered service * Add data source for apphub discovered service' * Add data source for apphub discovered service * resolved comments * retry logic added * add tests and documentation * Corrected tests and added project field in the data source * changed id field * Added random_suffix for the resources created and enabled iam policy and compute api * modified retry logic * Modified schema for the data source, and tests * Removed IAM permission blocks * Add dependency for compute api * Resolve merge conflict * Add time sleep * Modified test function name * Shorten service project name * Add billing account * corrected get env variable function call * Modified project id * Combined time delay * Resolving comments * Remove retry logic and add time sleep for resource ingestion --- .../provider/provider_mmv1_resources.go.erb | 1 + .../data_source_apphub_discovered_service.go | 171 ++++++++++++++++++ ...a_source_apphub_discovered_service_test.go | 128 +++++++++++++ .../d/apphub_discovered_service.html.markdown | 52 ++++++ 4 files changed, 352 insertions(+) create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service.go create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.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 33109889347c..0b2bd157e154 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -28,6 +28,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_alloydb_supported_database_flags": alloydb.DataSourceAlloydbSupportedDatabaseFlags(), "google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(), "google_app_engine_default_service_account": appengine.DataSourceGoogleAppEngineDefaultServiceAccount(), + "google_apphub_discovered_service": apphub.DataSourceApphubDiscoveredService(), <% unless version == 'ga' -%> "google_backup_dr_management_server": backupdr.DataSourceGoogleCloudBackupDRService(), <% end -%> diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service.go new file mode 100644 index 000000000000..3efee7c6b6ae --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service.go @@ -0,0 +1,171 @@ +package apphub + +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 DataSourceApphubDiscoveredService() *schema.Resource { + return &schema.Resource{ + Read: dataSourceApphubDiscoveredServiceRead, + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Optional: true, + }, + "location": { + Type: schema.TypeString, + Required: true, + }, + "service_uri": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "service_reference": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "uri": { + Type: schema.TypeString, + Computed: true, + }, + "path": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "service_properties": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "gcp_project": { + Type: schema.TypeString, + Computed: true, + }, + "location": { + Type: schema.TypeString, + Computed: true, + }, + "zone": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceApphubDiscoveredServiceRead(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, "{{ApphubBasePath}}projects/{{project}}/locations/{{location}}/discoveredServices:lookup?uri={{service_uri}}") + 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, + }) + + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("ApphubDiscoveredService %q", d.Id()), url) + } + + if err := d.Set("name", flattenApphubDiscoveredServiceName(res["discoveredService"].(map[string]interface{})["name"], d, config)); err != nil { + return fmt.Errorf("Error setting service name: %s", err) + } + + if err := d.Set("service_reference", flattenApphubDiscoveredServiceReference(res["discoveredService"].(map[string]interface{})["serviceReference"], d, config)); err != nil { + return fmt.Errorf("Error setting service reference: %s", err) + } + + if err := d.Set("service_properties", flattenApphubDiscoveredServiceProperties(res["discoveredService"].(map[string]interface{})["serviceProperties"], d, config)); err != nil { + return fmt.Errorf("Error setting service properties: %s", err) + } + + d.SetId(res["discoveredService"].(map[string]interface{})["name"].(string)) + + return nil + +} + +func flattenApphubDiscoveredServiceReference(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["uri"] = flattenApphubDiscoveredServiceDataUri(original["uri"], d, config) + transformed["path"] = flattenApphubDiscoveredServiceDataPath(original["path"], d, config) + return []interface{}{transformed} +} + +func flattenApphubDiscoveredServiceProperties(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["gcp_project"] = flattenApphubDiscoveredServiceDataGcpProject(original["gcpProject"], d, config) + transformed["location"] = flattenApphubDiscoveredServiceDataLocation(original["location"], d, config) + transformed["zone"] = flattenApphubDiscoveredServiceDataZone(original["zone"], d, config) + return []interface{}{transformed} +} + +func flattenApphubDiscoveredServiceName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataPath(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataGcpProject(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredServiceDataZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service_test.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service_test.go new file mode 100644 index 000000000000..6aaeabd5b908 --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_service_test.go @@ -0,0 +1,128 @@ +package apphub_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 TestAccDataSourceApphubDiscoveredService_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testDataSourceApphubDiscoveredService_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_apphub_discovered_service.catalog-service", "name"), + ), + }, + }, + }) +} + +func testDataSourceApphubDiscoveredService_basic(context map[string]interface{}) string { + return acctest.Nprintf( + ` +resource "google_project" "service_project" { + project_id ="tf-test-ah-%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + location = "us-central1" + # ServiceReference | Application Hub | Google Cloud + # Using this reference means that this resource will not be provisioned until the forwarding rule is fully created + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "ilb-network-%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "ilb-subnet-%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name = "forwarding-rule-%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "backend-service-%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "health-check-%{random_suffix}" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown new file mode 100644 index 000000000000..272491b8d089 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown @@ -0,0 +1,52 @@ +--- +subcategory: "Apphub" +description: |- + Get information about a discovered service. +--- + +# google\_apphub\_discovered_service + +Get information about a discovered service from its uri. + + +## Example Usage + + +```hcl +data "google_apphub_discovered_service" "my-service" { + location = "my-location" + service_uri = "my-service-uri" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `project` - The host project of the discovered service. +* `service_uri` - (Required) The uri of the service. +* `location` - (Required) The location of the discovered service. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `name` - Resource name of a Service. Format: "projects/{host-project-id}/locations/{location}/applications/{application-id}/services/{service-id}". + +* `service_reference` - Reference to an underlying networking resource that can comprise a Service. Structure is [documented below](#nested_service_reference) + +A `service_reference` object would contain the following fields: + +* `uri` - The underlying resource URI. + +* `path` - Additional path under the resource URI. + +* `service_properties` - Properties of an underlying compute resource that can comprise a Service. Structure is [documented below](#nested_service_properties) + +A `service_properties` object would contain the following fields: + +* `gcp_project` - The service project identifier that the underlying cloud resource resides in. + +* `location` - The location that the underlying resource resides in. + +* `zone` - The location that the underlying resource resides in if it is zonal. \ No newline at end of file From dd27044950e3806f23f260a14c04eada189880a0 Mon Sep 17 00:00:00 2001 From: Antoni Zawodny Date: Tue, 12 Mar 2024 15:33:21 +0100 Subject: [PATCH 109/200] Graduate support of GKE Queued Provisioning to GA (#10053) --- .../services/container/resource_container_node_pool.go.erb | 6 ------ .../container/resource_container_node_pool_test.go.erb | 2 -- .../website/docs/r/container_node_pool.html.markdown | 2 +- 3 files changed, 1 insertion(+), 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 025ed420fdde..99126aceb3bf 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,7 +207,6 @@ var schemaNodePool = map[string]*schema.Schema{ }, }, -<% unless version == 'ga' -%> "queued_provisioning": { Type: schema.TypeList, Optional: true, @@ -225,7 +224,6 @@ var schemaNodePool = map[string]*schema.Schema{ }, }, }, -<% end -%> "max_pods_per_node": &schema.Schema{ Type: schema.TypeInt, @@ -988,7 +986,6 @@ 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{}) @@ -997,7 +994,6 @@ func expandNodePool(d *schema.ResourceData, prefix string) (*container.NodePool, } } } -<% end -%> if v, ok := d.GetOk(prefix + "max_pods_per_node"); ok { np.MaxPodsConstraint = &container.MaxPodsConstraint{ @@ -1192,7 +1188,6 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c } } -<% unless version == 'ga' -%> if np.QueuedProvisioning != nil { nodePool["queued_provisioning"] = []map[string]interface{}{ { @@ -1200,7 +1195,6 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c }, } } -<% 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 ec3e852d8ce6..ac04e9501c21 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 @@ -1950,7 +1950,6 @@ resource "google_container_node_pool" "np" { `, cluster, networkName, subnetworkName, policyName, np) } -<% unless version == 'ga' -%> func TestAccContainerNodePool_enableQueuedProvisioning(t *testing.T) { t.Parallel() @@ -2022,7 +2021,6 @@ resource "google_container_node_pool" "np" { } `, 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 3649ce923de7..cbe26898c6e3 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,7 +172,7 @@ cluster. * `placement_policy` - (Optional) Specifies a custom placement policy for the nodes. -* `queued_provisioning` - (Optional, Beta) Specifies node pool-level settings of queued provisioning. +* `queued_provisioning` - (Optional) 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): From b24ef479852be21f400329a60156c6e1b6b727f2 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Tue, 12 Mar 2024 14:53:39 +0000 Subject: [PATCH 110/200] Update index page of documentation to link to issue templates for Bugs and FRs (#10160) * Update index page of documentation to link to issue templates for Bugs and FRs * Remove unused param from URL * Remove other unused parameter from URL --- mmv1/third_party/terraform/website/docs/index.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/index.html.markdown b/mmv1/third_party/terraform/website/docs/index.html.markdown index fee57ac9c426..d240af80b2cc 100644 --- a/mmv1/third_party/terraform/website/docs/index.html.markdown +++ b/mmv1/third_party/terraform/website/docs/index.html.markdown @@ -91,9 +91,9 @@ experience for you using the Google provider. If you have a bug or feature request without an existing issue -* and an existing resource or field is working in an unexpected way, [file a bug](https://github.com/hashicorp/terraform-provider-google/issues/new?template=bug.md). +* and an existing resource or field is working in an unexpected way, [file a bug](https://github.com/hashicorp/terraform-provider-google/issues/new?labels=bug&template=00_bug.yml). -* and you'd like the provider to support a new resource or field, [file an enhancement/feature request](https://github.com/hashicorp/terraform-provider-google/issues/new?template=enhancement.md). +* and you'd like the provider to support a new resource or field, [file an enhancement/feature request](https://github.com/hashicorp/terraform-provider-google/issues/new?labels=enhancement&template=01_enhancement.yml). The provider maintainers will often use the assignee field on an issue to mark who is working on it. From a6ceb9e3c35210af4ecfaee801958eb7b79ac377 Mon Sep 17 00:00:00 2001 From: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> Date: Tue, 12 Mar 2024 22:36:36 +0530 Subject: [PATCH 111/200] Add data source for AppHub discovered workload (#10107) * Add data source for Apphub discovered workload * Add data source for Apphub discovered workload * Add data source for Apphub Discovered Workload * Resolved comments * Resolved comments * Resolved comments * Resolved comments * Add tests and documentation for data source discovered workload * Resolved comments and added tests * Resolved comments * Added modifications in tests, data source and documentation * Added modifications in tests, data source and documentation * Added modifications in tests, data source and documentation * Verified tests * Tests Verification * Tests Verification * Updated logic to obtain workload_uri * Updated logic to obtain workload_uri * Resolved comments * Resolved comments * Add billing account and shorten service project name * Add header * Change the project name to start with tf-test * Resolved comments * Lint changes * Removing two sleeps * Removing two sleeps * Modifying documentation * Resolved tests * Resolved comments * Resolved comments * logic modification * Update Retry logic * Update Retry logic * Resolved tests * Adding workload_uri description * Adding workload_uri description --- .../provider/provider_mmv1_resources.go.erb | 1 + .../data_source_apphub_discovered_workload.go | 162 ++++++++++++++++++ ..._source_apphub_discovered_workload_test.go | 145 ++++++++++++++++ .../apphub_discovered_workload.html.markdown | 50 ++++++ 4 files changed, 358 insertions(+) create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload.go create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.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 0b2bd157e154..cf84c8032b16 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -27,6 +27,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_alloydb_locations": alloydb.DataSourceAlloydbLocations(), "google_alloydb_supported_database_flags": alloydb.DataSourceAlloydbSupportedDatabaseFlags(), "google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(), + "google_apphub_discovered_workload": apphub.DataSourceApphubDiscoveredWorkload(), "google_app_engine_default_service_account": appengine.DataSourceGoogleAppEngineDefaultServiceAccount(), "google_apphub_discovered_service": apphub.DataSourceApphubDiscoveredService(), <% unless version == 'ga' -%> diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload.go new file mode 100644 index 000000000000..1221ddc2c71e --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload.go @@ -0,0 +1,162 @@ +package apphub + +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 DataSourceApphubDiscoveredWorkload() *schema.Resource { + return &schema.Resource{ + Read: dataSourceApphubDiscoveredWorkloadRead, + Schema: map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Optional: true, + }, + "location": { + Type: schema.TypeString, + Required: true, + }, + "workload_uri": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "workload_reference": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "workload_properties": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "gcp_project": { + Type: schema.TypeString, + Computed: true, + }, + "location": { + Type: schema.TypeString, + Computed: true, + }, + "zone": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceApphubDiscoveredWorkloadRead(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, fmt.Sprintf("{{ApphubBasePath}}projects/{{project}}/locations/{{location}}/discoveredWorkloads:lookup?uri={{workload_uri}}")) + 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, + }) + + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("ApphubDiscoveredWorkload %q", d.Id()), url) + } + + if err := d.Set("name", flattenApphubDiscoveredWorkloadName(res["discoveredWorkload"].(map[string]interface{})["name"], d, config)); err != nil { + return fmt.Errorf("Error setting workload name: %s", err) + } + + if err := d.Set("workload_reference", flattenApphubDiscoveredWorkloadReference(res["discoveredWorkload"].(map[string]interface{})["workloadReference"], d, config)); err != nil { + return fmt.Errorf("Error setting service reference: %s", err) + } + + if err := d.Set("workload_properties", flattenApphubDiscoveredWorkloadProperties(res["discoveredWorkload"].(map[string]interface{})["workloadProperties"], d, config)); err != nil { + return fmt.Errorf("Error setting workload properties: %s", err) + } + + d.SetId(res["discoveredWorkload"].(map[string]interface{})["name"].(string)) + + return nil + +} + +func flattenApphubDiscoveredWorkloadReference(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["uri"] = flattenApphubDiscoveredWorkloadDataUri(original["uri"], d, config) + return []interface{}{transformed} +} + +func flattenApphubDiscoveredWorkloadProperties(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["gcp_project"] = flattenApphubDiscoveredWorkloadDataGcpProject(original["gcpProject"], d, config) + transformed["location"] = flattenApphubDiscoveredWorkloadDataLocation(original["location"], d, config) + transformed["zone"] = flattenApphubDiscoveredWorkloadDataZone(original["zone"], d, config) + return []interface{}{transformed} +} + +func flattenApphubDiscoveredWorkloadName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredWorkloadDataUri(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredWorkloadDataGcpProject(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredWorkloadDataLocation(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenApphubDiscoveredWorkloadDataZone(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload_test.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload_test.go new file mode 100644 index 000000000000..c305079251a0 --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_discovered_workload_test.go @@ -0,0 +1,145 @@ +package apphub_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 TestAccDataSourceApphubDiscoveredWorkload_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testDataSourceApphubDiscoveredWorkload_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.google_apphub_discovered_workload.catalog-workload", "name"), + ), + }, + }, + }) +} + +func testDataSourceApphubDiscoveredWorkload_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_project" "service_project" { + project_id ="tf-test-ah-%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +data "google_apphub_discovered_workload" "catalog-workload" { + location = "us-central1" + workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "l7-ilb-network-%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "l7-ilb-subnetwork-%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_region_instance_group_manager.mig] + create_duration = "120s" +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "l7-ilb-mig-template-%{random_suffix}" + project = google_project.service_project.project_id + machine_type = "e2-small" + tags = ["http-server"] + network_interface { + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id + access_config { + # add external ip to fetch packages + } + } + disk { + source_image = "debian-cloud/debian-10" + auto_delete = true + boot = true + } + # install nginx and serve a simple web page + metadata = { + startup-script = <<-EOF1 + #! /bin/bash + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y nginx-light jq + NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") + IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") + METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') + cat < /var/www/html/index.html +
+      Name: $NAME
+      IP: $IP
+      Metadata: $METADATA
+      
+ EOF + EOF1 + } + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_region_instance_group_manager" "mig" { + name = "l7-ilb-mig1-%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown new file mode 100644 index 000000000000..d9fc574eaff0 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown @@ -0,0 +1,50 @@ +--- +subcategory: "Apphub" +description: |- + Get information about a discovered workload. +--- + +# google\_apphub\_discovered_workload + +Get information about a discovered workload from its uri. + + +## Example Usage + + +```hcl +data "google_apphub_discovered_workload" "my-workload" { + location = "us-central1" + workload_uri = "my-workload-uri" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `project` - The host project of the discovered workload. +* `workload_uri` - (Required) The uri of the workload (instance group managed by the Instance Group Manager). Example: "//compute.googleapis.com/projects/1/regions/us-east1/instanceGroups/id1" +* `location` - (Required) The location of the discovered workload. + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `name` - Resource name of a Workload. Format: "projects/{host-project-id}/locations/{location}/applications/{application-id}/workloads/{workload-id}". + +* `workload_reference` - Reference to an underlying networking resource that can comprise a Workload. Structure is [documented below](#nested_workload_reference) + +The `workload_reference` block supports: + +* `uri` - The underlying resource URI. + +* `workload_properties` - Properties of an underlying compute resource that can comprise a Workload. Structure is [documented below](#nested_workload_properties) + +The `workload_properties` block supports: + +* `gcp_project` - The service project identifier that the underlying cloud resource resides in. + +* `location` - The location that the underlying resource resides in. + +* `zone` - The location that the underlying resource resides in if it is zonal. From f72682f39d30f1eb3263acf8a6b4c3603ba4acdd Mon Sep 17 00:00:00 2001 From: Charles Leon Date: Tue, 12 Mar 2024 14:24:19 -0700 Subject: [PATCH 112/200] Update Documentation for ACM Service Perimeter resources to reflect Granular Controls group support (#10087) groups Co-authored-by: Charles Leon --- .../ServicePerimeter.yaml | 31 ++++++---- .../ServicePerimeterEgressPolicy.yaml | 4 +- .../ServicePerimeterIngressPolicy.yaml | 6 +- .../ServicePerimeters.yaml | 28 +++++---- ...service_perimeter_granular_controls.tf.erb | 59 +++++++++++++++++++ 5 files changed, 99 insertions(+), 29 deletions(-) create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_granular_controls.tf.erb diff --git a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml index b79c83c666cf..d6b02a13d48d 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeter.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeter.yaml @@ -71,6 +71,9 @@ examples: primary_resource_id: 'service-perimeter' vars: service_perimeter_name: 'restrict_bigquery_dryrun_storage' + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_granular_controls' + skip_test: true custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/access_level_never_send_parent.go.erb custom_import: templates/terraform/custom_import/set_access_policy_parent_from_self_link.go.erb @@ -240,9 +243,10 @@ properties: item_type: Api::Type::String is_set: true description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + 'A list of identities that are allowed access through this `IngressPolicy`. + To specify an identity or identity group, use the IAM v1 + format specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' - !ruby/object:Api::Type::Array name: 'sources' description: | @@ -364,9 +368,10 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + 'A list of identities that are allowed access through this `EgressPolicy`. + To specify an identity or identity group, use the IAM v1 + format specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::NestedObject @@ -528,9 +533,10 @@ properties: item_type: Api::Type::String is_set: true description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + 'A list of identities that are allowed access through this `IngressPolicy`. + To specify an identity or identity group, use the IAM v1 + format specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' - !ruby/object:Api::Type::Array name: 'sources' description: | @@ -652,9 +658,10 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + 'A list of identities that are allowed access through this `EgressPolicy`. + To specify an identity or identity group, use the IAM v1 + format specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' item_type: Api::Type::String is_set: true - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index 5e46e6770c0d..738ceefd98bd 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -76,8 +76,8 @@ properties: name: 'identities' description: | A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + Should be in the format of an email address. The email address should + represent an individual user, service account, or Google group. item_type: Api::Type::String - !ruby/object:Api::Type::Array name: 'sources' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 8e671e4096ee..195b87db9bfa 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -78,9 +78,9 @@ properties: name: 'identities' item_type: Api::Type::String description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + A list of identities that are allowed access through this `IngressPolicy`. + Should be in the format of an email address. The email address should represent + an individual user, service account, or Google group. - !ruby/object:Api::Type::Array name: 'sources' description: | diff --git a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml index 2b941289d41a..655c3545a2e6 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeters.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeters.yaml @@ -220,9 +220,10 @@ properties: is_set: true item_type: Api::Type::String description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + 'A list of identities that are allowed access through this `IngressPolicy`. + To specify an identity or identity group, use the IAM v1 format + specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' - !ruby/object:Api::Type::Array name: 'sources' description: | @@ -329,9 +330,10 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + 'A list of identities that are allowed access through this `EgressPolicy`. + To specify an identity or identity group, use the IAM v1 format + specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' is_set: true item_type: Api::Type::String - !ruby/object:Api::Type::Array @@ -514,9 +516,10 @@ properties: is_set: true item_type: Api::Type::String description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. + 'A list of identities that are allowed access through this `IngressPolicy`. + To specify an identity or identity group, use the IAM v1 format + specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' - !ruby/object:Api::Type::Array name: 'sources' description: | @@ -623,9 +626,10 @@ properties: - !ruby/object:Api::Type::Array name: 'identities' description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. + 'A list of identities that are allowed access through this `EgressPolicy`. + To specify an identity or identity group, use the IAM v1 format + specified [here](https://cloud.google.com/iam/docs/principal-identifiers.md#v1). + The following prefixes are supprted: user, group, serviceAccount, principal, and principalSet.' item_type: Api::Type::String is_set: true - !ruby/object:Api::Type::Array diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_granular_controls.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_granular_controls.tf.erb new file mode 100644 index 000000000000..728b3a87ca83 --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_granular_controls.tf.erb @@ -0,0 +1,59 @@ +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "Policy with Granular Controls Group Support" +} + +resource "google_access_context_manager_service_perimeter" "test-access" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" + title = "%s" + perimeter_type = "PERIMETER_TYPE_REGULAR" + status { + restricted_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + + vpc_accessible_services { + enable_restriction = true + allowed_services = ["bigquery.googleapis.com", "storage.googleapis.com"] + } + + ingress_policies { + ingress_from { + sources { + access_level = google_access_context_manager_access_level.test-access.name + } + identities = ["group:database-admins@google.com"] + identities = ["principal://iam.googleapis.com/locations/global/workforcePools/1234/subject/janedoe"] + identities = ["principalSet://iam.googleapis.com/locations/global/workforcePools/1234/*"] + } + + ingress_to { + resources = [ "*" ] + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + + egress_policies { + egress_from { + identities = ["group:database-admins@google.com"] + identities = ["principal://iam.googleapis.com/locations/global/workforcePools/1234/subject/janedoe"] + identities = ["principalSet://iam.googleapis.com/locations/global/workforcePools/1234/*"] + } + egress_to { + resources = [ "*" ] + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } + } +} From aba1d05f1ea4bd7e93a485044fa19870bd887ddd Mon Sep 17 00:00:00 2001 From: bcreddy-gcp <123543489+bcreddy-gcp@users.noreply.github.com> Date: Wed, 13 Mar 2024 03:51:15 +0530 Subject: [PATCH 113/200] fix tags cause notebooks instances to recreate (#10179) * add labels to runtime update test * Add labels to ImportStateVerifyIgnore * fix indentation * fix tags cause notebooks instances to create --- mmv1/products/notebooks/Instance.yaml | 1 + .../terraform/constants/notebooks_instance.go | 18 ++++++++++++++++-- .../examples/notebook_instance_full.tf.erb | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/mmv1/products/notebooks/Instance.yaml b/mmv1/products/notebooks/Instance.yaml index b5fb92b0c1b1..613c50d70fab 100644 --- a/mmv1/products/notebooks/Instance.yaml +++ b/mmv1/products/notebooks/Instance.yaml @@ -393,6 +393,7 @@ properties: The Compute Engine tags to add to instance. item_type: Api::Type::String default_from_api: true + diff_suppress_func: NotebooksInstanceTagsDiffSuppress - !ruby/object:Api::Type::KeyValuePairs name: 'metadata' description: | diff --git a/mmv1/templates/terraform/constants/notebooks_instance.go b/mmv1/templates/terraform/constants/notebooks_instance.go index 230d2aece282..b1c47a704ffa 100644 --- a/mmv1/templates/terraform/constants/notebooks_instance.go +++ b/mmv1/templates/terraform/constants/notebooks_instance.go @@ -3,8 +3,22 @@ var NotebooksInstanceProvidedScopes = []string{ "https://www.googleapis.com/auth/userinfo.email", } +var NotebooksInstanceProvidedTags = []string{ + "deeplearning-vm", + "notebook-instance", +} + func NotebooksInstanceScopesDiffSuppress(_, _, _ string, d *schema.ResourceData) bool { - old, new := d.GetChange("service_account_scopes") + return NotebooksDiffSuppressTemplate("service_account_scopes", NotebooksInstanceProvidedScopes, d) +} + +func NotebooksInstanceTagsDiffSuppress(_, _, _ string, d *schema.ResourceData) bool { + return NotebooksDiffSuppressTemplate("tags", NotebooksInstanceProvidedTags, d) +} + +func NotebooksDiffSuppressTemplate(field string, defaults []string, d *schema.ResourceData) bool { + old, new := d.GetChange(field) + oldValue := old.([]interface{}) newValue := new.([]interface{}) oldValueList := []string{} @@ -17,7 +31,7 @@ func NotebooksInstanceScopesDiffSuppress(_, _, _ string, d *schema.ResourceData) for _, item := range newValue { newValueList = append(newValueList,item.(string)) } - newValueList= append(newValueList,NotebooksInstanceProvidedScopes...) + newValueList= append(newValueList,defaults...) sort.Strings(oldValueList) sort.Strings(newValueList) diff --git a/mmv1/templates/terraform/examples/notebook_instance_full.tf.erb b/mmv1/templates/terraform/examples/notebook_instance_full.tf.erb index 31f2af55ca3c..31de347bb0c6 100644 --- a/mmv1/templates/terraform/examples/notebook_instance_full.tf.erb +++ b/mmv1/templates/terraform/examples/notebook_instance_full.tf.erb @@ -34,6 +34,9 @@ resource "google_notebooks_instance" "<%= ctx[:primary_resource_id] %>" { "https://www.googleapis.com/auth/cloud-platform", "https://www.googleapis.com/auth/userinfo.email" ] + + tags = ["foo", "bar"] + disk_encryption = "CMEK" kms_key = "<%= ctx[:vars]['key_name'] %>" desired_state = "ACTIVE" From 9779afc017103e7986c2458f5efc77deeb581c2e Mon Sep 17 00:00:00 2001 From: Andrew Grasso Date: Tue, 12 Mar 2024 18:22:53 -0400 Subject: [PATCH 114/200] Documentation Fix compute_security_policy (#9732) Fix mixed up descriptions between request_uri and request_query_param. --- .../website/docs/r/compute_security_policy.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown index 92d2b5ab5b4f..2cf421900b64 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_security_policy.html.markdown @@ -280,9 +280,9 @@ The following arguments are supported: * `request_cookie` - (Optional) Request cookie whose value will be excluded from inspection during preconfigured WAF evaluation. Structure is [documented below](#nested_field_params). -* `request_uri` - (Optional) Request query parameter whose value will be excluded from inspection during preconfigured WAF evaluation. Note that the parameter can be in the query string or in the POST body. Structure is [documented below](#nested_field_params). +* `request_uri` - (Optional) Request URI from the request line to be excluded from inspection during preconfigured WAF evaluation. When specifying this field, the query or fragment part should be excluded. Structure is [documented below](#nested_field_params). -* `request_query_param` - (Optional) Request URI from the request line to be excluded from inspection during preconfigured WAF evaluation. When specifying this field, the query or fragment part should be excluded. Structure is [documented below](#nested_field_params). +* `request_query_param` - (Optional) Request query parameter whose value will be excluded from inspection during preconfigured WAF evaluation. Note that the parameter can be in the query string or in the POST body. Structure is [documented below](#nested_field_params). * `target_rule_set` - (Required) Target WAF rule set to apply the preconfigured WAF exclusion. From ca62aed93eb3f92e915a5041fb0ab5c32ff99475 Mon Sep 17 00:00:00 2001 From: Esha Goel Date: Wed, 13 Mar 2024 04:43:38 +0530 Subject: [PATCH 115/200] Add new resource Workload for Apphub (#10155) * Add new resource Workload for Apphub * Fix lint error * Add billing account * Remove extra delay from test * Resolve comments * Add handwritten update test * Fix lint error * Add data source changes * Remove merged changes * Remove merged changes * Batch all update tests into one step to make test fast * Add a delay between discovered resource fetch and managed instance group manager creation * Add back org_id * Update region from us-east1 to us-central1 * Use standard diff suppress function --------- Co-authored-by: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> Co-authored-by: Krishnan Gopal --- mmv1/products/apphub/Workload.yaml | 228 ++++++++++++++++++ .../examples/apphub_workload_basic.tf.erb | 126 ++++++++++ .../examples/apphub_workload_full.tf.erb | 147 +++++++++++ .../apphub/resource_apphub_workload_test.go | 180 ++++++++++++++ 4 files changed, 681 insertions(+) create mode 100644 mmv1/products/apphub/Workload.yaml create mode 100644 mmv1/templates/terraform/examples/apphub_workload_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/apphub_workload_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/apphub/resource_apphub_workload_test.go diff --git a/mmv1/products/apphub/Workload.yaml b/mmv1/products/apphub/Workload.yaml new file mode 100644 index 000000000000..b0c3466bb2d9 --- /dev/null +++ b/mmv1/products/apphub/Workload.yaml @@ -0,0 +1,228 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +base_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads +create_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads?workloadId={{workload_id}} +self_link: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads/{{workload_id}} +id_format: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads/{{workload_id}} +import_format: + - projects/{{project}}/locations/{{location}}/applications/{{application_id}}/workloads/{{workload_id}} +name: Workload +description: 'Workload represents a binary deployment (such as Managed Instance Groups (MIGs), GKE deployments, etc.) that performs the smallest logical subset of business functionality. + It registers identified workload to the Application.' +autogen_async: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "apphub_workload_basic" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + instance_template: "l7-ilb-mig-template" + mig: "l7-ilb-mig1" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT + - !ruby/object:Provider::Terraform::Examples + name: "apphub_workload_full" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + display_name: "Example Service Full" + description: "Register service for testing" + business_name: "Alice" + business_email: "alice@google.com" + developer_name: "Bob" + developer_email: "bob@google.com" + operator_name: "Charlie" + operator_email: "charlie@google.com" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + instance_template: "l7-ilb-mig-template" + mig: "l7-ilb-mig1" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT +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 +update_verb: :PATCH +update_mask: true +parameters: + - !ruby/object:Api::Type::String + name: location + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID} ' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: applicationId + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID}' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: workloadId + description: 'The Workload identifier. ' + url_param_only: true + required: true + immutable: true +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: "Identifier. The resource name of the Workload. Format:\"projects/{host-project-id}/locations/{location}/applications/{application-id}/workloads/{workload-id}\" " + - !ruby/object:Api::Type::String + name: displayName + description: 'User-defined name for the Workload. ' + - !ruby/object:Api::Type::String + name: description + description: 'User-defined description of a Workload. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: uri + description: 'Output only. The underlying compute resource uri. ' + output: true + output: true + name: workloadReference + description: 'Reference of an underlying compute resource represented by the Workload. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: gcpProject + description: "Output only. The service project identifier that the underlying + cloud resource resides in. Empty for non cloud resources. " + output: true + - !ruby/object:Api::Type::String + name: location + description: "Output only. The location that the underlying compute resource resides + in (e.g us-west1). " + output: true + - !ruby/object:Api::Type::String + name: zone + description: "Output only. The location that the underlying compute resource resides + in if it is zonal (e.g us-west1-a). " + output: true + output: true + name: workloadProperties + description: 'Properties of an underlying compute resource represented by the Workload. ' + - !ruby/object:Api::Type::String + name: discoveredWorkload + diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' + description: 'Immutable. The resource name of the original discovered workload. ' + required: true + immutable: true + - !ruby/object:Api::Type::NestedObject + name: attributes + description: 'Consumer provided attributes. ' + properties: + - !ruby/object:Api::Type::NestedObject + name: criticality + description: 'Criticality of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Criticality type. ' + required: true + values: + - :MISSION_CRITICAL + - :HIGH + - :MEDIUM + - :LOW + - !ruby/object:Api::Type::NestedObject + name: environment + description: 'Environment of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Environment type. ' + required: true + values: + - :PRODUCTION + - :STAGING + - :TEST + - :DEVELOPMENT + - !ruby/object:Api::Type::Array + name: developerOwners + description: 'Developer team that owns development and coding. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: operatorOwners + description: 'Operator team that ensures runtime and operations. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: businessOwners + description: 'Business team that ensures user needs are met and value is delivered ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::String + name: createTime + description: 'Output only. Create time. ' + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: 'Output only. Update time. ' + output: true + - !ruby/object:Api::Type::String + name: uid + description: "Output only. A universally unique identifier (UUID) for the `Workload` in the UUID4 format. " + output: true + - !ruby/object:Api::Type::String + name: state + description: "Output only. Workload state. Possible values: STATE_UNSPECIFIED CREATING ACTIVE DELETING DETACHED" + output: true diff --git a/mmv1/templates/terraform/examples/apphub_workload_basic.tf.erb b/mmv1/templates/terraform/examples/apphub_workload_basic.tf.erb new file mode 100644 index 000000000000..0c9a57b3ce94 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_workload_basic.tf.erb @@ -0,0 +1,126 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + + +# Discovered workload +data "google_apphub_discovered_workload" "catalog-workload" { + location = "us-central1" + workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_region_instance_group_manager.mig] + create_duration = "120s" +} + +resource "google_apphub_workload" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + workload_id = google_compute_region_instance_group_manager.mig.name + discovered_workload = data.google_apphub_discovered_workload.catalog-workload.name +} + +#Workload creation + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "<%= ctx[:vars]['instance_template'] %>" + project = google_project.service_project.project_id + machine_type = "e2-small" + tags = ["http-server"] + network_interface { + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id + access_config { + # add external ip to fetch packages + } + } + disk { + source_image = "debian-cloud/debian-10" + auto_delete = true + boot = true + } + # install nginx and serve a simple web page + metadata = { + startup-script = <<-EOF1 + #! /bin/bash + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y nginx-light jq + NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") + IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") + METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') + cat < /var/www/html/index.html +
+      Name: $NAME
+      IP: $IP
+      Metadata: $METADATA
+      
+ EOF + EOF1 + } + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_region_instance_group_manager" "mig" { + name = "<%= ctx[:vars]['mig'] %>" + project = google_project.service_project.project_id + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/apphub_workload_full.tf.erb b/mmv1/templates/terraform/examples/apphub_workload_full.tf.erb new file mode 100644 index 000000000000..a81dd6326175 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_workload_full.tf.erb @@ -0,0 +1,147 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# Discovered workload +data "google_apphub_discovered_workload" "catalog-workload" { + location = "us-central1" + workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_region_instance_group_manager.mig] + create_duration = "120s" +} + +resource "google_apphub_workload" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + workload_id = google_compute_region_instance_group_manager.mig.name + discovered_workload = data.google_apphub_discovered_workload.catalog-workload.name + display_name = "<%= ctx[:vars]['display_name'] %>" + description = "<%= ctx[:vars]['description'] %>" + attributes { + environment { + type = "STAGING" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "<%= ctx[:vars]['business_name'] %>" + email = "<%= ctx[:vars]['business_email'] %>" + } + developer_owners { + display_name = "<%= ctx[:vars]['developer_name'] %>" + email = "<%= ctx[:vars]['developer_email'] %>" + } + operator_owners { + display_name = "<%= ctx[:vars]['operator_name'] %>" + email = "<%= ctx[:vars]['operator_email'] %>" + } + } +} + +#Workload creation + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "<%= ctx[:vars]['instance_template'] %>" + project = google_project.service_project.project_id + machine_type = "e2-small" + tags = ["http-server"] + network_interface { + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id + access_config { + # add external ip to fetch packages + } + } + disk { + source_image = "debian-cloud/debian-10" + auto_delete = true + boot = true + } + # install nginx and serve a simple web page + metadata = { + startup-script = <<-EOF1 + #! /bin/bash + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y nginx-light jq + NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") + IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") + METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') + cat < /var/www/html/index.html +
+      Name: $NAME
+      IP: $IP
+      Metadata: $METADATA
+      
+ EOF + EOF1 + } + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_region_instance_group_manager" "mig" { + name = "<%= ctx[:vars]['mig'] %>" + project = google_project.service_project.project_id + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/apphub/resource_apphub_workload_test.go b/mmv1/third_party/terraform/services/apphub/resource_apphub_workload_test.go new file mode 100644 index 000000000000..2897307d1a93 --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/resource_apphub_workload_test.go @@ -0,0 +1,180 @@ +package apphub_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 TestAccApphubWorkload_apphubWorkloadUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + CheckDestroy: testAccCheckApphubWorkloadDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApphubWorkload_apphubWorkloadFullExample(context), + }, + { + ResourceName: "google_apphub_workload.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "workload_id"}, + }, + { + Config: testAccApphubWorkload_apphubWorkloadUpdate(context), + }, + { + ResourceName: "google_apphub_workload.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "workload_id"}, + }, + }, + }) +} + +func testAccApphubWorkload_apphubWorkloadUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "tf-test-example-application-1%{random_suffix}" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="tf-test-project-1%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# Discovered workload +data "google_apphub_discovered_workload" "catalog-workload" { + location = "us-central1" + workload_uri = "${replace(google_compute_region_instance_group_manager.mig.instance_group, "https://www.googleapis.com/compute/v1", "//compute.googleapis.com")}" + depends_on = [time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_region_instance_group_manager.mig] + create_duration = "120s" +} + +resource "google_apphub_workload" "example" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + workload_id = google_compute_region_instance_group_manager.mig.name + discovered_workload = data.google_apphub_discovered_workload.catalog-workload.name +} + +#Workload creation + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "tf-test-l7-ilb-network%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "tf-test-l7-ilb-subnet%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "tf-test-l7-ilb-mig-template%{random_suffix}" + project = google_project.service_project.project_id + machine_type = "e2-small" + tags = ["http-server"] + network_interface { + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id + access_config { + # add external ip to fetch packages + } + } + disk { + source_image = "debian-cloud/debian-10" + auto_delete = true + boot = true + } + # install nginx and serve a simple web page + metadata = { + startup-script = <<-EOF1 + #! /bin/bash + set -euo pipefail + export DEBIAN_FRONTEND=noninteractive + apt-get update + apt-get install -y nginx-light jq + NAME=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname") + IP=$(curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip") + METADATA=$(curl -f -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=True" | jq 'del(.["startup-script"])') + cat < /var/www/html/index.html +
+      Name: $NAME
+      IP: $IP
+      Metadata: $METADATA
+      
+ EOF + EOF1 + } + lifecycle { + create_before_destroy = true + } +} + +resource "google_compute_region_instance_group_manager" "mig" { + name = "tf-test-l7-ilb-mig1%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} +`, context) +} From 8bd772e43e95185514d5e325a93f6d499ddc5b5d Mon Sep 17 00:00:00 2001 From: shijeesh-ns <92889532+shijeesh-ns@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:23:16 -0700 Subject: [PATCH 116/200] Fix for PrivateNat test failures (#10174) --- .../services/compute/resource_compute_router_nat_test.go.erb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_router_nat_test.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_router_nat_test.go.erb index b1c17157506f..7436c9ccfa45 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_router_nat_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_router_nat_test.go.erb @@ -1679,6 +1679,9 @@ resource "google_compute_router" "foobar" { name = "%s" region = google_compute_subnetwork.subnet1.region network = google_compute_network.foobar.self_link + depends_on = [ + google_network_connectivity_spoke.primary + ] } `, routerName, routerName, routerName, routerName, routerName, hubName, routerName, routerName) } @@ -1793,4 +1796,4 @@ resource "google_compute_router_nat" "foobar" { `, testAccComputeRouterNatBaseResourcesWithPrivateNatSubnetworks(routerName, hubName), routerName, ruleNumber, ruleDescription, match) } -<% end -%> \ No newline at end of file +<% end -%> From 4fa7f7c5c43d93b9813acd33ecf232f6cd6151ed Mon Sep 17 00:00:00 2001 From: Esha Goel Date: Wed, 13 Mar 2024 04:53:57 +0530 Subject: [PATCH 117/200] Add new resource Service for Apphub (#10132) * Add new resource for Service Project for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Add new resource for Application for Apphub * Add new resource for Application for Apphub * Enable Apphub API in test cases * Add new resource for Service Project Attachment for Apphub FIXES https://github.com/hashicorp/terraform-provider-google/issues/17405 * Enable apphub API in test cases * Fix precheck error * Fix precheck error * Fix precheck error * Fix precheck error * Resolve comments * Fix lint error * Fix errors * Add new resource for Service for Apphub * Fix examples * Add test * Fix tests * Add IAM permissions * Add IAM permission * Fix IAM issues * Remove merged changes * Add billing account * Remove extra delay from tests * Add handwritten update test * Remove merged changes * Make changes to yaml file incorporating comments from https://github.com/GoogleCloudPlatform/magic-modules/pull/10155 * Fix lint errors in Service YAML definition * Add a delay between discovered resource fetch and forwarding rule creation * Add a delay between discovered resource fetch and forwarding rule creation * Add a delay between discovered resource fetch and forwarding rule creation * Batch update tests to improve speed * Use standard diff suppress function * Update region from us-east1 to us-central1 --------- Co-authored-by: Krishnan Gopal Co-authored-by: praseedhaPK <161299686+praseedhaPK@users.noreply.github.com> --- mmv1/products/apphub/Service.yaml | 235 ++++++++++++++++++ .../examples/apphub_service_basic.tf.erb | 110 ++++++++ .../examples/apphub_service_full.tf.erb | 132 ++++++++++ .../apphub/resource_apphub_service_test.go | 163 ++++++++++++ 4 files changed, 640 insertions(+) create mode 100644 mmv1/products/apphub/Service.yaml create mode 100644 mmv1/templates/terraform/examples/apphub_service_basic.tf.erb create mode 100644 mmv1/templates/terraform/examples/apphub_service_full.tf.erb create mode 100644 mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go diff --git a/mmv1/products/apphub/Service.yaml b/mmv1/products/apphub/Service.yaml new file mode 100644 index 000000000000..7558666e9582 --- /dev/null +++ b/mmv1/products/apphub/Service.yaml @@ -0,0 +1,235 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +base_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services +create_url: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services?serviceId={{service_id}} +self_link: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +id_format: projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +import_format: + - projects/{{project}}/locations/{{location}}/applications/{{application_id}}/services/{{service_id}} +name: Service +description: 'Service is a network/api interface that exposes some functionality to clients for consumption over the network. + Service typically has one or more Workloads behind it. It registers identified service to the Application.' +autogen_async: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "apphub_service_basic" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + forwarding_rule: "l7-ilb-forwarding-rule" + backend_service: "l7-ilb-backend-subnet" + health_check: "l7-ilb-hc" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT + - !ruby/object:Provider::Terraform::Examples + name: "apphub_service_full" + pull_external: true + primary_resource_id: "example" + vars: + application_id: "example-application-1" + service_project_attachment_id: "project-1" + display_name: "Example Service Full" + description: "Register service for testing" + business_name: "Alice" + business_email: "alice@google.com" + developer_name: "Bob" + developer_email: "bob@google.com" + operator_name: "Charlie" + operator_email: "charlie@google.com" + ilb_network: "l7-ilb-network" + ilb_subnet: "l7-ilb-subnet" + forwarding_rule: "l7-ilb-forwarding-rule" + backend_service: "l7-ilb-backend-subnet" + health_check: "l7-ilb-hc" + test_env_vars: + org_id: :ORG_ID + billing_account: :BILLING_ACCT +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 +update_verb: :PATCH +update_mask: true +parameters: + - !ruby/object:Api::Type::String + name: location + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID} ' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: applicationId + description: 'Part of `parent`. Full resource name of a parent Application. Example: projects/{HOST_PROJECT_ID}/locations/{LOCATION}/applications/{APPLICATION_ID}' + url_param_only: true + required: true + immutable: true + - !ruby/object:Api::Type::String + name: serviceId + description: 'The Service identifier. ' + url_param_only: true + required: true + immutable: true +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: "Identifier. The resource name of a Service. Format:\n\"projects/{host-project-id}/locations/{location}/applications/{application-id}/services/{service-id}\" " + - !ruby/object:Api::Type::String + name: displayName + description: 'User-defined name for the Service. ' + - !ruby/object:Api::Type::String + name: description + description: 'User-defined description of a Service. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: uri + description: "Output only. The underlying resource URI (For example, URI of Forwarding + Rule, URL Map,\nand Backend Service). " + output: true + output: true + name: serviceReference + description: 'Reference to an underlying networking resource that can comprise a + Service. ' + - !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: gcpProject + description: "Output only. The service project identifier that the underlying + cloud resource resides in. " + output: true + - !ruby/object:Api::Type::String + name: location + description: "Output only. The location that the underlying resource resides in, + for example, us-west1. " + output: true + - !ruby/object:Api::Type::String + name: zone + description: "Output only. The location that the underlying resource resides in + if it is zonal, for example, us-west1-a). " + output: true + output: true + name: serviceProperties + description: 'Properties of an underlying cloud resource that can comprise a Service. ' + - !ruby/object:Api::Type::NestedObject + name: attributes + description: 'Consumer provided attributes. ' + properties: + - !ruby/object:Api::Type::NestedObject + name: criticality + description: 'Criticality of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Criticality type. ' + required: true + values: + - :MISSION_CRITICAL + - :HIGH + - :MEDIUM + - :LOW + - !ruby/object:Api::Type::NestedObject + name: environment + description: 'Environment of the Application, Service, or Workload ' + properties: + - !ruby/object:Api::Type::Enum + name: type + description: 'Environment type. ' + required: true + values: + - :PRODUCTION + - :STAGING + - :TEST + - :DEVELOPMENT + - !ruby/object:Api::Type::Array + name: developerOwners + description: 'Developer team that owns development and coding. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: operatorOwners + description: 'Operator team that ensures runtime and operations. ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::Array + name: businessOwners + description: 'Business team that ensures user needs are met and value + is delivered ' + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: displayName + description: 'Contact''s name. ' + - !ruby/object:Api::Type::String + name: email + description: 'Required. Email address of the contacts. ' + required: true + - !ruby/object:Api::Type::String + name: discoveredService + diff_suppress_func: 'tpgresource.ProjectNumberDiffSuppress' + description: 'Immutable. The resource name of the original discovered + service. ' + required: true + immutable: true + - !ruby/object:Api::Type::String + name: createTime + description: 'Output only. Create time. ' + output: true + - !ruby/object:Api::Type::String + name: updateTime + description: 'Output only. Update time. ' + output: true + - !ruby/object:Api::Type::String + name: uid + description: "Output only. A universally unique identifier (UUID) for the `Service` + in the UUID4\nformat. " + output: true + - !ruby/object:Api::Type::String + name: state + description: "Output only. Service state. Possible values: STATE_UNSPECIFIED CREATING ACTIVE DELETING DETACHED" + output: true diff --git a/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb b/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb new file mode 100644 index 000000000000..f62288859da8 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_service_basic.tf.erb @@ -0,0 +1,110 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="<%= ctx[:vars]['forwarding_rule'] %>" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "<%= ctx[:vars]['backend_service'] %>" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "<%= ctx[:vars]['health_check'] %>" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} + + diff --git a/mmv1/templates/terraform/examples/apphub_service_full.tf.erb b/mmv1/templates/terraform/examples/apphub_service_full.tf.erb new file mode 100644 index 000000000000..2a0bdde9ed19 --- /dev/null +++ b/mmv1/templates/terraform/examples/apphub_service_full.tf.erb @@ -0,0 +1,132 @@ +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "<%= ctx[:vars]['application_id'] %>" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="<%= ctx[:vars]['service_project_attachment_id'] %>" + name = "Service Project" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name + display_name = "<%= ctx[:vars]['display_name'] %>" + description = "<%= ctx[:vars]['description'] %>" + attributes { + environment { + type = "STAGING" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "<%= ctx[:vars]['business_name'] %>" + email = "<%= ctx[:vars]['business_email'] %>" + } + developer_owners { + display_name = "<%= ctx[:vars]['developer_name'] %>" + email = "<%= ctx[:vars]['developer_email'] %>" + } + operator_owners { + display_name = "<%= ctx[:vars]['operator_name'] %>" + email = "<%= ctx[:vars]['operator_email'] %>" + } + } +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "<%= ctx[:vars]['ilb_network'] %>" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "<%= ctx[:vars]['ilb_subnet'] %>" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="<%= ctx[:vars]['forwarding_rule'] %>" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "<%= ctx[:vars]['backend_service'] %>" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "<%= ctx[:vars]['health_check'] %>" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} + + diff --git a/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go b/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go new file mode 100644 index 000000000000..0ea290f3992e --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/resource_apphub_service_test.go @@ -0,0 +1,163 @@ +package apphub_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 TestAccApphubService_serviceUpdate(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + CheckDestroy: testAccCheckApphubServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccApphubService_apphubServiceFullExample(context), + }, + { + ResourceName: "google_apphub_service.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "service_id"}, + }, + { + Config: testAccApphubService_apphubServiceUpdate(context), + }, + { + ResourceName: "google_apphub_service.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "application_id", "service_id"}, + }, + }, + }) +} + +func testAccApphubService_apphubServiceUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_apphub_application" "application" { + location = "us-central1" + application_id = "tf-test-example-application-1%{random_suffix}" + scope { + type = "REGIONAL" + } +} + +resource "google_project" "service_project" { + project_id ="tf-test-project-1%{random_suffix}" + name = "Service Project" + org_id = "%{org_id}" + billing_account = "%{billing_account}" +} + +# Enable Compute API +resource "google_project_service" "compute_service_project" { + project = google_project.service_project.project_id + service = "compute.googleapis.com" +} + +resource "time_sleep" "wait_120s" { + depends_on = [google_project_service.compute_service_project] + + create_duration = "120s" +} + +resource "google_apphub_service_project_attachment" "service_project_attachment" { + service_project_attachment_id = google_project.service_project.project_id + depends_on = [time_sleep.wait_120s] +} + +# discovered service block +data "google_apphub_discovered_service" "catalog-service" { + provider = google + location = "us-central1" + service_uri = "//compute.googleapis.com/${google_compute_forwarding_rule.forwarding_rule.id}" + depends_on = [google_apphub_service_project_attachment.service_project_attachment, time_sleep.wait_120s_for_resource_ingestion] +} + +resource "time_sleep" "wait_120s_for_resource_ingestion" { + depends_on = [google_compute_forwarding_rule.forwarding_rule] + create_duration = "120s" +} + +resource "google_apphub_service" "example" { + location = "us-central1" + application_id = google_apphub_application.application.application_id + service_id = google_compute_forwarding_rule.forwarding_rule.name + discovered_service = data.google_apphub_discovered_service.catalog-service.name +} + + +#creates service + + +# VPC network +resource "google_compute_network" "ilb_network" { + name = "tf-test-l7-ilb-network%{random_suffix}" + project = google_project.service_project.project_id + auto_create_subnetworks = false + depends_on = [time_sleep.wait_120s] +} + + +# backend subnet +resource "google_compute_subnetwork" "ilb_subnet" { + name = "tf-test-l7-ilb-subnet%{random_suffix}" + project = google_project.service_project.project_id + ip_cidr_range = "10.0.1.0/24" + region = "us-central1" + network = google_compute_network.ilb_network.id +} + +# forwarding rule +resource "google_compute_forwarding_rule" "forwarding_rule" { + name ="tf-test-l7-ilb-forwarding-rule%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + ip_version = "IPV4" + load_balancing_scheme = "INTERNAL" + all_ports = true + backend_service = google_compute_region_backend_service.backend.id + network = google_compute_network.ilb_network.id + subnetwork = google_compute_subnetwork.ilb_subnet.id +} + + + +# backend service +resource "google_compute_region_backend_service" "backend" { + name = "tf-test-l7-ilb-backend-subnet%{random_suffix}" + project = google_project.service_project.project_id + region = "us-central1" + health_checks = [google_compute_health_check.default.id] +} + +# health check +resource "google_compute_health_check" "default" { + name = "tf-test-l7-ilb-hc%{random_suffix}" + project = google_project.service_project.project_id + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } + depends_on = [time_sleep.wait_120s] +} +`, context) +} From 4555c3364bb74d340fb13db281fc79bd8f862249 Mon Sep 17 00:00:00 2001 From: kumailkermalli-datatonic <108349674+kumailkermalli-datatonic@users.noreply.github.com> Date: Tue, 12 Mar 2024 23:33:51 +0000 Subject: [PATCH 118/200] feat: add credentials_secret field in azure blob storage block for google storage transfer job resource (#9278) * feat: add `credentials_secret` in `azure_blob_storage_data` source config * feat: add version guard for `credentials_secret` as in preview * docs: add documentation on `credentials_secret` --- ...o => resource_storage_transfer_job.go.erb} | 53 +++++++++++++++---- .../docs/r/storage_transfer_job.html.markdown | 4 +- 2 files changed, 45 insertions(+), 12 deletions(-) rename mmv1/third_party/terraform/services/storagetransfer/{resource_storage_transfer_job.go => resource_storage_transfer_job.go.erb} (96%) diff --git a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go.erb similarity index 96% rename from mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go rename to mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go.erb index 148ab8c0af82..0a955d9f11b3 100644 --- a/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go +++ b/mmv1/third_party/terraform/services/storagetransfer/resource_storage_transfer_job.go.erb @@ -1,3 +1,4 @@ +<% autogen_exception -%> package storagetransfer import ( @@ -50,6 +51,12 @@ var ( "transfer_spec.0.aws_s3_data_source.0.aws_access_key", "transfer_spec.0.aws_s3_data_source.0.role_arn", } + <% unless version == 'ga' -%> + azureOptionCredentials = []string{ + "transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials", + "transfer_spec.0.azure_blob_storage_data_source.0.credentials_secret", + } + <% end -%> ) func ResourceStorageTransferJob() *schema.Resource { @@ -559,9 +566,14 @@ func azureBlobStorageDataSchema() *schema.Resource { Description: `Root path to transfer objects. Must be an empty string or full path name that ends with a '/'. This field is treated as an object prefix. As such, it should generally not begin with a '/'.`, }, "azure_credentials": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, + Type: schema.TypeList, + <% unless version == 'ga' -%> + Optional: true, + ExactlyOneOf: azureOptionCredentials, + <% else -%> + Required: true, + <% end -%> + MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "sas_token": { @@ -574,6 +586,14 @@ func azureBlobStorageDataSchema() *schema.Resource { }, Description: ` Credentials used to authenticate API requests to Azure.`, }, + <% unless version == 'ga' -%> + "credentials_secret": { + Optional: true, + Type: schema.TypeString, + Description: `The Resource name of a secret in Secret Manager containing SAS Credentials in JSON form. Service Agent must have permissions to access secret. If credentials_secret is specified, do not specify azure_credentials.`, + ExactlyOneOf: azureOptionCredentials, + }, + <% end -%> }, } } @@ -1099,6 +1119,11 @@ func expandAzureCredentials(azureCredentials []interface{}) *storagetransfer.Azu } func flattenAzureCredentials(d *schema.ResourceData) []map[string]interface{} { + <% unless version == 'ga' -%> + if d.Get("transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials.0.sas_token") == "" { + return []map[string]interface{}{} + } + <% end -%> data := map[string]interface{}{ "sas_token": d.Get("transfer_spec.0.azure_blob_storage_data_source.0.azure_credentials.0.sas_token"), } @@ -1114,19 +1139,25 @@ func expandAzureBlobStorageData(azureBlobStorageDatas []interface{}) *storagetra azureBlobStorageData := azureBlobStorageDatas[0].(map[string]interface{}) return &storagetransfer.AzureBlobStorageData{ - Container: azureBlobStorageData["container"].(string), - Path: azureBlobStorageData["path"].(string), - StorageAccount: azureBlobStorageData["storage_account"].(string), - AzureCredentials: expandAzureCredentials(azureBlobStorageData["azure_credentials"].([]interface{})), + Container: azureBlobStorageData["container"].(string), + Path: azureBlobStorageData["path"].(string), + StorageAccount: azureBlobStorageData["storage_account"].(string), + AzureCredentials: expandAzureCredentials(azureBlobStorageData["azure_credentials"].([]interface{})), + <% unless version == 'ga' -%> + CredentialsSecret: azureBlobStorageData["credentials_secret"].(string), + <% end -%> } } func flattenAzureBlobStorageData(azureBlobStorageData *storagetransfer.AzureBlobStorageData, d *schema.ResourceData) []map[string]interface{} { data := map[string]interface{}{ - "container": azureBlobStorageData.Container, - "path": azureBlobStorageData.Path, - "storage_account": azureBlobStorageData.StorageAccount, - "azure_credentials": flattenAzureCredentials(d), + "container": azureBlobStorageData.Container, + "path": azureBlobStorageData.Path, + "storage_account": azureBlobStorageData.StorageAccount, + "azure_credentials": flattenAzureCredentials(d), + <% unless version == 'ga' -%> + "credentials_secret": azureBlobStorageData.CredentialsSecret, + <% end -%> } return []map[string]interface{}{data} diff --git a/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown b/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown index c354672672d2..2f2d4ecb5d83 100644 --- a/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/storage_transfer_job.html.markdown @@ -247,7 +247,9 @@ The `aws_access_key` block supports: * `path` - (Required) Root path to transfer objects. Must be an empty string or full path name that ends with a '/'. This field is treated as an object prefix. As such, it should generally not begin with a '/'. -* `azure_credentials` - (Required) Credentials used to authenticate API requests to Azure block. +* `credentials_secret` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Full Resource name of a secret in Secret Manager containing [SAS Credentials in JSON form](https://cloud.google.com/storage-transfer/docs/reference/rest/v1/TransferSpec#azureblobstoragedata:~:text=begin%20with%20a%20%27/%27.-,credentialsSecret,-string). Service Agent for Storage Transfer must have permissions to access secret. If credentials_secret is specified, do not specify azure_credentials.`, + +* `azure_credentials` - (Required in GA, Optional in [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Credentials used to authenticate API requests to Azure block. The `azure_credentials` block supports: From e3a06e371bbcd7ccd50dd832b96f4108d27d97bc Mon Sep 17 00:00:00 2001 From: Xuran Liu Date: Tue, 12 Mar 2024 17:03:36 -0700 Subject: [PATCH 119/200] Added CloudQuotas service and Create QuotaInfo Datasource (#10071) * add quota info data source * add test and documention for quota_info data source * fix lint error * clean up * update test * manually import cloudquotas to terraform provider * Update mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb Co-authored-by: Riley Karson * Update mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb Co-authored-by: Riley Karson --------- Co-authored-by: Riley Karson --- mmv1/products/cloudquotas/product.yaml | 22 ++ .../components/inputs/services_beta.kt | 7 +- .../components/inputs/services_ga.kt | 7 +- .../provider/provider_mmv1_resources.go.erb | 4 + ...a_source_google_cloud_quotas_quota_info.go | 247 ++++++++++++++++++ ...rce_google_cloud_quotas_quota_info_test.go | 61 +++++ .../d/cloud_quotas_quota_info.html.markdown | 61 +++++ 7 files changed, 407 insertions(+), 2 deletions(-) create mode 100644 mmv1/products/cloudquotas/product.yaml create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info.go create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown diff --git a/mmv1/products/cloudquotas/product.yaml b/mmv1/products/cloudquotas/product.yaml new file mode 100644 index 000000000000..53c82344b0d2 --- /dev/null +++ b/mmv1/products/cloudquotas/product.yaml @@ -0,0 +1,22 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +name: CloudQuotas +display_name: Cloud Quotas +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://cloudquotas.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index 443987885a6f..e8beb038983d 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -178,6 +178,11 @@ var ServicesListBeta = mapOf( "displayName" to "Cloudids", "path" to "./google-beta/services/cloudids" ), + "cloudquotas" to mapOf( + "name" to "cloudquotas", + "displayName" to "Cloudquotas", + "path" to "./google-beta/services/cloudquotas" + ), "cloudrun" to mapOf( "name" to "cloudrun", "displayName" to "Cloudrun", @@ -693,4 +698,4 @@ var ServicesListBeta = mapOf( "displayName" to "Workstations", "path" to "./google-beta/services/workstations" ) -) \ No newline at end of file +) diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index 08ce6c2ee82f..071ea16ec879 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -178,6 +178,11 @@ var ServicesListGa = mapOf( "displayName" to "Cloudids", "path" to "./google/services/cloudids" ), + "cloudquotas" to mapOf( + "name" to "cloudquotas", + "displayName" to "Cloudquotas", + "path" to "./google/services/cloudquotas" + ), "cloudrun" to mapOf( "name" to "cloudrun", "displayName" to "Cloudrun", @@ -688,4 +693,4 @@ var ServicesListGa = mapOf( "displayName" to "Workstations", "path" to "./google/services/workstations" ) -) \ 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 cf84c8032b16..f58f2b57e660 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -15,6 +15,9 @@ import ( "github.com/hashicorp/terraform-provider-google/google/services/dataflow" "github.com/hashicorp/terraform-provider-google/google/services/servicenetworking" "github.com/hashicorp/terraform-provider-google/google/tpgiamresource" + <% if version == 'ga' -%> // https://github.com/hashicorp/terraform-provider-google/issues/15633 for details + "github.com/hashicorp/terraform-provider-google/google/services/cloudquotas" + <% end -%> ) // Datasources @@ -49,6 +52,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_cloud_identity_groups": cloudidentity.DataSourceGoogleCloudIdentityGroups(), "google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(), "google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(), + "google_cloud_quotas_quota_info": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfo(), "google_cloud_run_locations": cloudrun.DataSourceGoogleCloudRunLocations(), "google_cloud_run_service": cloudrun.DataSourceGoogleCloudRunService(), "google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(), diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info.go new file mode 100644 index 000000000000..e2ac85a5a99e --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info.go @@ -0,0 +1,247 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package cloudquotas + +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 DataSourceGoogleCloudQuotasQuotaInfo() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleCloudQuotasQuotaInfoRead, + + Schema: map[string]*schema.Schema{ + "parent": { + Type: schema.TypeString, + Required: true, + }, + "service": { + Type: schema.TypeString, + Required: true, + }, + "quota_id": { + Type: schema.TypeString, + Required: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "metric": { + Type: schema.TypeString, + Computed: true, + }, + "is_precise": { + Type: schema.TypeBool, + Computed: true, + }, + "refresh_interval": { + Type: schema.TypeString, + Computed: true, + }, + "container_type": { + Type: schema.TypeString, + Computed: true, + }, + "dimensions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "metric_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "quota_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "metric_unit": { + Type: schema.TypeString, + Computed: true, + }, + "quota_increase_eligibility": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_eligible": { + Type: schema.TypeBool, + Computed: true, + }, + "ineligibility_reason": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "is_fixed": { + Type: schema.TypeBool, + Computed: true, + }, + "dimensions_infos": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimensions": { + Type: schema.TypeMap, + Computed: true, + }, + "details": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "applicable_locations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "is_concurrent": { + Type: schema.TypeBool, + Computed: true, + }, + "service_request_quota_uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + UseJSONNumber: true, + } +} + +func dataSourceGoogleCloudQuotasQuotaInfoRead(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, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos/{{quota_id}}") + if err != nil { + return fmt.Errorf("error setting api endpoint") + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: userAgent, + }) + + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id())) + } + + if err := d.Set("name", res["name"]); err != nil { + return fmt.Errorf("error reading QuotaInfo name: %s", err) + } + if err := d.Set("quota_id", res["quotaId"]); err != nil { + return fmt.Errorf("error reading QuotaInfo quota_id: %s", err) + } + if err := d.Set("metric", res["metric"]); err != nil { + return fmt.Errorf("error reading QuotaInfo metric: %s", err) + } + if err := d.Set("service", res["service"]); err != nil { + return fmt.Errorf("error reading QuotaInfo service: %s", err) + } + if err := d.Set("is_precise", res["isPrecise"]); err != nil { + return fmt.Errorf("error reading QuotaInfo is_precise: %s", err) + } + if err := d.Set("refresh_interval", res["refreshInterval"]); err != nil { + return fmt.Errorf("error reading QuotaInfo refresh_interval: %s", err) + } + if err := d.Set("container_type", res["containerType"]); err != nil { + return fmt.Errorf("error reading QuotaInfo container_type: %s", err) + } + if err := d.Set("dimensions", res["dimensions"]); err != nil { + return fmt.Errorf("error reading QuotaInfo dimensions: %s", err) + } + if err := d.Set("metric_display_name", res["metricDisplayName"]); err != nil { + return fmt.Errorf("error reading QuotaInfo metric_display_name: %s", err) + } + if err := d.Set("quota_display_name", res["quotaDisplayName"]); err != nil { + return fmt.Errorf("error reading QuotaInfo quota_display_name: %s", err) + } + if err := d.Set("metric_unit", res["metricUnit"]); err != nil { + return fmt.Errorf("error reading QuotaInfo metric_unit: %s", err) + } + if err := d.Set("quota_increase_eligibility", flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(res["quotaIncreaseEligibility"], d, config)); err != nil { + return fmt.Errorf("error reading QuotaInfo quota_increase_eligibility: %s", err) + } + if err := d.Set("is_fixed", res["isFixed"]); err != nil { + return fmt.Errorf("error reading QuotaInfo is_fixed: %s", err) + } + if err := d.Set("dimensions_infos", flattenCloudQuotasQuotaInfoDimensionsInfos(res["dimensionsInfos"], d, config)); err != nil { + return fmt.Errorf("error reading QuotaInfo dimensions_infos: %s", err) + } + if err := d.Set("is_concurrent", res["isConcurrent"]); err != nil { + return fmt.Errorf("error reading QuotaInfo is_concurrent: %s", err) + } + if err := d.Set("service_request_quota_uri", res["serviceRequestQuotaUri"]); err != nil { + return fmt.Errorf("error reading QuotaInfo service_request_quota_uri: %s", err) + } + + d.SetId(res["name"].(string)) + return nil +} + +func flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(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["is_eligible"] = original["is_eligible"] + transformed["ineligibility_reason"] = original["ineligibility_reason"] + return []interface{}{transformed} +} + +func flattenCloudQuotasQuotaInfoDimensionsInfos(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) []interface{} { + if v == nil { + return make([]interface{}, 0) + } + + original := v.([]interface{}) + dimensionsInfos := make([]interface{}, 0, len(original)) + + for _, raw := range original { + data := make(map[string]interface{}) + data["details"] = flattenCloudQuotasQuotaInfoDetails(raw.(map[string]interface{})["details"], d, config) + data["applicable_locations"] = raw.(map[string]interface{})["applicableLocations"] + data["dimensions"] = raw.(map[string]interface{})["dimensions"] + + dimensionsInfos = append(dimensionsInfos, data) + } + return dimensionsInfos +} + +func flattenCloudQuotasQuotaInfoDetails(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + original, ok := v.(map[string]interface{}) + if !ok || len(original) == 0 { + return nil + } + + return []interface{}{ + map[string]interface{}{"value": original["value"]}, + } +} diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info_test.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info_test.go new file mode 100644 index 000000000000..9a4ff979b47d --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_info_test.go @@ -0,0 +1,61 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package cloudquotas_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 TestAccDataSourceGoogleQuotaInfo_basic(t *testing.T) { + t.Parallel() + + resourceName := "data.google_cloud_quotas_quota_info.my_quota_info" + service := "compute.googleapis.com" + quotaId := "CPUS-per-project-region" + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "service": service, + "quota_id": quotaId, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleQuotaInfo_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttr(resourceName, "quota_id", quotaId), + resource.TestCheckResourceAttr(resourceName, "metric", "compute.googleapis.com/cpus"), + resource.TestCheckResourceAttr(resourceName, "service", service), + resource.TestCheckResourceAttrSet(resourceName, "is_precise"), + resource.TestCheckResourceAttr(resourceName, "container_type", "PROJECT"), + resource.TestCheckResourceAttr(resourceName, "dimensions.0", "region"), + resource.TestCheckResourceAttr(resourceName, "metric_display_name", "CPUs"), + resource.TestCheckResourceAttr(resourceName, "quota_display_name", "CPUs"), + resource.TestCheckResourceAttrSet(resourceName, "metric_unit"), + resource.TestCheckResourceAttrSet(resourceName, "quota_increase_eligibility.0.is_eligible"), + resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.dimensions.region"), + resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.details.0.value"), + resource.TestCheckResourceAttrSet(resourceName, "dimensions_infos.0.applicable_locations.0"), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleQuotaInfo_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + data "google_cloud_quotas_quota_info" "my_quota_info" { + parent = "projects/%{project}" + quota_id = "%{quota_id}" + service = "%{service}" + } + `, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown new file mode 100644 index 000000000000..77e97d36489c --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown @@ -0,0 +1,61 @@ +--- +subcategory: "Cloud Quotas" +--- + +# google\_cloud\_quotas\_quota\_info + +Provides information about a particular quota for a given project, folder or organization. + +## Example Usage + +```hcl +data "google_cloud_quotas_quota_info" "my_quota_info" { + parent = "projects/my-project" + service = "compute.googleapis.com" + quota_id = "CPUS-per-project-region" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `parent` - (Required) The parent of the quota info. Allowed parents are "projects/[project-id / number]" or "folders/[folder-id / number]" or "organizations/[org-id / number]. + +* `quota_id` - (Required) The id of the quota, which is unique within the service. + +* `service` - (Required) The name of the service in which the quota is defined. + +## Attributes Reference + +The following attributes are exported: + +* `name` - (Output) Resource name of this QuotaInfo, for example: `projects/123/locations/global/services/compute.googleapis.com/quotaInfos/CpusPerProjectPerRegion`. +* `metric` - (Output) The metric of the quota. It specifies the resources consumption the quota is defined for, for example: `compute.googleapis.com/cpus`. +* `is_precise` - (Output) Whether this is a precise quota. A precise quota is tracked with absolute precision. In contrast, an imprecise quota is not tracked with precision. +* `refresh_interval` - (Output) The reset time interval for the quota. Refresh interval applies to rate quota only. Example: "minute" for per minute, "day" for per day, or "10 seconds" for every 10 seconds. +* `container_type` - (Output) The container type of the QuotaInfo. +* `dimensions` - (Output) The dimensions the quota is defined on. +* `metric_display_name` - (Output) The display name of the quota metric. +* `quota_display_name` - (Output) The display name of the quota. +* `metric_unit` - (Output) The unit in which the metric value is reported, e.g., `MByte`. +* `quota_increase_eligibility` - (Output) Whether it is eligible to request a higher quota value for this quota. +* `is_fixed` - (Output) Whether the quota value is fixed or adjustable. +* `dimensions_infos` - (Output) The collection of dimensions info ordered by their dimensions from more specific ones to less specific ones. +* `is_concurrent` - (Output) Whether the quota is a concurrent quota. Concurrent quotas are enforced on the total number of concurrent operations in flight at any given time. +* `service_request_quota_uri` - (Output) URI to the page where users can request more quota for the cloud service, for example: `https://console.cloud.google.com/iam-admin/quotas`. + + The `quota_increase_eligibility` block supports: + +* `is_eligible` - Whether a higher quota value can be requested for the quota. +* `ineligibility_reason` - The enumeration of reasons when it is ineligible to request increase adjustment. + + The `dimensions_infos` block supports: +* `dimensions` - The map of dimensions for this dimensions info. The key of a map entry is "region", "zone" or the name of a service specific dimension, and the value of a map entry is the value of the dimension. If a dimension does not appear in the map of dimensions, the dimensions info applies to all the dimension values except for those that have another DimenisonInfo instance configured for the specific value. Example: {"provider" : "Foo Inc"} where "provider" is a service specific dimension of a quota. + + An object containing a list of "key": value pairs, for example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`. +* `details` - The quota details for a map of dimensions. +* `applicable_locations` - The applicable regions or zones of this dimensions info. The field will be set to `['global']` for quotas that are not per region or per zone. Otherwise, it will be set to the list of locations this dimension info is applicable to. + + The `details` block supports: +* `value` - The value currently in effect and being enforced. From f23cbbedada43f94bfa7032005c6d41055ed3444 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:24:03 +0000 Subject: [PATCH 120/200] Update comments in .teamcity/ files for clarity (#10149) * Make warning about files being controlled by MM more explicit * Add guidance to the input files about how to update them, and when --- .../builds/build_configuration_per_package.kt | 2 +- .../components/builds/build_configuration_sweepers.kt | 2 +- .../builds/build_configuration_vcr_recording.kt | 2 +- .../.teamcity/components/builds/build_features.kt | 2 +- .../.teamcity/components/builds/build_parameters.kt | 2 +- .../.teamcity/components/builds/build_steps.kt | 2 +- .../.teamcity/components/builds/build_triggers.kt | 2 +- .../.teamcity/components/builds/vcr_build_steps.kt | 2 +- .../terraform/.teamcity/components/constants.kt | 2 +- .../terraform/.teamcity/components/inputs/packages.kt | 10 +++++++++- .../components/inputs/per_service_parallelism.kt | 2 +- .../.teamcity/components/inputs/services_beta.kt | 10 +++++++++- .../.teamcity/components/inputs/services_ga.kt | 10 +++++++++- .../FEATURE-BRANCH-provider-functions.kt | 2 +- .../components/projects/google_beta_subproject.kt | 2 +- .../components/projects/google_ga_subproject.kt | 2 +- .../components/projects/project_sweeper_project.kt | 2 +- .../components/projects/reused/mm_upstream.kt | 2 +- .../components/projects/reused/nightly_tests.kt | 2 +- .../components/projects/reused/vcr_recording.kt | 2 +- .../.teamcity/components/projects/root_project.kt | 2 +- .../terraform/.teamcity/components/unique_id.kt | 2 +- .../.teamcity/components/vcs_roots/vcs_roots.kt | 2 +- mmv1/third_party/terraform/.teamcity/settings.kts | 2 +- .../.teamcity/tests/build_configuration_features.kt | 2 +- .../terraform/.teamcity/tests/context_parameters.kt | 2 +- .../terraform/.teamcity/tests/nightly_tests_project.kt | 2 +- mmv1/third_party/terraform/.teamcity/tests/sweepers.kt | 2 +- .../terraform/.teamcity/tests/test_utils.kt | 2 +- .../third_party/terraform/.teamcity/tests/vcs_roots.kt | 2 +- 30 files changed, 54 insertions(+), 30 deletions(-) diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt index 395dc4da4a9c..f9be546f7eec 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_per_package.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_sweepers.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_sweepers.kt index 5d31f45db4bf..28ff7b99cdd0 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_sweepers.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_sweepers.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_vcr_recording.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_vcr_recording.kt index d647e3294737..134070d909ae 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_vcr_recording.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_configuration_vcr_recording.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_features.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_features.kt index 50734428b55f..ab2195c5111f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_features.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_features.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt index 7641bc858592..9786a95a44b4 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_parameters.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt index 4682f1240eb9..7286b2b82f7c 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_steps.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/build_triggers.kt b/mmv1/third_party/terraform/.teamcity/components/builds/build_triggers.kt index 95127f85e439..c7a119b0a158 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/build_triggers.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/build_triggers.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/builds/vcr_build_steps.kt b/mmv1/third_party/terraform/.teamcity/components/builds/vcr_build_steps.kt index 4453c4fd73a8..05bcb261e901 100644 --- a/mmv1/third_party/terraform/.teamcity/components/builds/vcr_build_steps.kt +++ b/mmv1/third_party/terraform/.teamcity/components/builds/vcr_build_steps.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package builds diff --git a/mmv1/third_party/terraform/.teamcity/components/constants.kt b/mmv1/third_party/terraform/.teamcity/components/constants.kt index 7ecf16baa052..ba1cd010f3ab 100644 --- a/mmv1/third_party/terraform/.teamcity/components/constants.kt +++ b/mmv1/third_party/terraform/.teamcity/components/constants.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. // Provider name that matches the name in the Registry const val ProviderNameGa = "google" diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt index 2e4b11ffb516..8c5cdb3d4970 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/packages.kt @@ -3,7 +3,15 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. + +/* + NOTE: This file is manually curated - any new packages added to the provider codebase will need to be accompanied with a change in this file. + When adding new entires make sure to ensure the path value is correct for TPG or TPGB + e.g. "path" to "./google/envvar" + versus + "path" to "./google-beta/envvar" +*/ package generated diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/per_service_parallelism.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/per_service_parallelism.kt index a57270c35250..175b063f26ac 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/per_service_parallelism.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/per_service_parallelism.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package generated diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index e8beb038983d..13510630f136 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -3,7 +3,15 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. + +/* + NOTE: This file is manually curated - any new service packages added to the provider codebase will need to be accompanied with a change in this file. + When adding new entires make sure to ensure the path value is correct for TPG or TPGB + + For this file, services_beta.kt, please ensure paths are like: + "./google-beta/services/accessapproval" +*/ package generated diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index 071ea16ec879..f4b303eccc69 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -3,7 +3,15 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. + +/* + NOTE: This file is manually curated - any new service packages added to the provider codebase will need to be accompanied with a change in this file. + When adding new entires make sure to ensure the path value is correct for TPG or TPGB + + For this file, services_ga.kt, please ensure paths are like: + "./google/services/accessapproval" +*/ package generated diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt index 3c1752e227f7..a795ef342fb4 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/feature_branches/FEATURE-BRANCH-provider-functions.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects.feature_branches diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/google_beta_subproject.kt b/mmv1/third_party/terraform/.teamcity/components/projects/google_beta_subproject.kt index 3824dcbfa97d..72233a701534 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/google_beta_subproject.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/google_beta_subproject.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/google_ga_subproject.kt b/mmv1/third_party/terraform/.teamcity/components/projects/google_ga_subproject.kt index da23e7767c9e..19b4395d1c29 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/google_ga_subproject.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/google_ga_subproject.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt b/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt index 732822a52ff6..2a484f583f9b 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/project_sweeper_project.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt index c26ed498edd4..9ca0a89b446a 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/mm_upstream.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects.reused diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt index 6fda2b7b7ab1..cb6455e5f752 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/nightly_tests.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects.reused diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt b/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt index c9916b27a722..8df65299015f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/reused/vcr_recording.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects.reused diff --git a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt index a78260dfe650..a05e236a5a36 100644 --- a/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt +++ b/mmv1/third_party/terraform/.teamcity/components/projects/root_project.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package projects diff --git a/mmv1/third_party/terraform/.teamcity/components/unique_id.kt b/mmv1/third_party/terraform/.teamcity/components/unique_id.kt index 00635a8f783c..b9a56d762186 100644 --- a/mmv1/third_party/terraform/.teamcity/components/unique_id.kt +++ b/mmv1/third_party/terraform/.teamcity/components/unique_id.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. fun replaceCharsId(id: String): String{ var newId = id.replace("-", "") diff --git a/mmv1/third_party/terraform/.teamcity/components/vcs_roots/vcs_roots.kt b/mmv1/third_party/terraform/.teamcity/components/vcs_roots/vcs_roots.kt index 3ee70f25f1ef..0e696f91fd2f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/vcs_roots/vcs_roots.kt +++ b/mmv1/third_party/terraform/.teamcity/components/vcs_roots/vcs_roots.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package vcs_roots diff --git a/mmv1/third_party/terraform/.teamcity/settings.kts b/mmv1/third_party/terraform/.teamcity/settings.kts index 7e748003d8f7..4e49b4abccb8 100644 --- a/mmv1/third_party/terraform/.teamcity/settings.kts +++ b/mmv1/third_party/terraform/.teamcity/settings.kts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. import projects.googleCloudRootProject import builds.AllContextParameters diff --git a/mmv1/third_party/terraform/.teamcity/tests/build_configuration_features.kt b/mmv1/third_party/terraform/.teamcity/tests/build_configuration_features.kt index ffde72f5ae79..7e3cc5b6ff58 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/build_configuration_features.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/build_configuration_features.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/context_parameters.kt b/mmv1/third_party/terraform/.teamcity/tests/context_parameters.kt index c9f373786be8..373ad78e29fe 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/context_parameters.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/context_parameters.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt b/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt index af3d7b8a9b24..fbdb4d9bd6d3 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/nightly_tests_project.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt index b05e38573e96..67940004bc68 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/sweepers.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt b/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt index 576e4b735c02..162a38eccf5c 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/test_utils.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/vcs_roots.kt b/mmv1/third_party/terraform/.teamcity/tests/vcs_roots.kt index a46abc0a89af..ae56484af86e 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/vcs_roots.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/vcs_roots.kt @@ -3,7 +3,7 @@ * SPDX-License-Identifier: MPL-2.0 */ -// This file is controlled by MMv1, any changes made here will be overwritten +// This file is maintained in the GoogleCloudPlatform/magic-modules repository and copied into the downstream provider repositories. Any changes to this file in the downstream will be overwritten. package tests From 48d346d562b56f53668e2b34e1eab4a536ba097a Mon Sep 17 00:00:00 2001 From: Rostislav Bobrovsky Date: Wed, 13 Mar 2024 14:48:22 +0100 Subject: [PATCH 121/200] Add fields pathTemplateMatch and pathTemplateRewrite to resource google_compute_region_url_map (#10157) --- mmv1/products/compute/RegionUrlMap.yaml | 38 ++++++++ .../region_url_map_path_template_match.tf.erb | 90 +++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 mmv1/templates/terraform/examples/region_url_map_path_template_match.tf.erb diff --git a/mmv1/products/compute/RegionUrlMap.yaml b/mmv1/products/compute/RegionUrlMap.yaml index 69d8e8fcb7ae..2d2645f08398 100644 --- a/mmv1/products/compute/RegionUrlMap.yaml +++ b/mmv1/products/compute/RegionUrlMap.yaml @@ -130,6 +130,15 @@ examples: skip_docs: true skip_test: true # Similar to other samples min_version: beta + - !ruby/object:Provider::Terraform::Examples + name: "region_url_map_path_template_match" + primary_resource_id: "urlmap" + vars: + url_map_name: "urlmap" + home_backend_service_name: "home-service" + cart_backend_service_name: "cart-service" + user_backend_service_name: "user-service" + health_check_name: "health-check" parameters: - !ruby/object:Api::Type::ResourceRef name: 'region' @@ -558,6 +567,18 @@ properties: and anchor supplied with the original URL. For regular expression grammar please see en.cppreference.com/w/cpp/regex/ecmascript Only one of prefixMatch, fullPathMatch or regexMatch must be specified. + - !ruby/object:Api::Type::String + name: 'pathTemplateMatch' + description: | + For satisfying the matchRule condition, the path of the request + must match the wildcard pattern specified in pathTemplateMatch + after removing any query parameters and anchor that may be part + of the original URL. + + pathTemplateMatch must be between 1 and 255 characters + (inclusive). The pattern specified by pathTemplateMatch may + have at most 5 wildcard operators and at most 5 variable + captures in total. - !ruby/object:Api::Type::NestedObject name: 'routeAction' description: | @@ -784,6 +805,23 @@ properties: Prior to forwarding the request to the selected backend service, the matching portion of the request's path is replaced by pathPrefixRewrite. The value must be between 1 and 1024 characters. + - !ruby/object:Api::Type::String + name: 'pathTemplateRewrite' + description: | + Prior to forwarding the request to the selected origin, if the + request matched a pathTemplateMatch, the matching portion of the + request's path is replaced re-written using the pattern specified + by pathTemplateRewrite. + + pathTemplateRewrite must be between 1 and 255 characters + (inclusive), must start with a '/', and must only use variables + captured by the route's pathTemplate matchers. + + pathTemplateRewrite may only be used when all of a route's + MatchRules specify pathTemplate. + + Only one of pathPrefixRewrite and pathTemplateRewrite may be + specified. - !ruby/object:Api::Type::Array name: 'weightedBackendServices' description: | diff --git a/mmv1/templates/terraform/examples/region_url_map_path_template_match.tf.erb b/mmv1/templates/terraform/examples/region_url_map_path_template_match.tf.erb new file mode 100644 index 000000000000..5a7008e1b80b --- /dev/null +++ b/mmv1/templates/terraform/examples/region_url_map_path_template_match.tf.erb @@ -0,0 +1,90 @@ +# [START cloudloadbalancing_url_map_path_template_match] +resource "google_compute_region_url_map" "<%= ctx[:primary_resource_id] %>" { + region = "us-central1" + + name = "<%= ctx[:vars]['url_map_name'] %>" + description = "a description" + + default_service = google_compute_region_backend_service.home-backend.id + + host_rule { + hosts = ["mysite.com"] + path_matcher = "mysite" + } + + path_matcher { + name = "mysite" + default_service = google_compute_region_backend_service.home-backend.id + + route_rules { + match_rules { + path_template_match = "/xyzwebservices/v2/xyz/users/{username=*}/carts/{cartid=**}" + } + service = google_compute_region_backend_service.cart-backend.id + priority = 1 + route_action { + url_rewrite { + path_template_rewrite = "/{username}-{cartid}/" + } + } + } + + route_rules { + match_rules { + path_template_match = "/xyzwebservices/v2/xyz/users/*/accountinfo/*" + } + service = google_compute_region_backend_service.user-backend.id + priority = 2 + } + } +} + +resource "google_compute_region_backend_service" "home-backend" { + region = "us-central1" + + name = "<%= ctx[:vars]['home_backend_service_name'] %>" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_backend_service" "cart-backend" { + region = "us-central1" + + name = "<%= ctx[:vars]['cart_backend_service_name'] %>" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_backend_service" "user-backend" { + region = "us-central1" + + name = "<%= ctx[:vars]['user_backend_service_name'] %>" + port_name = "http" + protocol = "HTTP" + timeout_sec = 10 + load_balancing_scheme = "EXTERNAL_MANAGED" + + health_checks = [google_compute_region_health_check.default.id] +} + +resource "google_compute_region_health_check" "default" { + region = "us-central1" + + name = "<%= ctx[:vars]['health_check_name'] %>" + check_interval_sec = 1 + timeout_sec = 1 + http_health_check { + port = 80 + request_path = "/" + } +} + +# [END cloudloadbalancing_url_map_path_template_match] From 6fc834e51978806baacac87ecd978efc9dfc8dc8 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Wed, 13 Mar 2024 07:14:18 -0700 Subject: [PATCH 122/200] Refactor TeamCity Services Diff Check to run as one job (#10158) --- .github/actions/build-downstream/action.yml | 105 ++++++++++++++++++ .../teamcity-services-diff-check-weekly.yml | 86 ++++++-------- .../teamcity-services-diff-check.yml | 80 +++++-------- 3 files changed, 166 insertions(+), 105 deletions(-) create mode 100644 .github/actions/build-downstream/action.yml diff --git a/.github/actions/build-downstream/action.yml b/.github/actions/build-downstream/action.yml new file mode 100644 index 000000000000..012248b10862 --- /dev/null +++ b/.github/actions/build-downstream/action.yml @@ -0,0 +1,105 @@ +name: build +description: Generates given downstream Magic Modules Repository from `repo` input +inputs: + repo: + description: "provider repo" + required: true + token: + description: "github token" + required: true + +runs: + using: "composite" + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Ruby + uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + with: + ruby-version: '3.1' + + - name: Cache Bundler gems + uses: actions/cache@v3 + with: + path: mmv1/vendor/bundle + key: ${{ runner.os }}-gems-${{ hashFiles('mmv1/**/Gemfile.lock') }} + restore-keys: | + ${{ runner.os }}-gems- + + - name: Install Ruby dependencies + shell: bash + run: | + bundle config path mmv1/vendor/bundle + bundle install + working-directory: mmv1 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '^1.20' + + # Cache Go modules + - name: Cache Go modules + uses: actions/cache@v3 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + + - run: go install golang.org/x/tools/cmd/goimports@latest + shell: bash + - name: Build ${{ inputs.repo }} + shell: bash + env: + BASE_BRANCH: ${{ github.event.pull_request.base.ref || github.ref_name }} + GITHUB_TOKEN: ${{ inputs.token }} + run: | + set -e + set -x + # Set GOPATH to a directory the runner user has access to + export GOPATH=~/go + + function clone_repo() { + export OUTPUT_PATH=$GOPATH/src/github.com/$UPSTREAM_OWNER/$GH_REPO + echo "OUTPUT_PATH=$OUTPUT_PATH" >> $GITHUB_ENV + GITHUB_PATH=https://x-access-token:$GITHUB_TOKEN@github.com/$UPSTREAM_OWNER/$GH_REPO + mkdir -p "$(dirname $OUTPUT_PATH)" + git clone $GITHUB_PATH $OUTPUT_PATH --branch $BASE_BRANCH + } + + GH_REPO="${{ inputs.repo }}" + if [ "$GH_REPO" == "docs-examples" ] && [ "$BASE_BRANCH" == "main" ]; then + BASE_BRANCH="master" + fi + + GITHUB_PATH=https://x-access-token:$GITHUB_TOKEN@github.com/$UPSTREAM_OWNER/$GH_REPO + + if [[ "$GH_REPO" == terraform-provider-google* ]]; then + UPSTREAM_OWNER=hashicorp + clone_repo + if [ "$GH_REPO" == "terraform-provider-google" ]; then + export VERSION=ga + else + export VERSION=beta + fi + make clean-provider + make provider + elif [ "$GH_REPO" == "terraform-google-conversion" ]; then + UPSTREAM_OWNER=GoogleCloudPlatform + clone_repo + make clean-tgc + make tgc + elif [ "$GH_REPO" == "docs-examples" ]; then + UPSTREAM_OWNER=terraform-google-modules + clone_repo + make tf-oics + else + echo "case not supported" + exit 1 + fi + + (current_dir=$(pwd) && cd $OUTPUT_PATH && zip -r "$current_dir/output.zip" .) \ No newline at end of file diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 1d0bf90820c5..355501e14d51 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -11,57 +11,37 @@ on: - cron: '0 4 * * 1-2' jobs: - terraform-provider-google: - uses: ./.github/workflows/build-downstream.yml - with: - repo: 'terraform-provider-google' - - terraform-provider-google-beta: - uses: ./.github/workflows/build-downstream.yml - with: - repo: 'terraform-provider-google-beta' - teamcity-services-diff-check: - needs: [terraform-provider-google, terraform-provider-google-beta] - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v4 - with: - go-version: '^1.20' - - - name: Download built artifacts - GA provider - uses: actions/download-artifact@v2 - with: - name: artifact-terraform-provider-google - path: artifacts - - - name: Unzip the artifacts and delete the zip - run: | - unzip -o artifacts/output.zip -d ./provider - rm artifacts/output.zip - - - name: Download built artifacts - Beta provider - uses: actions/download-artifact@v2 - with: - name: artifact-terraform-provider-google-beta - path: artifacts - - - name: Unzip the artifacts and delete the zip - run: | - unzip -o artifacts/output.zip -d ./provider - rm artifacts/output.zip - - - name: Check that new services have been added to the TeamCity configuration code - run: | - # Create lists of service packages in providers - ls provider/google/services > tools/teamcity-diff-check/services_ga.txt - ls provider/google-beta/services > tools/teamcity-diff-check/services_beta.txt - - # Run tool to compare service packages in the providers vs those listed in TeamCity config files - cd tools/teamcity-diff-check - go run main.go -service_file=services_ga - go run main.go -service_file=services_beta + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: TeamCity Google Provider Generate + uses: ./.github/actions/build-downstream + with: + repo: 'terraform-provider-google' + token: '$GITHUB_TOKEN' + # The path where GA/Beta providers are generated is grabbed from the OUTPUT_PATH that's set in build_downstream.yaml + # export OUTPUT_PATH=$GOPATH/src/github.com/$UPSTREAM_OWNER/$GH_REPO + # OUTPUT_PATH changes after each generate (GA/beta) + - name: Set GOOGLE_REPO_PATH to path where GA provider was generated + run: echo "GOOGLE_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV + - name: TeamCity Google Beta Provider Generate + uses: ./.github/actions/build-downstream + with: + repo: 'terraform-provider-google-beta' + token: '$GITHUB_TOKEN' + - name: Set GOOGLE_BETA_REPO_PATH to path where beta provider was generated + run: echo "GOOGLE_BETA_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV + - name: Check that new services have been added to the TeamCity configuration code + run: | + # Create lists of service packages in providers + ls ${{env.GOOGLE_REPO_PATH}}/google/services > tools/teamcity-diff-check/services_ga.txt + ls ${{env.GOOGLE_BETA_REPO_PATH}}/google-beta/services > tools/teamcity-diff-check/services_beta.txt + + # Run tool to compare service packages in the providers vs those listed in TeamCity config files + cd tools/teamcity-diff-check + go run main.go -service_file=services_ga + go run main.go -service_file=services_beta diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml index 37dd8e218554..9ffee2130bdb 100644 --- a/.github/workflows/teamcity-services-diff-check.yml +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -9,10 +9,10 @@ on: - 'mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt' - 'mmv1/products/**' jobs: - check-pr: + teamcity-services-diff-check: + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} runs-on: ubuntu-22.04 - outputs: - services: ${{steps.services.outputs.services}} steps: - name: Checkout Repository uses: actions/checkout@v4 @@ -24,61 +24,37 @@ jobs: newServices=$(($(git diff --name-only --diff-filter=A origin/main HEAD | grep -P "mmv1/products/.*/product.yaml" | wc -l))) echo "services=$newServices" >> "${GITHUB_OUTPUT}" if [ "$newServices" = "0" ];then - echo "No new service found." + echo "No new service found." fi - terraform-provider-google: - if: ${{needs.check-pr.outputs.services != '0'}} - needs: check-pr - uses: ./.github/workflows/build-downstream.yml - with: - repo: 'terraform-provider-google' - - terraform-provider-google-beta: - if: ${{needs.check-pr.outputs.services != '0'}} - needs: check-pr - uses: ./.github/workflows/build-downstream.yml - with: - repo: 'terraform-provider-google-beta' - - teamcity-services-diff-check: - needs: [terraform-provider-google, terraform-provider-google-beta] - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v4 + - name: TeamCity Google Provider Generate + id: generate + if: ${{steps.services.outputs.services != '0'}} + uses: ./.github/actions/build-downstream with: - go-version: '^1.20' - - - name: Download built artifacts - GA provider - uses: actions/download-artifact@v2 + repo: 'terraform-provider-google' + token: '$GITHUB_TOKEN' + # The path where GA/Beta providers are generated is grabbed from the OUTPUT_PATH that's set in build_downstream.yaml + # export OUTPUT_PATH=$GOPATH/src/github.com/$UPSTREAM_OWNER/$GH_REPO + # OUTPUT_PATH changes after each generate (GA/beta) + - name: Set GOOGLE_REPO_PATH to path where GA provider was generated + run: echo "GOOGLE_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV + - name: TeamCity Google Beta Provider Generate + if: steps.generate.outcome == 'success' + uses: ./.github/actions/build-downstream with: - name: artifact-terraform-provider-google - path: artifacts - - - name: Unzip the artifacts and delete the zip - run: | - unzip -o artifacts/output.zip -d ./provider - rm artifacts/output.zip - - - name: Download built artifacts - Beta provider - uses: actions/download-artifact@v2 - with: - name: artifact-terraform-provider-google-beta - path: artifacts - - - name: Unzip the artifacts and delete the zip - run: | - unzip -o artifacts/output.zip -d ./provider - rm artifacts/output.zip - + repo: 'terraform-provider-google-beta' + token: '$GITHUB_TOKEN' + - name: Set GOOGLE_BETA_REPO_PATH to path where beta provider was generated + run: echo "GOOGLE_BETA_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV + - name: Checkout Repository + if: steps.generate.outcome == 'success' + uses: actions/checkout@v4 - name: Check that new services have been added to the TeamCity configuration code + if: steps.generate.outcome == 'success' run: | # Create lists of service packages in providers - ls provider/google/services > tools/teamcity-diff-check/services_ga.txt - ls provider/google-beta/services > tools/teamcity-diff-check/services_beta.txt + ls ${{env.GOOGLE_REPO_PATH}}/google/services > tools/teamcity-diff-check/services_ga.txt + ls ${{env.GOOGLE_BETA_REPO_PATH}}/google-beta/services > tools/teamcity-diff-check/services_beta.txt # Run tool to compare service packages in the providers vs those listed in TeamCity config files cd tools/teamcity-diff-check From ec1164c823f43e0d962467a791c3bff0b27c7c4a Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:50:37 +0000 Subject: [PATCH 123/200] Add explicity dependency on IAM in PubSub acc test config (#9921) --- .../pubsub/resource_pubsub_subscription_test.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go index 11f8b050283d..25529a550cc2 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_subscription_test.go @@ -446,10 +446,15 @@ resource "google_pubsub_subscription" "foo" { name = "%s" topic = google_pubsub_topic.foo.id - bigquery_config { - table = "${google_bigquery_table.test.project}.${google_bigquery_table.test.dataset_id}.${google_bigquery_table.test.table_id}" - use_table_schema = %t - } + bigquery_config { + table = "${google_bigquery_table.test.project}.${google_bigquery_table.test.dataset_id}.${google_bigquery_table.test.table_id}" + use_table_schema = %t + } + + depends_on = [ + google_project_iam_member.viewer, + google_project_iam_member.editor + ] } `, dataset, table, topic, subscription, useTableSchema) } From ab93c2fa8e1bfa0bb4292a9296d0052899be3ae0 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Wed, 13 Mar 2024 13:20:33 -0400 Subject: [PATCH 124/200] Improve the error messages when mmv1 compilation fails (#10191) --- mmv1/compiler.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 2e4bc8b5b3ce..0f61a8eb4ccc 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -192,6 +192,9 @@ ) resource.validate resources.push(resource) + rescue StandardError => e + Google::LOGGER.error "Failed to compile #{file_path}: #{e}" + raise e end if override_dir @@ -221,6 +224,9 @@ ) resource.validate resources.push(resource) + rescue StandardError => e + Google::LOGGER.error "Failed to compile using override #{override_path}: #{e}" + raise e end end resources = resources.sort_by(&:name) From ab05386925a64c265787f3014486b797bae335f4 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Wed, 13 Mar 2024 14:41:54 -0400 Subject: [PATCH 125/200] Update enrolled teams (#10192) --- tools/issue-labeler/labeler/enrolled_teams.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/issue-labeler/labeler/enrolled_teams.yml b/tools/issue-labeler/labeler/enrolled_teams.yml index f2d88536d0c8..8da24bb5c517 100755 --- a/tools/issue-labeler/labeler/enrolled_teams.yml +++ b/tools/issue-labeler/labeler/enrolled_teams.yml @@ -327,6 +327,7 @@ service/filestore: resources: - google_filestore_.* service/firebase: + team: firebase-terraform resources: - google_firebase_.* - google_firebaserules_.* @@ -529,6 +530,7 @@ service/redis-instance: resources: - google_redis_instance service/run: + team: cloud-run-control-plane resources: - google_cloud_run_.* - google_cloud_run_v2_.* From ab811636776f9e49966a52deb44ea44cf1431ee3 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 13 Mar 2024 13:15:38 -0700 Subject: [PATCH 126/200] Fix generate comment diff processor build failure (#10164) * Refactored generate_comment to continue in the face of errors Also switched to go template for comment formatting * Moved to structured data for diffs Also added error formatting into comment * Added basic tests for comment formatting * Skipped missing tests and breaking changes if repo failed to clone * Force generation * Breaking change * Fixed error display in diff comment * Marked diff-processor targets as not being real files * Added PATH to diffProcessorEnv * Fixed formatting for error sections * Cleaned up passthrough env var usage * Made exec.sh exit 1 if there are any errors running the magician * Don't error on initial build of the magician binary * Added missing env var for diff processor build * Force generation of tf-oics * Revert "Force generation of tf-oics" This reverts commit fcb65f121cbb0f7040a6b40c635eae3b318d936d. * Revert "Force generation" This reverts commit 596d1eb5afb10d36ab934411e0f1c47aa8b363e9. * Revert "Breaking change" This reverts commit fb04ad401e1d4ee93ef767297a2a59af7d2acffa. * Force missing test run * force missing tests to run - take 2 * Revert "force missing tests to run - take 2" This reverts commit 34f7d16a8442f09aa4a52e0ceafb8dae73f89b08. * Revert "Force missing test run" This reverts commit 90e664a935c4645314c3aabf1f48836e4547fc68. --- .ci/magician/cmd/DIFF_COMMENT.md | 36 ++ .ci/magician/cmd/generate_comment.go | 466 ++++++++++++---------- .ci/magician/cmd/generate_comment_test.go | 192 +++++++-- .ci/magician/cmd/mock_runner_test.go | 53 +-- .ci/magician/source/repo.go | 2 +- .ci/scripts/go-plus/magician/exec.sh | 2 + tools/diff-processor/GNUmakefile | 2 + 7 files changed, 488 insertions(+), 265 deletions(-) create mode 100644 .ci/magician/cmd/DIFF_COMMENT.md diff --git a/.ci/magician/cmd/DIFF_COMMENT.md b/.ci/magician/cmd/DIFF_COMMENT.md new file mode 100644 index 000000000000..b2c44b960823 --- /dev/null +++ b/.ci/magician/cmd/DIFF_COMMENT.md @@ -0,0 +1,36 @@ +Hi there, I'm the Modular magician. I've detected the following information about your changes: + +## Diff report +{{ $diffsLength := len .Diffs }}{{if eq $diffsLength 0 }} +Your PR hasn't generated any diffs, but I'll let you know if a future commit does. +{{else}} +Your PR generated some diffs in downstreams - here they are. + +{{range .Diffs -}} +{{.Title}}: [Diff](https://github.com/modular-magician/{{.Repo}}/compare/auto-pr-{{$.PrNumber}}-old..auto-pr-{{$.PrNumber}}) ({{.DiffStats}}) +{{end -}} +{{end -}} + +{{- $breakingChangesLength := len .BreakingChanges }} +{{- if gt $breakingChangesLength 0}} +## Breaking Change(s) Detected + +The following breaking change(s) were detected within your pull request. + +{{- range .BreakingChanges}} +- {{.}}{{end}} + +If you believe this detection to be incorrect please raise the concern with your reviewer. +If you intend to make this change you will need to wait for a [major release](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#example-major-number-increments) window. +An `override-breaking-change` label can be added to allow merging. +{{end}} +{{.MissingTests}} +{{- $errorsLength := len .Errors}} +{{- if gt $errorsLength 0}} +## Errors +{{range .Errors}} +{{.Title}}: +{{- range .Errors}} +- {{.}}{{end}} +{{end}} +{{- end -}} \ No newline at end of file diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index b78bbf35fd3c..d1d5cd2936b4 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -23,12 +23,41 @@ import ( "magician/source" "os" "path/filepath" - "regexp" + "sort" + "strconv" "strings" + "text/template" "github.com/spf13/cobra" + "golang.org/x/exp/maps" + + _ "embed" +) + +var ( + //go:embed DIFF_COMMENT.md + diffComment string ) +type Diff struct { + Title string + Repo string + DiffStats string +} + +type Errors struct { + Title string + Errors []string +} + +type diffCommentData struct { + PrNumber int + Diffs []Diff + BreakingChanges []string + MissingTests string + Errors []Errors +} + const allowBreakingChangesLabel = "override-breaking-change" var gcEnvironmentVariables = [...]string{ @@ -84,7 +113,22 @@ var generateCommentCmd = &cobra.Command{ os.Exit(1) } ctlr := source.NewController(filepath.Join("workspace", "go"), "modular-magician", env["GITHUB_TOKEN_DOWNSTREAMS"], rnr) - execGenerateComment(env, gh, rnr, ctlr) + prNumber, err := strconv.Atoi(env["PR_NUMBER"]) + if err != nil { + fmt.Println("Error parsing PR_NUMBER: ", err) + os.Exit(1) + } + execGenerateComment( + prNumber, + env["GITHUB_TOKEN_MAGIC_MODULES"], + env["BUILD_ID"], + env["BUILD_STEP"], + env["PROJECT_ID"], + env["COMMIT_SHA"], + gh, + rnr, + ctlr, + ) }, } @@ -96,196 +140,219 @@ func listGCEnvironmentVariables() string { return result } -func execGenerateComment(env map[string]string, gh GithubClient, rnr ExecRunner, ctlr *source.Controller) { - newBranch := "auto-pr-" + env["PR_NUMBER"] - oldBranch := "auto-pr-" + env["PR_NUMBER"] + "-old" +func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, projectId, commitSha string, gh GithubClient, rnr ExecRunner, ctlr *source.Controller) { + newBranch := fmt.Sprintf("auto-pr-%d", prNumber) + oldBranch := fmt.Sprintf("auto-pr-%d-old", prNumber) wd := rnr.GetCWD() mmLocalPath := filepath.Join(wd, "..", "..") - tpgRepoName := "terraform-provider-google" - tpgLocalPath := filepath.Join(mmLocalPath, "..", "tpg") - tpgbRepoName := "terraform-provider-google-beta" - tpgbLocalPath := filepath.Join(mmLocalPath, "..", "tpgb") - tfoicsRepoName := "docs-examples" - tfoicsLocalPath := filepath.Join(mmLocalPath, "..", "tfoics") - // For backwards compatibility until at least Nov 15 2021 - tfcRepoName := "terraform-google-conversion" - tfcLocalPath := filepath.Join(mmLocalPath, "..", "tfc") - - var diffs string - for _, repo := range []*source.Repo{ - { - Name: tpgRepoName, - Title: "Terraform GA", - Path: tpgLocalPath, - }, - { - Name: tpgbRepoName, - Title: "Terraform Beta", - Path: tpgbLocalPath, - }, - { - Name: tfcRepoName, - Title: "TF Conversion", - Path: tfcLocalPath, - DiffCanFail: true, - }, - { - Name: tfoicsRepoName, - Title: "TF OiCS", - Path: tfoicsLocalPath, - }, - } { - // TPG/TPGB difference - repoDiffs, err := cloneAndDiff(repo, oldBranch, newBranch, ctlr) + + tpgRepo := source.Repo{ + Name: "terraform-provider-google", + Title: "`google` provider", + Path: filepath.Join(mmLocalPath, "..", "tpg"), + Version: provider.GA, + } + tpgbRepo := source.Repo{ + Name: "terraform-provider-google-beta", + Title: "`google-beta` provider", + Path: filepath.Join(mmLocalPath, "..", "tpgb"), + Version: provider.Beta, + } + tgcRepo := source.Repo{ + Name: "terraform-google-conversion", + Title: "`terraform-google-conversion`", + Path: filepath.Join(mmLocalPath, "..", "tgc"), + Version: provider.Beta, + } + tfoicsRepo := source.Repo{ + Name: "docs-examples", + Title: "Open in Cloud Shell", + Path: filepath.Join(mmLocalPath, "..", "tfoics"), + } + + // Initialize repos + data := diffCommentData{ + PrNumber: prNumber, + } + errors := map[string][]string{"Other": []string{}} + var err error + for _, repo := range []*source.Repo{&tpgRepo, &tpgbRepo, &tgcRepo, &tfoicsRepo} { + errors[repo.Title] = []string{} + repo.Branch = newBranch + if err := ctlr.Clone(repo); err != nil { + fmt.Println("Failed to clone repo: ", err) + errors[repo.Title] = append(errors[repo.Title], "Failed to clone repo") + } else { + repo.Cloned = true + } + } + + diffs := []Diff{} + for _, repo := range []source.Repo{tpgRepo, tpgbRepo, tgcRepo, tfoicsRepo} { + if !repo.Cloned { + fmt.Println("Skipping diff; repo failed to clone: ", repo.Name) + continue + } + diffStats, err := computeDiff(&repo, oldBranch, ctlr) if err != nil { - fmt.Printf("Error cloning and diffing tpg repo: %v\n", err) - if !repo.DiffCanFail { - os.Exit(1) - } + fmt.Println("diffing repo: ", err) + errors[repo.Title] = append(errors[repo.Title], "Failed to compute repo diff stats") } - if repoDiffs != "" { - diffs += "\n" + repoDiffs + if diffStats != "" { + diffs = append(diffs, Diff{ + Title: repo.Title, + Repo: repo.Name, + DiffStats: diffStats, + }) } } + data.Diffs = diffs - var showBreakingChangesFailed bool - var err error + // The breaking changes are unique across both provider versions + uniqueBreakingChanges := map[string]struct{}{} diffProcessorPath := filepath.Join(mmLocalPath, "tools", "diff-processor") - // versionedBreakingChanges is a map of breaking change output by provider version. - versionedBreakingChanges := make(map[provider.Version]string, 2) - - env["OLD_REF"] = oldBranch - env["NEW_REF"] = newBranch - for _, repo := range []*source.Repo{ - { - Title: "TPG", - Path: tpgLocalPath, - Version: provider.GA, - }, - { - Title: "TPGB", - Path: tpgbLocalPath, - Version: provider.Beta, - }, - } { - // TPG(B) diff processor - err = buildDiffProcessor(diffProcessorPath, repo.Path, env, rnr) + diffProcessorEnv := map[string]string{ + "OLD_REF": oldBranch, + "NEW_REF": newBranch, + // Passthrough vars required for a valid build environment. + "PATH": os.Getenv("PATH"), + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), + } + for _, repo := range []source.Repo{tpgRepo, tpgbRepo} { + if !repo.Cloned { + fmt.Println("Skipping breaking changes; repo failed to clone: ", repo.Name) + continue + } + err = buildDiffProcessor(diffProcessorPath, repo.Path, diffProcessorEnv, rnr) if err != nil { - fmt.Println(err) - os.Exit(1) + fmt.Println("building diff processor: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor failed to build. This is usually due to the downstream provider failing to compile.") + continue } - output, err := computeBreakingChanges(diffProcessorPath, rnr) + + breakingChanges, err := computeBreakingChanges(diffProcessorPath, rnr) if err != nil { - fmt.Println("Error computing TPG breaking changes: ", err) - showBreakingChangesFailed = true + fmt.Println("computing breaking changes: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor crashed while computing breaking changes. This is usually due to the downstream provider failing to compile.") + } + for _, breakingChange := range breakingChanges { + uniqueBreakingChanges[breakingChange] = struct{}{} } - versionedBreakingChanges[repo.Version] = strings.TrimSuffix(output, "\n") - err = addLabels(diffProcessorPath, env, rnr) + + addLabelsEnv := map[string]string{ + "GITHUB_TOKEN_MAGIC_MODULES": ghTokenMagicModules, + } + err = addLabels(prNumber, diffProcessorPath, addLabelsEnv, rnr) if err != nil { - fmt.Println("Error adding TPG labels to PR: ", err) + fmt.Println("adding service labels: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor crashed while adding labels.") } err = cleanDiffProcessor(diffProcessorPath, rnr) if err != nil { - fmt.Println("Error cleaning up diff processor: ", err) - os.Exit(1) + fmt.Println("cleaning up diff processor: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor failed to clean up properly.") } } + breakingChangesSlice := maps.Keys(uniqueBreakingChanges) + sort.Strings(breakingChangesSlice) + data.BreakingChanges = breakingChangesSlice - var breakingChanges string - if showBreakingChangesFailed { - breakingChanges = `## Breaking Change Detection Failed -The breaking change detector crashed during execution. This is usually due to the downstream provider(s) failing to compile. Please investigate or follow up with your reviewer.` - } else { - breakingChanges = combineBreakingChanges(versionedBreakingChanges[provider.GA], versionedBreakingChanges[provider.Beta]) - } - - // Missing test detector - missingTests, err := detectMissingTests(mmLocalPath, tpgbLocalPath, oldBranch, rnr) - if err != nil { - fmt.Println("Error setting up missing test detector: ", err) - os.Exit(1) - } - - message := "Hi there, I'm the Modular magician. I've detected the following information about your changes:\n\n" + // Update breaking changes status on PR breakingState := "success" - if breakingChanges != "" { - message += breakingChanges + "\n\n" + if len(uniqueBreakingChanges) > 0 { + breakingState = "failure" - pullRequest, err := gh.GetPullRequest(env["PR_NUMBER"]) + pullRequest, err := gh.GetPullRequest(strconv.Itoa(prNumber)) if err != nil { fmt.Printf("Error getting pull request: %v\n", err) - os.Exit(1) - } - - breakingChangesAllowed := false - for _, label := range pullRequest.Labels { - if label.Name == allowBreakingChangesLabel { - breakingChangesAllowed = true - break + errors["Other"] = append(errors["Other"], "Failed to check for `override-breaking-change` label") + } else { + for _, label := range pullRequest.Labels { + if label.Name == allowBreakingChangesLabel { + breakingState = "success" + break + } } } - if !breakingChangesAllowed { - breakingState = "failure" - } } - - if diffs == "" { - message += "## Diff report\nYour PR hasn't generated any diffs, but I'll let you know if a future commit does." - } else { - message += "## Diff report\nYour PR generated some diffs in downstreams - here they are.\n" + diffs + "\n" - if missingTests != "" { - message += "\n" + missingTests + "\n" - } + 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(strconv.Itoa(prNumber), "terraform-provider-breaking-change-test", breakingState, targetURL, commitSha); err != nil { + fmt.Printf("Error posting build status for pr %d commit %s: %v\n", prNumber, commitSha, err) + errors["Other"] = append(errors["Other"], "Failed to update breaking-change status check with state: "+breakingState) } - if err := gh.PostComment(env["PR_NUMBER"], message); err != nil { - fmt.Printf("Error posting comment to PR %s: %v\n", env["PR_NUMBER"], err) + // Run missing test detector (currently only for beta) + missingTestsPath := mmLocalPath + for _, repo := range []source.Repo{tpgbRepo} { + if !repo.Cloned { + fmt.Println("Skipping missing tests; repo failed to clone: ", repo.Name) + continue + } + missingTests, err := detectMissingTests(missingTestsPath, repo.Path, oldBranch, rnr) + if err != nil { + fmt.Println("Error running missing test detector: ", err) + errors[repo.Title] = append(errors[repo.Title], "The missing test detector failed to run.") + } + data.MissingTests = missingTests + } + + // Run unit tests for missing test detector + if err = runMissingTestUnitTests( + mmLocalPath, + tpgbRepo.Path, + targetURL, + commitSha, + prNumber, + gh, + rnr, + ); err != nil { + fmt.Println("Error running missing test detector unit tests: ", err) + errors["Other"] = append(errors["Other"], "Missing test detector unit tests failed to run.") + } + + // Add errors to data as an ordered list + errorsList := []Errors{} + for _, repo := range []source.Repo{tpgRepo, tpgbRepo, tgcRepo, tfoicsRepo} { + if len(errors[repo.Title]) > 0 { + errorsList = append(errorsList, Errors{ + Title: repo.Title, + Errors: errors[repo.Title], + }) + } } - - targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", env["BUILD_ID"], env["BUILD_STEP"], env["PROJECT_ID"]) - if err := gh.PostBuildStatus(env["PR_NUMBER"], "terraform-provider-breaking-change-test", breakingState, targetURL, env["COMMIT_SHA"]); err != nil { - fmt.Printf("Error posting build status for pr %s commit %s: %v\n", env["PR_NUMBER"], env["COMMIT_SHA"], err) - os.Exit(1) + if len(errors["Other"]) > 0 { + errorsList = append(errorsList, Errors{ + Title: "Other", + Errors: errors["Other"], + }) } + data.Errors = errorsList - if err := rnr.PushDir(mmLocalPath); err != nil { - fmt.Println(err) + // Post diff comment + message, err := formatDiffComment(data) + if err != nil { + fmt.Println("Error formatting message: ", err) + fmt.Printf("Data: %v\n", data) os.Exit(1) } - if diffs := rnr.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, env, gh, rnr); err != nil { - fmt.Printf("Error testing tools in %s: %v\n", mmLocalPath, err) - os.Exit(1) - } - } - if err := rnr.PopDir(); err != nil { - fmt.Println(err) + if err := gh.PostComment(strconv.Itoa(prNumber), message); err != nil { + fmt.Printf("Error posting comment to PR %d: %v\n", prNumber, err) + fmt.Println("Comment: ", message) os.Exit(1) } } -func cloneAndDiff(repo *source.Repo, oldBranch, newBranch string, ctlr *source.Controller) (string, error) { - // Clone the repo to the desired repo.Path. - repo.Branch = newBranch - if err := ctlr.Clone(repo); err != nil { - return "", fmt.Errorf("error cloning %s: %v\n", repo.Name, err) - } - +func computeDiff(repo *source.Repo, oldBranch string, ctlr *source.Controller) (string, error) { if err := ctlr.Fetch(repo, oldBranch); err != nil { return "", err } - - // Return summary, if any. - diffs, err := ctlr.Diff(repo, oldBranch, newBranch) + // Get shortstat summary of the diff + diff, err := ctlr.Diff(repo, oldBranch, repo.Branch) if err != nil { return "", err } - if diffs == "" { - return "", nil - } - diffs = strings.TrimSuffix(diffs, "\n") - return fmt.Sprintf("%s: [Diff](https://github.com/modular-magician/%s/compare/%s..%s) (%s)", repo.Title, repo.Name, oldBranch, newBranch, diffs), nil + return strings.TrimSuffix(diff, "\n"), nil } // Build the diff processor for tpg or tpgb @@ -304,22 +371,27 @@ func buildDiffProcessor(diffProcessorPath, providerLocalPath string, env map[str return rnr.PopDir() } -func computeBreakingChanges(diffProcessorPath string, rnr ExecRunner) (string, error) { +func computeBreakingChanges(diffProcessorPath string, rnr ExecRunner) ([]string, error) { if err := rnr.PushDir(diffProcessorPath); err != nil { - return "", err + return nil, err } - breakingChanges, err := rnr.Run("bin/diff-processor", []string{"breaking-changes"}, nil) + output, err := rnr.Run("bin/diff-processor", []string{"breaking-changes"}, nil) if err != nil { - return "", err + return nil, err + } + + if output == "" { + return nil, nil } - return breakingChanges, rnr.PopDir() + + return strings.Split(strings.TrimSuffix(output, "\n"), "\n"), rnr.PopDir() } -func addLabels(diffProcessorPath string, env map[string]string, rnr ExecRunner) error { +func addLabels(prNumber int, diffProcessorPath string, env map[string]string, rnr ExecRunner) error { if err := rnr.PushDir(diffProcessorPath); err != nil { return err } - output, err := rnr.Run("bin/diff-processor", []string{"add-labels", env["PR_NUMBER"]}, env) + output, err := rnr.Run("bin/diff-processor", []string{"add-labels", strconv.Itoa(prNumber)}, env) fmt.Println(output) if err != nil { return err @@ -336,48 +408,6 @@ func cleanDiffProcessor(diffProcessorPath string, rnr ExecRunner) error { return nil } -// Get the breaking change message including the unique tpg messages and all tpgb messages. -func combineBreakingChanges(tpgBreaking, tpgbBreaking string) string { - var allMessages []string - if tpgBreaking == "" { - if tpgbBreaking == "" { - return "" - } - allMessages = strings.Split(tpgbBreaking, "\n") - } else if tpgbBreaking == "" { - allMessages = strings.Split(tpgBreaking, "\n") - } else { - dashExp := regexp.MustCompile("-.*") - tpgMessages := strings.Split(tpgBreaking, "\n") - tpgbMessages := strings.Split(tpgbBreaking, "\n") - tpgbSet := make(map[string]struct{}, len(tpgbMessages)) - var tpgUnique []string - for _, message := range tpgbMessages { - simple := dashExp.ReplaceAllString(message, "") - tpgbSet[simple] = struct{}{} - } - for _, message := range tpgMessages { - simple := dashExp.ReplaceAllString(message, "") - if _, ok := tpgbSet[simple]; !ok { - tpgUnique = append(tpgUnique, message) - } - } - allMessages = append(tpgUnique, tpgbMessages...) - } - if len(allMessages) > 0 { - return `## Breaking Change(s) Detected -The following breaking change(s) were detected within your pull request. - -* ` + strings.Join(allMessages, "\n* ") + ` - -If you believe this detection to be incorrect please raise the concern with your reviewer. -If you intend to make this change you will need to wait for a [major release](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#example-major-number-increments) window. -An ` + "`override-breaking-change`" + ` label can be added to allow merging. -` - } - return "" -} - // 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. @@ -449,9 +479,24 @@ func updatePackageName(name, path string, rnr ExecRunner) error { return rnr.PopDir() } -// Run unit tests for the missing test detector and diff processor. +// Run unit tests for the missing test detector. // Report results using Github API. -func testTools(mmLocalPath, tpgbLocalPath string, env map[string]string, gh GithubClient, rnr ExecRunner) error { +func runMissingTestUnitTests(mmLocalPath, tpgbLocalPath, targetURL, commitSha string, prNumber int, gh GithubClient, rnr ExecRunner) error { + if err := rnr.PushDir(mmLocalPath); err != nil { + return err + } + + diffs, err := rnr.Run("git", []string{"diff", "HEAD", "origin/main", "tools/missing-test-detector"}, nil) + if err != nil { + return err + } + if diffs == "" { + // Short-circuit if there are no changes to the missing test detector + return rnr.PopDir() + } + + fmt.Printf("Found diffs in missing test detector:\n%s\nRunning tests.\n", diffs) + missingTestDetectorPath := filepath.Join(mmLocalPath, "tools", "missing-test-detector") rnr.PushDir(missingTestDetectorPath) if _, err := rnr.Run("go", []string{"mod", "tidy"}, nil); err != nil { @@ -460,20 +505,33 @@ func testTools(mmLocalPath, tpgbLocalPath string, env map[string]string, gh Gith servicesDir := filepath.Join(tpgbLocalPath, "google-beta", "services") state := "success" if _, err := rnr.Run("go", []string{"test"}, map[string]string{ - "GOPATH": env["GOPATH"], - "HOME": env["HOME"], "SERVICES_DIR": servicesDir, + // Passthrough vars required for a valid build environment. + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), }); err != nil { fmt.Printf("error from running go test in %s: %v\n", missingTestDetectorPath, err) state = "failure" } - targetURL := fmt.Sprintf("https://console.cloud.google.com/cloud-build/builds;region=global/%s;step=%s?project=%s", env["BUILD_ID"], env["BUILD_STEP"], env["PROJECT_ID"]) - if err := gh.PostBuildStatus(env["PR_NUMBER"], "unit-tests-missing-test-detector", state, targetURL, env["COMMIT_SHA"]); err != nil { + if err := gh.PostBuildStatus(strconv.Itoa(prNumber), "unit-tests-missing-test-detector", state, targetURL, commitSha); err != nil { return err } return rnr.PopDir() } +func formatDiffComment(data diffCommentData) (string, error) { + tmpl, err := template.New("DIFF_COMMENT.md").Parse(diffComment) + if err != nil { + panic(fmt.Sprintf("Unable to parse DIFF_COMMENT.md: %s", err)) + } + sb := new(strings.Builder) + err = tmpl.Execute(sb, data) + if err != nil { + return "", err + } + return sb.String(), nil +} + func init() { rootCmd.AddCommand(generateCommentCmd) } diff --git a/.ci/magician/cmd/generate_comment_test.go b/.ci/magician/cmd/generate_comment_test.go index c8a1c14ed487..456267619bb8 100644 --- a/.ci/magician/cmd/generate_comment_test.go +++ b/.ci/magician/cmd/generate_comment_test.go @@ -16,9 +16,12 @@ package cmd import ( - "magician/source" + "os" "reflect" "testing" + + "github.com/stretchr/testify/assert" + "magician/source" ) func TestExecGenerateComment(t *testing.T) { @@ -27,25 +30,27 @@ func TestExecGenerateComment(t *testing.T) { calledMethods: make(map[string][][]any), } ctlr := source.NewController("/mock/dir/go", "modular-magician", "*******", mr) - env := map[string]string{ - "BUILD_ID": "build1", - "BUILD_STEP": "17", - "COMMIT_SHA": "sha1", - "GITHUB_TOKEN_MAGIC_MODULES": "*******", - "PR_NUMBER": "pr1", - "PROJECT_ID": "project1", - } diffProcessorEnv := map[string]string{ - "BUILD_ID": "build1", - "BUILD_STEP": "17", - "COMMIT_SHA": "sha1", + "NEW_REF": "auto-pr-123456", + "OLD_REF": "auto-pr-123456-old", + "PATH": os.Getenv("PATH"), + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), + } + addLabelsEnv := map[string]string{ "GITHUB_TOKEN_MAGIC_MODULES": "*******", - "NEW_REF": "auto-pr-pr1", - "OLD_REF": "auto-pr-pr1-old", - "PR_NUMBER": "pr1", - "PROJECT_ID": "project1", } - execGenerateComment(env, gh, mr, ctlr) + execGenerateComment( + 123456, + "*******", + "build1", + "17", + "project1", + "sha1", + gh, + mr, + ctlr, + ) for method, expectedCalls := range map[string][]ParameterList{ "Copy": { @@ -64,25 +69,25 @@ func TestExecGenerateComment(t *testing.T) { {"/mock/dir/magic-modules/tools/diff-processor/bin"}, }, "Run": { - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google", "/mock/dir/tpg"}, map[string]string(nil)}, - {"/mock/dir/tpg", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, - {"/mock/dir/tpg", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta", "/mock/dir/tpgb"}, map[string]string(nil)}, - {"/mock/dir/tpgb", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, - {"/mock/dir/tpgb", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion", "/mock/dir/tfc"}, map[string]string(nil)}, - {"/mock/dir/tfc", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, - {"/mock/dir/tfc", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-pr1", "https://modular-magician:*******@github.com/modular-magician/docs-examples", "/mock/dir/tfoics"}, map[string]string(nil)}, - {"/mock/dir/tfoics", "git", []string{"fetch", "origin", "auto-pr-pr1-old"}, map[string]string(nil)}, - {"/mock/dir/tfoics", "git", []string{"diff", "origin/auto-pr-pr1-old", "origin/auto-pr-pr1", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-123456", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google", "/mock/dir/tpg"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-123456", "https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta", "/mock/dir/tpgb"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-123456", "https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion", "/mock/dir/tgc"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/.ci/magician", "git", []string{"clone", "-b", "auto-pr-123456", "https://modular-magician:*******@github.com/modular-magician/docs-examples", "/mock/dir/tfoics"}, map[string]string(nil)}, + {"/mock/dir/tpg", "git", []string{"fetch", "origin", "auto-pr-123456-old"}, map[string]string(nil)}, + {"/mock/dir/tpg", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "git", []string{"fetch", "origin", "auto-pr-123456-old"}, map[string]string(nil)}, + {"/mock/dir/tpgb", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/tgc", "git", []string{"fetch", "origin", "auto-pr-123456-old"}, map[string]string(nil)}, + {"/mock/dir/tgc", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, + {"/mock/dir/tfoics", "git", []string{"fetch", "origin", "auto-pr-123456-old"}, map[string]string(nil)}, + {"/mock/dir/tfoics", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "pr1"}, diffProcessorEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "123456"}, addLabelsEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "pr1"}, diffProcessorEnv}, - {"/mock/dir/tpgbold", "git", []string{"checkout", "origin/auto-pr-pr1-old"}, map[string]string(nil)}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "123456"}, addLabelsEnv}, + {"/mock/dir/tpgbold", "git", []string{"checkout", "origin/auto-pr-123456-old"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", "s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g", "{}", "+"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.mod"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.sum"}, map[string]string(nil)}, @@ -110,8 +115,8 @@ func TestExecGenerateComment(t *testing.T) { } for method, expectedCalls := range map[string][][]any{ - "PostBuildStatus": {{"pr1", "terraform-provider-breaking-change-test", "success", "https://console.cloud.google.com/cloud-build/builds;region=global/build1;step=17?project=project1", "sha1"}}, - "PostComment": {{"pr1", "Hi there, I'm the Modular magician. I've detected the following information about your changes:\n\n## Diff report\nYour PR generated some diffs in downstreams - here they are.\n\nTerraform GA: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/auto-pr-pr1-old..auto-pr-pr1) ( 2 files changed, 40 insertions(+))\nTerraform Beta: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/auto-pr-pr1-old..auto-pr-pr1) ( 2 files changed, 40 insertions(+))\nTF Conversion: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/auto-pr-pr1-old..auto-pr-pr1) ( 1 file changed, 10 insertions(+))\n\n## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n\n"}}, + "PostBuildStatus": {{"123456", "terraform-provider-breaking-change-test", "success", "https://console.cloud.google.com/cloud-build/builds;region=global/build1;step=17?project=project1", "sha1"}}, + "PostComment": {{"123456", "Hi there, I'm the Modular magician. I've detected the following information about your changes:\n\n## Diff report\n\nYour PR generated some diffs in downstreams - here they are.\n\n`google` provider: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/auto-pr-123456-old..auto-pr-123456) ( 2 files changed, 40 insertions(+))\n`google-beta` provider: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/auto-pr-123456-old..auto-pr-123456) ( 2 files changed, 40 insertions(+))\n`terraform-google-conversion`: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/auto-pr-123456-old..auto-pr-123456) ( 1 file changed, 10 insertions(+))\n\n## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n"}}, } { if actualCalls, ok := gh.calledMethods[method]; !ok { t.Fatalf("Found no calls for %s", method) @@ -126,3 +131,122 @@ func TestExecGenerateComment(t *testing.T) { } } } + +func TestFormatDiffComment(t *testing.T) { + cases := map[string]struct { + data diffCommentData + expectedStrings []string + notExpectedStrings []string + }{ + "basic message": { + data: diffCommentData{}, + expectedStrings: []string{"## Diff report", "hasn't generated any diffs"}, + notExpectedStrings: []string{ + "generated some diffs", + "## Breaking Change(s) Detected", + "## Errors", + "## Missing test report", + }, + }, + "errors are displayed": { + data: diffCommentData{ + Errors: []Errors{ + { + Title: "`google` provider", + Errors: []string{"Provider 1"}, + }, + { + Title: "Other", + Errors: []string{"Error 1", "Error 2"}, + }, + }, + }, + expectedStrings: []string{"## Diff report", "## Errors", "`google` provider:\n- Provider 1\n\nOther:\n- Error 1\n- Error 2\n"}, + notExpectedStrings: []string{ + "generated some diffs", + "## Breaking Change(s) Detected", + "## Missing test report", + }, + }, + "diffs are displayed": { + data: diffCommentData{ + PrNumber: 1234567890, + Diffs: []Diff{ + { + Title: "Repo 1", + Repo: "repo-1", + DiffStats: "+1 added, -1 removed", + }, + { + Title: "Repo 2", + Repo: "repo-2", + DiffStats: "+2 added, -2 removed", + }, + }, + }, + expectedStrings: []string{ + "## Diff report", + "generated some diffs", + "Repo 1: [Diff](https://github.com/modular-magician/repo-1/compare/auto-pr-1234567890-old..auto-pr-1234567890) (+1 added, -1 removed)\nRepo 2: [Diff](https://github.com/modular-magician/repo-2/compare/auto-pr-1234567890-old..auto-pr-1234567890) (+2 added, -2 removed)", + }, + notExpectedStrings: []string{ + "hasn't generated any diffs", + "## Breaking Change(s) Detected", + "## Errors", + "## Missing test report", + }, + }, + "breaking changes are displayed": { + data: diffCommentData{ + BreakingChanges: []string{ + "Breaking change 1", + "Breaking change 2", + }, + }, + expectedStrings: []string{ + "## Diff report", + "## Breaking Change(s) Detected", + "major release", + "`override-breaking-change`", + "- Breaking change 1\n- Breaking change 2\n", + }, + notExpectedStrings: []string{ + "generated some diffs", + "## Errors", + "## Missing test report", + }, + }, + "missing tests are displayed": { + data: diffCommentData{ + MissingTests: "## Missing test report", + }, + expectedStrings: []string{ + "## Diff report", + "## Missing test report", + }, + notExpectedStrings: []string{ + "generated some diffs", + "## Breaking Change(s) Detected", + "## Errors", + }, + }, + } + + for tn, tc := range cases { + tc := tc + t.Run(tn, func(t *testing.T) { + t.Parallel() + + comment, err := formatDiffComment(tc.data) + assert.Nil(t, err) + + for _, s := range tc.expectedStrings { + assert.Contains(t, comment, s) + } + + for _, s := range tc.notExpectedStrings { + assert.NotContains(t, comment, s) + } + }) + } +} diff --git a/.ci/magician/cmd/mock_runner_test.go b/.ci/magician/cmd/mock_runner_test.go index 5789d9878a3f..bc470b13d685 100644 --- a/.ci/magician/cmd/mock_runner_test.go +++ b/.ci/magician/cmd/mock_runner_test.go @@ -41,32 +41,33 @@ func NewMockRunner() MockRunner { return &mockRunner{ calledMethods: make(map[string][]ParameterList), cmdResults: map[string]string{ - "/mock/dir/tfc git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/docs-examples /mock/dir/tfoics] map[]": "", - "/mock/dir/tpgb git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion /mock/dir/tfc] map[]": "", - " git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google /mock/dir/tpg] map[]": "", - "/mock/dir/tpg git [clone -b auto-pr-pr1 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] map[]": "", - "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", - "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", - "/mock/dir/magic-modules/tools/diff-processor make [build] map[OLD_REF:auto-pr-pr1-old NEW_REF:auto-pr-pr1]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [mod tidy] map[]": "", - "/mock/dir/magic-modules/tools/missing-test-detector go [run . -services-dir=/mock/dir/tpgb/google-beta/services] map[]": "## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n", - "/mock/dir/tfc git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 1 file changed, 10 insertions(+)\n", - "/mock/dir/tfc git [fetch origin auto-pr-pr1-old] map[]": "", - "/mock/dir/tfoics git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": "", - "/mock/dir/tfoics git [fetch origin auto-pr-pr1-old] map[]": "", - "/mock/dir/tpg git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", - "/mock/dir/tpg git [fetch origin auto-pr-pr1-old] map[]": "", - "/mock/dir/tpgb find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/new~g {} +] map[]": "", - "/mock/dir/tpgb git [diff origin/auto-pr-pr1-old origin/auto-pr-pr1 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", - "/mock/dir/tpgb git [fetch origin auto-pr-pr1-old] map[]": "", - "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.mod] map[]": "", - "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.sum] map[]": "", - "/mock/dir/tpgbold find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g {} +] map[]": "", - "/mock/dir/tpgbold git [checkout origin/auto-pr-pr1-old] map[]": "", - "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.mod] map[]": "", - "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.sum] map[]": "", + "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/docs-examples /mock/dir/tfoics] map[]": "", + "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-google-conversion /mock/dir/tgc] map[]": "", + "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google /mock/dir/tpg] map[]": "", + "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] map[]": "", + "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", + "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", + "/mock/dir/magic-modules/tools/diff-processor make [build] map[NEW_REF:auto-pr-123456 OLD_REF:auto-pr-123456-old]": "", + "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [add-labels 123456] map[GITHUB_TOKEN_MAGIC_MODULES:*******]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [mod tidy] map[]": "", + "/mock/dir/magic-modules/tools/missing-test-detector go [run . -services-dir=/mock/dir/tpgb/google-beta/services] map[]": "## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n", + "/mock/dir/tgc git [diff origin/auto-pr-123456-old origin/auto-pr-123456 --shortstat] map[]": " 1 file changed, 10 insertions(+)\n", + "/mock/dir/tgc git [fetch origin auto-pr-123456-old] map[]": "", + "/mock/dir/tfoics git [diff origin/auto-pr-123456-old origin/auto-pr-123456 --shortstat] map[]": "", + "/mock/dir/tfoics git [fetch origin auto-pr-123456-old] map[]": "", + "/mock/dir/tpg git [diff origin/auto-pr-123456-old origin/auto-pr-123456 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", + "/mock/dir/tpg git [fetch origin auto-pr-123456-old] map[]": "", + "/mock/dir/tpgb find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/new~g {} +] map[]": "", + "/mock/dir/tpgb git [diff origin/auto-pr-123456-old origin/auto-pr-123456 --shortstat] map[]": " 2 files changed, 40 insertions(+)\n", + "/mock/dir/tpgb git [fetch origin auto-pr-123456-old] map[]": "", + "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.mod] map[]": "", + "/mock/dir/tpgb sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/new|g go.sum] map[]": "", + "/mock/dir/tpgbold find [. -type f -name *.go -exec sed -i.bak s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g {} +] map[]": "", + "/mock/dir/tpgbold git [checkout origin/auto-pr-123456-old] map[]": "", + "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.mod] map[]": "", + "/mock/dir/tpgbold sed [-i.bak s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g go.sum] map[]": "", }, cwd: "/mock/dir/magic-modules/.ci/magician", dirStack: list.New(), diff --git a/.ci/magician/source/repo.go b/.ci/magician/source/repo.go index 2d62d531431f..529cf97200ee 100644 --- a/.ci/magician/source/repo.go +++ b/.ci/magician/source/repo.go @@ -14,7 +14,7 @@ type Repo struct { Owner string // Owner of repo, optional Path string // local Path once cloned, including Name Version provider.Version - DiffCanFail bool // whether to allow the command to continue if cloning or diffing the repo fails + Cloned bool } type Controller struct { diff --git a/.ci/scripts/go-plus/magician/exec.sh b/.ci/scripts/go-plus/magician/exec.sh index a0cb4078e6b6..c438fb69cb22 100755 --- a/.ci/scripts/go-plus/magician/exec.sh +++ b/.ci/scripts/go-plus/magician/exec.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e + # Get the directory of the current script DIR="$(dirname $(realpath $0))" diff --git a/tools/diff-processor/GNUmakefile b/tools/diff-processor/GNUmakefile index 8e4f18ba9b05..c9e336230d17 100644 --- a/tools/diff-processor/GNUmakefile +++ b/tools/diff-processor/GNUmakefile @@ -56,3 +56,5 @@ endif go mod tidy mkdir -p bin/ go build -o ./bin/ . + +.PHONY: clone clean build From 6c7c0fb58933099b137bdbb7ac1771cc3b609cbd Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 13 Mar 2024 13:25:05 -0700 Subject: [PATCH 127/200] Rewrite versions related functions (#10181) --- mmv1/api/product.go | 136 ++++++++++++----------- mmv1/api/product/version.go | 8 ++ mmv1/api/product_test.go | 129 ++++++++++++++++++++++ mmv1/api/resource.go | 38 +++++++ mmv1/api/resource_test.go | 145 ++++++++++++++++++++++++ mmv1/api/type.go | 43 +++++--- mmv1/api/type_test.go | 214 ++++++++++++++++++++++++++++++++++++ 7 files changed, 632 insertions(+), 81 deletions(-) create mode 100644 mmv1/api/product_test.go create mode 100644 mmv1/api/resource_test.go create mode 100644 mmv1/api/type_test.go diff --git a/mmv1/api/product.go b/mmv1/api/product.go index bfaed3a19869..5c5b718d8767 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -14,6 +14,9 @@ package api import ( + "log" + "strings" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" "golang.org/x/exp/slices" @@ -50,7 +53,7 @@ type Product struct { // The API versions of this product - Versions []product.Version + Versions []*product.Version // The base URL for the service API endpoint // For example: `https://www.googleapis.com/compute/v1/` @@ -77,6 +80,9 @@ func (p *Product) Validate() { for _, o := range p.Objects { o.ProductMetadata = p } + + p.SetApiName() + p.SetDisplayName() } // def validate @@ -101,73 +107,82 @@ func (p *Product) Validate() { // check :versions, type: Array, item_type: Api::Product::Version, required: true // end -// // ==================== -// // Custom Getters -// // ==================== +// ==================== +// Custom Setters +// ==================== -// // The name of the product's API; "compute", "accesscontextmanager" -// def api_name -// name.downcase -// end +func (p *Product) SetApiName() { + // The name of the product's API; "compute", "accesscontextmanager" + p.ApiName = strings.ToLower(p.Name) +} // The product full name is the "display name" in string form intended for // users to read in documentation; "Google Compute Engine", "Cloud Bigtable" -func (p Product) GetDisplayName() string { +func (p *Product) SetDisplayName() { if p.DisplayName == "" { - return google.SpaceSeparated(p.Name) + p.DisplayName = google.SpaceSeparated(p.Name) } - - return p.DisplayName } -// // Most general version that exists for the product -// // If GA is present, use that, else beta, else alpha -// def lowest_version -// Version::ORDER.each do |ordered_version_name| -// @versions.each do |product_version| -// return product_version if ordered_version_name == product_version.name -// end -// end -// raise "Unable to find lowest version for product //{display_name}" -// end - -// def version_obj(name) -// @versions.each do |v| -// return v if v.name == name -// end +// ==================== +// Version-related methods +// ==================== + +// Most general version that exists for the product +// If GA is present, use that, else beta, else alpha +func (p Product) lowestVersion() *product.Version { + for _, orderedVersionName := range product.ORDER { + for _, productVersion := range p.Versions { + if orderedVersionName == productVersion.Name { + return productVersion + } + } + } -// raise "API version '//{name}' does not exist for product '//{@name}'" -// end + log.Fatalf("Unable to find lowest version for product %s", p.DisplayName) + return nil +} -// // Get the version of the object specified by the version given if present -// // Or else fall back to the closest version in the chain defined by Version::ORDER -// def version_obj_or_closest(name) -// return version_obj(name) if exists_at_version(name) +func (p Product) versionObj(name string) *product.Version { + for _, v := range p.Versions { + if v.Name == name { + return v + } + } -// // versions should fall back to the closest version to them that exists -// name ||= Version::ORDER[0] -// lower_versions = Version::ORDER[0..Version::ORDER.index(name)] + log.Fatalf("API version '%s' does not exist for product '%s'", name, p.Name) + return nil +} -// lower_versions.reverse_each do |version| -// return version_obj(version) if exists_at_version(version) -// end +// Get the version of the object specified by the version given if present +// Or else fall back to the closest version in the chain defined by product.ORDER +func (p Product) VersionObjOrClosest(name string) *product.Version { + if p.ExistsAtVersion(name) { + return p.versionObj(name) + } -// raise "Could not find object for version //{name} and product //{display_name}" -// end + // versions should fall back to the closest version to them that exists + if name == "" { + name = product.ORDER[0] + } -// def exists_at_version_or_lower(name) -// // Versions aren't normally going to be empty since products need a -// // base_url. This nil check exists for atypical products, like _bundle. -// return true if @versions.nil? + lowerVersions := make([]string, 0) + for _, v := range product.ORDER { + lowerVersions = append(lowerVersions, v) + if v == name { + break + } + } -// name ||= Version::ORDER[0] -// return false unless Version::ORDER.include?(name) + for i := len(lowerVersions) - 1; i >= 0; i-- { + if p.ExistsAtVersion(lowerVersions[i]) { + return p.versionObj(lowerVersions[i]) + } + } -// (0..Version::ORDER.index(name)).each do |i| -// return true if exists_at_version(Version::ORDER[i]) -// end -// false -// end + log.Fatalf("Could not find object for version %s and product %s", name, p.DisplayName) + return nil +} func (p *Product) ExistsAtVersionOrLower(name string) bool { if !slices.Contains(product.ORDER, name) { @@ -192,20 +207,9 @@ func (p *Product) ExistsAtVersion(name string) bool { return false } -// def exists_at_version(name) -// // Versions aren't normally going to be empty since products need a -// // base_url. This nil check exists for atypical products, like _bundle. -// return true if @versions.nil? - -// @versions.any? { |v| v.name == name } -// end - -// // Not a conventional setter, so ignore rubocop's warning -// // rubocop:disable Naming/AccessorMethodName -// def set_properties_based_on_version(version) -// @base_url = version.base_url -// end -// // rubocop:enable Naming/AccessorMethodName +func (p *Product) SetPropertiesBasedOnVersion(version *product.Version) { + p.BaseUrl = version.BaseUrl +} // // ==================== // // Debugging Methods diff --git a/mmv1/api/product/version.go b/mmv1/api/product/version.go index 3c2ef6a670c0..aa5bdd335c10 100644 --- a/mmv1/api/product/version.go +++ b/mmv1/api/product/version.go @@ -13,6 +13,10 @@ package product +import ( + "golang.org/x/exp/slices" +) + // require 'api/object' var ORDER = []string{"ga", "beta", "alpha", "private"} @@ -50,3 +54,7 @@ type Version struct { // def <=>(other) // ORDER.index(name) <=> ORDER.index(other.name) if other.is_a?(Version) // end + +func (v *Version) CompareTo(other *Version) int { + return slices.Index(ORDER, v.Name) - slices.Index(ORDER, other.Name) +} diff --git a/mmv1/api/product_test.go b/mmv1/api/product_test.go new file mode 100644 index 000000000000..682cd7b6a784 --- /dev/null +++ b/mmv1/api/product_test.go @@ -0,0 +1,129 @@ +package api + +import ( + "reflect" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + +func TestProductLowestVersion(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + obj Product + expected string + }{ + { + description: "lowest version is ga", + obj: Product{ + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + }, + expected: "ga", + }, + { + description: "lowest version is ga", + obj: Product{ + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + }, + expected: "beta", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + versionObj := tc.obj.lowestVersion() + + if got, want := versionObj.Name, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestProductVersionObjOrClosest(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + obj Product + input string + expected string + }{ + { + description: "closest version object to ga", + obj: Product{ + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + }, + }, + input: "ga", + expected: "ga", + }, + { + description: "closest version object to alpha", + obj: Product{ + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + }, + }, + input: "alpha", + expected: "beta", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + versionObj := tc.obj.VersionObjOrClosest(tc.input) + + if got, want := versionObj.Name, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 894850e765c1..069c935af0d8 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -13,6 +13,7 @@ package api import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/resource" "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider/terraform" ) @@ -292,3 +293,40 @@ func (r *Resource) setResourceMetada(properties []*Type) { property.ResourceMetadata = r } } + +// ==================== +// Version-related methods +// ==================== + +func (r Resource) MinVersionObj() *product.Version { + if r.MinVersion != "" { + return r.ProductMetadata.versionObj(r.MinVersion) + } else { + return r.ProductMetadata.lowestVersion() + } +} + +func (r Resource) NotInVersion(version *product.Version) bool { + return version.CompareTo(r.MinVersionObj()) < 0 +} + +// Recurses through all nested properties and parameters and changes their +// 'exclude' instance variable if the property is at a version below the +// one that is passed in. +func (r *Resource) ExcludeIfNotInVersion(version *product.Version) { + if !r.Exclude { + r.Exclude = r.NotInVersion(version) + } + + if r.Properties != nil { + for _, p := range r.Properties { + p.ExcludeIfNotInVersion(version) + } + } + + if r.Parameters != nil { + for _, p := range r.Parameters { + p.ExcludeIfNotInVersion(version) + } + } +} diff --git a/mmv1/api/resource_test.go b/mmv1/api/resource_test.go new file mode 100644 index 000000000000..a9cb0c3c4a65 --- /dev/null +++ b/mmv1/api/resource_test.go @@ -0,0 +1,145 @@ +package api + +import ( + "reflect" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + +func TestResourceMinVersionObj(t *testing.T) { + t.Parallel() + p := Product{ + NamedObject: NamedObject{ + Name: "test", + }, + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + } + + cases := []struct { + description string + obj Resource + expected string + }{ + { + description: "resource minVersion is empty", + obj: Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + expected: "ga", + }, + { + description: "resource minVersion is not empty", + obj: Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ProductMetadata: &p, + }, + expected: "beta", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + versionObj := tc.obj.MinVersionObj() + + if got, want := versionObj.Name, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestResourceNotInVersion(t *testing.T) { + t.Parallel() + p := Product{ + NamedObject: NamedObject{ + Name: "test", + }, + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + } + + cases := []struct { + description string + obj Resource + input *product.Version + expected bool + }{ + { + description: "ga is in version if MinVersion is empty", + obj: Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + input: &product.Version{ + Name: "ga", + }, + expected: false, + }, + { + description: "ga is not in version if MinVersion is beta", + obj: Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ProductMetadata: &p, + }, + input: &product.Version{ + Name: "ga", + }, + expected: true, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := tc.obj.NotInVersion(tc.input), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/api/type.go b/mmv1/api/type.go index 0fe6f165e6dd..f80777231810 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -13,6 +13,10 @@ package api +import ( + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + // require 'api/object' // require 'google/string_utils' // require 'provider/terraform/validation' @@ -441,24 +445,33 @@ const MAX_NAME = 20 // // @__parent // } -// func (t *Type) min_version() { -// // if @min_version.nil? -// // @__resource.min_version -// // else -// // @__resource.__product.version_obj(@min_version) -// // end -// } +func (t *Type) MinVersionObj() *product.Version { + if t.MinVersion != "" { + return t.ResourceMetadata.ProductMetadata.versionObj(t.MinVersion) + } else { + return t.ResourceMetadata.MinVersionObj() + } +} -// func (t *Type) exact_version() { -// // return nil if @exact_version.nil? || @exact_version.empty? +func (t *Type) exactVersionObj() *product.Version { + if t.ExactVersion == "" { + return nil + } -// // @__resource.__product.version_obj(@exact_version) -// } + return t.ResourceMetadata.ProductMetadata.versionObj(t.ExactVersion) +} -// func (t *Type) exclude_if_not_in_version!(version) { -// // @exclude ||= exact_version != version unless exact_version.nil? -// // @exclude ||= version < min_version -// } +func (t *Type) ExcludeIfNotInVersion(version *product.Version) { + if !t.Exclude { + if versionObj := t.exactVersionObj(); versionObj != nil { + t.Exclude = versionObj.CompareTo(version) != 0 + } + + if !t.Exclude { + t.Exclude = version.CompareTo(t.MinVersionObj()) < 0 + } + } +} // // Overriding is_a? to enable class overrides. // // Ruby does not let you natively change types, so this is the next best diff --git a/mmv1/api/type_test.go b/mmv1/api/type_test.go new file mode 100644 index 000000000000..86c3e2e57b1e --- /dev/null +++ b/mmv1/api/type_test.go @@ -0,0 +1,214 @@ +package api + +import ( + "reflect" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" +) + +func TestTypeMinVersionObj(t *testing.T) { + t.Parallel() + + p := Product{ + NamedObject: NamedObject{ + Name: "test", + }, + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + } + + cases := []struct { + description string + obj Type + expected string + }{ + { + description: "type minVersion is empty and resource minVersion is empty", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + }, + expected: "ga", + }, + { + description: "type minVersion is empty and resource minVersion is beta", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ProductMetadata: &p, + }, + }, + expected: "beta", + }, + { + description: "type minVersion is not empty", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + }, + expected: "beta", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + versionObj := tc.obj.MinVersionObj() + + if got, want := versionObj.Name, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestTypeExcludeIfNotInVersion(t *testing.T) { + t.Parallel() + + p := Product{ + NamedObject: NamedObject{ + Name: "test", + }, + Versions: []*product.Version{ + &product.Version{ + Name: "beta", + BaseUrl: "beta_url", + }, + &product.Version{ + Name: "ga", + BaseUrl: "ga_url", + }, + &product.Version{ + Name: "alpha", + BaseUrl: "alpha_url", + }, + }, + } + + cases := []struct { + description string + obj Type + input *product.Version + expected bool + }{ + { + description: "type has Exclude true", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + Exclude: true, + MinVersion: "", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + }, + input: &product.Version{ + Name: "ga", + }, + expected: true, + }, + { + description: "type has Exclude false and not empty ExactVersion", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + Exclude: false, + ExactVersion: "beta", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + ProductMetadata: &p, + }, + }, + input: &product.Version{ + Name: "ga", + }, + expected: true, + }, + { + description: "type has Exclude false and empty ExactVersion", + obj: Type{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "beta", + Exclude: false, + ExactVersion: "", + ResourceMetadata: &Resource{ + NamedObject: NamedObject{ + Name: "test", + }, + MinVersion: "", + ProductMetadata: &p, + }, + }, + input: &product.Version{ + Name: "ga", + }, + expected: true, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + tc.obj.ExcludeIfNotInVersion(tc.input) + if got, want := tc.obj.Exclude, tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} From 7fa597482534e1a969520e28f330d7421b25f3ae Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 20:40:59 +0000 Subject: [PATCH 128/200] Update Dockerfiles to Go 1.21 (#10175) --- .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 2f2dcb85ecf5..d2f11e881954 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.20-bullseye AS builder +FROM golang:1.21-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.20-bullseye /usr/local/go /usr/local/go +COPY --from=golang:1.21-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 655f976726bf..b37e5ee8b996 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.20-bullseye AS builder +FROM golang:1.21-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.20-bullseye +FROM golang:1.21-bullseye SHELL ["/bin/bash", "-c"] ENV GOCACHE=/go/cache From 7b1ac65bae60038f8cb41a217174040f82183c6d Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Wed, 13 Mar 2024 13:41:48 -0700 Subject: [PATCH 129/200] Add an override for generating long form tests (#10162) --- tpgtools/override.go | 1 + tpgtools/property.go | 20 ++++++++++++++------ tpgtools/resource.go | 23 +++++++++++++++++++++++ tpgtools/sample.go | 9 ++++++--- tpgtools/serialization.go.base | 2 +- tpgtools/templates/serialization.go.tmpl | 16 ++++++++++++---- 6 files changed, 57 insertions(+), 14 deletions(-) diff --git a/tpgtools/override.go b/tpgtools/override.go index 5ce55962733c..53bd465818be 100644 --- a/tpgtools/override.go +++ b/tpgtools/override.go @@ -55,6 +55,7 @@ const ( TerraformProductName = "CUSTOM_TERRAFORM_PRODUCT_NAME" CustomTimeout = "CUSTOM_TIMEOUT" StateUpgrade = "STATE_UPGRADE" + GenerateLongFormTests = "GENERATE_LONG_FORM_TESTS" ) // Field-level Overrides diff --git a/tpgtools/property.go b/tpgtools/property.go index 62e5aa4fa51c..813b89e719ae 100644 --- a/tpgtools/property.go +++ b/tpgtools/property.go @@ -95,6 +95,11 @@ type Property struct { // the field being unset and being set to false. EnumBool bool + // Whether this field is only used as a url parameter + Parameter bool + // Whether this field has long form behavior in the DCL + HasLongForm bool + // An IdentityGetter is a function to retrieve the value of an "identity" field // from state. Identity fields will sometimes allow retrieval from multiple // fields or from the user's environment variables. @@ -210,7 +215,7 @@ func (t Type) IsSet() bool { } // Complex map is for maps of string --> object that are supported in DCL but -// not in Terraform. We handle this by adding a field in the Terraform schema +// not in Terraform. We handle this by adding a field in the Terraform schema // for the key in the map. This must be added via a COMPLEX_MAP_KEY_NAME // override func (t Type) IsComplexMap() bool { @@ -618,6 +623,9 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher } } + p.Parameter, _ = v.Extension["x-dcl-parameter"].(bool) + p.HasLongForm, _ = v.Extension["x-dcl-has-long-form"].(bool) + // Handle object properties if len(v.Properties) > 0 { props, err := createPropertiesFromSchema(v, typeFetcher, overrides, resource, &p, location) @@ -691,11 +699,11 @@ func createPropertiesFromSchema(schema *openapi.Schema, typeFetcher *TypeFetcher return nil, fmt.Errorf("failed to find complex map key name for map named: %s", p.Name()) } keyProp := Property{ - title: cm.KeyName, - Type: Type{&openapi.Schema{Type: "string"}}, - resource: resource, - parent: &p, - Required: true, + title: cm.KeyName, + Type: Type{&openapi.Schema{Type: "string"}}, + resource: resource, + parent: &p, + Required: true, Description: "The name for the key in the map for which this object is mapped to in the API", } props = append([]Property{keyProp}, props...) diff --git a/tpgtools/resource.go b/tpgtools/resource.go index 5ceda2b47bb5..c7916dd303a1 100644 --- a/tpgtools/resource.go +++ b/tpgtools/resource.go @@ -178,6 +178,9 @@ type Resource struct { SchemaVersion int // The schema versions from 0 to the current schema version SchemaVersions []int + + // Whether to generate long form versions of resource sample tests + GenerateLongFormTests bool } type Link struct { @@ -711,6 +714,10 @@ func createResource(schema *openapi.Schema, info *openapi.Info, typeFetcher *Typ } } + if overrides.ResourceOverride(GenerateLongFormTests, location) { + res.GenerateLongFormTests = true + } + res.Samples = res.loadSamples() return &res, nil @@ -977,7 +984,23 @@ func (r *Resource) loadDCLSamples() []Sample { sample.IgnoreRead = append(sample.IgnoreRead, "annotations") } + if r.GenerateLongFormTests { + longFormSample := sample + longFormSample.LongForm = true + var longFormDependencies []Dependency + mainResourceLongForm := longFormSample.generateSampleDependencyWithName(primaryResource, "primary") + longFormDependencies = append(longFormDependencies, mainResourceLongForm) + for _, dFileName := range longFormSample.DependencyFileNames { + longFormDependency := sample.generateSampleDependency(dFileName) + longFormDependencies = append(longFormDependencies, longFormDependency) + } + longFormSample.DependencyList = longFormDependencies + longFormSample.TestSlug += "LongForm" + samples = append(samples, longFormSample) + } + samples = append(samples, sample) + } return samples diff --git a/tpgtools/sample.go b/tpgtools/sample.go index 057b74dfa518..c934575ea8bd 100644 --- a/tpgtools/sample.go +++ b/tpgtools/sample.go @@ -46,6 +46,9 @@ type Sample struct { // in the testcase. (if the test doesn't have a ga version of the test) HasGAEquivalent bool + // LongForm is whether this sample is a copy with long form fields expanded to include `/` + LongForm bool + // SamplesPath is the path to the directory where the original sample data is stored SamplesPath Filepath @@ -165,7 +168,7 @@ func findDCLReferencePackage(product SnakeCaseProductName) (DCLPackageName, erro } // BuildDependency produces a Dependency using a file and filename -func BuildDependency(fileName string, product SnakeCaseProductName, localname, version string, hasGAEquivalent bool, b []byte) (*Dependency, error) { +func BuildDependency(fileName string, product SnakeCaseProductName, localname, version string, hasGAEquivalent, makeLongForm bool, b []byte) (*Dependency, error) { // Miscellaneous name rather than "resource name" because this is the name in the sample json file - which might not match the TF name! // we have to account for that. var resourceName miscellaneousNameSnakeCase @@ -194,7 +197,7 @@ func BuildDependency(fileName string, product SnakeCaseProductName, localname, v return nil, fmt.Errorf("Error generating sample dependency reference %s: %s", fileName, err) } - block, err := ConvertSampleJSONToHCL(packageName, resourceName, version, hasGAEquivalent, b) + block, err := ConvertSampleJSONToHCL(packageName, resourceName, version, hasGAEquivalent, makeLongForm, b) if err != nil { glog.Errorf("failed to convert %q", fileName) return nil, fmt.Errorf("Error generating sample dependency %s: %s", fileName, err) @@ -223,7 +226,7 @@ func (s *Sample) generateSampleDependencyWithName(fileName, localname string) De dependencyBytes, err := ioutil.ReadFile(path.Join(string(s.SamplesPath), fileName)) version := s.resourceReference.versionMetadata.V product := s.resourceReference.productMetadata.ProductName - d, err := BuildDependency(fileName, product, localname, version, s.HasGAEquivalent, dependencyBytes) + d, err := BuildDependency(fileName, product, localname, version, s.HasGAEquivalent, s.LongForm, dependencyBytes) if err != nil { glog.Exit(err) } diff --git a/tpgtools/serialization.go.base b/tpgtools/serialization.go.base index 58f01e79d9ba..d29fea9ab9fd 100644 --- a/tpgtools/serialization.go.base +++ b/tpgtools/serialization.go.base @@ -8,7 +8,7 @@ func DCLToTerraformReference(product DCLPackageName, resource miscellaneousNameS return "", fmt.Errorf("unimplemented - did you run `make serialize`?") } -func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSnakeCase, version string, hasGAEquivalent bool, b []byte) (string, error) { +func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSnakeCase, version string, hasGAEquivalent, makeLongForm bool, b []byte) (string, error) { return "", fmt.Errorf("unimplemented - did you run `make serialize`?") } diff --git a/tpgtools/templates/serialization.go.tmpl b/tpgtools/templates/serialization.go.tmpl index faba0a38cdfc..c1c46b76f030 100644 --- a/tpgtools/templates/serialization.go.tmpl +++ b/tpgtools/templates/serialization.go.tmpl @@ -72,7 +72,7 @@ func DCLToTerraformReference(product DCLPackageName, resource miscellaneousNameS } // ConvertSampleJSONToHCL unmarshals json to an HCL string. -func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSnakeCase, version string, hasGAEquivalent bool, b []byte) (string, error) { +func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSnakeCase, version string, hasGAEquivalent, makeLongForm bool, b []byte) (string, error) { {{- range $version, $resList := $.Resources }} {{- if not (eq $version.V "ga") }} if version == "{{$version.V}}" { @@ -86,7 +86,7 @@ func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSn {{- if $res.CustomSerializer }} return {{$res.CustomSerializer}}(*r, hasGAEquivalent) {{- else }} - return {{$res.TitleCaseFullName}}{{$version.SerializationSuffix}}AsHCL(*r, hasGAEquivalent) + return {{$res.TitleCaseFullName}}{{$version.SerializationSuffix}}AsHCL(*r, hasGAEquivalent, makeLongForm) {{- end }} {{- end }} } @@ -103,7 +103,7 @@ func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSn {{- if $res.CustomSerializer }} return {{$res.CustomSerializer}}(*r, hasGAEquivalent) {{- else }} - return {{$res.TitleCaseFullName}}{{$version.SerializationSuffix}}AsHCL(*r, hasGAEquivalent) + return {{$res.TitleCaseFullName}}{{$version.SerializationSuffix}}AsHCL(*r, hasGAEquivalent, makeLongForm) {{- end }} {{- end }} default: @@ -123,7 +123,7 @@ func ConvertSampleJSONToHCL(product DCLPackageName, resource miscellaneousNameSn // the crucial point is that `terraform import; terraform apply` will not produce // any changes. We do not validate that the resource specified will pass terraform // validation unless is an object returned from the API after an Apply. -func {{ $res.TitleCaseFullName }}{{$version.SerializationSuffix}}AsHCL(r {{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLStructName}}, hasGAEquivalent bool) (string, error) { +func {{ $res.TitleCaseFullName }}{{$version.SerializationSuffix}}AsHCL(r {{$res.Package}}{{$version.SerializationSuffix}}.{{$res.DCLStructName}}, hasGAEquivalent, makeLongForm bool) (string, error) { outputConfig := "resource \"{{$res.TerraformName}}\" \"output\" {\n" {{- range $field := $res.Properties}} {{- if $field.ShouldShowUpInSamples }} @@ -138,7 +138,15 @@ func {{ $res.TitleCaseFullName }}{{$version.SerializationSuffix}}AsHCL(r {{$res. } {{- else }} if r.{{$field.PackageName}} != nil { + {{- if or $field.Parameter $field.HasLongForm }} + if makeLongForm { + outputConfig += fmt.Sprintf("\t{{$field.Name}} = %#v\n", "long/form/" + *r.{{$field.PackageName}}) + } else { + outputConfig += fmt.Sprintf("\t{{$field.Name}} = %#v\n", *r.{{$field.PackageName}}) + } + {{- else }} outputConfig += fmt.Sprintf("\t{{$field.Name}} = %#v\n", *r.{{$field.PackageName}}) + {{- end }} } {{- end}} {{- else if $field.Type.IsObject }} From 67e2505f1821f00aeee54dac5f666a3ac913a71f Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 20:48:41 +0000 Subject: [PATCH 130/200] Update to go 1.21 (#10169) * Update .go-version file in TPG and TPGB repos * Update go.mod used to generate TPG/TPGB and run `go mod tidy` * Update go.mod in mmv1/third_party/terraform/scripts * Update go.mod in mmv1 * Update go.mod in docs * Update go.mod in tools/go-changelog and run `go mod tidy` * Update go.mod in tools/missing-test-detector and run `go mod tidy` * Update go.mod in tools/diff-processor * Update go.mod in tools/issue-labeler * Update go.mod in tools/teamcity-generator * Update go.mod in tpgtools and run `go mod tidy` * Update doctor script to ensure developers use Go 1.21 locally * Update GHA workflows to use Go 1.21 * Add missing update to GHA --- .ci/magician/go.mod | 2 +- .../gcb-membership-checker-test.yml | 2 +- .github/workflows/build-downstream.yml | 2 +- .github/workflows/membership-checker.yml | 2 +- .github/workflows/request-reviewer.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 +- .../workflows/unit-tests-diff-processor.yml | 2 +- docs/go.mod | 2 +- mmv1/go.mod | 2 +- mmv1/third_party/terraform/.go-version | 2 +- mmv1/third_party/terraform/go.mod.erb | 2 +- mmv1/third_party/terraform/go.sum | 29 +- mmv1/third_party/terraform/scripts/go.mod | 2 +- scripts/doctor | 4 +- tools/diff-processor/go.mod | 2 +- tools/go-changelog/go.mod | 1 - tools/go-changelog/go.sum | 18 -- tools/issue-labeler/go.mod | 8 +- tools/missing-test-detector/go.mod | 56 +--- tools/missing-test-detector/go.sum | 306 +----------------- tools/teamcity-generator/go.mod | 2 +- tpgtools/go.mod | 2 +- tpgtools/go.sum | 1 + 26 files changed, 59 insertions(+), 400 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 95f0b951ab1c..4f089f20df4f 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -1,6 +1,6 @@ module magician -go 1.20 +go 1.21 replace github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler => ../../tools/issue-labeler diff --git a/.ci/unit-tests/gcb-membership-checker-test.yml b/.ci/unit-tests/gcb-membership-checker-test.yml index 1c0c63636ba2..a77f10fc1f48 100644 --- a/.ci/unit-tests/gcb-membership-checker-test.yml +++ b/.ci/unit-tests/gcb-membership-checker-test.yml @@ -1,6 +1,6 @@ --- steps: - - name: 'golang:1.20' + - name: 'golang:1.21' args: - '-c' - | diff --git a/.github/workflows/build-downstream.yml b/.github/workflows/build-downstream.yml index 91f33499bd10..10fcc1c768da 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@v4 with: - go-version: '^1.20' + go-version: '^1.21' # Cache Go modules - name: Cache Go modules diff --git a/.github/workflows/membership-checker.yml b/.github/workflows/membership-checker.yml index 7a206b519eaa..6650f101acc2 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.20.1' + go-version: '^1.21' - name: Run membership checker unit tests run: | cd .ci/magician diff --git a/.github/workflows/request-reviewer.yml b/.github/workflows/request-reviewer.yml index 2831ec975caa..de54d2e2f353 100644 --- a/.github/workflows/request-reviewer.yml +++ b/.github/workflows/request-reviewer.yml @@ -28,7 +28,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '^1.20' + go-version: '^1.21' # Disable caching for now due to issues with large provider dependency caches cache: false - name: Build magician diff --git a/.github/workflows/test-tgc.yml b/.github/workflows/test-tgc.yml index 190bb6ae68c0..1edfa5b9399a 100644 --- a/.github/workflows/test-tgc.yml +++ b/.github/workflows/test-tgc.yml @@ -80,7 +80,7 @@ jobs: if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} uses: actions/setup-go@v4 with: - go-version: '^1.20' + go-version: '^1.21' - 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 9edca790e1ec..c59f4355f19d 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -70,7 +70,7 @@ jobs: if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} uses: actions/setup-go@v4 with: - go-version: '^1.20' + go-version: '^1.21' - 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 f254f91240db..34011a802bed 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@v4 with: - go-version: '^1.20' + go-version: '^1.21' - 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 ac925a0fe621..e394fd9ab8d4 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@v4 with: - go-version: '^1.20' + go-version: '^1.21' - name: Build Provider run: | diff --git a/.github/workflows/unit-tests-diff-processor.yml b/.github/workflows/unit-tests-diff-processor.yml index 91d081716ab3..8718b49b7e61 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.20.1' + go-version: '^1.21.0' - name: Build run: | diff --git a/docs/go.mod b/docs/go.mod index 35af46f9dda9..8d0779b9cb98 100644 --- a/docs/go.mod +++ b/docs/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/docs -go 1.20 +go 1.21 require ( github.com/alex-shpak/hugo-book v0.0.0-20230424134111-d86d5e70c7c0 // indirect diff --git a/mmv1/go.mod b/mmv1/go.mod index 24d9a6c630d1..58a9d896cd1a 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/mmv1 -go 1.20 +go 1.21 require ( golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 diff --git a/mmv1/third_party/terraform/.go-version b/mmv1/third_party/terraform/.go-version index 5fb5a6b4f547..d2ab029d32c6 100644 --- a/mmv1/third_party/terraform/.go-version +++ b/mmv1/third_party/terraform/.go-version @@ -1 +1 @@ -1.20 +1.21 diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index fa30a092113d..812e2da3e939 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -1,7 +1,7 @@ <% autogen_exception -%> module github.com/hashicorp/terraform-provider-google -go 1.20 +go 1.21 require ( cloud.google.com/go/bigtable v1.19.0 diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 63d8188cf48c..1cfc99eed33f 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -14,10 +14,12 @@ cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWO cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0 h1:s4Y6r6RrYLBnqosGXLwR0h1Gqr0VT3wgd6rqvHsD9OE= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.62.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= @@ -28,6 +30,7 @@ github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJE github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -47,12 +50,14 @@ github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbi github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creachadair/staticfile v0.1.2/go.mod h1:a3qySzCIXEprDGxk6tSxSI+dBBdLzqeBOMhZ+o2d3pM= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 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= @@ -70,8 +75,11 @@ github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git/v5 v5.10.1 h1:tu8/D8i+TWxgKpzQ3Vc43e+kkhXqtsZCKI/egajKnxk= +github.com/go-git/go-git/v5 v5.10.1/go.mod h1:uEuHjxkHap8kAl//V5F/nNWwqIYtP/402ddd05mp0wg= 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-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -81,6 +89,7 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 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/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 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= @@ -106,6 +115,7 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu 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/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 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= @@ -177,8 +187,11 @@ github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv2 github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= 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/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/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= @@ -214,15 +227,18 @@ 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/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/errors v0.8.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/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 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/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= 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= @@ -234,6 +250,7 @@ github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1F 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.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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= @@ -242,6 +259,7 @@ github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21 github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -258,6 +276,7 @@ go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFu go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -336,6 +355,7 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= 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= @@ -359,6 +379,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 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= @@ -404,6 +425,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= @@ -413,5 +435,4 @@ 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.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/mmv1/third_party/terraform/scripts/go.mod b/mmv1/third_party/terraform/scripts/go.mod index 8db8f05e9c85..0265d3bcb20a 100644 --- a/mmv1/third_party/terraform/scripts/go.mod +++ b/mmv1/third_party/terraform/scripts/go.mod @@ -1,3 +1,3 @@ module github.com/hashicorp/terraform-provider-google/scripts -go 1.20 +go 1.21 diff --git a/scripts/doctor b/scripts/doctor index ce131165d7f6..6a39b637e35c 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.20.0" ]]; then + if [[ "$version" < "go1.21.0" ]]; then exitcode=1 - warn "yel" " $version is installed, but go 1.20 or later is required. See https://golang.org/doc/install for information on installing it." + warn "yel" " $version is installed, but go 1.21 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 78da81c6aeaa..f740f857b9cf 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.20 +go 1.21 replace google/provider/old => ./old diff --git a/tools/go-changelog/go.mod b/tools/go-changelog/go.mod index 1dcdd361463b..3a898fd8dcdd 100644 --- a/tools/go-changelog/go.mod +++ b/tools/go-changelog/go.mod @@ -7,7 +7,6 @@ require ( github.com/go-git/go-git/v5 v5.4.2 github.com/google/go-github v17.0.0+incompatible github.com/google/go-querystring v1.0.0 // indirect - github.com/manifoldco/promptui v0.8.0 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20190423024810-112230192c58 ) diff --git a/tools/go-changelog/go.sum b/tools/go-changelog/go.sum index f15669f53a7b..ffa6cde2ab37 100644 --- a/tools/go-changelog/go.sum +++ b/tools/go-changelog/go.sum @@ -10,12 +10,6 @@ github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 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= @@ -47,8 +41,6 @@ github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH 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/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= -github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= 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/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -59,16 +51,8 @@ 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/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= -github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo= -github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -103,7 +87,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -121,7 +104,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 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= diff --git a/tools/issue-labeler/go.mod b/tools/issue-labeler/go.mod index a1fcbec43647..658e2f70955f 100644 --- a/tools/issue-labeler/go.mod +++ b/tools/issue-labeler/go.mod @@ -1,13 +1,11 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler -go 1.20 +go 1.21 require ( github.com/golang/glog v1.1.1 + golang.org/x/exp v0.0.0-20230810033253-352e893a4cad gopkg.in/yaml.v2 v2.4.0 ) -require ( - golang.org/x/exp v0.0.0-20230810033253-352e893a4cad // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect -) +require gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect diff --git a/tools/missing-test-detector/go.mod b/tools/missing-test-detector/go.mod index a074a5d1b471..e5d9ede9b28b 100644 --- a/tools/missing-test-detector/go.mod +++ b/tools/missing-test-detector/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/tools/missing-test-detector -go 1.20 +go 1.21 replace google/provider/old => github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230302220542-203a52c6e3e1 @@ -11,85 +11,41 @@ require ( github.com/hashicorp/hcl/v2 v2.14.1 github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 github.com/zclconf/go-cty v1.11.0 - google/provider/new v0.0.0-00010101000000-000000000000 - google/provider/old v0.0.0-00010101000000-000000000000 ) require ( - bitbucket.org/creachadair/stringset v0.0.8 // indirect - cloud.google.com/go v0.105.0 // indirect - cloud.google.com/go/bigtable v1.17.0 // indirect - cloud.google.com/go/compute v1.13.0 // indirect - cloud.google.com/go/compute/metadata v0.2.2 // indirect - cloud.google.com/go/iam v0.8.0 // indirect - cloud.google.com/go/longrunning v0.3.0 // indirect - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 // indirect github.com/agext/levenshtein v1.2.2 // indirect - github.com/apparentlymart/go-cidr v1.1.0 // 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.2.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 // indirect - github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect - github.com/envoyproxy/protoc-gen-validate v0.1.0 // indirect github.com/fatih/color v1.13.0 // indirect - github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 // indirect - github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/go-cpy v0.0.0-20211218193943-a9c933c06932 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/hashicorp/errwrap v1.0.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.4 // 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/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-go v0.14.0 // indirect github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect - github.com/hashicorp/terraform-provider-google-beta v1.20.0 // indirect - github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c // 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/kr/pretty v0.2.1 // indirect + github.com/kr/text v0.2.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/hashstructure v1.1.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/sergi/go-diff v1.2.0 // indirect + github.com/stretchr/testify 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.1 // indirect - go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 // indirect golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.105.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20221206210731-b1a01be3a5f6 // indirect - google.golang.org/grpc v1.51.0 // indirect google.golang.org/protobuf v1.28.1 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect ) diff --git a/tools/missing-test-detector/go.sum b/tools/missing-test-detector/go.sum index 9200a80bcd61..0adca9eb9012 100644 --- a/tools/missing-test-detector/go.sum +++ b/tools/missing-test-detector/go.sum @@ -1,204 +1,52 @@ -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.105.0 h1:DNtEKRBAAzeS4KyIory52wWHuClNaXJ5x1F7xa4q+5Y= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go/bigtable v1.17.0 h1:8t48YTxxFsYKy+AWuHdoePgAr4J2gEtntbdWclbEbco= -cloud.google.com/go/bigtable v1.17.0/go.mod h1:wtf7lFV1Wa5ay6aKa/gv/T2Ci7J6qXpBX8Ofij2z5mo= -cloud.google.com/go/compute v1.13.0 h1:AYrLkB8NPdDRslNp4Jxmzrhdr03fUAIDbiGFjLWowoU= -cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= -cloud.google.com/go/compute/metadata v0.2.2 h1:aWKAjYaBaOSrpKl57+jnS/3fJRQnxL7TvR/u1VVbt6k= -cloud.google.com/go/compute/metadata v0.2.2/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 h1:YhWTPhOf6gVpA9mSfnLOuL8Y6j8W5pzmHE7flXjTke4= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= -github.com/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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= -github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= 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-dump v0.0.0-20190214190832-042adf3cf4a0/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= 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 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= -github.com/cespare/xxhash/v2 v2.1.1/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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/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-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 h1:zH8ljVhhq7yC0MIeUL/IviMtY8hx2mK8cN9wEYb8ggw= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/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.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 h1:xvqufLtNVwAhN8NMyWklVgxnWohi+wtMGQMhtxexlm0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 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/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= -github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= -github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -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/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/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.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -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.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/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.6/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 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/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/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.0 h1:y8Yozv7SZtlU//QXbezB6QkpuE6jMD2/gfzk4AftXjs= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -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/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 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.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ= -github.com/hashicorp/go-plugin v1.4.4/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-go v0.14.0 h1:ttnSlS8bz3ZPYbMb84DpcPhY4F5DsQtcAS7cHo8uvP4= github.com/hashicorp/terraform-plugin-go v0.14.0/go.mod h1:2nNCBeRLaenyQEi78xrGrs9hMbulveqG/zDMQSvVJTE= 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-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-beta v1.20.0 h1:rxZwjTPOQgmSaBINGCRhGTf9svsFU3n1iaF5i3rYIbo= -github.com/hashicorp/terraform-provider-google-beta v1.20.0/go.mod h1:t8+8q1zjjAREhGZHvwPU35evEHk9FqNvCpP8+HwJ3Cw= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230302220542-203a52c6e3e1 h1:SQt8Fqd3Gn3/kztAZP66iPeAZWc0sSI8BuAInGlz7fY= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230302220542-203a52c6e3e1/go.mod h1:t2+a8diaNw8ijSr89vu1SXw8xaHPZ6xSHnNEnRHNfvk= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230303123138-8194a951d003 h1:JKikj+wm7GTMmjN27QJHiQpngOW/5JE7Az58Gk4YNcs= -github.com/hashicorp/terraform-provider-google-beta v1.20.1-0.20230303123138-8194a951d003/go.mod h1:t2+a8diaNw8ijSr89vu1SXw8xaHPZ6xSHnNEnRHNfvk= -github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c h1:D8aRO6+mTqHfLsK/BC3j5OAoogv1WLRWzY1AaTo3rBg= -github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI= -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.1 h1:4/2yi5LyDPP7nN+Hiird1SAJ6YoxUm13/oxHGRnbPd8= -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= @@ -206,10 +54,8 @@ 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= @@ -218,45 +64,24 @@ github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9 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/hashstructure v1.1.0/go.mod h1:xUDAozZz0Wmdiufv0uyhnHkUTN6/6d8ulp4AwfLKrmA= 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/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce h1:RPclfga2SEJmgMmz2k+Mg7cowZ8yv4Trqw9UsJby758= -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/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4v2r9jz+c9i1IfIttS/OkmLfrk1jne5hs= 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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -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/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -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= @@ -269,167 +94,44 @@ github.com/vmihailenco/msgpack/v4 v4.3.12 h1:07s4sz9IReOgdikxLTKNbBdqDMLsjPKXwvC github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1 h1:quXMXlA39OCbd2wAdTsGDlK9RkOk6Wuw+x37wVyIuWY= github.com/vmihailenco/tagparser v0.1.1/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.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -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.0.0-20220517005047-85d78b3ac167 h1:O8uGbHCqlTp2P6QJSLmCojM4mN6UemYv8K+dCnmHmu0= -golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -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.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -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.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 h1:nt+Q6cXKz4MosCSpnbMtqiQ8Oz0pxTef2B4Vca2lvfk= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= 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/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-20200323222414-85ca7c5b95cd/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-20210119212857-b64e53b001e4/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.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.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.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 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.105.0 h1:t6P9Jj+6XTn4U9I2wycQai6Q/Kz7iOT+QzjJ3G2V4x8= -google.golang.org/api v0.105.0/go.mod h1:qh7eD5FJks5+BcE+cjBIm6Gz8vioK7EHvnlniqXBnqI= 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-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20221206210731-b1a01be3a5f6 h1:AGXp12e/9rItf6/4QymU7WsAUwCf+ICW75cuR91nJIc= -google.golang.org/genproto v0.0.0-20221206210731-b1a01be3a5f6/go.mod h1:1dOng4TWOomJrDGhpXjfCD35wQC6jnC7HpRmOFRqEV0= -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.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U= -google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= -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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/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.3/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/tools/teamcity-generator/go.mod b/tools/teamcity-generator/go.mod index 3f998f908e09..52feebc78ba3 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.20 +go 1.21 require golang.org/x/text v0.11.0 diff --git a/tpgtools/go.mod b/tpgtools/go.mod index 90f55b270e1e..370f45a397b2 100644 --- a/tpgtools/go.mod +++ b/tpgtools/go.mod @@ -1,6 +1,6 @@ module github.com/GoogleCloudPlatform/magic-modules/tpgtools -go 1.20 +go 1.21 require ( bitbucket.org/creachadair/stringset v0.0.11 diff --git a/tpgtools/go.sum b/tpgtools/go.sum index 30d683a7cf40..93cccba40a06 100644 --- a/tpgtools/go.sum +++ b/tpgtools/go.sum @@ -108,6 +108,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From 5114e38e93aa6bb80ef4d3040d1e06ff96023caf Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Wed, 13 Mar 2024 22:28:26 +0000 Subject: [PATCH 131/200] Add note about permissions (#10195) --- .../terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mmv1/third_party/terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md b/mmv1/third_party/terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md index 08bf66acb3a3..ee0d3c3a0cef 100644 --- a/mmv1/third_party/terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md +++ b/mmv1/third_party/terraform/.teamcity/USE_CONFIG_WITH_TEAMCITY.md @@ -8,6 +8,10 @@ Contents: * [Editing configuration files](#editing-configuration-files) * [Pushing configuration changes to TeamCity](#pushing-configuration-changes-to-teamcity) +## Permissions + +Actions in this file require Project Administrator permissions - ask for these if you are unsure if you have them. + ## Using configuration files for the first time in a project From ca2bf3fb16fac2bc518da50d5d8c241207b4732f Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Wed, 13 Mar 2024 16:14:37 -0700 Subject: [PATCH 132/200] Fix the bug for computed labels and annotations (#10182) --- .../resource_bigquery_dataset_test.go | 70 +++++++++++++++++++ ...esource_cloudbuild_worker_pool_test.go.erb | 63 +++++++++++++++++ .../terraform/tpgresource/annotations.go | 9 +++ .../terraform/tpgresource/labels.go | 13 ++++ 4 files changed, 155 insertions(+) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go index f4c23fd09306..eec2a3a37c56 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_dataset_test.go @@ -98,6 +98,55 @@ func TestAccBigQueryDataset_basic(t *testing.T) { }) } +func TestAccBigQueryDataset_withComputedLabels(t *testing.T) { + // Skip it in VCR test because of the randomness of uuid in "labels" field + // which causes the replaying mode after recording mode failing in VCR test + acctest.SkipIfVcr(t) + t.Parallel() + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + }, + CheckDestroy: testAccCheckBigQueryDatasetDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryDataset(datasetID), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.env", "foo"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "labels.default_table_expiration_ms", "3600000"), + + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.%", "2"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.env", "foo"), + resource.TestCheckResourceAttr("google_bigquery_dataset.test", "effective_labels.default_table_expiration_ms", "3600000"), + ), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + // The labels field in the state is decided by the configuration. + // During importing, the configuration is unavailable, so the labels field in the state after importing is empty. + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + { + Config: testAccBigQueryDatasetUpdated_withComputedLabels(datasetID), + }, + { + ResourceName: "google_bigquery_dataset.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, + }, + }, + }) +} + func TestAccBigQueryDataset_withProvider5(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() @@ -493,6 +542,27 @@ resource "google_bigquery_dataset" "test" { `, datasetID) } +func testAccBigQueryDatasetUpdated_withComputedLabels(datasetID string) string { + return fmt.Sprintf(` +resource "random_uuid" "test" { +} + +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" + # friendly_name = "bar" + description = "This is a bar description" + location = "EU" + default_partition_expiration_ms = 7200000 + default_table_expiration_ms = 7200000 + + labels = { + env = "${random_uuid.test.result}" + default_table_expiration_ms = 7200000 + } +} +`, datasetID) +} + func testAccBigQueryDatasetDeleteContents(datasetID string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "contents_test" { diff --git a/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_test.go.erb b/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_test.go.erb index 2954e203a654..73d952177b0b 100644 --- a/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudbuild/resource_cloudbuild_worker_pool_test.go.erb @@ -14,6 +14,47 @@ import ( transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" ) +func TestAccCloudbuildWorkerPool_withComputedAnnotations(t *testing.T) { + // Skip it in VCR test because of the randomness of uuid in "annotations" field + // which causes the replaying mode after recording mode failing in VCR test + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "project": envvar.GetTestProjectFromEnv(), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + }, + CheckDestroy: funcAccTestCloudbuildWorkerPoolCheckDestroy(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudbuildWorkerPool_updated(context), + }, + { + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, + ResourceName: "google_cloudbuild_worker_pool.pool", + }, + { + Config: testAccCloudbuildWorkerPool_withComputedAnnotations(context), + }, + { + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"annotations"}, + ResourceName: "google_cloudbuild_worker_pool.pool", + }, + }, + }) +} + func TestAccCloudbuildWorkerPool_basic(t *testing.T) { t.Parallel() @@ -89,6 +130,28 @@ resource "google_cloudbuild_worker_pool" "pool" { `, context) } +func testAccCloudbuildWorkerPool_withComputedAnnotations(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "random_uuid" "test" { +} + +resource "google_cloudbuild_worker_pool" "pool" { + name = "pool%{random_suffix}" + location = "europe-west1" + worker_config { + disk_size_gb = 101 + machine_type = "e2-standard-4" + no_external_ip = false + } + + annotations = { + env = "${random_uuid.test.result}" + default_expiration_ms = 3600000 + } +} +`, context) +} + func testAccCloudbuildWorkerPool_noWorkerConfig(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_cloudbuild_worker_pool" "pool" { diff --git a/mmv1/third_party/terraform/tpgresource/annotations.go b/mmv1/third_party/terraform/tpgresource/annotations.go index 410fbd2355d4..d43d608d16de 100644 --- a/mmv1/third_party/terraform/tpgresource/annotations.go +++ b/mmv1/third_party/terraform/tpgresource/annotations.go @@ -17,6 +17,15 @@ func SetAnnotationsDiff(_ context.Context, d *schema.ResourceDiff, meta interfac return fmt.Errorf("`effective_annotations` field is not present in the resource schema.") } + // If "annotations" field is computed, set "effective_annotations" to computed. + // https://github.com/hashicorp/terraform-provider-google/issues/16217 + if !d.GetRawPlan().GetAttr("annotations").IsWhollyKnown() { + if err := d.SetNewComputed("effective_annotations"); err != nil { + return fmt.Errorf("error setting effective_annotations to computed: %w", err) + } + return nil + } + o, n := d.GetChange("annotations") effectiveAnnotations := d.Get("effective_annotations").(map[string]interface{}) diff --git a/mmv1/third_party/terraform/tpgresource/labels.go b/mmv1/third_party/terraform/tpgresource/labels.go index 0465456e254a..5cfaa93ef41a 100644 --- a/mmv1/third_party/terraform/tpgresource/labels.go +++ b/mmv1/third_party/terraform/tpgresource/labels.go @@ -69,6 +69,19 @@ func SetLabelsDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) return fmt.Errorf("`effective_labels` field is not present in the resource schema.") } + // If "labels" field is computed, set "terraform_labels" and "effective_labels" to computed. + // https://github.com/hashicorp/terraform-provider-google/issues/16217 + if !d.GetRawPlan().GetAttr("labels").IsWhollyKnown() { + if err := d.SetNewComputed("terraform_labels"); err != nil { + return fmt.Errorf("error setting terraform_labels to computed: %w", err) + } + + if err := d.SetNewComputed("effective_labels"); err != nil { + return fmt.Errorf("error setting effective_labels to computed: %w", err) + } + return nil + } + config := meta.(*transport_tpg.Config) // Merge provider default labels with the user defined labels in the resource to get terraform managed labels From 1e3a728a0e161678338b385ee04d4a92b4603c57 Mon Sep 17 00:00:00 2001 From: Lingkai Shen Date: Thu, 14 Mar 2024 11:27:35 -0400 Subject: [PATCH 133/200] AndroidApp package_name should be immutable & required (#10194) --- mmv1/products/firebase/AndroidApp.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mmv1/products/firebase/AndroidApp.yaml b/mmv1/products/firebase/AndroidApp.yaml index 3e58993f5e98..47b74005bd5c 100644 --- a/mmv1/products/firebase/AndroidApp.yaml +++ b/mmv1/products/firebase/AndroidApp.yaml @@ -122,8 +122,10 @@ properties: This identifier should be treated as an opaque token, as the data format is not specified. - !ruby/object:Api::Type::String name: packageName + immutable: true + required: true description: | - Immutable. The canonical package name of the Android app as would appear in the Google Play + The canonical package name of the Android app as would appear in the Google Play Developer Console. - !ruby/object:Api::Type::Array name: sha1Hashes From 10f99b700278026de23a26bc1475783d300a411c Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 14 Mar 2024 11:41:51 -0700 Subject: [PATCH 134/200] Fix service team reviews (#10200) * Corrected unknown command messge to clean up stderr * Made tests throw error if team name is empty * Fixed handling of unset github_team name --- .ci/magician/cmd/mock_github_test.go | 9 ++++++- .ci/magician/cmd/mock_runner_test.go | 26 +++++++++++++++++-- .ci/magician/cmd/request_service_reviewers.go | 2 +- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.ci/magician/cmd/mock_github_test.go b/.ci/magician/cmd/mock_github_test.go index 69eb80eee99f..5a836ff602f0 100644 --- a/.ci/magician/cmd/mock_github_test.go +++ b/.ci/magician/cmd/mock_github_test.go @@ -15,7 +15,11 @@ */ package cmd -import "magician/github" +import ( + "errors" + + "magician/github" +) type mockGithub struct { pullRequest github.PullRequest @@ -53,6 +57,9 @@ func (m *mockGithub) GetPullRequestPreviousReviewers(prNumber string) ([]github. func (m *mockGithub) GetTeamMembers(organization, team string) ([]github.User, error) { m.calledMethods["GetTeamMembers"] = append(m.calledMethods["GetTeamMembers"], []any{organization, team}) + if team == "" { + return nil, errors.New("No team members set") + } return m.teamMembers[team], nil } diff --git a/.ci/magician/cmd/mock_runner_test.go b/.ci/magician/cmd/mock_runner_test.go index bc470b13d685..72587c26b418 100644 --- a/.ci/magician/cmd/mock_runner_test.go +++ b/.ci/magician/cmd/mock_runner_test.go @@ -20,7 +20,12 @@ import ( "errors" "fmt" "log" + "os" "path/filepath" + "sort" + "strings" + + "golang.org/x/exp/maps" ) type ParameterList []any @@ -37,7 +42,24 @@ type mockRunner struct { dirStack *list.List } +func sortedEnvString(env map[string]string) string { + keys := maps.Keys(env) + sort.Strings(keys) + kvs := make([]string, len(keys)) + for i, k := range keys { + kvs[i] = fmt.Sprintf("%s:%s", k, env[k]) + } + return fmt.Sprintf("map[%s]", strings.Join(kvs, " ")) +} + func NewMockRunner() MockRunner { + diffProcessorEnv := map[string]string{ + "NEW_REF": "auto-pr-123456", + "OLD_REF": "auto-pr-123456-old", + "PATH": os.Getenv("PATH"), + "GOPATH": os.Getenv("GOPATH"), + "HOME": os.Getenv("HOME"), + } return &mockRunner{ calledMethods: make(map[string][]ParameterList), cmdResults: map[string]string{ @@ -47,7 +69,7 @@ func NewMockRunner() MockRunner { "/mock/dir/magic-modules/.ci/magician git [clone -b auto-pr-123456 https://modular-magician:*******@github.com/modular-magician/terraform-provider-google-beta /mock/dir/tpgb] map[]": "", "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", - "/mock/dir/magic-modules/tools/diff-processor make [build] map[NEW_REF:auto-pr-123456 OLD_REF:auto-pr-123456-old]": "", + "/mock/dir/magic-modules/tools/diff-processor make [build] " + sortedEnvString(diffProcessorEnv): "", "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [add-labels 123456] map[GITHUB_TOKEN_MAGIC_MODULES:*******]": "", "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", @@ -128,7 +150,7 @@ func (mr *mockRunner) PopDir() error { func (mr *mockRunner) Run(name string, args []string, env map[string]string) (string, error) { mr.calledMethods["Run"] = append(mr.calledMethods["Run"], ParameterList{mr.cwd, name, args, env}) - cmd := fmt.Sprintf("%s %s %v %v", mr.cwd, name, args, env) + cmd := fmt.Sprintf("%s %s %v %s", mr.cwd, name, args, sortedEnvString(env)) if result, ok := mr.cmdResults[cmd]; ok { return result, nil } diff --git a/.ci/magician/cmd/request_service_reviewers.go b/.ci/magician/cmd/request_service_reviewers.go index 6ef80c5283c0..70343946ee34 100644 --- a/.ci/magician/cmd/request_service_reviewers.go +++ b/.ci/magician/cmd/request_service_reviewers.go @@ -89,7 +89,7 @@ func execRequestServiceReviewers(prNumber string, gh GithubClient, enrolledTeams continue } teamCount += 1 - if labelData, ok := enrolledTeams[label.Name]; ok { + if labelData, ok := enrolledTeams[label.Name]; ok && labelData.Team != "" { githubTeamsSet[labelData.Team] = struct{}{} } } From 16d4f0faa68159cdeffa19bb1cc1df810d191d73 Mon Sep 17 00:00:00 2001 From: Benjamin Kaplan <58792807+bskaplan@users.noreply.github.com> Date: Thu, 14 Mar 2024 12:30:19 -0700 Subject: [PATCH 135/200] Add gcs volume type to Cloud Run v2 beta provider (#9746) * Add gcs volume type to Cloud Run v2 beta provider * update gcs v2 docs to specify required launch stage and execution environment * merge changes with upstream --- mmv1/products/cloudrunv2/Job.yaml | 23 ++++ mmv1/products/cloudrunv2/Service.yaml | 12 +- ... => resource_cloud_run_v2_job_test.go.erb} | 89 +++++++++++++++ .../resource_cloud_run_v2_service_test.go.erb | 103 +++++++++++++++++- 4 files changed, 224 insertions(+), 3 deletions(-) rename mmv1/third_party/terraform/services/cloudrunv2/{resource_cloud_run_v2_job_test.go => resource_cloud_run_v2_job_test.go.erb} (77%) diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index 176c056e5715..4daa40450fc6 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -399,6 +399,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::String name: 'secret' @@ -437,6 +438,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Array name: 'instances' @@ -452,6 +454,7 @@ properties: # - template.0.template.0.volumes.0.secret # - template.0.template.0.volumes.0.cloudSqlInstance # - template.0.template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Enum name: 'medium' @@ -464,6 +467,26 @@ properties: name: 'sizeLimit' description: |- Limit on the storage usable by this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. This field's values are of the 'Quantity' k8s type: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir. + - !ruby/object:Api::Type::NestedObject + name: 'gcs' + description: |- + Cloud Storage bucket mounted as a volume using GCSFuse. This feature requires the launch stage to be set to ALPHA or BETA. + min_version: beta + # exactly_one_of: + # - template.0.volumes.0.secret + # - template.0.volumes.0.cloudSqlInstance + # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs + properties: + - !ruby/object:Api::Type::String + name: 'bucket' + required: true + description: |- + Name of the cloud storage bucket to back the volume. The resource service account must have permission to access the bucket. + - !ruby/object:Api::Type::Boolean + name: 'readOnly' + description: |- + If true, mount this volume as read-only in all mounts. If false, mount this volume as read-write. - !ruby/object:Api::Type::String name: 'timeout' description: |- diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index bbedcc2cf10c..909b454786a6 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -741,6 +741,7 @@ properties: # - template.0.volumes.0.secret # - template.0.volumes.0.cloudSqlInstance # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Array name: 'instances' @@ -757,6 +758,7 @@ properties: # - template.0.volumes.0.secret # - template.0.volumes.0.cloudSqlInstance # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::Enum name: 'medium' @@ -770,8 +772,14 @@ properties: description: |- Limit on the storage usable by this EmptyDir volume. The size limit is also applicable for memory medium. The maximum usage on memory medium EmptyDir would be the minimum value between the SizeLimit specified here and the sum of memory limits of all containers in a pod. This field's values are of the 'Quantity' k8s type: https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/. The default is nil which means that the limit is undefined. More info: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir. - !ruby/object:Api::Type::NestedObject - name: gcs - description: Represents a GCS Bucket mounted as a volume. + name: 'gcs' + description: |- + Cloud Storage bucket mounted as a volume using GCSFuse. This feature is only supported in the gen2 execution environment and requires launch-stage to be set to ALPHA or BETA. + # exactly_one_of: + # - template.0.volumes.0.secret + # - template.0.volumes.0.cloudSqlInstance + # - template.0.volumes.0.emptyDir + # - template.0.volumes.0.gcs properties: - !ruby/object:Api::Type::String name: bucket diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb similarity index 77% rename from mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go rename to mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb index e2cbbba9a30a..feca32ee81e7 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go.erb @@ -1,3 +1,4 @@ +<% autogen_exception -%> package cloudrunv2_test import ( @@ -298,3 +299,91 @@ func testAccCloudRunV2Job_cloudrunv2JobWithDirectVPCUpdate(context map[string]in } `, context) } + +<% unless version == 'ga' -%> +func TestAccCloudRunV2Job_cloudrunv2JobWithGcsUpdate(t *testing.T) { + t.Parallel() + + jobName := fmt.Sprintf("tf-test-cloudrun-service%s", acctest.RandString(t, 10)) + context := map[string]interface{}{ + "job_name": jobName, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2JobDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Job_cloudrunv2JobWithNoVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + }, + { + Config: testAccCloudRunV2Job_cloudrunv2JobWithGcsVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + }, + }, + }) +} + +func testAccCloudRunV2Job_cloudrunv2JobWithNoVolume(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_cloud_run_v2_job" "default" { + name = "%{job_name}" + location = "us-central1" + launch_stage = "BETA" + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } + } +`, context) +} + +func testAccCloudRunV2Job_cloudrunv2JobWithGcsVolume(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_cloud_run_v2_job" "default" { + name = "%{job_name}" + location = "us-central1" + launch_stage = "BETA" + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + volume_mounts { + name = "gcs" + mount_path = "/mnt/gcs" + } + } + volumes { + name = "gcs" + gcs { + bucket = "gcp-public-data-landsat" + read_only = true + } + } + } + } + } +`, context) +} +<% end -%> diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb index bacaa401b2d6..b4f3b6ad5a9a 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go.erb @@ -46,6 +46,7 @@ func TestAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(t *testing.T) { }) } + func testAccCloudRunV2Service_cloudrunv2ServiceFull(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_cloud_run_v2_service" "default" { @@ -109,7 +110,6 @@ resource "google_service_account" "service_account" { } `, context) } - func testAccCloudRunV2Service_cloudrunv2ServiceFullUpdate(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_cloud_run_v2_service" "default" { @@ -208,7 +208,108 @@ resource "google_compute_network" "custom_test" { } `, context) } +<% unless version == 'ga' -%> +func TestAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(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: testAccCheckCloudRunV2ServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(context), + }, + { + ResourceName: "google_cloud_run_v2_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location", "annotations", "labels", "terraform_labels", "launch_stage"}, + }, + }, + }) +} + +func testAccCloudRunV2Service_cloudrunv2ServiceGcsVolume(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_service" "default" { + name = "tf-test-cloudrun-service%{random_suffix}" + description = "description creating" + location = "us-central1" + launch_stage = "BETA" + annotations = { + generated-by = "magic-modules" + } + ingress = "INGRESS_TRAFFIC_ALL" + labels = { + label-1 = "value-1" + } + client = "client-1" + client_version = "client-version-1" + template { + labels = { + label-1 = "value-1" + } + timeout = "300s" + service_account = google_service_account.service_account.email + execution_environment = "EXECUTION_ENVIRONMENT_GEN2" + scaling { + max_instance_count = 3 + min_instance_count = 1 + } + annotations = { + generated-by = "magic-modules" + } + volumes { + name = "gcs" + gcs { + bucket = "gcp-public-data-landsat" + read_only = true + } + } + containers { + name = "container-1" + image = "us-docker.pkg.dev/cloudrun/container/hello" + env { + name = "SOURCE" + value = "remote" + } + env { + name = "TARGET" + value = "home" + } + ports { + name = "h2c" + container_port = 8080 + } + volume_mounts { + name = "gcs" + mount_path = "/mnt/landsat" + } + resources { + cpu_idle = true + startup_cpu_boost = true + limits = { + cpu = "4" + memory = "2Gi" + } + } + } + session_affinity = false + } +} +resource "google_service_account" "service_account" { + account_id = "tf-test-my-account%{random_suffix}" + display_name = "Test Service Account" +} +`, context) +} +<%end -%> func TestAccCloudRunV2Service_cloudrunv2ServiceTCPProbesUpdate(t *testing.T) { t.Parallel() From 219ab589aaafa919c7011967def03305f56c8462 Mon Sep 17 00:00:00 2001 From: Ali Ebrahim Date: Thu, 14 Mar 2024 13:36:33 -0700 Subject: [PATCH 136/200] cloudrunv2: Validate number of ports specified restricting to 1. (#10173) * cloudrunv2: Validate number of ports specified restricting to 1. * Update mmv1/products/cloudrunv2/Service.yaml --- mmv1/products/cloudrunv2/Service.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index 909b454786a6..2568620c8fc7 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -448,6 +448,7 @@ properties: Determines whether CPU should be boosted on startup of a new container instance above the requested CPU threshold, this can help reduce cold-start latency. - !ruby/object:Api::Type::Array name: 'ports' + max_size: 1 description: |- List of ports to expose from the container. Only a single port can be specified. The specified ports must be listening on all interfaces (0.0.0.0) within the container to be accessible. From fab4b93a978a4cb74f7d4726c4102ac500961a1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:15:54 -0700 Subject: [PATCH 137/200] Bump google.golang.org/protobuf from 1.28.1 to 1.33.0 in /.ci/magician (#10196) Bumps google.golang.org/protobuf from 1.28.1 to 1.33.0. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .ci/magician/go.mod | 11 +++++++---- .ci/magician/go.sum | 21 +++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 4f089f20df4f..165526d48c67 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -13,7 +13,11 @@ require ( google.golang.org/api v0.112.0 ) -require github.com/otiai10/copy v1.12.0 +require ( + github.com/otiai10/copy v1.12.0 + github.com/stretchr/testify v1.8.4 + gopkg.in/yaml.v2 v2.4.0 +) require ( cloud.google.com/go/compute v1.18.0 // indirect @@ -25,8 +29,8 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/net v0.15.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect @@ -35,7 +39,6 @@ require ( google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect google.golang.org/grpc v1.53.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.ci/magician/go.sum b/.ci/magician/go.sum index cc6550f565aa..7fc76449804d 100644 --- a/.ci/magician/go.sum +++ b/.ci/magician/go.sum @@ -5,13 +5,13 @@ cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOV 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/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler v0.0.0-20231219215713-49252d7a95dc h1:EhpDpfqwRHmrIgDJQkdNOMhm374ylpVuR1sN7EdgVr4= -github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler v0.0.0-20231219215713-49252d7a95dc/go.mod h1:mqTMlyCznI9dA2Mf8oVdRuCArfCwfHE+5vpe3wEQ7qI= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 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/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +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= @@ -47,6 +47,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -56,12 +57,20 @@ github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1Yu github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= +github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= @@ -80,8 +89,6 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230314191032-db074128a8ec h1:pAv+d8BM2JNnNctsLJ6nnZ6NqXT8N4+eauvZSb3P0I0= -golang.org/x/exp v0.0.0-20230314191032-db074128a8ec/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp v0.0.0-20230810033253-352e893a4cad h1:g0bG7Z4uG+OgH2QDODnjp6ggkk1bJDsINcuWmJN1iJU= golang.org/x/exp v0.0.0-20230810033253-352e893a4cad/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -148,9 +155,11 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 944450cac1644467f78fbcde4ed870ccbd07ba6f Mon Sep 17 00:00:00 2001 From: askubis Date: Thu, 14 Mar 2024 23:18:59 +0100 Subject: [PATCH 138/200] attempt at fixing the (R)IGM.status output message (#10188) * attempt at fixing the (R)IGM.status output message * Fix plural of instances * Fix plural of instances * Fix plural of instances * Fix plural of instances --- ...urce_compute_instance_group_manager.go.erb | 22 ++++++++++++------- ...mpute_region_instance_group_manager.go.erb | 7 +++++- ...mpute_instance_group_manager.html.markdown | 12 ++++++++-- ...egion_instance_group_manager.html.markdown | 12 ++++++++-- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb index 97baae34251f..7ee2ac2bbb18 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_group_manager.go.erb @@ -459,13 +459,18 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { Computed: true, Description: `Status of all-instances configuration on the group.`, Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "effective": { - Type: schema.TypeBool, - Computed: true, - Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, - }, - }, + Schema: map[string]*schema.Schema{ + "effective": { + Type: schema.TypeBool, + Computed: true, + Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, + }, + "current_revision": { + Type: schema.TypeString, + Computed: true, + Description: `Current all-instances configuration revision. This value is in RFC3339 text format.`, + }, + }, }, }, "stateful": { @@ -482,7 +487,7 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { "per_instance_configs": { Type: schema.TypeList, Computed: true, - Description: `Status of per-instance configs on the instance.`, + Description: `Status of per-instance configs on the instances.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "all_effective": { @@ -1492,6 +1497,7 @@ func flattenStatusAllInstancesConfig(allInstancesConfig *compute.InstanceGroupMa results := []map[string]interface{}{} data := map[string]interface{}{ "effective": allInstancesConfig.Effective, + "current_revision": allInstancesConfig.CurrentRevision, } results = append(results, data) return results diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb index 8c756656264c..9a380f05eaf5 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_group_manager.go.erb @@ -492,6 +492,11 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Computed: true, Description: `A bit indicating whether this configuration has been applied to all managed instances in the group.`, }, + "current_revision": { + Type: schema.TypeString, + Computed: true, + Description: `Current all-instances configuration revision. This value is in RFC3339 text format.`, + }, }, }, }, @@ -509,7 +514,7 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { "per_instance_configs": { Type: schema.TypeList, Computed: true, - Description: `Status of per-instance configs on the instance.`, + Description: `Status of per-instance configs on the instances.`, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "all_effective": { diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown index 04f576cb43cf..b76ff773958b 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_group_manager.html.markdown @@ -329,17 +329,25 @@ The `status` block holds: * `version_target` - A status of consistency of Instances' versions with their target version specified by version field on Instance Group Manager. +* `all_instances_config` - Status of all-instances configuration on the group. + +* `stateful` - Stateful status of the given Instance Group Manager. + The `version_target` block holds: * `version_target` - A bit indicating whether version target has been reached in this managed instance group, i.e. all instances are in their target version. Instances' target version are specified by version field on Instance Group Manager. -* `stateful` - Stateful status of the given Instance Group Manager. +The `all_instances_config` block holds: + +* `effective` - A bit indicating whether this configuration has been applied to all managed instances in the group. + +* `current_revision` - Current all-instances configuration revision. This value is in RFC3339 text format. The `stateful` block holds: * `has_stateful_config` - A bit indicating whether the managed instance group has stateful configuration, that is, if you have configured any items in a stateful policy or in per-instance configs. The group might report that it has no stateful config even when there is still some preserved state on a managed instance, for example, if you have deleted all PICs but not yet applied those deletions. -* `per_instance_configs` - Status of per-instance configs on the instance. +* `per_instance_configs` - Status of per-instance configs on the instances. The `per_instance_configs` block holds: diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown index eeab84344718..052747cdee7f 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_group_manager.html.markdown @@ -336,19 +336,27 @@ The `status` block holds: * `is_stable` - A bit indicating whether the managed instance group is in a stable state. A stable state means that: none of the instances in the managed instance group is currently undergoing any type of change (for example, creation, restart, or deletion); no future changes are scheduled for instances in the managed instance group; and the managed instance group itself is not being modified. +* `all_instances_config` - Status of all-instances configuration on the group. + +* `stateful` - Stateful status of the given Instance Group Manager. + * `version_target` - A status of consistency of Instances' versions with their target version specified by version field on Instance Group Manager. The `version_target` block holds: * `version_target` - A bit indicating whether version target has been reached in this managed instance group, i.e. all instances are in their target version. Instances' target version are specified by version field on Instance Group Manager. -* `stateful` - Stateful status of the given Instance Group Manager. +The `all_instances_config` block holds: + +* `effective` - A bit indicating whether this configuration has been applied to all managed instances in the group. + +* `current_revision` - Current all-instances configuration revision. This value is in RFC3339 text format. The `stateful` block holds: * `has_stateful_config` - A bit indicating whether the managed instance group has stateful configuration, that is, if you have configured any items in a stateful policy or in per-instance configs. The group might report that it has no stateful config even when there is still some preserved state on a managed instance, for example, if you have deleted all PICs but not yet applied those deletions. -* `per_instance_configs` - Status of per-instance configs on the instance. +* `per_instance_configs` - Status of per-instance configs on the instances. The `per_instance_configs` block holds: From 7f8a73595635f1ddd917fd6b33ce9a6d1bcf2c97 Mon Sep 17 00:00:00 2001 From: Charles Leon Date: Thu, 14 Mar 2024 15:21:16 -0700 Subject: [PATCH 139/200] Access Context Manager - make ingress and egress rules immutable (#10147) * Access Context Manager - make ingress and egress rules immutable * Move immutable state to top level resource --------- Co-authored-by: Charles Leon --- .../ServicePerimeterEgressPolicy.yaml | 10 ++++- .../ServicePerimeterIngressPolicy.yaml | 10 ++++- ...ger_service_perimeter_egress_policy.tf.erb | 36 +++++++++++++++++ ...er_service_perimeter_ingress_policy.tf.erb | 39 +++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index 738ceefd98bd..5c26b6c85bc8 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -18,6 +18,7 @@ self_link: '{{perimeter}}' create_verb: :PATCH delete_verb: :PATCH update_mask: true +immutable: true identity: - egressFrom - egressTo @@ -37,6 +38,14 @@ description: | within the ServicePerimeter to access a defined set of projects outside the perimeter in certain contexts (e.g. to read data from a Cloud Storage bucket or query against a BigQuery dataset). + + ~> **Note:** By default, updates to this resource will remove the EgressPolicy from the + from the perimeter and add it back in a non-atomic manner. To ensure that the new EgressPolicy + is added before the old one is removed, add a `lifecycle` block with `create_before_destroy = true` to this resource. +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_egress_policy' + skip_test: true autogen_async: true exclude_tgc: true # Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter @@ -54,7 +63,6 @@ parameters: description: | The name of the Service Perimeter to add this resource to. required: true - immutable: true url_param_only: true properties: - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 195b87db9bfa..c17f8a3e0471 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -18,6 +18,7 @@ self_link: '{{perimeter}}' create_verb: :PATCH delete_verb: :PATCH update_mask: true +immutable: true identity: - ingressFrom - ingressTo @@ -38,6 +39,14 @@ description: | For access from private networks, using the project of the hosting network is required. Individual ingress policies can be limited by restricting which services and/ or actions they match using the ingressTo field. + + ~> **Note:** By default, updates to this resource will remove the IngressPolicy from the + from the perimeter and add it back in a non-atomic manner. To ensure that the new IngressPolicy + is added before the old one is removed, add a `lifecycle` block with `create_before_destroy = true` to this resource. +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_ingress_policy' + skip_test: true autogen_async: true exclude_tgc: true # Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter @@ -55,7 +64,6 @@ parameters: description: | The name of the Service Perimeter to add this resource to. required: true - immutable: true url_param_only: true properties: - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb new file mode 100644 index 000000000000..7ea39e59976f --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_egress_policy.tf.erb @@ -0,0 +1,36 @@ +resource "google_access_context_manager_service_perimeter" "storage-perimeter" { + parent = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}/serviceperimeters/storage-perimeter" + title = "Storage Perimeter" + status { + restricted_services = ["storage.googleapis.com"] + } + lifecycle { + ignore_changes = [status[0].resources] + } +} + +resource "google_access_context_manager_service_perimeter_egress_policy" "egress_policy" { + perimeter = "${google_access_context_manager_service_perimeter.storage-perimeter.name}" + egress_from { + identity_type = "ANY_IDENTITY" + } + egress_to { + resources = ["*"] + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + method = "*" + } + } + } + lifecycle { + create_before_destroy = true + } +} + + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "Storage Policy" +} diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb new file mode 100644 index 000000000000..b54c62bcc207 --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_ingress_policy.tf.erb @@ -0,0 +1,39 @@ +resource "google_access_context_manager_service_perimeter" "storage-perimeter" { + parent = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}/serviceperimeters/storage-perimeter" + title = "Storage Perimeter" + status { + restricted_services = ["storage.googleapis.com"] + } + lifecycle { + ignore_changes = [status[0].resources] + } +} + +resource "google_access_context_manager_service_perimeter_ingress_policy" "ingress_policy" { + perimeter = "${google_access_context_manager_service_perimeter.storage-perimeter.name}" + ingress_from { + identity_type = "any_identity" + sources { + access_level = "*" + } + } + ingress_to { + resources = ["*"] + operations { + service_name = "bigquery.googleapis.com" + method_selectors { + method = "*" + } + } + } + lifecycle { + create_before_destroy = true + } +} + + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "Storage Policy" +} From 809bb4d0ff12d871736ef450986894512b57f394 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 15:54:00 -0700 Subject: [PATCH 140/200] Bump golang.org/x/net from 0.10.0 to 0.17.0 in /.ci/magician (#9243) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.10.0 to 0.17.0. - [Commits](https://github.com/golang/net/compare/v0.10.0...v0.17.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .ci/magician/go.mod | 4 ++-- .ci/magician/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 165526d48c67..9c2971179e9f 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -32,9 +32,9 @@ require ( github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/net v0.15.0 // indirect + golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect - golang.org/x/sys v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect diff --git a/.ci/magician/go.sum b/.ci/magician/go.sum index 7fc76449804d..ce55618fb1c3 100644 --- a/.ci/magician/go.sum +++ b/.ci/magician/go.sum @@ -101,8 +101,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn 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-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +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.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= @@ -113,8 +113,8 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h 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-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/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/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= From 3218971e9a3a93c444b05f761bfaa89568044a48 Mon Sep 17 00:00:00 2001 From: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Date: Thu, 14 Mar 2024 16:08:34 -0700 Subject: [PATCH 141/200] fix datastream private connection sweeper (#10201) * fix datastream private connection sweeper * update * run gofmt --- .../datastream/PrivateConnection.yaml | 2 + ...e_datastream_private_connection_sweeper.go | 126 ++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go diff --git a/mmv1/products/datastream/PrivateConnection.yaml b/mmv1/products/datastream/PrivateConnection.yaml index f2bc7884d1db..4d38f0b9fe56 100644 --- a/mmv1/products/datastream/PrivateConnection.yaml +++ b/mmv1/products/datastream/PrivateConnection.yaml @@ -25,6 +25,8 @@ description: | immutable: true schema_version: 1 state_upgraders: true +# Skipping the sweeper since the resource needs force-deletion +skip_sweeper: true id_format: projects/{{project}}/locations/{{location}}/privateConnections/{{private_connection_id}} import_format: [ diff --git a/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go b/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go new file mode 100644 index 000000000000..81150729a74b --- /dev/null +++ b/mmv1/third_party/terraform/services/datastream/resource_datastream_private_connection_sweeper.go @@ -0,0 +1,126 @@ +package datastream + +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("DatastreamPrivateConnection", testSweepDatastreamPrivateConnection) +} + +// At the time of writing, the CI only passes us-central1 as the region +func testSweepDatastreamPrivateConnection(region string) error { + resourceName := "DatastreamPrivateConnection" + 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://datastream.googleapis.com/v1/projects/{{project}}/locations/{{location}}/privateConnections", "?")[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["privateConnections"] + 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{}) + var name string + // Id detected in the delete URL, attempt to use id. + if obj["id"] != nil { + name = tpgresource.GetResourceNameFromSelfLink(obj["id"].(string)) + } else if obj["name"] != nil { + name = tpgresource.GetResourceNameFromSelfLink(obj["name"].(string)) + } else { + log.Printf("[INFO][SWEEPER_LOG] %s resource name and id were nil", resourceName) + return nil + } + // Skip resources that shouldn't be sweeped + if !sweeper.IsSweepableTestResource(name) { + nonPrefixCount++ + continue + } + + deleteTemplate := "https://datastream.googleapis.com/v1/projects/{{project}}/locations/{{location}}/privateConnections/{{private_connection_id}}" + 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 + "?force=true" + + // 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 +} From 0152b9d97c10ace81f1e4c12d5152398d6e94482 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:46:45 +0000 Subject: [PATCH 142/200] Add SarahFrench to on vacation list (#10189) --- .ci/magician/github/membership.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index 908970d1b08f..112388d4a75a 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -46,7 +46,9 @@ var ( trustedContributors = []string{} // 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{} + onVacationReviewers = []string{ + "SarahFrench", + } ) type UserType int64 From 28c58f90bcb46bac2fc699812130ccc775902f28 Mon Sep 17 00:00:00 2001 From: Ryan Oaks Date: Fri, 15 Mar 2024 10:59:43 -0400 Subject: [PATCH 143/200] Modify issue labeler to skip linked issues (#10199) * Modify issue labeler to skip linked issues * Update tests --- tools/issue-labeler/labeler/backfill.go | 8 ++++++++ tools/issue-labeler/labeler/backfill_test.go | 12 +++--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tools/issue-labeler/labeler/backfill.go b/tools/issue-labeler/labeler/backfill.go index 12db0cc04238..89eed2d58077 100644 --- a/tools/issue-labeler/labeler/backfill.go +++ b/tools/issue-labeler/labeler/backfill.go @@ -98,6 +98,14 @@ func ComputeIssueUpdates(issues []Issue, regexpLabels []RegexpLabel) []IssueUpda continue } + // Decision was made to no longer add new service labels to linked tickets, because it is + // more difficult to know which teams have received those tickets and which haven't. + // Forwarding a ticket to a different service team should involve removing the old service + // label and `linked` label. + if linked { + continue + } + var issueUpdate IssueUpdate for label := range desired { issueUpdate.OldLabels = append(issueUpdate.OldLabels, label) diff --git a/tools/issue-labeler/labeler/backfill_test.go b/tools/issue-labeler/labeler/backfill_test.go index c58e7f14b8e6..36ffa8defee3 100644 --- a/tools/issue-labeler/labeler/backfill_test.go +++ b/tools/issue-labeler/labeler/backfill_test.go @@ -136,7 +136,7 @@ func TestComputeIssueUpdates(t *testing.T) { }, }, }, - "add missing service labels even if already linked": { + "don't add missing service labels if already linked": { issues: []Issue{ { Number: 1, @@ -145,14 +145,8 @@ func TestComputeIssueUpdates(t *testing.T) { PullRequest: map[string]any{}, }, }, - regexpLabels: defaultRegexpLabels, - expectedIssueUpdates: []IssueUpdate{ - { - Number: 1, - Labels: []string{"forward/linked", "service/service1", "service/service2-subteam1"}, - OldLabels: []string{"service/service2-subteam1", "forward/linked"}, - }, - }, + regexpLabels: defaultRegexpLabels, + expectedIssueUpdates: []IssueUpdate{}, }, } From 4c432c6d4d96c2537b7818afdbef4387d8894733 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Fri, 15 Mar 2024 15:57:19 +0000 Subject: [PATCH 144/200] Remove misleading examples from docs for `google_dataform_repository`, add new example (#10187) * Remove misleading examples from docs for `google_dataform_repository`, add new example * Remove unusued var from new example * Fix typo * Fix other instances of typo --- mmv1/products/dataform/Repository.yaml | 27 ++++++++++-- .../examples/dataform_repository.tf.erb | 7 +-- ...rm_repository_with_cloudsource_repo.tf.erb | 43 +++++++++++++++++++ ...tory_with_cloudsource_repo_and_ssh.tf.erb} | 0 .../resource_dataform_repository_test.go.erb | 8 ++-- 5 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb rename mmv1/templates/terraform/examples/{dataform_repository_ssh.tf.erb => dataform_repository_with_cloudsource_repo_and_ssh.tf.erb} (100%) diff --git a/mmv1/products/dataform/Repository.yaml b/mmv1/products/dataform/Repository.yaml index 1d99d98c8fb7..41c8bfd4e289 100644 --- a/mmv1/products/dataform/Repository.yaml +++ b/mmv1/products/dataform/Repository.yaml @@ -34,7 +34,24 @@ import_format: examples: - !ruby/object:Provider::Terraform::Examples name: 'dataform_repository' - primary_resource_id: dataform_respository + # This example is used in the docs to address this issue + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + skip_test: true + primary_resource_id: dataform_repository + primary_resource_name: + 'fmt.Sprintf("tf_test_dataform_repository%s", context["random_suffix"])' + min_version: beta + vars: + dataform_repository_name: 'dataform_repository' + data: secret-data + secret_name: my-secret + - !ruby/object:Provider::Terraform::Examples + name: 'dataform_repository_with_cloudsource_repo' + # Although the Terraform config can be applied without error, the connection between Dataform and the SourceRepo aren't yet functional + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + # See : https://issuetracker.google.com/issues/287850319 + skip_docs: true + primary_resource_id: dataform_repository primary_resource_name: 'fmt.Sprintf("tf_test_dataform_repository%s", context["random_suffix"])' min_version: beta @@ -44,8 +61,12 @@ examples: data: secret-data secret_name: my-secret - !ruby/object:Provider::Terraform::Examples - name: 'dataform_repository_ssh' - primary_resource_id: dataform_respository + name: 'dataform_repository_with_cloudsource_repo_and_ssh' + # Although the Terraform config can be applied without error, the connection between Dataform and the SourceRepo aren't yet functional + # See : https://github.com/hashicorp/terraform-provider-google/issues/17335 + # See : https://issuetracker.google.com/issues/287850319 + skip_docs: true + primary_resource_id: dataform_repository min_version: beta vars: git_repository_name: 'my/repository' diff --git a/mmv1/templates/terraform/examples/dataform_repository.tf.erb b/mmv1/templates/terraform/examples/dataform_repository.tf.erb index 1e76e9133b1e..ff237f57c15c 100644 --- a/mmv1/templates/terraform/examples/dataform_repository.tf.erb +++ b/mmv1/templates/terraform/examples/dataform_repository.tf.erb @@ -1,8 +1,3 @@ -resource "google_sourcerepo_repository" "git_repository" { - provider = google-beta - name = "<%= ctx[:vars]['git_repository_name'] %>" -} - resource "google_secret_manager_secret" "secret" { provider = google-beta secret_id = "<%= ctx[:vars]['secret_name'] %>" @@ -30,7 +25,7 @@ resource "google_dataform_repository" "<%= ctx[:primary_resource_id] %>" { } git_remote_settings { - url = google_sourcerepo_repository.git_repository.url + url = "https://github.com/OWNER/REPOSITORY.git" default_branch = "main" authentication_token_secret_version = google_secret_manager_secret_version.secret_version.id } diff --git a/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb new file mode 100644 index 000000000000..1e76e9133b1e --- /dev/null +++ b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo.tf.erb @@ -0,0 +1,43 @@ +resource "google_sourcerepo_repository" "git_repository" { + provider = google-beta + name = "<%= ctx[:vars]['git_repository_name'] %>" +} + +resource "google_secret_manager_secret" "secret" { + provider = google-beta + secret_id = "<%= ctx[:vars]['secret_name'] %>" + + replication { + auto {} + } +} + +resource "google_secret_manager_secret_version" "secret_version" { + provider = google-beta + secret = google_secret_manager_secret.secret.id + + secret_data = "<%= ctx[:vars]['data'] %>" +} + +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 + default_branch = "main" + authentication_token_secret_version = google_secret_manager_secret_version.secret_version.id + } + + workspace_compilation_overrides { + default_database = "database" + schema_suffix = "_suffix" + table_prefix = "prefix_" + } +} diff --git a/mmv1/templates/terraform/examples/dataform_repository_ssh.tf.erb b/mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo_and_ssh.tf.erb similarity index 100% rename from mmv1/templates/terraform/examples/dataform_repository_ssh.tf.erb rename to mmv1/templates/terraform/examples/dataform_repository_with_cloudsource_repo_and_ssh.tf.erb diff --git a/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb b/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb index fd24afe43b3f..396a5703a77a 100644 --- a/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb +++ b/mmv1/third_party/terraform/services/dataform/resource_dataform_repository_test.go.erb @@ -26,7 +26,7 @@ func TestAccDataformRepository_updated(t *testing.T) { Config: testAccDataformRepository_basic(context), }, { - ResourceName: "google_dataform_repository.dataform_respository", + ResourceName: "google_dataform_repository.dataform_repository", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"region"}, @@ -35,7 +35,7 @@ func TestAccDataformRepository_updated(t *testing.T) { Config: testAccDataformRepository_updated(context), }, { - ResourceName: "google_dataform_repository.dataform_respository", + ResourceName: "google_dataform_repository.dataform_repository", ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"region"}, @@ -67,7 +67,7 @@ resource "google_secret_manager_secret_version" "secret_version" { secret_data = "tf-test-secret-data%{random_suffix}" } -resource "google_dataform_repository" "dataform_respository" { +resource "google_dataform_repository" "dataform_repository" { provider = google-beta name = "tf_test_dataform_repository%{random_suffix}" @@ -109,7 +109,7 @@ resource "google_secret_manager_secret_version" "secret_version" { secret_data = "tf-test-secret-data%{random_suffix}" } -resource "google_dataform_repository" "dataform_respository" { +resource "google_dataform_repository" "dataform_repository" { provider = google-beta name = "tf_test_dataform_repository%{random_suffix}" From fdafe53d72b626ee367c769efb5bca6d70429cac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 10:20:20 -0700 Subject: [PATCH 145/200] Bump google.golang.org/grpc from 1.53.0 to 1.56.3 in /.ci/magician (#9366) Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.53.0 to 1.56.3. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.53.0...v1.56.3) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .ci/magician/go.mod | 14 +++++++------- .ci/magician/go.sum | 28 ++++++++++++++-------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.ci/magician/go.mod b/.ci/magician/go.mod index 9c2971179e9f..3ac92fda1f95 100644 --- a/.ci/magician/go.mod +++ b/.ci/magician/go.mod @@ -10,7 +10,7 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 // indirect golang.org/x/exp v0.0.0-20230810033253-352e893a4cad - google.golang.org/api v0.112.0 + google.golang.org/api v0.114.0 ) require ( @@ -20,25 +20,25 @@ require ( ) require ( - cloud.google.com/go/compute v1.18.0 // indirect + cloud.google.com/go/compute v1.19.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/glog v1.1.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/googleapis/gax-go/v2 v2.7.1 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/oauth2 v0.7.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 // indirect - google.golang.org/grpc v1.53.0 // indirect + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect + google.golang.org/grpc v1.56.3 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/.ci/magician/go.sum b/.ci/magician/go.sum index ce55618fb1c3..d63fb6058429 100644 --- a/.ci/magician/go.sum +++ b/.ci/magician/go.sum @@ -1,7 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY= -cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs= +cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= +cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= 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/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= @@ -37,8 +37,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq 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.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +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/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= @@ -53,8 +53,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -104,8 +104,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY 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.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -126,8 +126,8 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 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/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.112.0 h1:iDmzvZ4C086R3+en4nSyIf07HlQKMOX1Xx2dmia/+KQ= -google.golang.org/api v0.112.0/go.mod h1:737UfWHNsOq4F3REUTmb+GN9pugkgNLCayLTfoIKpPc= +google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE= +google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= 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.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= @@ -135,15 +135,15 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID 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-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488 h1:QQF+HdiI4iocoxUjjpLgvTYDHKm99C/VtTBFnfiCJos= -google.golang.org/genproto v0.0.0-20230303212802-e74f57abe488/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= 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.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= -google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= +google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= 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= From 77816ee766a56cf2b09c332b9b9fbc3bd6d50cea Mon Sep 17 00:00:00 2001 From: roop2 <161707562+roop2@users.noreply.github.com> Date: Fri, 15 Mar 2024 23:24:19 +0530 Subject: [PATCH 146/200] Moving the netapp kmsconfig resource update test to a different region to avoid conflict with create test (#10185) --- .../netapp/resource_netapp_kmsconfig_test.go | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go b/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go index 0f309e3f5a8d..5bd73fde3264 100644 --- a/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go +++ b/mmv1/third_party/terraform/services/netapp/resource_netapp_kmsconfig_test.go @@ -1,20 +1,6 @@ // 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 ( @@ -63,7 +49,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Full(context map[string]inter return acctest.Nprintf(` resource "google_kms_key_ring" "keyring" { name = "tf-test-key-ring%{random_suffix}" - location = "us-central1" + location = "us-east4" } resource "google_kms_crypto_key" "crypto_key" { @@ -75,7 +61,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Full(context map[string]inter name = "tf-test-kms-test%{random_suffix}" description="this is a test description" crypto_key_name=google_kms_crypto_key.crypto_key.id - location="us-central1" + location="us-east4" } `, context) } @@ -84,7 +70,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Update(context map[string]int return acctest.Nprintf(` resource "google_kms_key_ring" "keyring" { name = "tf-test-key-ring%{random_suffix}" - location = "us-central1" + location = "us-east4" } resource "google_kms_crypto_key" "crypto_key" { @@ -96,7 +82,7 @@ func testAccNetappkmsconfig_kmsConfigCreateExample_Update(context map[string]int name = "tf-test-kms-test%{random_suffix}" description="kmsconfig update" crypto_key_name=google_kms_crypto_key.crypto_key.id - location="us-central1" + location="us-east4" labels = { "foo": "bar", } From 6dfce95e0728bdfc9ca43d3f616c1759d54b3341 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 15 Mar 2024 11:11:28 -0700 Subject: [PATCH 147/200] Only run mmv1 rake tests and yaml linting if relevant files have changed (#10207) * Only run mmv1 rake tests and yaml linting if relevant files have changed * fix path for rb files Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --------- Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com> --- ...modules.yml => mmv1-lint-product-yaml.yml} | 33 ++-------------- .github/workflows/mmv1-rake-tests.yml | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 30 deletions(-) rename .github/workflows/{magic-modules.yml => mmv1-lint-product-yaml.yml} (56%) create mode 100644 .github/workflows/mmv1-rake-tests.yml diff --git a/.github/workflows/magic-modules.yml b/.github/workflows/mmv1-lint-product-yaml.yml similarity index 56% rename from .github/workflows/magic-modules.yml rename to .github/workflows/mmv1-lint-product-yaml.yml index d92e666e2b60..7a732c6c7402 100644 --- a/.github/workflows/magic-modules.yml +++ b/.github/workflows/mmv1-lint-product-yaml.yml @@ -1,9 +1,11 @@ -name: magic-modules +name: mmv1-lint-product-yaml permissions: read-all on: pull_request: + paths: + - 'mmv1/products/**' jobs: lint-yaml: @@ -32,32 +34,3 @@ jobs: - name: Lint YAML files if: ${{ !failure() && steps.pull_request.outputs.yamlfiles != '' }} run: yamllint -c repo/.yamllint ${{steps.pull_request.outputs.yamlfiles}} - rake-tests: - runs-on: ubuntu-22.04 - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - with: - path: repo - fetch-depth: 2 - - name: Merge base branch - id: pull_request - run: | - cd repo - git config user.name "modular-magician" - git config user.email "magic-modules@google.com" - git fetch origin ${{ github.base_ref }} # Fetch the base branch - git merge --no-ff origin/${{ github.base_ref }} # Merge with the base branch - - name: Set up Ruby - uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 - with: - ruby-version: '3.1' - - name: Install dependencies - run: | - cd repo/mmv1 - bundle install - - name: Run rake tests - run: | - cd repo/mmv1 - bundle exec rake test - diff --git a/.github/workflows/mmv1-rake-tests.yml b/.github/workflows/mmv1-rake-tests.yml new file mode 100644 index 000000000000..e6d1ecb5ea1f --- /dev/null +++ b/.github/workflows/mmv1-rake-tests.yml @@ -0,0 +1,39 @@ +name: mmv1-rake-tests + +permissions: read-all + +on: + pull_request: + paths: + - 'mmv1/**/*.rb' + +jobs: + rake-tests: + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + with: + path: repo + fetch-depth: 2 + - name: Merge base branch + id: pull_request + run: | + cd repo + git config user.name "modular-magician" + git config user.email "magic-modules@google.com" + git fetch origin ${{ github.base_ref }} # Fetch the base branch + git merge --no-ff origin/${{ github.base_ref }} # Merge with the base branch + - name: Set up Ruby + uses: ruby/setup-ruby@036ef458ddccddb148a2b9fb67e95a22fdbf728b # v1.160.0 + with: + ruby-version: '3.1' + - name: Install dependencies + run: | + cd repo/mmv1 + bundle install + - name: Run rake tests + run: | + cd repo/mmv1 + bundle exec rake test + From 64b712308bdcc40f68f7d17d05a2c476e902298b Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 15 Mar 2024 13:06:49 -0700 Subject: [PATCH 148/200] Clean up functions and add slice utility functions (#10210) * Clean up function all_resourcerefs * Add slice utility functions * Change sensitive_props as resource method --- mmv1/api/resource.rb | 45 +----- mmv1/google/slice_utils.go | 41 ++++++ mmv1/google/slice_utils_test.go | 138 ++++++++++++++++++ .../terraform/resource.html.markdown.erb | 5 +- 4 files changed, 185 insertions(+), 44 deletions(-) create mode 100644 mmv1/google/slice_utils.go create mode 100644 mmv1/google/slice_utils_test.go diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index 7ff67c56035a..a3036a3c6d79 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -389,11 +389,6 @@ def all_nested_properties(props) nested end - # Returns all resourcerefs at any depth - def all_resourcerefs - resourcerefs_for_properties(all_user_properties, self) - end - # All settable properties in the resource. # Fingerprints aren't *really" settable properties, but they behave like one. # At Create, they have no value but they can just be read in anyways, and after a Read @@ -425,6 +420,10 @@ def root_properties end end + def sensitive_props + all_nested_properties(root_properties).select(&:sensitive) + end + # Return the product-level async object, or the resource-specific one # if one exists. def async @@ -770,41 +769,5 @@ def validate_identity if all_user_properties.select { |p| p.name == i }.empty? end end - - # Given an array of properties, return all ResourceRefs contained within - # Requires: - # props- a list of props - # original_object - the original object containing props. This is to - # avoid self-referencing objects. - def resourcerefs_for_properties(props, original_obj) - rrefs = [] - props.each do |p| - # We need to recurse on ResourceRefs to get all levels - # We do not want to recurse on resourcerefs of type self to avoid - # infinite loop. - if p.is_a? Api::Type::ResourceRef - # We want to avoid a circular reference - # This reference may be the next reference or have some number of refs - # in between it. - next if p.resource_ref == original_obj - next if p.resource_ref == p.__resource - - rrefs << p - rrefs.concat(resourcerefs_for_properties(p.resource_ref - .required_properties, - original_obj)) - elsif !p.nested_properties.nil? - rrefs.concat(resourcerefs_for_properties(p.nested_properties, original_obj)) - elsif p.is_a? Api::Type::Array - if p.item_type.is_a? Api::Type::ResourceRef - rrefs << p.item_type - rrefs.concat(resourcerefs_for_properties(p.item_type.resource_ref - .required_properties, - original_obj)) - end - end - end - rrefs.uniq - end end end diff --git a/mmv1/google/slice_utils.go b/mmv1/google/slice_utils.go new file mode 100644 index 000000000000..75ad22de3b7d --- /dev/null +++ b/mmv1/google/slice_utils.go @@ -0,0 +1,41 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google + +// Returns a new slice containing all of the elements +// for which the test function returns true in the original slice +func Select[T any](S []T, test func(T) bool) (ret []T) { + for _, s := range S { + if test(s) { + ret = append(ret, s) + } + } + return +} + +// Returns a new slice containing all of the elements +// for which the test function returns false in the original slice +func Reject[T any](S []T, test func(T) bool) (ret []T) { + for _, s := range S { + if !test(s) { + ret = append(ret, s) + } + } + return +} + +// Concat two slices +func Concat[T any](S1 []T, S2 []T) (ret []T) { + return append(S1, S2...) +} diff --git a/mmv1/google/slice_utils_test.go b/mmv1/google/slice_utils_test.go new file mode 100644 index 000000000000..98532795f8b0 --- /dev/null +++ b/mmv1/google/slice_utils_test.go @@ -0,0 +1,138 @@ +package google + +import ( + "reflect" + "testing" +) + +func TestSliceSelect(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S []int + testFun func(int) bool + expected int + }{ + { + description: "interger slice selects even numbers", + S: []int{0, 1, 2}, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 2, + }, + { + description: "empty slice", + S: make([]int, 0), + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + { + description: "nil slice", + S: nil, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Select(tc.S, tc.testFun)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestSliceReject(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S []int + testFun func(int) bool + expected int + }{ + { + description: "interger slice rejects even numbers", + S: []int{0, 1, 2}, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 1, + }, + { + description: "empty slice", + S: make([]int, 0), + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + { + description: "nil slice", + S: nil, + testFun: func(n int) bool { + return n%2 == 0 + }, + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Reject(tc.S, tc.testFun)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} + +func TestSliceConcat(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + S1 []int + S2 []int + expected int + }{ + { + description: "interger slice rejects even numbers", + S1: []int{0, 1, 2}, + S2: []int{3, 4}, + expected: 5, + }, + { + description: "empty slice", + S1: nil, + S2: make([]int, 0), + expected: 0, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := len(Concat(tc.S1, tc.S2)), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/templates/terraform/resource.html.markdown.erb b/mmv1/templates/terraform/resource.html.markdown.erb index bc03202abe3d..f411914debeb 100644 --- a/mmv1/templates/terraform/resource.html.markdown.erb +++ b/mmv1/templates/terraform/resource.html.markdown.erb @@ -40,7 +40,6 @@ tf_subcategory = (object.__product.display_name) terraform_name = object.legacy_name || "google_#{tf_product}_#{object.name.underscore}" properties = object.all_user_properties - sensitive_props = object.all_nested_properties(object.root_properties).select(&:sensitive) # In order of preference, use TF override, # general defined timeouts, or default Timeouts timeouts = object.timeouts @@ -87,9 +86,9 @@ To get more information about <%= object.name -%>, see: ~> **Note:** <%= object.docs.note -%> <%- end -%> -<%- if !sensitive_props.empty? -%> +<%- if !object.sensitive_props.empty? -%> <%- - sense_props = sensitive_props.map! {|prop| "`"+prop.lineage+"`"}.join(', ') + sense_props = object.sensitive_props.map! {|prop| "`"+prop.lineage+"`"}.join(', ') -%> ~> **Warning:** All arguments including the following potentially sensitive From 1b2c21428b470c523ac42c47ddecb9bfd84d3331 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 15 Mar 2024 13:18:29 -0700 Subject: [PATCH 149/200] Removed github-differ bash scripts (#10208) --- .../github-differ/compare_breaking_changes.sh | 59 ----- .../go-plus/github-differ/generate_comment.sh | 221 ------------------ .../go-plus/github-differ/test_tools.sh | 39 ---- .ci/scripts/go-plus/github-differ/utils.sh | 15 -- 4 files changed, 334 deletions(-) delete mode 100755 .ci/scripts/go-plus/github-differ/compare_breaking_changes.sh delete mode 100755 .ci/scripts/go-plus/github-differ/generate_comment.sh delete mode 100755 .ci/scripts/go-plus/github-differ/test_tools.sh delete mode 100755 .ci/scripts/go-plus/github-differ/utils.sh diff --git a/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh b/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh deleted file mode 100755 index 921554908999..000000000000 --- a/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -# input: two environment variables -# TPG_BREAKING - results of runing breaking change detector -# against tpg -# TPGB_BREAKING - results of runing breaking change detector -# against tpgb -# output: echo to console -# message section cotaining: a header, -# tpg's unique messages, and all of tpgb's messages - -tpgUnique="" -newline=$'\n' - -# This while loop itterates over each individual -# line of TPG_BREAKING. The input to the while loop -# is through the <<< at the conclusion of the loop. -while read -r tpgi; do - simpleTPG=$(sed 's/-.*//' <<< "$tpgi") - found="false" - while read -r tpgbi; do - simpleTPGB=$(sed 's/-.*//' <<< "$tpgbi") - if [ "$simpleTPG" == "$simpleTPGB" ]; then - found="true" - fi - done <<< "$TPGB_BREAKING" - if [ "$found" != "true" ]; then - if [ "$tpgUnique" == "" ]; then - tpgUnique="${tpgi}" - else - tpgUnique="${tpgUnique}${newline}${tpgi}" - fi - fi -done <<< "$TPG_BREAKING" - - -breakingchanges="" -if [ "$tpgUnique" != "" ]; then - tpgUnique=$(sed 's/^/\* /' <<< "$tpgUnique") - breakingchanges="${breakingchanges}${tpgUnique}${newline}" -fi - -if [ "$TPGB_BREAKING" != "" ]; then - tpgbBreaking=$(sed 's/^/\* /' <<< "$TPGB_BREAKING") - breakingchanges="${breakingchanges}${tpgbBreaking}${newline}" -fi - -if [ "$breakingchanges" != "" ]; then -message="## Breaking Change(s) Detected -The following breaking change(s) were detected within your pull request. - -${breakingchanges} - -If you believe this detection to be incorrect please raise the concern with your reviewer. If you intend to make this change you will need to wait for a [major release](https://www.terraform.io/plugin/sdkv2/best-practices/versioning#example-major-number-increments) window. An \`override-breaking-change\` label can be added to allow merging. -" -fi - -echo "$message" - - diff --git a/.ci/scripts/go-plus/github-differ/generate_comment.sh b/.ci/scripts/go-plus/github-differ/generate_comment.sh deleted file mode 100755 index 191dde497fb4..000000000000 --- a/.ci/scripts/go-plus/github-differ/generate_comment.sh +++ /dev/null @@ -1,221 +0,0 @@ -#! /bin/bash - -set -e - -if [ $# -lt 1 ]; then - echo "Usage: $0 pr-number" - exit 1 -fi -if [ -z "$GITHUB_TOKEN" ]; then - echo "Did not provide GITHUB_TOKEN environment variable." - exit 1 -fi - -# Get the directory of the current script -script_dir=$(dirname "$0") - -# make utility functions avalible -source "$script_dir/utils.sh" - -PR_NUMBER=$1 -NEW_BRANCH=auto-pr-$PR_NUMBER -OLD_BRANCH=auto-pr-$PR_NUMBER-old -MM_LOCAL_PATH=$PWD -TPG_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-provider-google -TPG_LOCAL_PATH=$PWD/../tpg -TPGB_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-provider-google-beta -TPGB_LOCAL_PATH=$PWD/../tpgb -TFOICS_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/docs-examples -TFOICS_LOCAL_PATH=$PWD/../tfoics -BREAKING_CHANGE_BUILD_FAILURE=0 - -# For backwards compatibility until at least Nov 15 2021 -TFC_SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/modular-magician/terraform-google-conversion -TFC_LOCAL_PATH=$PWD/../tfc - -DIFFS="" -NEWLINE=$'\n' - -# TPG/TPGB difference -mkdir -p $TPG_LOCAL_PATH -git clone -b $NEW_BRANCH $TPG_SCRATCH_PATH $TPG_LOCAL_PATH -pushd $TPG_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}Terraform GA: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -mkdir -p $TPGB_LOCAL_PATH -git clone -b $NEW_BRANCH $TPGB_SCRATCH_PATH $TPGB_LOCAL_PATH -pushd $TPGB_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}Terraform Beta: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -## Diff processor - TPG -set +e -pushd $MM_LOCAL_PATH/tools/diff-processor -cp -r $TPG_LOCAL_PATH old/ -cp -r $TPG_LOCAL_PATH new/ -make build OLD_REF=$OLD_BRANCH NEW_REF=$NEW_BRANCH - -### Breaking changes -TPG_BREAKING="$(bin/diff-processor breaking-changes)" -retVal=$? -if [ $retVal -ne 0 ]; then - TPG_BREAKING="" - BREAKING_CHANGE_BUILD_FAILURE=1 -fi - -### Add labels -GITHUB_TOKEN=$GITHUB_TOKEN $MM_LOCAL_PATH/tools/diff-processor/bin/diff-processor add-labels $PR_NUMBER -rm -rf ./old/ ./new/ ./bin/ -popd -set -e - -## Diff processor - TPGB -set +e -pushd $MM_LOCAL_PATH/tools/diff-processor -cp -r $TPGB_LOCAL_PATH old/ -cp -r $TPGB_LOCAL_PATH new/ -make build OLD_REF=$OLD_BRANCH NEW_REF=$NEW_BRANCH - -### Breaking changes -TPGB_BREAKING="$(bin/diff-processor breaking-changes)" -retVal=$? -if [ $retVal -ne 0 ]; then - TPGB_BREAKING="" - BREAKING_CHANGE_BUILD_FAILURE=1 -fi - -### Add labels -GITHUB_TOKEN=$GITHUB_TOKEN $MM_LOCAL_PATH/tools/diff-processor/bin/diff-processor add-labels $PR_NUMBER -rm -rf ./old/ ./new/ ./bin/ -popd -set -e - -## Report breaking change failures -set +e -if [ $BREAKING_CHANGE_BUILD_FAILURE -eq 0 ]; then - echo "Breaking changes succeeded" - # Export variables here so that they can be used in compare_breaking_changes - # exporting earlier would cause the retvals to not be calculated properly. - export TPG_BREAKING=$TPG_BREAKING - export TPGB_BREAKING=$TPGB_BREAKING - BREAKINGCHANGES="$($script_dir/compare_breaking_changes.sh)" -else - echo "Breaking changes failed" - BREAKINGCHANGES="## Breaking Change Detection Failed${NEWLINE}The breaking change detector crashed during execution. This is usually due to the downstream provider(s) failing to compile. Please investigate or follow up with your reviewer." -fi -set -e - -## Missing test setup and execution -TPGB_LOCAL_PATH_OLD="${TPGB_LOCAL_PATH}old" -mkdir -p $TPGB_LOCAL_PATH_OLD -cp -r $TPGB_LOCAL_PATH/. $TPGB_LOCAL_PATH_OLD - -pushd $TPGB_LOCAL_PATH -git checkout origin/$NEW_BRANCH -update_package_name "github.com/hashicorp/terraform-provider-google-beta" "google/provider/new" -popd - -pushd $TPGB_LOCAL_PATH_OLD -git checkout origin/$OLD_BRANCH -update_package_name "github.com/hashicorp/terraform-provider-google-beta" "google/provider/old" -popd - -set +e -pushd $MM_LOCAL_PATH/tools/missing-test-detector -go mod edit -replace google/provider/new=$(realpath $TPGB_LOCAL_PATH) -go mod edit -replace google/provider/old=$(realpath $TPGB_LOCAL_PATH_OLD) -go mod tidy -MISSINGTESTS="$(go run . -services-dir=$TPGB_LOCAL_PATH/google-beta/services)" -retVal=$? -if [ $retVal -ne 0 ]; then - MISSINGTESTS="" -fi -set -e -popd - -# TF Conversion - for compatibility until at least Nov 15 2021 -mkdir -p $TFC_LOCAL_PATH -# allow this to fail for compatibility during tfv/tgc transition phase -if git clone -b $NEW_BRANCH $TFC_SCRATCH_PATH $TFC_LOCAL_PATH; then - pushd $TFC_LOCAL_PATH - git fetch origin $OLD_BRANCH - if ! git diff --exit-code origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY=`git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat` - DIFFS="${DIFFS}${NEWLINE}TF Conversion: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" - fi - popd -fi - -# TF OICS -mkdir -p $TFOICS_LOCAL_PATH -git clone -b $NEW_BRANCH $TFOICS_SCRATCH_PATH $TFOICS_LOCAL_PATH -pushd $TFOICS_LOCAL_PATH -git fetch origin $OLD_BRANCH -if ! git diff --exit-code --quiet origin/$OLD_BRANCH origin/$NEW_BRANCH; then - SUMMARY="$(git diff origin/$OLD_BRANCH origin/$NEW_BRANCH --shortstat)" - DIFFS="${DIFFS}${NEWLINE}TF OiCS: [Diff](https://github.com/modular-magician/docs-examples/compare/$OLD_BRANCH..$NEW_BRANCH) ($SUMMARY)" -fi -popd - -MESSAGE="Hi there, I'm the Modular magician. I've detected the following information about your changes:${NEWLINE}${NEWLINE}" - -BREAKINGSTATE="success" -if [ -n "$BREAKINGCHANGES" ]; then - MESSAGE="${MESSAGE}${BREAKINGCHANGES}${NEWLINE}${NEWLINE}" - - BREAKINGCHANGE_OVERRIDE=$(curl \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer $GITHUB_TOKEN" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/$PR_NUMBER"\ - | jq ".labels|any(.id==4598495472)") - - if [ "${BREAKINGCHANGE_OVERRIDE}" == "true" ]; then - BREAKINGSTATE="success" - else - BREAKINGSTATE="failure" - fi -fi - - -if [ -z "$DIFFS" ]; then - MESSAGE="${MESSAGE}## Diff report ${NEWLINE}Your PR hasn't generated any diffs, but I'll let you know if a future commit does." -else - MESSAGE="${MESSAGE}## Diff report ${NEWLINE}Your PR generated some diffs in downstreams - here they are.${NEWLINE}${DIFFS}" - if [ -n "$MISSINGTESTS" ]; then - MESSAGE="${MESSAGE}${NEWLINE}${MISSINGTESTS}${NEWLINE}" - fi -fi - - - -#;region=global/${BUILD_ID};step=19?project=${PROJECT_ID}" -BREAKINGSTATE_BODY=$( jq -n \ - --arg context "terraform-provider-breaking-change-test" \ - --arg target_url "https://console.cloud.google.com/cloud-build/builds;region=global/${BUILD_ID};step=${BUILD_STEP}?project=${PROJECT_ID}" \ - --arg breakingstate "${BREAKINGSTATE}" \ - '{context: $context, target_url: $target_url, state: $breakingstate}') - -curl \ - -X POST \ - -u "$github_username:$GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/$COMMIT_SHA" \ - -d "$BREAKINGSTATE_BODY" - -curl -H "Authorization: token ${GITHUB_TOKEN}" \ - -d "$(jq -r --arg diffs "$MESSAGE" -n "{body: \$diffs}")" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/${PR_NUMBER}/comments" - -if ! git diff --exit-code origin/main tools; then - ## Run unit tests for breaking change and missing test detector. - "$script_dir/test_tools.sh" "$MM_LOCAL_PATH" "$TPGB_LOCAL_PATH" "$COMMIT_SHA" "$BUILD_ID" "$BUILD_STEP" "$PROJECT_ID" -fi diff --git a/.ci/scripts/go-plus/github-differ/test_tools.sh b/.ci/scripts/go-plus/github-differ/test_tools.sh deleted file mode 100755 index 5f47c0408d68..000000000000 --- a/.ci/scripts/go-plus/github-differ/test_tools.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -MM_LOCAL_PATH=$1 -TPGB_LOCAL_PATH=$2 -mm_commit_sha=$3 -build_id=$4 -build_step=$5 -project_id=$6 - -github_username=modular-magician - -set +e -pushd $MM_LOCAL_PATH/tools/missing-test-detector -go mod tidy -SERVICES_DIR=$TPGB_LOCAL_PATH/google-beta/services go test -exit_code=$? -popd -set -e - - -if [ $exit_code -ne 0 ]; then - state="failure" -else - state="success" -fi - -post_body=$( jq -n \ - --arg context "unit-tests-missing-test-detector" \ - --arg target_url "https://console.cloud.google.com/cloud-build/builds;region=global/${build_id};step=${build_step}?project=${project_id}" \ - --arg state "${state}" \ - '{context: $context, target_url: $target_url, state: $state}') - -curl \ - -X POST \ - -u "$github_username:$GITHUB_TOKEN" \ - -H "Accept: application/vnd.github.v3+json" \ - "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/statuses/$mm_commit_sha" \ - -d "$post_body" - diff --git a/.ci/scripts/go-plus/github-differ/utils.sh b/.ci/scripts/go-plus/github-differ/utils.sh deleted file mode 100755 index 9a4329a6ad84..000000000000 --- a/.ci/scripts/go-plus/github-differ/utils.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -update_package_name() { - old_package_name="$1" - new_package_name="$2" - - # Update import statements and references within files - find . -type f -name "*.go" -exec sed -i.bak "s~$old_package_name~$new_package_name~g" {} + - - # Update go.mod file - sed -i.bak "s|$old_package_name|$new_package_name|g" go.mod - - # Optional: Update go.sum file - sed -i.bak "s|$old_package_name|$new_package_name|g" go.sum -} From 046681494d8e99d6517c273e0a806513fc8afbe6 Mon Sep 17 00:00:00 2001 From: fayssalmartanigcp <73672393+fayssalmartanigcp@users.noreply.github.com> Date: Fri, 15 Mar 2024 17:44:11 -0400 Subject: [PATCH 150/200] Add ingestion settings to `google_pubsub_topic` (#9985) * Add ingestion settings to `google_pubsub_topic` * Add ingestion settings to `google_pubsub_topic` * Add create/update tests for `google_pubsub_topic` ingestion settings * Update topic ingestion settings test --- mmv1/products/pubsub/Topic.yaml | 42 ++++++++++++ .../pubsub_topic_ingestion_kinesis.tf.erb | 13 ++++ .../pubsub/resource_pubsub_topic_test.go | 68 +++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb diff --git a/mmv1/products/pubsub/Topic.yaml b/mmv1/products/pubsub/Topic.yaml index 95bb9563576f..275da6ceabca 100644 --- a/mmv1/products/pubsub/Topic.yaml +++ b/mmv1/products/pubsub/Topic.yaml @@ -72,6 +72,11 @@ examples: schema_name: 'example' test_env_vars: project_name: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: 'pubsub_topic_ingestion_kinesis' + primary_resource_id: 'example' + vars: + topic_name: 'example-topic' custom_code: !ruby/object:Provider::Terraform::CustomCode encoder: templates/terraform/encoders/no_send_name.go.erb update_encoder: templates/terraform/update_encoder/pubsub_topic.erb @@ -149,3 +154,40 @@ properties: set, message retention is controlled by settings on individual subscriptions. The rotation period has the format of a decimal number, followed by the letter `s` (seconds). Cannot be more than 31 days or less than 10 minutes. + - !ruby/object:Api::Type::NestedObject + name: 'ingestionDataSourceSettings' + description: | + Settings for ingestion from a data source into this topic. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'awsKinesis' + description: | + Settings for ingestion from Amazon Kinesis Data Streams. + properties: + - !ruby/object:Api::Type::String + name: 'streamArn' + description: | + The Kinesis stream ARN to ingest data from. + required: true + - !ruby/object:Api::Type::String + name: 'consumerArn' + description: | + The Kinesis consumer ARN to used for ingestion in + Enhanced Fan-Out mode. The consumer must be already + created and ready to be used. + required: true + - !ruby/object:Api::Type::String + name: 'awsRoleArn' + description: | + AWS role ARN to be used for Federated Identity authentication with + Kinesis. Check the Pub/Sub docs for how to set up this role and the + required permissions that need to be attached to it. + required: true + - !ruby/object:Api::Type::String + name: 'gcpServiceAccount' + description: | + The GCP service account to be used for Federated Identity authentication + with Kinesis (via a `AssumeRoleWithWebIdentity` call for the provided + role). The `awsRoleArn` must be set up with `accounts.google.com:sub` + equals to this service account number. + required: true diff --git a/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb b/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb new file mode 100644 index 000000000000..b47c80e8a9fa --- /dev/null +++ b/mmv1/templates/terraform/examples/pubsub_topic_ingestion_kinesis.tf.erb @@ -0,0 +1,13 @@ +resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['topic_name'] %>" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/fake-role-name" + gcp_service_account = "fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} diff --git a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go index b5f13d882c1f..7a944302ea21 100644 --- a/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go +++ b/mmv1/third_party/terraform/services/pubsub/resource_pubsub_topic_test.go @@ -140,6 +140,38 @@ func TestAccPubsubTopic_migration(t *testing.T) { }) } +func TestAccPubsubTopic_kinesisIngestionUpdate(t *testing.T) { + t.Parallel() + + topic := fmt.Sprintf("tf-test-topic-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckPubsubTopicDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccPubsubTopic_updateWithKinesisIngestionSettings(topic), + }, + { + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccPubsubTopic_updateWithUpdatedKinesisIngestionSettings(topic), + }, + { + ResourceName: "google_pubsub_topic.foo", + ImportStateId: topic, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccPubsubTopic_update(topic, key, value string) string { return fmt.Sprintf(` resource "google_pubsub_topic" "foo" { @@ -212,3 +244,39 @@ resource "google_pubsub_topic" "bar" { } `, schema, topic) } + +func testAccPubsubTopic_updateWithKinesisIngestionSettings(topic string) string { + return fmt.Sprintf(` +resource "google_pubsub_topic" "foo" { + name = "%s" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/fake-role-name" + gcp_service_account = "fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} +`, topic) +} + +func testAccPubsubTopic_updateWithUpdatedKinesisIngestionSettings(topic string) string { + return fmt.Sprintf(` +resource "google_pubsub_topic" "foo" { + name = "%s" + + # Outside of automated terraform-provider-google CI tests, these values must be of actual AWS resources for the test to pass. + ingestion_data_source_settings { + aws_kinesis { + stream_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/updated-fake-stream-name" + consumer_arn = "arn:aws:kinesis:us-west-2:111111111111:stream/updated-fake-stream-name/consumer/consumer-1:1111111111" + aws_role_arn = "arn:aws:iam::111111111111:role/updated-fake-role-name" + gcp_service_account = "updated-fake-service-account@fake-gcp-project.iam.gserviceaccount.com" + } + } +} +`, topic) +} From 7c0a51c93476181d4bd8864fb132d511b2b18995 Mon Sep 17 00:00:00 2001 From: Patrick Costello Date: Mon, 18 Mar 2024 12:40:56 -0700 Subject: [PATCH 151/200] Run Firestore index tests in fresh databases. (#10168) * Run Firestore index tests in fresh databases. This removes the index dependency on creating a document, as creating indexes on a non-existent collection is a valid operation in Firestore. This removes the dependency on a fixed (default) database, which should deflake tests. Fixes #17393. * Move project_id to test_env_vars. * Move project_id to test_env_vars for datastore_mode example. --- mmv1/products/firestore/Index.yaml | 11 +++-- .../examples/firestore_index_basic.tf.erb | 41 +++---------------- .../firestore_index_datastore_mode.tf.erb | 16 ++++++-- 3 files changed, 24 insertions(+), 44 deletions(-) diff --git a/mmv1/products/firestore/Index.yaml b/mmv1/products/firestore/Index.yaml index 06a76d2af452..d96f36e65f9c 100644 --- a/mmv1/products/firestore/Index.yaml +++ b/mmv1/products/firestore/Index.yaml @@ -60,19 +60,18 @@ examples: primary_resource_id: 'my-index' vars: - project_id: "project-id" + database_id: "database-id" test_env_vars: - org_id: :ORG_ID + project_id: :PROJECT_NAME pull_external: true - !ruby/object:Provider::Terraform::Examples name: 'firestore_index_datastore_mode' primary_resource_id: 'my-index' + vars: + database_id: "database-id-dm" test_env_vars: - # This example relies on a well-known collection having been created and - # Firestore being enabled on the project. We can't do that automatically - # for Datastore mode so we need a pre-created project. - project_id: :FIRESTORE_PROJECT_NAME + project_id: :PROJECT_NAME custom_code: !ruby/object:Provider::Terraform::CustomCode custom_import: templates/terraform/custom_import/index_self_link_as_name_set_project.go.erb encoder: templates/terraform/encoders/index.go.erb diff --git a/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb b/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb index 0b3c2cd71548..b706e3be2817 100644 --- a/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_index_basic.tf.erb @@ -1,45 +1,17 @@ -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" "database" { - project = google_project.project.project_id - name = "(default)" + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "<%= ctx[:vars]['database_id'] %>" location_id = "nam5" type = "FIRESTORE_NATIVE" - depends_on = [google_project_service.firestore] -} - -# Creating a document also creates its collection -resource "google_firestore_document" "document" { - project = google_project.project.project_id - database = google_firestore_database.database.name - collection = "somenewcollection" - document_id = "<%= ctx[:vars]['document_id'] %>" - fields = "{\"something\":{\"mapValue\":{\"fields\":{\"akey\":{\"stringValue\":\"avalue\"}}}}}" + delete_protection_state = "DELETE_PROTECTION_DISABLED" + deletion_policy = "DELETE" } resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { - project = google_project.project.project_id + project = "<%= ctx[:test_env_vars]['project_id'] %>" database = google_firestore_database.database.name - collection = google_firestore_document.document.collection + collection = "atestcollection" fields { field_path = "name" @@ -50,5 +22,4 @@ resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { field_path = "description" order = "DESCENDING" } - } diff --git a/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb b/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb index bc944770c839..4ec2fc640954 100644 --- a/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb +++ b/mmv1/templates/terraform/examples/firestore_index_datastore_mode.tf.erb @@ -1,7 +1,17 @@ +resource "google_firestore_database" "database" { + project = "<%= ctx[:test_env_vars]['project_id'] %>" + name = "<%= ctx[:vars]['database_id'] %>" + location_id = "nam5" + type = "DATASTORE_MODE" + + delete_protection_state = "DELETE_PROTECTION_DISABLED" + deletion_policy = "DELETE" +} + resource "google_firestore_index" "<%= ctx[:primary_resource_id] %>" { - project = "<%= ctx[:test_env_vars]['project_id'] %>" - database = "(default)" - collection = "chatrooms" + project = "<%= ctx[:test_env_vars]['project_id'] %>" + database = google_firestore_database.database.name + collection = "atestcollection" query_scope = "COLLECTION_RECURSIVE" api_scope = "DATASTORE_MODE_API" From 5b99a9a281b329b84b6a12d3947dcd31896b0a30 Mon Sep 17 00:00:00 2001 From: Charles Leon Date: Mon, 18 Mar 2024 15:42:34 -0700 Subject: [PATCH 152/200] AccessContextManager - Add dry run service perimeter resource (#10145) Co-authored-by: Charlesleonius --- .../ServicePerimeterDryRunResource.yaml | 89 +++++++++++ .../ServicePerimeterResource.yaml | 3 +- ...ce_perimeter_dry_run_resource_basic.tf.erb | 22 +++ ..._service_perimeter_dry_run_resource.go.erb | 1 + ..._context_manager_access_policy_test.go.erb | 31 ++-- ...service_perimeter_dry_run_resource_test.go | 139 ++++++++++++++++++ 6 files changed, 269 insertions(+), 16 deletions(-) create mode 100644 mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml create mode 100644 mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb create mode 100644 mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb create mode 100644 mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml new file mode 100644 index 000000000000..9b39f873b779 --- /dev/null +++ b/mmv1/products/accesscontextmanager/ServicePerimeterDryRunResource.yaml @@ -0,0 +1,89 @@ +# 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::Resource +name: 'ServicePerimeterDryRunResource' +create_url: '{{perimeter_name}}' +base_url: '' +self_link: '{{perimeter_name}}' +create_verb: :PATCH +delete_verb: :PATCH +immutable: true +update_mask: true +identity: + - resource +nested_query: !ruby/object:Api::Resource::NestedQuery + modify_by_patch: true + is_list_of_ids: true + keys: + - spec + - resources +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Service Perimeter Quickstart': 'https://cloud.google.com/vpc-service-controls/docs/quickstart' + api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters' +description: | + Allows configuring a single GCP resource that should be inside of the `spec` block of a dry run service perimeter. + This resource is intended to be used in cases where it is not possible to compile a full list + of projects to include in a `google_access_context_manager_service_perimeter` resource, + to enable them to be added separately. + If your perimeter is NOT in dry-run mode use `google_access_context_manager_service_perimeter_resource` instead. + + ~> **Note:** If this resource is used alongside a `google_access_context_manager_service_perimeter` resource, + the service perimeter resource must have a `lifecycle` block with `ignore_changes = [spec[0].resources]` so + they don't fight over which resources should be in the policy. +docs: !ruby/object:Provider::Terraform::Docs + warning: | + If you are using User ADCs (Application Default Credentials) with this resource, + you must specify a `billing_project` and set `user_project_override` to true + in the provider configuration. Otherwise the ACM API will return a 403 error. + Your account must have the `serviceusage.services.use` permission on the + `billing_project` you defined. +autogen_async: true +exclude_tgc: true +# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter +skip_sweeper: true +id_format: '{{perimeter_name}}/{{resource}}' +import_format: ['{{perimeter_name}}/{{resource}}'] +mutex: '{{perimeter_name}}' +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'access_context_manager_service_perimeter_dry_run_resource_basic' + skip_test: true + primary_resource_id: 'service-perimeter-dry-run-resource' + vars: + service_perimeter_name: 'restrict_all' +custom_code: !ruby/object:Provider::Terraform::CustomCode + custom_import: templates/terraform/custom_import/access_context_manager_service_perimeter_resource.go.erb + pre_update: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb + pre_create: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb + pre_delete: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb +parameters: + - !ruby/object:Api::Type::ResourceRef + name: 'perimeterName' + resource: 'ServicePerimeter' + imports: 'name' + description: | + The name of the Service Perimeter to add this resource to. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'resource' + description: | + A GCP resource that is inside of the service perimeter. + Currently only projects are allowed. + Format: projects/{project_number} + required: true + immutable: true diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml index b5264b1dadda..298b2bad26d7 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterResource.yaml @@ -33,10 +33,11 @@ references: !ruby/object:Api::Resource::ReferenceLinks 'Service Perimeter Quickstart': 'https://cloud.google.com/vpc-service-controls/docs/quickstart' api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters' description: | - Allows configuring a single GCP resource that should be inside of a service perimeter. + Allows configuring a single GCP resource that should be inside the `status` block of a service perimeter. This resource is intended to be used in cases where it is not possible to compile a full list of projects to include in a `google_access_context_manager_service_perimeter` resource, to enable them to be added separately. + If your perimeter is in dry-run mode use `google_access_context_manager_service_perimeter_dry_run_resource` instead. ~> **Note:** If this resource is used alongside a `google_access_context_manager_service_perimeter` resource, the service perimeter resource must have a `lifecycle` block with `ignore_changes = [status[0].resources]` so diff --git a/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb new file mode 100644 index 000000000000..04b6ebfbb10e --- /dev/null +++ b/mmv1/templates/terraform/examples/access_context_manager_service_perimeter_dry_run_resource_basic.tf.erb @@ -0,0 +1,22 @@ +resource "google_access_context_manager_service_perimeter_dry_run_resource" "<%= ctx[:primary_resource_id] %>" { + perimeter_name = google_access_context_manager_service_perimeter.<%= ctx[:primary_resource_id] %>.name + resource = "projects/987654321" +} + +resource "google_access_context_manager_service_perimeter" "<%= ctx[:primary_resource_id] %>" { + parent = "accessPolicies/${google_access_context_manager_access_policy.access-policy.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.access-policy.name}/servicePerimeters/<%= ctx[:vars]['service_perimeter_name'] %>" + title = "<%= ctx[:vars]['service_perimeter_name'] %>" + spec { + restricted_services = ["storage.googleapis.com"] + } + use_explicit_dry_run_spec = true + lifecycle { + ignore_changes = [spec[0].resources] + } +} + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "my policy" +} diff --git a/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb b/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb new file mode 100644 index 000000000000..7e9f036c027b --- /dev/null +++ b/mmv1/templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb @@ -0,0 +1 @@ +obj["use_explicit_dry_run_spec"] = true diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb index 944066fd5ed2..76ea6244cbfd 100644 --- a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_access_policy_test.go.erb @@ -17,21 +17,22 @@ import ( // can exist, they need to be run serially func TestAccAccessContextManager(t *testing.T) { testCases := map[string]func(t *testing.T){ - "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, - "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, - "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, - "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, - "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, - "access_level": testAccAccessContextManagerAccessLevel_basicTest, - "access_level_full": testAccAccessContextManagerAccessLevel_fullTest, - "access_level_custom": testAccAccessContextManagerAccessLevel_customTest, - "access_levels": testAccAccessContextManagerAccessLevels_basicTest, - "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, - "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, - "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, - "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, - "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, - "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, + "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, + "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, + "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, + "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, + "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, + "service_perimeter_dry_run_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, + "access_level": testAccAccessContextManagerAccessLevel_basicTest, + "access_level_full": testAccAccessContextManagerAccessLevel_fullTest, + "access_level_custom": testAccAccessContextManagerAccessLevel_customTest, + "access_levels": testAccAccessContextManagerAccessLevels_basicTest, + "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, + "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, + "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, + "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, + "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, + "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, } for name, tc := range testCases { diff --git a/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go new file mode 100644 index 000000000000..3c240fdd5d85 --- /dev/null +++ b/mmv1/third_party/terraform/services/accesscontextmanager/resource_access_context_manager_service_perimeter_dry_run_resource_test.go @@ -0,0 +1,139 @@ +package accesscontextmanager_test + +import ( + "fmt" + "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" +) + +// Since each test here is acting on the same organization and only one AccessPolicy +// can exist, they need to be run serially. See AccessPolicy for the test runner. + +func testAccAccessContextManagerServicePerimeterDryRunResource_basicTest(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + org := envvar.GetTestOrgFromEnv(t) + projects := acctest.BootstrapServicePerimeterProjects(t, 2) + policyTitle := "my policy" + perimeterTitle := "perimeter" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerServicePerimeterDryRunResource_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber, projects[1].ProjectNumber), + }, + { + ResourceName: "google_access_context_manager_service_perimeter_dry_run_resource.test-access1", + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_access_context_manager_service_perimeter_dry_run_resource.test-access2", + ImportState: true, + ImportStateVerify: true, + }, + // Use a separate TestStep rather than a CheckDestroy because we need the service perimeter to still exist + { + Config: testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitle), + Check: testAccCheckAccessContextManagerServicePerimeterDryRunResourceDestroyProducer(t), + }, + }, + }) +} + +func testAccCheckAccessContextManagerServicePerimeterDryRunResourceDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "google_access_context_manager_service_perimeter_dry_run_resource" { + continue + } + + config := acctest.GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{AccessContextManagerBasePath}}{{perimeter_name}}") + if err != nil { + return err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: config.UserAgent, + }) + if err != nil { + return err + } + + v, ok := res["spec"] + if !ok || v == nil { + return nil + } + + res = v.(map[string]interface{}) + v, ok = res["resources"] + if !ok || v == nil { + return nil + } + + resources := v.([]interface{}) + if len(resources) == 0 { + return nil + } + + return fmt.Errorf("expected 0 resources in perimeter, found %d: %v", len(resources), resources) + } + + return nil + } +} + +func testAccAccessContextManagerServicePerimeterDryRunResource_basic(org, policyTitle, perimeterTitleName string, projectNumber1, projectNumber2 int64) string { + return fmt.Sprintf(` +%s + +resource "google_access_context_manager_service_perimeter_dry_run_resource" "test-access1" { + perimeter_name = google_access_context_manager_service_perimeter.test-access.name + resource = "projects/%d" +} + +resource "google_access_context_manager_service_perimeter_dry_run_resource" "test-access2" { + perimeter_name = google_access_context_manager_service_perimeter.test-access.name + resource = "projects/%d" +} +`, testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitleName), projectNumber1, projectNumber2) +} + +func testAccAccessContextManagerServicePerimeterDryRunResource_destroy(org, policyTitle, perimeterTitleName string) string { + return fmt.Sprintf(` +resource "google_access_context_manager_access_policy" "test-access" { + parent = "organizations/%s" + title = "%s" +} + +resource "google_access_context_manager_service_perimeter" "test-access" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" + title = "%s" + perimeter_type = "PERIMETER_TYPE_REGULAR" + status { + restricted_services = ["storage.googleapis.com"] + } + spec { + restricted_services = ["storage.googleapis.com"] + } + use_explicit_dry_run_spec = true + lifecycle { + ignore_changes = [spec[0].resources] + } +} +`, org, policyTitle, perimeterTitleName, perimeterTitleName) +} From 55deca52e291505ba1692b3fea275116b2adfe85 Mon Sep 17 00:00:00 2001 From: Xuran Liu Date: Tue, 19 Mar 2024 06:59:44 -0700 Subject: [PATCH 153/200] Create quota infos datasource (#10074) * add quota info data source * add test and documention for quota_info data source * fix lint error * add quota infos datasource * update read test * remove duplicate import * update formatting and documentation * remove pagination parameters, concat and return all qualified entries * remove specific check for number of entries --- .../provider/provider_mmv1_resources.go.erb | 1 + ..._source_google_cloud_quotas_quota_infos.go | 215 ++++++++++++++++++ ...ce_google_cloud_quotas_quota_infos_test.go | 51 +++++ .../d/cloud_quotas_quota_info.html.markdown | 1 - .../d/cloud_quotas_quota_infos.html.markdown | 62 +++++ 5 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go create mode 100644 mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.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 f58f2b57e660..f828b8c13ff2 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -53,6 +53,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(), "google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(), "google_cloud_quotas_quota_info": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfo(), + "google_cloud_quotas_quota_infos": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfos(), "google_cloud_run_locations": cloudrun.DataSourceGoogleCloudRunLocations(), "google_cloud_run_service": cloudrun.DataSourceGoogleCloudRunService(), "google_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(), diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go new file mode 100644 index 000000000000..5b0c90afd9f8 --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos.go @@ -0,0 +1,215 @@ +package cloudquotas + +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 DataSourceGoogleCloudQuotasQuotaInfos() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGoogleCloudQuotasQuotaInfosRead, + + Schema: map[string]*schema.Schema{ + "parent": { + Type: schema.TypeString, + Required: true, + }, + "service": { + Type: schema.TypeString, + Required: true, + }, + "quota_infos": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "service": { + Type: schema.TypeString, + Computed: true, + }, + "quota_id": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "metric": { + Type: schema.TypeString, + Computed: true, + }, + "is_precise": { + Type: schema.TypeBool, + Computed: true, + }, + "refresh_interval": { + Type: schema.TypeString, + Computed: true, + }, + "container_type": { + Type: schema.TypeString, + Computed: true, + }, + "dimensions": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "metric_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "quota_display_name": { + Type: schema.TypeString, + Computed: true, + }, + "metric_unit": { + Type: schema.TypeString, + Computed: true, + }, + "quota_increase_eligibility": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "is_eligible": { + Type: schema.TypeBool, + Computed: true, + }, + "ineligibility_reason": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "is_fixed": { + Type: schema.TypeBool, + Computed: true, + }, + "dimensions_infos": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "dimensions": { + Type: schema.TypeMap, + Computed: true, + }, + "details": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "value": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "applicable_locations": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "is_concurrent": { + Type: schema.TypeBool, + Computed: true, + }, + "service_request_quota_uri": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + UseJSONNumber: true, + } +} + +func dataSourceGoogleCloudQuotasQuotaInfosRead(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, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos") + if err != nil { + return fmt.Errorf("error setting api endpoint") + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id())) + } + + var quotaInfos []map[string]interface{} + for { + fetchedQuotaInfos := res["quotaInfos"].([]interface{}) + for _, rawQuotaInfo := range fetchedQuotaInfos { + quotaInfos = append(quotaInfos, flattenCloudQuotasQuotaInfo(rawQuotaInfo.(map[string]interface{}), d, config)) + } + + if res["nextPageToken"] == nil || res["nextPageToken"].(string) == "" { + break + } + url, err = tpgresource.ReplaceVars(d, config, "{{CloudQuotasBasePath}}{{parent}}/locations/global/services/{{service}}/quotaInfos?pageToken="+res["nextPageToken"].(string)) + if err != nil { + return fmt.Errorf("error setting api endpoint") + } + res, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: userAgent, + }) + if err != nil { + return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("CloudQuotasQuotaInfo %q", d.Id()), url) + } + } + + if err := d.Set("quota_infos", quotaInfos); err != nil { + return fmt.Errorf("error reading quota infos : %s", err) + } + + d.SetId(url) + return nil +} + +func flattenCloudQuotasQuotaInfo(rawQuotaInfo map[string]interface{}, d *schema.ResourceData, config *transport_tpg.Config) map[string]interface{} { + quotaInfo := make(map[string]interface{}) + + quotaInfo["name"] = rawQuotaInfo["name"] + quotaInfo["quota_id"] = rawQuotaInfo["quotaId"] + quotaInfo["metric"] = rawQuotaInfo["metric"] + quotaInfo["service"] = rawQuotaInfo["service"] + quotaInfo["is_precise"] = rawQuotaInfo["isPrecise"] + quotaInfo["refresh_interval"] = rawQuotaInfo["refreshInterval"] + quotaInfo["container_type"] = rawQuotaInfo["containerType"] + quotaInfo["dimensions"] = rawQuotaInfo["dimensions"] + quotaInfo["metric_display_name"] = rawQuotaInfo["metricDisplayName"] + quotaInfo["quota_display_name"] = rawQuotaInfo["quotaDisplayName"] + quotaInfo["metric_unit"] = rawQuotaInfo["metricUnit"] + quotaInfo["quota_increase_eligibility"] = flattenCloudQuotasQuotaInfoQuotaIncreaseEligibility(rawQuotaInfo["quotaIncreaseEligibility"], d, config) + quotaInfo["is_fixed"] = rawQuotaInfo["isFixed"] + quotaInfo["dimensions_infos"] = flattenCloudQuotasQuotaInfoDimensionsInfos(rawQuotaInfo["dimensionsInfos"], d, config) + quotaInfo["is_concurrent"] = rawQuotaInfo["isConcurrent"] + quotaInfo["service_request_quota_uri"] = rawQuotaInfo["serviceRequestQuotaUri"] + + return quotaInfo +} diff --git a/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go new file mode 100644 index 000000000000..99db75f58074 --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/data_source_google_cloud_quotas_quota_infos_test.go @@ -0,0 +1,51 @@ +package cloudquotas_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 TestAccDataSourceGoogleQuotaInfos_basic(t *testing.T) { + t.Parallel() + + resourceName := "data.google_cloud_quotas_quota_infos.my_quota_infos" + service := "compute.googleapis.com" + + context := map[string]interface{}{ + "project": envvar.GetTestProjectFromEnv(), + "service": service, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGoogleQuotaInfos_basic(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.name"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.quota_id"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.metric"), + resource.TestCheckResourceAttr(resourceName, "quota_infos.0.service", service), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.is_precise"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.container_type"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.quota_increase_eligibility.0.is_eligible"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.dimensions_infos.0.details.0.value"), + resource.TestCheckResourceAttrSet(resourceName, "quota_infos.0.dimensions_infos.0.applicable_locations.0"), + ), + }, + }, + }) +} + +func testAccDataSourceGoogleQuotaInfos_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + data "google_cloud_quotas_quota_infos" "my_quota_infos" { + parent = "projects/%{project}" + service = "%{service}" + } + `, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown index 77e97d36489c..2f88f3c3abdc 100644 --- a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_info.html.markdown @@ -53,7 +53,6 @@ The following attributes are exported: The `dimensions_infos` block supports: * `dimensions` - The map of dimensions for this dimensions info. The key of a map entry is "region", "zone" or the name of a service specific dimension, and the value of a map entry is the value of the dimension. If a dimension does not appear in the map of dimensions, the dimensions info applies to all the dimension values except for those that have another DimenisonInfo instance configured for the specific value. Example: {"provider" : "Foo Inc"} where "provider" is a service specific dimension of a quota. - An object containing a list of "key": value pairs, for example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`. * `details` - The quota details for a map of dimensions. * `applicable_locations` - The applicable regions or zones of this dimensions info. The field will be set to `['global']` for quotas that are not per region or per zone. Otherwise, it will be set to the list of locations this dimension info is applicable to. diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown new file mode 100644 index 000000000000..b160791ce1ca --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/cloud_quotas_quota_infos.html.markdown @@ -0,0 +1,62 @@ +--- +subcategory: "Cloud Quotas" +--- + +# google\_cloud\_quotas\_quota\_infos + +Provides information about all quotas for a given project, folder or organization. + +## Example Usage + +```hcl +data "google_cloud_quotas_quota_infos" "my_quota_infos" { + parent = "projects/my-project" + service = "compute.googleapis.com" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `parent` - (Required) Parent value of QuotaInfo resources. Listing across different resource containers (such as 'projects/-') is not allowed. Allowed parents are "projects/[project-id / number]" or "folders/[folder-id / number]" or "organizations/[org-id / number]. + +* `service` - (Required) The name of the service in which the quotas are defined. + + +## Attributes Reference + +The following attributes are exported: + +* `quota_infos` - (Output) The list of QuotaInfo. + + The `quota_infos` block supports: + +* `name` - (Output) Resource name of this QuotaInfo, for example: `projects/123/locations/global/services/compute.googleapis.com/quotaInfos/CpusPerProjectPerRegion`. +* `metric` - (Output) The metric of the quota. It specifies the resources consumption the quota is defined for, for example: `compute.googleapis.com/cpus`. +* `is_precise` - (Output) Whether this is a precise quota. A precise quota is tracked with absolute precision. In contrast, an imprecise quota is not tracked with precision. +* `refresh_interval` - (Output) The reset time interval for the quota. Refresh interval applies to rate quota only. Example: "minute" for per minute, "day" for per day, or "10 seconds" for every 10 seconds. +* `container_type` - (Output) The container type of the QuotaInfo. +* `dimensions` - (Output) The dimensions the quota is defined on. +* `metric_display_name` - (Output) The display name of the quota metric. +* `quota_display_name` - (Output) The display name of the quota. +* `metric_unit` - (Output) The unit in which the metric value is reported, e.g., `MByte`. +* `quota_increase_eligibility` - (Output) Whether it is eligible to request a higher quota value for this quota. +* `is_fixed` - (Output) Whether the quota value is fixed or adjustable. +* `dimensions_infos` - (Output) The collection of dimensions info ordered by their dimensions from more specific ones to less specific ones. +* `is_concurrent` - (Output) Whether the quota is a concurrent quota. Concurrent quotas are enforced on the total number of concurrent operations in flight at any given time. +* `service_request_quota_uri` - (Output) URI to the page where users can request more quota for the cloud service, for example: `https://console.cloud.google.com/iam-admin/quotas`. + + The `quota_increase_eligibility` block supports: + +* `is_eligible` - Whether a higher quota value can be requested for the quota. +* `ineligibility_reason` - The enumeration of reasons when it is ineligible to request increase adjustment. + + The `dimensions_infos` block supports: +* `dimensions` - The map of dimensions for this dimensions info. The key of a map entry is "region", "zone" or the name of a service specific dimension, and the value of a map entry is the value of the dimension. If a dimension does not appear in the map of dimensions, the dimensions info applies to all the dimension values except for those that have another DimenisonInfo instance configured for the specific value. Example: {"provider" : "Foo Inc"} where "provider" is a service specific dimension of a quota. + +* `details` - The quota details for a map of dimensions. +* `applicable_locations` - The applicable regions or zones of this dimensions info. The field will be set to `['global']` for quotas that are not per region or per zone. Otherwise, it will be set to the list of locations this dimension info is applicable to. + + The `details` block supports: +* `value` - The value currently in effect and being enforced. From 5e5b8d75bfb2d2e98d048a3616a10302b6515493 Mon Sep 17 00:00:00 2001 From: rahul2393 Date: Tue, 19 Mar 2024 20:49:03 +0530 Subject: [PATCH 154/200] fix(spanner): remove validation on version retention period on spanner database (#10184) * fix(spanner): remove validation on version retention period on spanner database * fix build --- mmv1/products/spanner/Database.yaml | 2 - .../constants/spanner_database.go.erb | 38 ---------- .../resource_spanner_database_test.go.erb | 72 ------------------- 3 files changed, 112 deletions(-) diff --git a/mmv1/products/spanner/Database.yaml b/mmv1/products/spanner/Database.yaml index ea33c9ad211c..bcb1c3c21033 100644 --- a/mmv1/products/spanner/Database.yaml +++ b/mmv1/products/spanner/Database.yaml @@ -120,8 +120,6 @@ properties: the values 1d, 24h, 1440m, and 86400s are equivalent. Default value is 1h. If this property is used, you must avoid adding new DDL statements to `ddl` that update the database's version_retention_period. - validation: !ruby/object:Provider::Terraform::Validation - function: ValidateDatabaseRetentionPeriod default_from_api: true - !ruby/object:Api::Type::Array name: 'ddl' diff --git a/mmv1/templates/terraform/constants/spanner_database.go.erb b/mmv1/templates/terraform/constants/spanner_database.go.erb index bc2c1ae45088..926488ac8c68 100644 --- a/mmv1/templates/terraform/constants/spanner_database.go.erb +++ b/mmv1/templates/terraform/constants/spanner_database.go.erb @@ -44,44 +44,6 @@ func resourceSpannerDBDdlCustomDiff(_ context.Context, diff *schema.ResourceDiff return resourceSpannerDBDdlCustomDiffFunc(diff) } -func ValidateDatabaseRetentionPeriod(v interface{}, k string) (ws []string, errors []error) { - value := v.(string) - valueError := fmt.Errorf("version_retention_period should be in range [1h, 7d], in a format resembling 1d, 24h, 1440m, or 86400s") - - r := regexp.MustCompile("^(\\d{1}d|\\d{1,3}h|\\d{2,5}m|\\d{4,6}s)$") - if !r.MatchString(value) { - errors = append(errors, valueError) - return - } - - unit := value[len(value)-1:] - multiple := value[:len(value)-1] - num, err := strconv.Atoi(multiple) - if err != nil { - errors = append(errors, valueError) - return - } - - if unit == "d" && (num < 1 || num > 7) { - errors = append(errors, valueError) - return - } - if unit == "h" && (num < 1 || num > 7*24) { - errors = append(errors, valueError) - return - } - if unit == "m" && (num < 1*60 || num > 7*24*60) { - errors = append(errors, valueError) - return - } - if unit == "s" && (num < 1*60*60 || num > 7*24*60*60) { - errors = append(errors, valueError) - return - } - - return -} - func resourceSpannerDBVirtualUpdate(d *schema.ResourceData, resourceSchema map[string]*schema.Schema) bool { // deletion_protection is the only virtual field if d.HasChange("deletion_protection") { 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 3eb94e373be8..75f625c37217 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 @@ -9,7 +9,6 @@ import ( "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-provider-google/google/services/spanner" ) func TestAccSpannerDatabase_basic(t *testing.T) { @@ -466,77 +465,6 @@ resource "google_spanner_database" "basic" { `, instanceName, instanceName, databaseName) } -// Unit Tests for validation of retention period argument -func TestValidateDatabaseRetentionPeriod(t *testing.T) { - t.Parallel() - testCases := map[string]struct { - input string - expectError bool - }{ - // Not valid input - "empty_string": { - input: "", - expectError: true, - }, - "number_with_no_unit": { - input: "1", - expectError: true, - }, - "less_than_1h": { - input: "59m", - expectError: true, - }, - "more_than_7days": { - input: "8d", - expectError: true, - }, - // Valid input - "1_hour_in_secs": { - input: "3600s", - expectError: false, - }, - "1_hour_in_mins": { - input: "60m", - expectError: false, - }, - "1_hour_in_hours": { - input: "1h", - expectError: false, - }, - "7_days_in_secs": { - input: fmt.Sprintf("%ds", 7*24*60*60), - expectError: false, - }, - "7_days_in_mins": { - input: fmt.Sprintf("%dm", 7*24*60), - expectError: false, - }, - "7_days_in_hours": { - input: fmt.Sprintf("%dh", 7*24), - expectError: false, - }, - "7_days_in_days": { - input: "7d", - expectError: false, - }, - } - - for tn, tc := range testCases { - t.Run(tn, func(t *testing.T) { - _, errs := spanner.ValidateDatabaseRetentionPeriod(tc.input, "foobar") - var wantErrCount string - if tc.expectError { - wantErrCount = "1+" - } else { - wantErrCount = "0" - } - if (len(errs) > 0 && tc.expectError == false) || (len(errs) == 0 && tc.expectError == true) { - t.Errorf("failed, expected `%s` test case validation to have %s errors", tn, wantErrCount) - } - }) - } -} - func TestAccSpannerDatabase_deletionProtection(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() From 974267d4ade60c1ca9eab3e4efea058f2e95c792 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Tue, 19 Mar 2024 12:54:44 -0500 Subject: [PATCH 155/200] initial mmv1 go templating and flags (#10219) --- mmv1/go.mod | 2 + mmv1/go.sum | 2 + mmv1/google/string_utils.go | 26 +- mmv1/main.go | 35 ++- mmv1/provider/template_data.go | 195 ++++++++++++ mmv1/provider/terraform.go | 290 +++++++++--------- mmv1/templates/terraform/resource.go.tmpl | 31 ++ .../terraform/resource.html.markdown.tmpl | 30 ++ 8 files changed, 437 insertions(+), 174 deletions(-) create mode 100644 mmv1/provider/template_data.go create mode 100644 mmv1/templates/terraform/resource.go.tmpl create mode 100644 mmv1/templates/terraform/resource.html.markdown.tmpl diff --git a/mmv1/go.mod b/mmv1/go.mod index 58a9d896cd1a..b297c2158ba6 100644 --- a/mmv1/go.mod +++ b/mmv1/go.mod @@ -6,3 +6,5 @@ require ( golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 gopkg.in/yaml.v2 v2.4.0 ) + +require github.com/golang/glog v1.2.0 // indirect diff --git a/mmv1/go.sum b/mmv1/go.sum index b8ec4cc09d5a..3e041fb75ba4 100644 --- a/mmv1/go.sum +++ b/mmv1/go.sum @@ -1,3 +1,5 @@ +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/mmv1/google/string_utils.go b/mmv1/google/string_utils.go index 264f031893c6..a9e4fb0db978 100644 --- a/mmv1/google/string_utils.go +++ b/mmv1/google/string_utils.go @@ -20,23 +20,15 @@ import ( // // Helper class to process and mutate strings. // class StringUtils -// // Converts string from camel case to underscore -// def self.underscore(source) -// source.gsub(/::/, '/') -// .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') -// .gsub(/([a-z\d])([A-Z])/, '\1_\2') -// .tr('-', '_') -// .tr('.', '_') -// .downcase -// end - -// // Converts from PascalCase to Space Separated -// def self.space_separated(source) -// tmp = source.gsub(/([A-Z]+)([A-Z][a-z])/, '\1 \2') -// .gsub(/([a-z\d])([A-Z])/, '\1 \2') -// .downcase -// tmp[0].upcase.concat(tmp[1..]) -// end +// Converts string from camel case to underscore +func Underscore(source string) string { + tmp := regexp.MustCompile(`([A-Z]+)([A-Z][a-z])`).ReplaceAllString(source, "${1}_${2}") + tmp = regexp.MustCompile(`([a-z\d])([A-Z])`).ReplaceAllString(tmp, "${1}_${2}") + tmp = strings.Replace(tmp, "-", "_", 1) + tmp = strings.Replace(tmp, ".", "_", 1) + tmp = strings.ToLower(tmp) + return tmp +} // Converts from PascalCase to Space Separated // For example, converts "AccessApproval" to "Access Approval" diff --git a/mmv1/main.go b/mmv1/main.go index b01aad864eaf..11f04126cc44 100644 --- a/mmv1/main.go +++ b/mmv1/main.go @@ -1,6 +1,7 @@ package main import ( + "flag" "fmt" "log" "os" @@ -16,14 +17,26 @@ import ( "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider" ) +// TODO Q2: additional flags + +// Example usage: --output $GOPATH/src/github.com/terraform-providers/terraform-provider-google-beta +var outputPath = flag.String("output", "", "path to output generated files to") + +// Example usage: --version beta +var version = flag.String("version", "", "optional version name. If specified, this version is preferred for resource generation when applicable") + func main() { - // TODO Q2: parse flags - var version = "beta" - var outputPath = "." + flag.Parse() var generateCode = true var generateDocs = true - log.Printf("Initiating go MM compiler") + if outputPath == nil || *outputPath == "" { + log.Fatalf("No output path specified") + } + + if version == nil || *version == "" { + log.Fatalf("No version specified") + } // TODO Q1: allow specifying one product (flag or hardcoded) // var productsToGenerate []string @@ -51,8 +64,8 @@ func main() { log.Fatalf("No product.yaml file found.") } - log.Printf("Generating MM output to '%s'", outputPath) - log.Printf("Using %s version", version) + log.Printf("Generating MM output to '%s'", *outputPath) + log.Printf("Using %s version", *version) // Building compute takes a long time and can't be parallelized within the product // so lets build it first @@ -93,8 +106,8 @@ func main() { // prod, _ := json.Marshal(productApi) // log.Printf("prod %s", string(prod)) - if !productApi.ExistsAtVersionOrLower(version) { - log.Printf("%s does not have a '%s' version, skipping", productName, version) + if !productApi.ExistsAtVersionOrLower(*version) { + log.Printf("%s does not have a '%s' version, skipping", productName, *version) continue } @@ -132,7 +145,7 @@ func main() { } // TODO Q2: override resources - log.Printf("resources before sorting %#v", resources) + // log.Printf("resources before sorting %#v", resources) // Sort resources by name sort.Slice(resources, func(i, j int) bool { @@ -143,7 +156,7 @@ func main() { productApi.Validate() // TODO Q2: set other providers via flag - providerToGenerate := provider.NewTerraform(productApi) + providerToGenerate := provider.NewTerraform(productApi, *version) if !slices.Contains(productsToGenerate, productName) { log.Printf("%s not specified, skipping generation", productName) @@ -151,7 +164,7 @@ func main() { } log.Printf("%s: Generating files", productName) - providerToGenerate.Generate(outputPath, productName, generateCode, generateDocs) + providerToGenerate.Generate(*outputPath, productName, generateCode, generateDocs) } // TODO Q2: copy common files diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go new file mode 100644 index 000000000000..23ee5ebffd12 --- /dev/null +++ b/mmv1/provider/template_data.go @@ -0,0 +1,195 @@ +// Copyright 2024 Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package provider + +import ( + "bytes" + "fmt" + "go/format" + "log" + "os" + "strings" + + "text/template" + + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/golang/glog" +) + +type TemplateData struct { + // include Compile::Core + + OutputFolder string + Version product.Version + + TerraformResourceDirectory string + TerraformProviderModule string + + // TODO Q2: is this needed? + // # Information about the local environment + // # (which formatters are enabled, start-time) + // attr_accessor :env +} + +var TemplateFunctions = template.FuncMap{ + "title": strings.Title, + // "patternToRegex": PatternToRegex, + "replace": strings.Replace, + // "isLastIndex": isLastIndex, + // "escapeDescription": escapeDescription, + // "shouldAllowForwardSlashInFormat": shouldAllowForwardSlashInFormat, +} + +var GA_VERSION = "ga" +var BETA_VERSION = "beta" +var ALPHA_VERSION = "alpha" + +func NewTemplateData(outputFolder string, version product.Version) *TemplateData { + td := TemplateData{OutputFolder: outputFolder, Version: version} + + if version.Name == GA_VERSION { + td.TerraformResourceDirectory = "google" + td.TerraformProviderModule = "github.com/hashicorp/terraform-provider-google/google" + } else if version.Name == ALPHA_VERSION { + td.TerraformResourceDirectory = "google-private" + td.TerraformProviderModule = "internal/terraform-next" + } else { + td.TerraformResourceDirectory = "google-beta" + td.TerraformProviderModule = "github.com/hashicorp/terraform-provider-google-beta" + } + + return &td +} + +func (td *TemplateData) GenerateResourceFile(filePath string, resource api.Resource) { + + log.Printf("Generating %s", filePath) + + tmpl, err := template.New("resource.go.tmpl").Funcs(TemplateFunctions).ParseFiles( + "templates/terraform/resource.go.tmpl", + ) + if err != nil { + glog.Exit(err) + } + + contents := bytes.Buffer{} + if err = tmpl.ExecuteTemplate(&contents, "resource.go.tmpl", resource); err != nil { + glog.Exit(err) + } + + if err != nil { + glog.Exit(err) + } + + formatted, err := td.FormatSource(&contents) + if err != nil { + glog.Error(fmt.Errorf("error formatting %s", filePath)) + } + + err = os.WriteFile(filePath, formatted, 0644) + if err != nil { + glog.Exit(err) + } +} + +func (td *TemplateData) GenerateDocumentationFile(filePath string, resource api.Resource) { + +} + +// # path is the output name of the file +// # template is used to determine metadata about the file based on how it is +// # generated +// def format_output_file(path, template) +// return unless path.end_with?('.go') && @env[:goformat_enabled] + +// run_formatter("gofmt -w -s #{path}") +// run_formatter("goimports -w #{path}") unless template.include?('third_party/terraform') +// end + +// def run_formatter(command) +// output = %x(#{command} 2>&1) +// Google::LOGGER.error output unless $CHILD_STATUS.to_i.zero? +// end + +// def relative_path(target, base) +// Pathname.new(target).relative_path_from(Pathname.new(base)) +// end +// end + +// # Responsible for compiling provider-level files, rather than product-specific ones +// class ProviderFileTemplate < Provider::FileTemplate +// # All the products that are being compiled with the provider on this run +// attr_accessor :products + +// # Optional path to the directory where overrides reside. Used to locate files +// # outside of the MM root directory +// attr_accessor :override_path + +// def initialize(output_folder, version, env, products, override_path = nil) +// super() + +// @output_folder = output_folder +// @version = version +// @env = env +// @products = products +// @override_path = override_path +// end +// end + +// # Responsible for generating a file in the context of a product +// # with a given set of parameters. +// class ProductFileTemplate < Provider::FileTemplate +// # The name of the resource +// attr_accessor :name +// # The resource itself. +// attr_accessor :object +// # The entire API object. +// attr_accessor :product + +// class << self +// # Construct a new ProductFileTemplate based on a resource object +// def file_for_resource(output_folder, object, version, env) +// file_template = new(output_folder, object.name, object.__product, version, env) +// file_template.object = object +// file_template +// end +// end + +// def initialize(output_folder, name, product, version, env) +// super() + +// @name = name +// @product = product +// @output_folder = output_folder +// @version = version +// @env = env +// end +// end +// end + +func (td *TemplateData) FormatSource(source *bytes.Buffer) ([]byte, error) { + sourceByte := source.Bytes() + // Replace import path based on version (beta/alpha) + if td.TerraformResourceDirectory != "google" { + sourceByte = bytes.Replace(sourceByte, []byte("github.com/hashicorp/terraform-provider-google/google"), []byte(td.TerraformProviderModule+"/"+td.TerraformResourceDirectory), -1) + } + + output, err := format.Source(sourceByte) + if err != nil { + return []byte(source.String()), err + } + + return output, nil +} diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index fb620c1ddce5..54a91b38f208 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -14,9 +14,15 @@ package provider import ( + "fmt" "log" + "os" + "path" + "strings" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" ) const TERRAFORM_PROVIDER_GA = "github.com/hashicorp/terraform-provider-google" @@ -32,52 +38,159 @@ type Terraform struct { IAMResourceCount int ResourcesForVersion []api.Resource + + TargetVersionName string + + Version product.Version + + Product api.Product } -func NewTerraform(product *api.Product) *Terraform { - t := Terraform{ResourceCount: 0, IAMResourceCount: 0} +func NewTerraform(product *api.Product, versionName string) *Terraform { + t := Terraform{ + ResourceCount: 0, + IAMResourceCount: 0, + Product: *product, + TargetVersionName: versionName, + Version: *product.VersionObjOrClosest(versionName)} - // TODO Q1 - // @target_version_name = version_name - // - // @version = @api.version_obj_or_closest(version_name) - // @api.set_properties_based_on_version(@version) + t.Product.SetPropertiesBasedOnVersion(&t.Version) return &t } -// -// # Main entry point for generation. -// def generate(output_folder, types, product_path, dump_yaml, generate_code, generate_docs) +func (t *Terraform) Generate(outputFolder, productPath string, generateCode, generateDocs bool) { + if err := os.MkdirAll(outputFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating output directory %v: %v", outputFolder, err)) + } -// end + t.GenerateObjects(outputFolder, generateCode, generateDocs) -func (t *Terraform) Generate(outputFolder, productPath string, generateCode, generateDocs bool) { - log.Printf("Generate function called with %s %s %t %t", outputFolder, productPath, generateCode, generateDocs) + if generateCode { + t.GenerateOperation(outputFolder) + } +} + +func (t *Terraform) GenerateObjects(outputFolder string, generateCode, generateDocs bool) { + for _, object := range t.Product.Objects { + // TODO Q2: Exclude objects + // 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) - // TODO Q1 - // generate_objects(output_folder, types, generate_code, generate_docs) + t.GenerateObject(*object, outputFolder, t.TargetVersionName, generateCode, generateDocs) + } +} + +func (t *Terraform) GenerateObject(object api.Resource, outputFolder, productPath string, generateCode, generateDocs bool) { + + templateData := NewTemplateData(outputFolder, t.Version) + + if !object.ExcludeResource { + log.Printf("Generating %s resource", object.Name) + t.GenerateResource(object, *templateData, outputFolder, generateCode, generateDocs) + + if generateCode { + log.Printf("Generating %s tests", object.Name) + // TODO Q2 + // generate_resource_tests(pwd, data.clone) + // generate_resource_sweepers(pwd, data.clone) + } + } + + // TODO Q2 + // # 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 - // pwd = Dir.pwd - // if generate_code - // Dir.chdir output_folder + // 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 // - // generate_operation(pwd, output_folder, types) - // Dir.chdir pwd - // end + // end +} + +func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateData, outputFolder string, generateCode, generateDocs bool) { + if generateCode { + productName := t.Product.ApiName + targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName) + + if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) + } + + targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s.go", t.FullResourceName(object))) + + templateData.GenerateResourceFile(targetFilePath, object) + } + + if generateDocs { + templateData.GenerateDocumentationFile(outputFolder, object) + } +} + +func (t *Terraform) GenerateOperation(outputFolder string) { + + // TODO Q2 + // def generate_operation(pwd, output_folder, _types) + // return if @api.objects.select(&:autogen_async).empty? // - // # Write a file with the final version of the api, after overrides - // # have been applied. - // return unless dump_yaml + // product_name = @api.api_name + // product_name_underscore = @api.name.underscore + // data = build_object_data(pwd, @api.objects.first, output_folder, @target_version_name) // - // raise 'Path to output the final yaml was not specified.' \ - // if product_path.nil? || product_path == '' + // data.object = @api.objects.select(&:autogen_async).first // - // 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 + // data.async = data.object.async + // target_folder = File.join(folder_name(data.version), 'services', product_name) + // FileUtils.mkpath target_folder + // data.generate(pwd, + // 'templates/terraform/operation.go.erb', + // "#{target_folder}/#{product_name_underscore}_operation.go", + // self) + // end +} + +func (t *Terraform) FolderName() string { + if t.Version.Name == "ga" { + return "google" + } + return "google-beta" +} + +func (t *Terraform) FullResourceName(object api.Resource) string { + if object.LegacyName != "" { + return strings.Replace(object.LegacyName, "google_", "", 1) + } + + var name string + if object.FilenameOverride != "" { + name = object.FilenameOverride + } else { + name = google.Underscore(object.Name) + } + + var productName string + if t.Product.LegacyName != "" { + productName = t.Product.LegacyName + } else { + productName = google.Underscore(t.Product.Name) + } + + return fmt.Sprintf("%s_%s", productName, name) } // @@ -325,66 +438,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // services // 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 -// # Uncomment for go YAML -// # generate_object_modified object, output_folder, @target_version_name -// 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 generate_object_modified(object, output_folder, version_name) -// pwd = Dir.pwd -// data = build_object_data(pwd, object, output_folder, version_name) -// FileUtils.mkpath output_folder -// Dir.chdir output_folder -// Google::LOGGER.debug "Generating #{object.name} rewrite yaml" -// generate_newyaml(pwd, data.clone) -// Dir.chdir pwd -// end -// // def generate_newyaml(pwd, data) // # @api.api_name is the service folder name // product_name = @api.api_name @@ -720,25 +773,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // version == 'ga' ? 'google' : "google-#{version}" // end // -// # This function uses the resource.erb template to create one file -// # per resource. The resource.erb template forms the basis of a single -// # GCP Resource on Terraform. -// def generate_resource(pwd, data, generate_code, generate_docs) -// if generate_code -// # @api.api_name is the service folder name -// product_name = @api.api_name -// target_folder = File.join(folder_name(data.version), 'services', product_name) -// FileUtils.mkpath target_folder -// data.generate(pwd, -// '/templates/terraform/resource.erb', -// "#{target_folder}/resource_#{full_resource_name(data)}.go", -// self) -// end -// -// return unless generate_docs -// -// generate_documentation(pwd, data) -// end // // def generate_documentation(pwd, data) // target_folder = data.output_folder @@ -786,24 +820,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // self) // end // -// def generate_operation(pwd, output_folder, _types) -// return if @api.objects.select(&:autogen_async).empty? -// -// product_name = @api.api_name -// product_name_underscore = @api.name.underscore -// data = build_object_data(pwd, @api.objects.first, output_folder, @target_version_name) -// -// data.object = @api.objects.select(&:autogen_async).first -// -// data.async = data.object.async -// target_folder = File.join(folder_name(data.version), 'services', product_name) -// FileUtils.mkpath target_folder -// data.generate(pwd, -// 'templates/terraform/operation.go.erb', -// "#{target_folder}/#{product_name_underscore}_operation.go", -// self) -// end -// // # Generate the IAM policy for this object. This is used to query and test // # IAM policies separately from the resource itself // def generate_iam_policy(pwd, data, generate_code, generate_docs) @@ -850,15 +866,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // data.generate(pwd, 'templates/terraform/datasource_iam.html.markdown.erb', filepath, self) // end // -// def build_object_data(_pwd, object, output_folder, version) -// TerraformProductFileTemplate.file_for_resource( -// output_folder, -// object, -// version, -// build_env -// ) -// end -// // def extract_identifiers(url) // url.scan(/\{\{%?(\w+)\}\}/).flatten // end @@ -870,15 +877,6 @@ func (t *Terraform) Generate(outputFolder, productPath string, generateCode, gen // object.id_format || object.self_link_uri // end // -// def full_resource_name(data) -// if data.object.legacy_name -// data.object.legacy_name.sub(/^google_/, '') -// else -// name = data.object.filename_override || data.object.name.underscore -// product_name = data.product.legacy_name || data.product.name.underscore -// "#{product_name}_#{name}" -// end -// end // // # Returns the extension for DCL packages for the given version. This is needed // # as the DCL uses "alpha" for preview resources, while we use "private" diff --git a/mmv1/templates/terraform/resource.go.tmpl b/mmv1/templates/terraform/resource.go.tmpl new file mode 100644 index 000000000000..70ce7a03e4ea --- /dev/null +++ b/mmv1/templates/terraform/resource.go.tmpl @@ -0,0 +1,31 @@ +{{- /* Copyright 2024 Google LLC. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ -}} +// 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. +// +// ---------------------------------------------------------------------------- + +// {{$.ProductMetadata.Name}} {{$.Name}} \ No newline at end of file diff --git a/mmv1/templates/terraform/resource.html.markdown.tmpl b/mmv1/templates/terraform/resource.html.markdown.tmpl new file mode 100644 index 000000000000..80a5c85d93dd --- /dev/null +++ b/mmv1/templates/terraform/resource.html.markdown.tmpl @@ -0,0 +1,30 @@ +{{- /* Copyright 2024 Google LLC. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ -}} +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- + +{{$.ProductMetadata.Name}} {{$.Name}} +--- From 3b9c61bd50c271e769a6cb81dbd28d5ba7512c15 Mon Sep 17 00:00:00 2001 From: kautikdk <144651627+kautikdk@users.noreply.github.com> Date: Tue, 19 Mar 2024 18:04:35 +0000 Subject: [PATCH 156/200] Adds support for Soft Delete feature, which allows setting soft delete policy on 'google_storage_bucket' resource. (#10171) --- .../storage/resource_storage_bucket.go.erb | 63 +++++++++++++++- .../resource_storage_bucket_test.go.erb | 74 +++++++++++++++++++ .../docs/r/storage_bucket.html.markdown | 8 ++ 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 ed7422389d82..fc17d08790b8 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 @@ -482,6 +482,28 @@ func ResourceStorageBucket() *schema.Resource { Computed: true, Description: `Prevents public access to a bucket.`, }, + "soft_delete_policy": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Computed: true, + Description: `The bucket's soft delete policy, which defines the period of time that soft-deleted objects will be retained, and cannot be permanently deleted. If it is not provided, by default Google Cloud Storage sets this to default soft delete policy`, + Elem : &schema.Resource{ + Schema: map[string]*schema.Schema{ + "retention_duration_seconds": { + Type: schema.TypeInt, + Default: 604800, + Optional: true, + Description: `The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Default value is 604800.`, + }, + "effective_time": { + Type: schema.TypeString, + Computed: true, + Description: `Server-determined value that indicates the time from which the policy, or one with a greater retention, was effective. This value is in RFC 3339 format.`, + }, + }, + }, + }, }, UseJSONNumber: true, } @@ -612,6 +634,10 @@ func resourceStorageBucketCreate(d *schema.ResourceData, meta interface{}) error sb.Rpo = v.(string) } + if v, ok := d.GetOk("soft_delete_policy"); ok { + sb.SoftDeletePolicy = expandBucketSoftDeletePolicy(v.([]interface{})) + } + var res *storage.Bucket err = transport_tpg.Retry(transport_tpg.RetryOptions{ @@ -784,6 +810,12 @@ func resourceStorageBucketUpdate(d *schema.ResourceData, meta interface{}) error } } + if d.HasChange("soft_delete_policy") { + if v, ok := d.GetOk("soft_delete_policy"); ok { + sb.SoftDeletePolicy = expandBucketSoftDeletePolicy(v.([]interface{})) + } + } + res, err := config.NewStorageClient(userAgent).Buckets.Patch(d.Get("name").(string), sb).Do() if err != nil { return err @@ -1166,6 +1198,32 @@ func flattenBucketObjectRetention(bucketObjectRetention *storage.BucketObjectRet return false } +func expandBucketSoftDeletePolicy(configured interface{}) *storage.BucketSoftDeletePolicy{ + configuredSoftDeletePolicies := configured.([]interface{}) + if len(configuredSoftDeletePolicies) == 0 { + return nil + } + configuredSoftDeletePolicy := configuredSoftDeletePolicies[0].(map[string]interface{}) + softDeletePolicy := &storage.BucketSoftDeletePolicy{ + RetentionDurationSeconds: int64(configuredSoftDeletePolicy["retention_duration_seconds"].(int)), + } + softDeletePolicy.ForceSendFields=append(softDeletePolicy.ForceSendFields,"RetentionDurationSeconds") + return softDeletePolicy +} + +func flattenBucketSoftDeletePolicy(softDeletePolicy *storage.BucketSoftDeletePolicy) []map[string]interface{} { + policies := make([]map[string]interface{}, 0, 1) + if softDeletePolicy == nil { + return policies + } + policy := map[string]interface{}{ + "retention_duration_seconds": softDeletePolicy.RetentionDurationSeconds, + "effective_time": softDeletePolicy.EffectiveTime, + } + policies = append(policies, policy) + return policies +} + func expandBucketVersioning(configured interface{}) *storage.BucketVersioning { versionings := configured.([]interface{}) if len(versionings) == 0 { @@ -1689,7 +1747,7 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res } // 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 { + 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 { @@ -1717,6 +1775,9 @@ func setStorageBucket(d *schema.ResourceData, config *transport_tpg.Config, res return fmt.Errorf("Error setting RPO setting : %s", err) } } + if err := d.Set("soft_delete_policy", flattenBucketSoftDeletePolicy(res.SoftDeletePolicy)); err != nil { + return fmt.Errorf("Error setting soft_delete_policy: %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 f62447cb399e..22ef2baecef6 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 @@ -1338,6 +1338,66 @@ func TestAccStorageBucket_retentionPolicyLocked(t *testing.T) { }) } +func TestAccStorageBucket_SoftDeletePolicy(t *testing.T) { + t.Parallel() + + var bucket storage.Bucket + bucketName := fmt.Sprintf("tf-test-acc-bucket-%d", acctest.RandInt(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( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "604800"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_SoftDeletePolicy(bucketName,7776000), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "7776000"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + { + Config: testAccStorageBucket_SoftDeletePolicy(bucketName,0), + Check: resource.ComposeTestCheckFunc( + testAccCheckStorageBucketExists( + t, "google_storage_bucket.bucket", bucketName, &bucket), + resource.TestCheckResourceAttr( + "google_storage_bucket.bucket", "soft_delete_policy.0.retention_duration_seconds", "0"), + ), + }, + { + ResourceName: "google_storage_bucket.bucket", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"force_destroy"}, + }, + }, + }) +} + func testAccCheckStorageBucketExists(t *testing.T, n string, bucketName string, bucket *storage.Bucket) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -2264,6 +2324,20 @@ resource "google_storage_bucket" "bucket" { `, bucketName) } +func testAccStorageBucket_SoftDeletePolicy(bucketName string, duration int) string { + return fmt.Sprintf(` +resource "google_storage_bucket" "bucket" { + name = "%s" + location = "US" + force_destroy = true + + soft_delete_policy { + retention_duration_seconds = %d + } +} +`, bucketName, duration) +} + func testAccStorageBucket_websiteNoAttributes(bucketName string) string { return fmt.Sprintf(` resource "google_storage_bucket" "website" { 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 2389ac04bf55..58e1e1cf5056 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 @@ -133,6 +133,8 @@ The following arguments are supported: * `custom_placement_config` - (Optional) The bucket's custom location configuration, which specifies the individual regions that comprise a dual-region bucket. If the bucket is designated a single or multi-region, the parameters are empty. Structure is [documented below](#nested_custom_placement_config). +* `soft_delete_policy` - (Optional, Computed) The bucket's soft delete policy, which defines the period of time that soft-deleted objects will be retained, and cannot be permanently deleted. If the block is not provided, Server side value will be kept which means removal of block won't generate any terraform change. Structure is [documented below](#nested_soft_delete_policy). + The `lifecycle_rule` block supports: * `action` - (Required) The Lifecycle Rule's action configuration. A single block of this type is supported. Structure is [documented below](#nested_action). @@ -233,6 +235,12 @@ The following arguments are supported: * `data_locations` - (Required) The list of individual regions that comprise a dual-region bucket. See [Cloud Storage bucket locations](https://cloud.google.com/storage/docs/dual-regions#availability) for a list of acceptable regions. **Note**: If any of the data_locations changes, it will [recreate the bucket](https://cloud.google.com/storage/docs/locations#key-concepts). +The `soft_delete_policy` block supports: + +* `retention_duration_seconds` - (Optional, Default: 604800) The duration in seconds that soft-deleted objects in the bucket will be retained and cannot be permanently deleted. Default value is 604800. The value must be in between 604800(7 days) and 7776000(90 days). **Note**: To disable the soft delete policy on a bucket, This field must be set to 0. + +* `effective_time` - (Computed) Server-determined value that indicates the time from which the policy, or one with a greater retention, was effective. This value is in RFC 3339 format. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are From f4abf45f154501fe04509c2da704ac0dc0d4400e Mon Sep 17 00:00:00 2001 From: Salome Papiashvili Date: Tue, 19 Mar 2024 19:35:34 +0100 Subject: [PATCH 157/200] Fixes and enhancements after the bug bash. (#10223) * remove float from documentation * change storage-gb type to int * Revert "change storage-gb type to int" This reverts commit 89795a80889287fb287497fbcbbfdbb365d40884. * add support for dag_processor count * fix int64 unpacking * add validation for composer internal ip range size * add upper limit for dag_prcessor.count --- .../resource_composer_environment.go.erb | 26 +++++++++++++++++++ .../resource_composer_environment_test.go.erb | 2 ++ .../docs/r/composer_environment.html.markdown | 4 +-- 3 files changed, 30 insertions(+), 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 e192b510fa65..2a2f0b545757 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 @@ -3,6 +3,7 @@ package composer import ( "fmt" + "net" "log" "regexp" "strings" @@ -390,6 +391,7 @@ func ResourceComposerEnvironment() *schema.Resource { Computed: true, Optional: true, ForceNew: true, + ValidateFunc: validateComposerInternalIpv4CidrBlock, Description: `IPv4 cidr range that will be used by Composer internal components.`, }, <% end -%> @@ -969,6 +971,14 @@ func ResourceComposerEnvironment() *schema.Resource { ValidateFunc: validation.FloatAtLeast(0), Description: `Storage (GB) request and limit for DAG processor.`, }, + "count": { + Type: schema.TypeInt, + Optional: true, + ForceNew: false, + Computed: true, + ValidateFunc: validation.IntBetween(0, 3), + Description: `Number of DAG processors.`, + }, }, }, }, @@ -1887,6 +1897,7 @@ func flattenComposerEnvironmentConfigWorkloadsConfig(workloadsConfig *composer.W transformedDagProcessor["cpu"] = wlCfgDagProcessor.Cpu transformedDagProcessor["memory_gb"] = wlCfgDagProcessor.MemoryGb transformedDagProcessor["storage_gb"] = wlCfgDagProcessor.StorageGb + transformedDagProcessor["count"] = wlCfgDagProcessor.Count } <% end -%> @@ -2398,6 +2409,7 @@ func expandComposerEnvironmentConfigWorkloadsConfig(v interface{}, d *schema.Res transformedDagProcessor.Cpu = originalDagProcessorRaw["cpu"].(float64) transformedDagProcessor.MemoryGb = originalDagProcessorRaw["memory_gb"].(float64) transformedDagProcessor.StorageGb = originalDagProcessorRaw["storage_gb"].(float64) + transformedDagProcessor.Count = int64(originalDagProcessorRaw["count"].(int)) transformed.DagProcessor = transformedDagProcessor } } @@ -3096,4 +3108,18 @@ func versionValidationCustomizeDiffFunc(ctx context.Context, d *schema.ResourceD } } return nil +} + +func validateComposerInternalIpv4CidrBlock(v any, k string) (warns []string, errs []error) { + cidr_range := v.(string) + _, ip_net, err := net.ParseCIDR(cidr_range) + if err != nil { + errs = append(errs, fmt.Errorf("Invalid CIDR range: %s", err)) + return + } + ones, _ := ip_net.Mask.Size() + if ones != 20 { + errs = append(errs, fmt.Errorf("Composer Internal IPv4 CIDR range must have size /20")) + } + return } \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb index bde25f487b1f..e2ee2668fb80 100644 --- a/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb +++ b/mmv1/third_party/terraform/services/composer/resource_composer_environment_test.go.erb @@ -3159,6 +3159,7 @@ resource "google_composer_environment" "test" { cpu = 1 memory_gb = 2.5 storage_gb = 2 + count = 1 } } enable_private_environment = true @@ -3202,6 +3203,7 @@ resource "google_composer_environment" "test" { cpu = 2 memory_gb = 2 storage_gb = 1 + count = 2 } } enable_private_environment = false 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 81865ec37908..e46ad1f6a9ed 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 @@ -1371,7 +1371,7 @@ The `worker` block supports: (Optional) The amount of memory (GB) for a single Airflow worker. -* `float storage_gb` +* `storage_gb` (Optional) The amount of storage (GB) for a single Airflow worker. @@ -1396,7 +1396,7 @@ The `dag_processor` block supports: (Optional) Memory (GB) request and limit for DAG processor. -* `float storage_gb` +* `storage_gb` (Optional) Storage (GB) request and limit for DAG processor. From cbd78670f83239f1029a12684b856f5b0a0c63c6 Mon Sep 17 00:00:00 2001 From: Daniel Randell Date: Tue, 19 Mar 2024 19:00:25 +0000 Subject: [PATCH 158/200] google_monitoring_alert_policy periods doc update & dataproc doc update (#10226) * enable_http_port_access is a boolean not a string * add doc update to alert policy notification rate limit period --- mmv1/products/monitoring/AlertPolicy.yaml | 1 + .../services/dataproc/resource_dataproc_cluster_test.go.erb | 2 +- .../terraform/website/docs/r/dataproc_cluster.html.markdown | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mmv1/products/monitoring/AlertPolicy.yaml b/mmv1/products/monitoring/AlertPolicy.yaml index d968e2d4ea1c..52e00415e3c2 100644 --- a/mmv1/products/monitoring/AlertPolicy.yaml +++ b/mmv1/products/monitoring/AlertPolicy.yaml @@ -926,6 +926,7 @@ properties: name: period description: | Not more than one notification per period. + A duration in seconds with up to nine fractional digits, terminated by 's'. Example "60.5s". - !ruby/object:Api::Type::String name: autoClose description: | diff --git a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb index 6c003db6e7b0..0a41895275ba 100644 --- a/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb +++ b/mmv1/third_party/terraform/services/dataproc/resource_dataproc_cluster_test.go.erb @@ -2127,7 +2127,7 @@ resource "google_dataproc_cluster" "with_endpoint_config" { } endpoint_config { - enable_http_port_access = "true" + enable_http_port_access = true } } } diff --git a/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown b/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown index a09753653a04..796a14b262f8 100644 --- a/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/dataproc_cluster.html.markdown @@ -926,7 +926,7 @@ cluster_config { ```hcl cluster_config { endpoint_config { - enable_http_port_access = "true" + enable_http_port_access = true } } ``` From 676288eca33da129da405db05a0b02f6af61011b Mon Sep 17 00:00:00 2001 From: joelkattapuram <46967875+joelkattapuram@users.noreply.github.com> Date: Tue, 19 Mar 2024 12:22:01 -0700 Subject: [PATCH 159/200] Add support for boost configs in workstations configs (#10176) * add boostConfig workstationConfig * add boostConfig workstationConfig * link example * remove * update descriptions and add update test * update machine type * fix update test --- .../workstations/WorkstationConfig.yaml | 39 +++++++++ .../examples/workstation_config_boost.tf.erb | 56 +++++++++++++ ...orkstations_workstation_config_test.go.erb | 79 +++++++++++++++++++ 3 files changed, 174 insertions(+) create mode 100644 mmv1/templates/terraform/examples/workstation_config_boost.tf.erb diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index 39fada27bca8..65a868209b9a 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -108,6 +108,13 @@ examples: vars: workstation_cluster_name: 'workstation-cluster' workstation_config_name: 'workstation-config' + - !ruby/object:Provider::Terraform::Examples + name: 'workstation_config_boost' + min_version: beta + primary_resource_id: 'default' + vars: + workstation_cluster_name: 'workstation-cluster' + workstation_config_name: 'workstation-config' - !ruby/object:Provider::Terraform::Examples name: 'workstation_config_encryption_key' min_version: beta @@ -213,6 +220,7 @@ properties: - 'host.gceInstance.shieldedInstanceConfig.enableIntegrityMonitoring' - 'host.gceInstance.confidentialInstanceConfig.enableConfidentialCompute' - 'host.gceInstance.accelerators' + - 'host.gceInstance.boostConfigs' - 'host.gceInstance.disableSsh' properties: - !ruby/object:Api::Type::NestedObject @@ -319,6 +327,37 @@ properties: description: | Number of accelerator cards exposed to the instance. required: true + - !ruby/object:Api::Type::Array + name: 'boostConfigs' + description: | + A list of the boost configurations that workstations created using this workstation configuration are allowed to use. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'id' + description: | + The id to be used for the boost config. + required: true + - !ruby/object:Api::Type::String + name: 'machineType' + description: | + The type of machine that boosted VM instances will use—for example, e2-standard-4. For more information about machine types that Cloud Workstations supports, see the list of available machine types https://cloud.google.com/workstations/docs/available-machine-types. Defaults to e2-standard-4. + - !ruby/object:Api::Type::Array + name: 'accelerators' + description: | + An accelerator card attached to the boost instance. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'type' + description: | + Type of accelerator resource to attach to the instance, for example, "nvidia-tesla-p100". + required: true + - !ruby/object:Api::Type::Integer + name: 'count' + description: | + Number of accelerator cards exposed to the instance. + required: true - !ruby/object:Api::Type::Array name: 'persistentDirectories' description: | diff --git a/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb b/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb new file mode 100644 index 000000000000..d498c3eb1281 --- /dev/null +++ b/mmv1/templates/terraform/examples/workstation_config_boost.tf.erb @@ -0,0 +1,56 @@ +resource "google_compute_network" "default" { + provider = google-beta + name = "<%= ctx[:vars]['workstation_cluster_name'] %>" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "<%= ctx[:vars]['workstation_cluster_name'] %>" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name +} + +resource "google_workstations_workstation_cluster" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + workstation_cluster_id = "<%= ctx[:vars]['workstation_cluster_name'] %>" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + + labels = { + "label" = "key" + } + + annotations = { + label-one = "value-one" + } +} + +resource "google_workstations_workstation_config" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + workstation_config_id = "<%= ctx[:vars]['workstation_config_name'] %>" + workstation_cluster_id = google_workstations_workstation_cluster.<%= ctx[:primary_resource_id] %>.workstation_cluster_id + location = "us-central1" + + host { + gce_instance { + machine_type = "e2-standard-4" + boot_disk_size_gb = 35 + disable_public_ip_addresses = true + boost_configs { + id = "boost-1" + machine_type = "n1-standard-2" + accelerators { + type = "nvidia-tesla-t4" + count = "1" + } + } + boost_configs { + id = "boost-1" + machine_type = "e2-standard-2" + } + } + } +} diff --git a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb index e29069d6ab11..10839661da72 100644 --- a/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb +++ b/mmv1/third_party/terraform/services/workstations/resource_workstations_workstation_config_test.go.erb @@ -476,6 +476,80 @@ func testAccWorkstationsWorkstationConfig_serviceAccount(context map[string]inte `, context) } +func TestAccWorkstationsWorkstationConfig_boost(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationConfig_boost(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + }, + }) +} + +func testAccWorkstationsWorkstationConfig_boost(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_compute_network" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + auto_create_subnetworks = false + } + + resource "google_compute_subnetwork" "default" { + provider = google-beta + name = "tf-test-workstation-cluster%{random_suffix}" + ip_cidr_range = "10.0.0.0/24" + region = "us-central1" + network = google_compute_network.default.name + } + + resource "google_workstations_workstation_cluster" "default" { + provider = google-beta + workstation_cluster_id = "tf-test-workstation-cluster%{random_suffix}" + network = google_compute_network.default.id + subnetwork = google_compute_subnetwork.default.id + location = "us-central1" + } + + resource "google_workstations_workstation_config" "default" { + provider = google-beta + workstation_config_id = "tf-test-workstation-config%{random_suffix}" + workstation_cluster_id = google_workstations_workstation_cluster.default.workstation_cluster_id + location = "us-central1" + host { + gce_instance { + boost_configs { + id = "boost-1" + machine_type = "n1-standard-2" + accelerators { + type = "nvidia-tesla-t4" + count = 1 + } + } + boost_configs { + id = "boost-1" + machine_type = "e2-standard-2" + } + } + } + } +`, context) +} + func TestAccWorkstationsWorkstationConfig_disableTcpConnections(t *testing.T) { t.Parallel() @@ -886,6 +960,11 @@ resource "google_workstations_workstation_config" "default" { confidential_instance_config { enable_confidential_compute = true } + + boost_configs { + id = "boost-1" + machine_type = "n2d-standard-2" + } } } } From d58db7cbcd766462bc0be7d50cd467507fc34899 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Tue, 19 Mar 2024 13:14:59 -0700 Subject: [PATCH 160/200] Add a rule for removing diff suppress functions (#10167) * Add a rule for removing diff suppress functions * Add rule link to docs --- .../breaking-changes/breaking-changes.md | 2 +- tools/diff-processor/rules/rules_field.go | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/content/develop/breaking-changes/breaking-changes.md b/docs/content/develop/breaking-changes/breaking-changes.md index 0b17be06b890..6e2b93039bb6 100644 --- a/docs/content/develop/breaking-changes/breaking-changes.md +++ b/docs/content/develop/breaking-changes/breaking-changes.md @@ -79,7 +79,7 @@ For more information, see and modifying examples and modules may achieve the intended effect with a smaller blast radius. * Modifying how field data is stored in state * For example, changing the case of a value returned by the API in a flattener or decorder -* Removing diff suppression from a field. +* Removing diff suppression from a field. * For MMv1 resources, removing `diff_suppress_func` from a field. * For handwritten resources, removing `DiffSuppressFunc` from a field. * Removing update support from a field. diff --git a/tools/diff-processor/rules/rules_field.go b/tools/diff-processor/rules/rules_field.go index 1b5645571731..793a768fedf0 100644 --- a/tools/diff-processor/rules/rules_field.go +++ b/tools/diff-processor/rules/rules_field.go @@ -27,6 +27,7 @@ var FieldRules = []FieldRule{ fieldRule_DefaultModification, fieldRule_GrowingMin, fieldRule_ShrinkingMax, + fieldRule_RemovingDiffSuppress, fieldRule_ChangingFieldDataFormat, } @@ -211,6 +212,25 @@ func fieldRule_ShrinkingMax_func(old, new *schema.Schema, mc MessageContext) str return "" } +var fieldRule_RemovingDiffSuppress = FieldRule{ + name: "Removing Diff Suppress Function", + definition: "Diff suppress functions cannot be removed. Otherwise terraform configurations that previously had no diffs would show diffs.", + message: "Field {{field}} lost its diff suppress function", + identifier: "field-removing-diff-suppress", + isRuleBreak: fieldRule_RemovingDiffSuppress_func, +} + +func fieldRule_RemovingDiffSuppress_func(old, new *schema.Schema, mc MessageContext) string { + // ignore for added / removed fields + if old == nil || new == nil { + return "" + } + if old.DiffSuppressFunc != nil && new.DiffSuppressFunc == nil { + return populateMessageContext(mc.message, mc) + } + return "" +} + func fieldRulesToRuleArray(frs []FieldRule) []Rule { var rules []Rule for _, fr := range frs { From 5fddaec1797fd46f5f57241dc878642b5bcf60f2 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Tue, 19 Mar 2024 13:55:00 -0700 Subject: [PATCH 161/200] Rewrite Resource functions (#10228) --- mmv1/api/async.go | 8 +- mmv1/api/product.go | 20 +- mmv1/api/resource.go | 452 ++++++++++++++++++++++++++++++- mmv1/api/resource.rb | 20 -- mmv1/api/timeouts.go | 8 + mmv1/api/type.go | 123 +++++---- mmv1/google/string_utils.go | 51 ++-- mmv1/google/string_utils_test.go | 54 ++++ mmv1/provider/terraform.rb | 8 - 9 files changed, 629 insertions(+), 115 deletions(-) create mode 100644 mmv1/google/string_utils_test.go diff --git a/mmv1/api/async.go b/mmv1/api/async.go index dc4090fe7663..51a740aaffcd 100644 --- a/mmv1/api/async.go +++ b/mmv1/api/async.go @@ -26,7 +26,7 @@ type Async struct { google.YamlValidator // Describes an operation - Operation Operation + Operation *Operation // The list of methods where operations are used. Actions []string @@ -50,7 +50,7 @@ type Operation struct { // Contains information about an long-running operation, to make // requests for the state of an operation. - Timeouts Timeouts + Timeouts *Timeouts Result Result } @@ -79,7 +79,7 @@ type OpAsync struct { // TODO: Should embed Async or not? // < Async - Operation OpAsyncOperation + Operation *OpAsyncOperation Result OpAsyncResult @@ -127,7 +127,7 @@ type OpAsyncOperation struct { WaitMs int `yaml:"wait_ms"` - Timeouts Timeouts + Timeouts *Timeouts // Use this if the resource includes the full operation url. FullUrl string `yaml:"full_url"` diff --git a/mmv1/api/product.go b/mmv1/api/product.go index 5c5b718d8767..e3defe678c82 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -67,7 +67,7 @@ type Product struct { OperationRetry string `yaml:"operation_retry"` - Async OpAsync + Async *OpAsync LegacyName string `yaml:"legacy_name"` @@ -211,21 +211,21 @@ func (p *Product) SetPropertiesBasedOnVersion(version *product.Version) { p.BaseUrl = version.BaseUrl } -// // ==================== -// // Debugging Methods -// // ==================== +// ==================== +// Debugging Methods +// ==================== // def to_s // // relies on the custom to_json definitions // JSON.pretty_generate(self) // end -// // Prints a dot notation path to where the field is nested within the parent -// // object when called on a property. eg: parent.meta.label.foo -// // Redefined on Product to terminate the calls up the parent chain. -// def lineage -// name -// end +// Prints a dot notation path to where the field is nested within the parent +// object when called on a property. eg: parent.meta.label.foo +// Redefined on Product to terminate the calls up the parent chain. +func (p Product) Lineage() string { + return p.Name +} // def to_json(opts = nil) // json_out = {} diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index 069c935af0d8..ad71a8eb23e8 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -13,9 +13,14 @@ package api import ( + "fmt" + "strings" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/resource" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" "github.com/GoogleCloudPlatform/magic-modules/mmv1/provider/terraform" + "golang.org/x/exp/slices" ) type Resource struct { @@ -64,13 +69,13 @@ type Resource struct { // ==================== // // [Optional] The "identity" URL of the resource. Defaults to: - // * base_url when the create_verb is :POST - // * self_link when the create_verb is :PUT or :PATCH + // * base_url when the create_verb is POST + // * self_link when the create_verb is PUT or PATCH SelfLink string `yaml:"self_link"` // [Optional] The URL used to creating the resource. Defaults to: - // * collection url when the create_verb is :POST - // * self_link when the create_verb is :PUT or :PATCH + // * collection url when the create_verb is POST + // * self_link when the create_verb is PUT or PATCH CreateUrl string `yaml:"create_url"` // [Optional] The URL used to delete the resource. Defaults to the self @@ -80,16 +85,16 @@ type Resource struct { // [Optional] The URL used to update the resource. Defaults to the self // link. UpdateUrl string `yaml:"update_url"` - // [Optional] The HTTP verb used during create. Defaults to :POST. + // [Optional] The HTTP verb used during create. Defaults to POST. CreateVerb string `yaml:"create_verb"` - // [Optional] The HTTP verb used during read. Defaults to :GET. + // [Optional] The HTTP verb used during read. Defaults to GET. ReadVerb string `yaml:"read_verb"` - // [Optional] The HTTP verb used during update. Defaults to :PUT. + // [Optional] The HTTP verb used during update. Defaults to PUT. UpdateVerb string `yaml:"update_verb"` - // [Optional] The HTTP verb used during delete. Defaults to :DELETE. + // [Optional] The HTTP verb used during delete. Defaults to DELETE. DeleteVerb string `yaml:"delete_verb"` // [Optional] Additional Query Parameters to append to GET. Defaults to "" @@ -204,7 +209,7 @@ type Resource struct { // If true, skip sweeper generation for this resource SkipSweeper bool `yaml:"skip_sweeper"` - Timeouts Timeouts + Timeouts *Timeouts // An array of function names that determine whether an error is retryable. ErrorRetryPredicates []string `yaml:"error_retry_predicates"` @@ -268,6 +273,8 @@ type Resource struct { // Add a deprecation message for a resource that's been deprecated in the API. DeprecationMessage string `yaml:"deprecation_message"` + Async *OpAsync + Properties []*Type Parameters []*Type @@ -294,10 +301,284 @@ func (r *Resource) setResourceMetada(properties []*Type) { } } +// ==================== +// Custom Getters and Setters +// ==================== + +// Returns all properties and parameters including the ones that are +// excluded. This is used for PropertyOverride validation + +// TODO: remove the ruby function name +// def all_properties +func (r Resource) AllProperties() []*Type { + return google.Concat(r.Properties, r.Parameters) +} + +// def properties_with_excluded +func (r Resource) PropertiesWithExcluded() []*Type { + return r.Properties +} + +// def properties +func (r Resource) UserProperites() []*Type { + return google.Reject(r.Properties, func(p *Type) bool { + return p.Exclude + }) +} + +// def parameters +func (r Resource) UserParameters() []*Type { + return google.Reject(r.Parameters, func(p *Type) bool { + return p.Exclude + }) +} + +// Return the user-facing properties in client tools; this ends up meaning +// both properties and parameters but without any that are excluded due to +// version mismatches or manual exclusion + +// def all_user_properties +func (r Resource) AllUserProperties() []*Type { + return google.Concat(r.UserProperites(), r.UserParameters()) +} + +// def required_properties +func (r Resource) RequiredProperties() []*Type { + return google.Select(r.AllUserProperties(), func(p *Type) bool { + return p.Required + }) +} + +// def all_nested_properties(props) +func allNestedProperties(props []*Type) []*Type { + nested := props + for _, prop := range props { + if nestedProperties := prop.NestedProperties(); !prop.FlattenObject && nestedProperties != nil { + nested = google.Concat(nested, allNestedProperties(nestedProperties)) + } + } + + return nested +} + +// sensitive_props +func (r Resource) SensitiveProps() []*Type { + props := allNestedProperties(r.RootProperties()) + return google.Select(props, func(p *Type) bool { + return p.Sensitive + }) +} + +// All settable properties in the resource. +// Fingerprints aren't *really" settable properties, but they behave like one. +// At Create, they have no value but they can just be read in anyways, and after a Read +// they will need to be set in every Update. + +// def settable_properties +func (r Resource) settableProperties() []*Type { + props := make([]*Type, 0) + + props = google.Reject(r.AllUserProperties(), func(v *Type) bool { + return v.Output && !v.IsA("Fingerprint") && !v.IsA("KeyValueEffectiveLabels") + }) + + props = google.Reject(props, func(v *Type) bool { + return v.UrlParamOnly + }) + + props = google.Reject(props, func(v *Type) bool { + return v.IsA("KeyValueLabels") || v.IsA("KeyValueAnnotations") + }) + + return props +} + +// Properties that will be returned in the API body + +// def gettable_properties +func (r Resource) GettableProperties() []*Type { + return google.Reject(r.AllUserProperties(), func(v *Type) bool { + return v.UrlParamOnly + }) +} + +// Returns the list of top-level properties once any nested objects with flatten_object +// set to true have been collapsed + +// def root_properties +func (r Resource) RootProperties() []*Type { + props := make([]*Type, 0) + + for _, p := range r.AllUserProperties() { + if p.FlattenObject { + props = google.Concat(props, p.RootProperties()) + } else { + props = append(props, p) + } + } + return props +} + +// Return the product-level async object, or the resource-specific one +// if one exists. + +// def async +func (r Resource) GetAsync() *OpAsync { + if r.Async != nil { + return r.Async + } + + return r.ProductMetadata.Async +} + +// Return the resource-specific identity properties, or a best guess of the +// `name` value for the resource. + +// def identity +func (r Resource) GetIdentity() []*Type { + props := r.AllUserProperties() + + if r.Identity != nil { + identities := google.Select(props, func(p *Type) bool { + return slices.Contains(r.Identity, p.Name) + }) + + slices.SortFunc(identities, func(a, b *Type) int { + return slices.Index(r.Identity, a.Name) - slices.Index(r.Identity, b.Name) + }) + + return identities + } + + return google.Select(props, func(p *Type) bool { + return p.Name == "name" + }) + +} + +// TODO Q1 +// def add_labels_related_fields(props, parent) +// props.each do |p| +// if p.is_a? Api::Type::KeyValueLabels +// add_labels_fields(props, parent, p) +// elsif p.is_a? Api::Type::KeyValueAnnotations +// add_annotations_fields(props, parent, p) +// elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? +// p.properties = add_labels_related_fields(p.all_properties, p) +// end +// end +// props +// end + +// def add_labels_fields(props, parent, labels) +// @custom_diff ||= [] +// if parent.nil? || parent.flatten_object +// @custom_diff.append('tpgresource.SetLabelsDiff') +// elsif parent.name == 'metadata' +// @custom_diff.append('tpgresource.SetMetadataLabelsDiff') +// end + +// props << build_terraform_labels_field('labels', parent, labels) +// props << build_effective_labels_field('labels', labels) + +// // The effective_labels field is used to write to API, instead of the labels field. +// labels.ignore_write = true +// labels.description = "//{labels.description}\n\n//{get_labels_field_note(labels.name)}" +// return unless parent.nil? + +// labels.immutable = false +// end + +// def add_annotations_fields(props, parent, annotations) +// // The effective_annotations field is used to write to API, +// // instead of the annotations field. +// annotations.ignore_write = true +// note = get_labels_field_note(annotations.name) +// annotations.description = "//{annotations.description}\n\n//{note}" + +// @custom_diff ||= [] +// if parent.nil? +// @custom_diff.append('tpgresource.SetAnnotationsDiff') +// elsif parent.name == 'metadata' +// @custom_diff.append('tpgresource.SetMetadataAnnotationsDiff') +// end + +// props << build_effective_labels_field('annotations', annotations) +// end + +// def build_effective_labels_field(name, labels) +// description = "All of //{name} (key/value pairs)\ +// present on the resource in GCP, including the //{name} configured through Terraform,\ +// other clients and services." + +// Api::Type::KeyValueEffectiveLabels.new( +// name: "effective//{name.capitalize}", +// output: true, +// api_name: name, +// description:, +// min_version: labels.field_min_version, +// update_verb: labels.update_verb, +// update_url: labels.update_url, +// immutable: labels.immutable +// ) +// end + +// def build_terraform_labels_field(name, parent, labels) +// description = "The combination of //{name} configured directly on the resource +// and default //{name} configured on the provider." + +// immutable = if parent.nil? +// false +// else +// labels.immutable +// end + +// Api::Type::KeyValueTerraformLabels.new( +// name: "terraform//{name.capitalize}", +// output: true, +// api_name: name, +// description:, +// min_version: labels.field_min_version, +// ignore_write: true, +// update_url: labels.update_url, +// immutable: +// ) +// end + +// // Check if the resource has root "labels" field +// def root_labels? +// root_properties.each do |p| +// return true if p.is_a? Api::Type::KeyValueLabels +// end +// false +// end + +// // Return labels fields that should be added to ImportStateVerifyIgnore +// def ignore_read_labels_fields(props) +// fields = [] +// props.each do |p| +// if (p.is_a? Api::Type::KeyValueLabels) || +// (p.is_a? Api::Type::KeyValueTerraformLabels) || +// (p.is_a? Api::Type::KeyValueAnnotations) +// fields << p.terraform_lineage +// elsif (p.is_a? Api::Type::NestedObject) && !p.all_properties.nil? +// fields.concat(ignore_read_labels_fields(p.all_properties)) +// end +// end +// fields +// end + +// def get_labels_field_note(title) +// "**Note**: This field is non-authoritative, and will only manage the //{title} present " \ +// "in your configuration. +// Please refer to the field `effective_//{title}` for all of the //{title} present on the resource." +// end + // ==================== // Version-related methods // ==================== +// def min_version func (r Resource) MinVersionObj() *product.Version { if r.MinVersion != "" { return r.ProductMetadata.versionObj(r.MinVersion) @@ -306,6 +587,7 @@ func (r Resource) MinVersionObj() *product.Version { } } +// def not_in_version?(version) func (r Resource) NotInVersion(version *product.Version) bool { return version.CompareTo(r.MinVersionObj()) < 0 } @@ -313,6 +595,8 @@ func (r Resource) NotInVersion(version *product.Version) bool { // Recurses through all nested properties and parameters and changes their // 'exclude' instance variable if the property is at a version below the // one that is passed in. + +// def exclude_if_not_in_version!(version) func (r *Resource) ExcludeIfNotInVersion(version *product.Version) { if !r.Exclude { r.Exclude = r.NotInVersion(version) @@ -330,3 +614,153 @@ func (r *Resource) ExcludeIfNotInVersion(version *product.Version) { } } } + +// ==================== +// URL-related methods +// ==================== + +// Returns the "self_link_url" which is generally really the resource's GET +// URL. In older resources generally, this was the self_link value & was the +// product.base_url + resource.base_url + '/name' +// In newer resources there is much less standardisation in terms of value. +// Generally for them though, it's the product.base_url + resource.name + +// def self_link_url +func (r Resource) SelfLinkUrl() string { + s := []string{r.ProductMetadata.BaseUrl, r.SelfLinkUri()} + return strings.Join(s, "") +} + +// Returns the partial uri / relative path of a resource. In newer resources, +// this is the name. This fn is named self_link_uri for consistency, but +// could otherwise be considered to be "path" + +// def self_link_uri +func (r Resource) SelfLinkUri() string { + // If the terms in this are not snake-cased, this will require + // an override in Terraform. + if r.SelfLink != "" { + return r.SelfLink + } + + return strings.Join([]string{r.BaseUrl, "{{name}}"}, "/") +} + +// def collection_url +func (r Resource) CollectionUrl() string { + s := []string{r.ProductMetadata.BaseUrl, r.collectionUri()} + return strings.Join(s, "") +} + +// def collection_uri +func (r Resource) collectionUri() string { + return r.BaseUrl +} + +// def create_uri +func (r Resource) CreateUri() string { + if r.CreateUrl != "" { + return r.CreateUrl + } + + if r.CreateVerb == "" || r.CreateVerb == "POST" { + return r.collectionUri() + } + + return r.SelfLinkUri() +} + +// def delete_uri +func (r Resource) DeleteUri() string { + if r.DeleteUrl != "" { + return r.DeleteUrl + } + + return r.SelfLinkUri() +} + +// def resource_name +func (r Resource) ResourceName() string { + return fmt.Sprintf("%s%s", r.ProductMetadata.Name, r.Name) +} + +// 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) +func propertiesWithoutCustomUpdate(properties []*Type) []*Type { + return google.Select(properties, func(p *Type) bool { + return p.UpdateUrl == "" || p.UpdateVerb == "" || p.UpdateVerb == "NOOP" + }) +} + +// def update_body_properties +func (r Resource) UpdateBodyProperties() []*Type { + updateProp := propertiesWithoutCustomUpdate(r.settableProperties()) + if r.UpdateVerb == "PATCH" { + updateProp = google.Reject(updateProp, func(p *Type) bool { + return p.Immutable + }) + } + return updateProp +} + +// Handwritten TF Operation objects will be shaped like accessContextManager +// while the Google Go Client will have a name like accesscontextmanager + +// def client_name_pascal +func (r Resource) ClientNamePascal() string { + clientName := r.ProductMetadata.ClientName + if clientName == "" { + clientName = r.ProductMetadata.Name + } + + return google.Camelize(clientName, "upper") +} + +// In order of preference, use TF override, +// general defined timeouts, or default Timeouts + +// def timeouts +func (r Resource) GetTimeouts() *Timeouts { + timeoutsFiltered := r.Timeouts + if timeoutsFiltered == nil { + if async := r.GetAsync(); async != nil && async.Operation != nil { + timeoutsFiltered = async.Operation.Timeouts + } + + if timeoutsFiltered == nil { + timeoutsFiltered = NewTimeouts() + } + } + + return timeoutsFiltered +} + +// def project? +func (r Resource) HasProject() bool { + return strings.Contains(r.BaseUrl, "{{project}}") || strings.Contains(r.CreateUrl, "{{project}}") +} + +// def region? +func (r Resource) HasRegion() bool { + return strings.Contains(r.BaseUrl, "{{region}}") || strings.Contains(r.CreateUrl, "{{region}}") +} + +// def zone? +func (r Resource) HasZone() bool { + return strings.Contains(r.BaseUrl, "{{zone}}") || strings.Contains(r.CreateUrl, "{{zone}}") +} + +// ==================== +// Debugging Methods +// ==================== + +// Prints a dot notation path to where the field is nested within the parent +// object when called on a property. eg: parent.meta.label.foo +// Redefined on Resource to terminate the calls up the parent chain. + +// def lineage +func (r Resource) Lineage() string { + return r.Name +} diff --git a/mmv1/api/resource.rb b/mmv1/api/resource.rb index a3036a3c6d79..7e086ad13fd1 100644 --- a/mmv1/api/resource.rb +++ b/mmv1/api/resource.rb @@ -445,18 +445,6 @@ def identity end end - def kind? - !@kind.nil? - end - - def encoder? - !@transport&.encoder.nil? - end - - def decoder? - !@transport&.decoder.nil? - end - def add_labels_related_fields(props, parent) props.each do |p| if p.is_a? Api::Type::KeyValueLabels @@ -635,10 +623,6 @@ def collection_uri @base_url end - def full_create_url - [@__product.base_url, create_uri].flatten.join - end - def create_uri if @create_url.nil? if @create_verb.nil? || @create_verb == :POST @@ -651,10 +635,6 @@ def create_uri end end - def full_delete_url - [@__product.base_url, delete_uri].flatten.join - end - def delete_uri if @delete_url.nil? self_link_uri diff --git a/mmv1/api/timeouts.go b/mmv1/api/timeouts.go index 41134697a969..31d1e61b2f8f 100644 --- a/mmv1/api/timeouts.go +++ b/mmv1/api/timeouts.go @@ -42,6 +42,14 @@ type Timeouts struct { // validate // end +func NewTimeouts() *Timeouts { + return &Timeouts{ + InsertMinutes: DEFAULT_INSERT_TIMEOUT_MINUTES, + UpdateMinutes: DEFAULT_UPDATE_TIMEOUT_MINUTES, + DeleteMinutes: DEFAULT_DELETE_TIMEOUT_MINUTES, + } +} + // def validate // super diff --git a/mmv1/api/type.go b/mmv1/api/type.go index f80777231810..43afc0f77f8b 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -14,7 +14,12 @@ package api import ( + "fmt" + "log" + "reflect" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" + "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" ) // require 'api/object' @@ -120,19 +125,20 @@ type Type struct { RequiredWith []string `yaml:"required_with"` // Can only be overridden - we should never set this ourselves. - // TODO: set a specific type intead of interface{} - NewType interface{} + NewType string // A pattern that maps expected user input to expected API input. // TODO: remove? Pattern string - Properties []Type + Properties []*Type EnumValues []string `yaml:"enum_values"` ItemType string `yaml:"item_type"` + Resource string + // ==================== // Terraform Overrides // ==================== @@ -305,11 +311,15 @@ const MAX_NAME = 20 // object. eg: parent.meta.label.foo // The only intended purpose is to allow better error messages. Some objects // and at some points in the build this doesn't output a valid output. -// func (t *Type) lineage() { -// return name&.underscore if __parent.nil? -// "//{__parent.lineage}.//{name&.underscore}" -// } +// def lineage +func (t *Type) Lineage() string { + if t.ParentMetadata == nil { + return google.Underscore(t.Name) + } + + return fmt.Sprintf("%s.%s", t.ParentMetadata.Lineage(), google.Underscore(t.Name)) +} // Prints the access path of the field in the configration eg: metadata.0.labels // The only intended purpose is to get the value of the labes field by calling d.Get(). @@ -445,6 +455,7 @@ const MAX_NAME = 20 // // @__parent // } +// def min_version func (t *Type) MinVersionObj() *product.Version { if t.MinVersion != "" { return t.ResourceMetadata.ProductMetadata.versionObj(t.MinVersion) @@ -453,6 +464,7 @@ func (t *Type) MinVersionObj() *product.Version { } } +// def exact_version func (t *Type) exactVersionObj() *product.Version { if t.ExactVersion == "" { return nil @@ -461,6 +473,7 @@ func (t *Type) exactVersionObj() *product.Version { return t.ResourceMetadata.ProductMetadata.versionObj(t.ExactVersion) } +// def exclude_if_not_in_version!(version) func (t *Type) ExcludeIfNotInVersion(version *product.Version) { if !t.Exclude { if versionObj := t.exactVersionObj(); versionObj != nil { @@ -473,14 +486,24 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { } } -// // Overriding is_a? to enable class overrides. -// // Ruby does not let you natively change types, so this is the next best -// // thing. +// Overriding is_a? to enable class overrides. +// Ruby does not let you natively change types, so this is the next best +// thing. + +// TODO Q1: check the type of superclasses of property t // func (t *Type) is_a?(clazz) { -// // return Module.const_get(@new_type).new.is_a?(clazz) if @new_type +func (t *Type) IsA(clazz string) bool { + if clazz == "" { + log.Fatalf("class cannot be empty") + } -// // super(clazz) -// } + if t.NewType != "" { + return t.NewType == clazz + } + + return reflect.TypeOf(t).Name() == fmt.Sprintf("main.%s", clazz) + // super(clazz) +} // // Overriding class to enable class overrides. // // Ruby does not let you natively change types, so this is the next best @@ -491,11 +514,6 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // // super // } -// // Returns nested properties for this property. -// func (t *Type) nested_properties() { -// // nil -// } - // func (t *Type) removed() { // // !(@removed_message.nil? || @removed_message == '') // } @@ -634,12 +652,12 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // if @item_type.is_a? NestedObject // end -// func (t *Type) nested_properties -// return @item_type.nested_properties.reject(&:exclude) \ -// if @item_type.is_a?(Api::Type::NestedObject) +// func (t *Type) nested_properties +// return @item_type.nested_properties.reject(&:exclude) \ +// if @item_type.is_a?(Api::Type::NestedObject) -// super -// end +// super +// end // func (t *Type) item_type_class // return @item_type \ @@ -726,12 +744,15 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // return props.first unless props.empty? // end -// func (t *Type) resource_ref -// product = @__resource.__product -// resources = product.objects.select { |obj| obj.name == @resource } +// func (t *Type) resource_ref +func (t *Type) ResourceRef() *Resource { + product := t.ResourceMetadata.ProductMetadata + resources := google.Select(product.Objects, func(obj *Resource) bool { + return obj.Name == t.Resource + }) -// resources[0] -// end + return resources[0] +} // func (t *Type) property_class // type = property_ns_prefix @@ -783,27 +804,37 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // @properties // end -// func (t *Type) properties -// raise "Field '//{lineage}' properties are nil!" if @properties.nil? +// func (t *Type) properties +func (t *Type) UserProperties() []*Type { + if t.Properties == nil { + log.Fatalf("Field '{%s}' properties are nil!", t.Lineage()) + } -// @properties.reject(&:exclude) -// end + return google.Reject(t.Properties, func(p *Type) bool { + return p.Exclude + }) +} -// func (t *Type) nested_properties -// properties -// end +// func (t *Type) nested_properties +func (t *Type) NestedProperties() []*Type { + return t.UserProperties() +} -// // Returns the list of top-level properties once any nested objects with -// // flatten_object set to true have been collapsed -// func (t *Type) root_properties -// properties.flat_map do |p| -// if p.flatten_object -// p.root_properties -// else -// p -// end -// end -// end +// Returns the list of top-level properties once any nested objects with +// flatten_object set to true have been collapsed +// +// func (t *Type) root_properties +func (t *Type) RootProperties() []*Type { + props := make([]*Type, 0) + for _, p := range t.UserProperties() { + if p.FlattenObject { + props = google.Concat(props, p.RootProperties()) + } else { + props = append(props, p) + } + } + return props +} // func (t *Type) exclude_if_not_in_version!(version) // super diff --git a/mmv1/google/string_utils.go b/mmv1/google/string_utils.go index a9e4fb0db978..880460ee9ddb 100644 --- a/mmv1/google/string_utils.go +++ b/mmv1/google/string_utils.go @@ -14,8 +14,10 @@ package google import ( + "log" "regexp" "strings" + "unicode" ) // // Helper class to process and mutate strings. @@ -83,21 +85,34 @@ func SpaceSeparated(source string) string { // "//{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 +func Camelize(term string, firstLetter string) string { + if firstLetter != "upper" && firstLetter != "lower" { + log.Fatalf("Invalid option, use either upper or lower") + } + + res := term + if firstLetter == "upper" { + res = regexp.MustCompile(`^[a-z\d]*/`).ReplaceAllStringFunc(res, func(match string) string { + return strings.Title(match) + }) + } else { + // TODO: rewrite with the regular expression. Lookahead(?=) is not supported in Go + // acronymsCamelizeRegex := regexp.MustCompile(`^(?:(?=a)b(?=\b|[A-Z_])|\w)`) + // res = acronymsCamelizeRegex.ReplaceAllStringFunc(res, func(match string) string { + // return strings.ToLower(match) + // }) + if len(res) != 0 { + r := []rune(res) + r[0] = unicode.ToLower(r[0]) + res = string(r) + } + } + // handle snake case + re := regexp.MustCompile(`(?:_)([a-z\d]*)`) + res = re.ReplaceAllStringFunc(res, func(match string) string { + word := match[1:] + word = strings.Title(word) + return word + }) + return res +} diff --git a/mmv1/google/string_utils_test.go b/mmv1/google/string_utils_test.go new file mode 100644 index 000000000000..cde78a98d0dd --- /dev/null +++ b/mmv1/google/string_utils_test.go @@ -0,0 +1,54 @@ +package google + +import ( + "reflect" + "testing" +) + +func TestStringCamelize(t *testing.T) { + t.Parallel() + + cases := []struct { + description string + term string + firstLetter string + expected string + }{ + { + description: "Camelize string with lowercase first letter", + term: "AuthorizedOrgsDesc", + firstLetter: "lower", + expected: "authorizedOrgsDesc", + }, + { + description: "Camelize string with uppercase first letter", + term: "AuthorizedOrgsDesc", + firstLetter: "upper", + expected: "AuthorizedOrgsDesc", + }, + { + description: "Camelize snakecase string with lowercase first letter", + term: "Authorized_Orgs_Desc", + firstLetter: "lower", + expected: "authorizedOrgsDesc", + }, + { + description: "Camelize snakecase string with uppercase first letter", + term: "Authorized_Orgs_Desc", + firstLetter: "upper", + expected: "AuthorizedOrgsDesc", + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.description, func(t *testing.T) { + t.Parallel() + + if got, want := Camelize(tc.term, tc.firstLetter), tc.expected; !reflect.DeepEqual(got, want) { + t.Errorf("expected %v to be %v", got, want) + } + }) + } +} diff --git a/mmv1/provider/terraform.rb b/mmv1/provider/terraform.rb index 37fd2de9f525..cd781e5da8eb 100644 --- a/mmv1/provider/terraform.rb +++ b/mmv1/provider/terraform.rb @@ -466,14 +466,6 @@ def properties_by_custom_update(properties) 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 From cbcabf77af2a2a035338003ce717e5cfd73b0060 Mon Sep 17 00:00:00 2001 From: Harrison Powers Date: Tue, 19 Mar 2024 18:56:57 -0400 Subject: [PATCH 162/200] Add missing guest_os_features enumeration value (#10229) --- mmv1/products/compute/Disk.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/mmv1/products/compute/Disk.yaml b/mmv1/products/compute/Disk.yaml index 2097550860c1..9fdca5f907ee 100644 --- a/mmv1/products/compute/Disk.yaml +++ b/mmv1/products/compute/Disk.yaml @@ -500,6 +500,7 @@ properties: - :SEV_SNP_CAPABLE - :SUSPEND_RESUME_COMPATIBLE - :TDX_CAPABLE + - :SEV_LIVE_MIGRATABLE_V2 - !ruby/object:Api::Type::Array name: 'licenses' description: Any applicable license URI. From 8f3a9892f4cfeddbaf4dc8457849e30e6ac49b8e Mon Sep 17 00:00:00 2001 From: Max Portocarrero CI&T <105444618+maxi-cit@users.noreply.github.com> Date: Tue, 19 Mar 2024 20:51:00 -0500 Subject: [PATCH 163/200] add billing project id support to firewall endpoint resource (#10122) * add billing project support * removed description field due to API issue * test updated and fixed for ADC support * added ADC warning * removing ADC --- .../networksecurity/FirewallEndpoint.yaml | 12 +++++ ...ork_security_firewall_endpoint_test.go.erb | 49 ++++++++++--------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/mmv1/products/networksecurity/FirewallEndpoint.yaml b/mmv1/products/networksecurity/FirewallEndpoint.yaml index bc53ec4fa5a5..a2118263106c 100644 --- a/mmv1/products/networksecurity/FirewallEndpoint.yaml +++ b/mmv1/products/networksecurity/FirewallEndpoint.yaml @@ -23,6 +23,13 @@ description: | A Firewall endpoint is a Cloud Firewall resource that enables layer 7 advanced protection capabilities, such as intrusion prevention, in your network. +docs: !ruby/object:Provider::Terraform::Docs + warning: | + If you are using User ADCs (Application Default Credentials) with this resource, + you must specify a `billing_project` and set `user_project_override` to true + in the provider configuration. Otherwise the ACM API will return a 403 error. + Your account must have the `serviceusage.services.use` permission on the + `billing_project` you defined. references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/firewall/docs/reference/network-security/rest/v1beta1/organizations.locations.firewallEndpoints' @@ -110,3 +117,8 @@ properties: name: 'state' description: The current state of the endpoint. output: true + - !ruby/object:Api::Type::String + name: 'billingProjectId' + description: | + Project to bill on endpoint uptime usage. + required: true diff --git a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb index 05413b1545ec..888d865f9fbb 100644 --- a/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb +++ b/mmv1/third_party/terraform/services/networksecurity/resource_network_security_firewall_endpoint_test.go.erb @@ -20,6 +20,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { acctest.SkipIfVcr(t) t.Parallel() + billingProjectId := envvar.GetTestProjectFromEnv() orgId := envvar.GetTestOrgFromEnv(t) randomSuffix := acctest.RandString(t, 10) @@ -29,7 +30,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { CheckDestroy: testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccNetworkSecurityFirewallEndpoints_basic(orgId, randomSuffix), + Config: testAccNetworkSecurityFirewallEndpoints_basic(orgId, billingProjectId, randomSuffix), }, { ResourceName: "google_network_security_firewall_endpoint.foobar", @@ -38,7 +39,7 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { ImportStateVerifyIgnore: []string{"labels", "terraform_labels"}, }, { - Config: testAccNetworkSecurityFirewallEndpoints_update(orgId, randomSuffix), + Config: testAccNetworkSecurityFirewallEndpoints_update(orgId, billingProjectId, randomSuffix), }, { ResourceName: "google_network_security_firewall_endpoint.foobar", @@ -50,34 +51,38 @@ func TestAccNetworkSecurityFirewallEndpoints_basic(t *testing.T) { }) } -func testAccNetworkSecurityFirewallEndpoints_basic(orgId string, randomSuffix string) string { +func testAccNetworkSecurityFirewallEndpoints_basic(orgId string, billingProjectId string, randomSuffix string) string { return fmt.Sprintf(` resource "google_network_security_firewall_endpoint" "foobar" { - provider = google-beta - name = "tf-test-my-firewall-endpoint%s" - parent = "organizations/%s" - location = "us-central1-a" - - labels = { - foo = "bar" - } + provider = google-beta + + name = "tf-test-my-firewall-endpoint%[1]s" + parent = "organizations/%[2]s" + location = "us-central1-a" + billing_project_id = "%[3]s" + + labels = { + foo = "bar" + } } -`, randomSuffix, orgId) +`, randomSuffix, orgId, billingProjectId) } -func testAccNetworkSecurityFirewallEndpoints_update(orgId string, randomSuffix string) string { +func testAccNetworkSecurityFirewallEndpoints_update(orgId string, billingProjectId string, randomSuffix string) string { return fmt.Sprintf(` resource "google_network_security_firewall_endpoint" "foobar" { - provider = google-beta - name = "tf-test-my-firewall-endpoint%s" - parent = "organizations/%s" - location = "us-central1-a" - - labels = { - foo = "bar-updated" - } + provider = google-beta + + name = "tf-test-my-firewall-endpoint%[1]s" + parent = "organizations/%[2]s" + location = "us-central1-a" + billing_project_id = "%[3]s" + + labels = { + foo = "bar-updated" + } } -`, randomSuffix, orgId) +`, randomSuffix, orgId, billingProjectId) } func testAccCheckNetworkSecurityFirewallEndpointDestroyProducer(t *testing.T) func(s *terraform.State) error { From 96a71f83d4c35f9cf36676d595d412513ad7d9c4 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 20 Mar 2024 08:33:49 -0700 Subject: [PATCH 164/200] Upgraded version of actions related to scorecard (#10234) --- .github/workflows/scorecard.yml | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index cd6776998c7c..cd54f8e44a32 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -32,34 +32,24 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2 + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 with: results_file: results.sarif results_format: sarif - # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: - # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecard on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. - # repo_token: ${{ secrets.SCORECARD_TOKEN }} - - # Public repositories: - # - Publish results to OpenSSF REST API for easy access by consumers - # - Allows the repository to include the Scorecard badge. - # - See https://github.com/ossf/scorecard-action#publishing-results. - # For private repositories: - # - `publish_results` will always be set to `false`, regardless - # of the value entered here. + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. publish_results: true # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - name: "Upload artifact" - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: SARIF file path: results.sarif @@ -67,6 +57,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4 + uses: github/codeql-action/upload-sarif@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 with: sarif_file: results.sarif From 50e40919b75d72244d3774e124758a21241bc4f9 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 20 Mar 2024 09:08:29 -0700 Subject: [PATCH 165/200] Don't re-request review if initial PR comment is edited (#10232) --- .github/workflows/request-reviewer.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/request-reviewer.yml b/.github/workflows/request-reviewer.yml index de54d2e2f353..2fbedea0d6a4 100644 --- a/.github/workflows/request-reviewer.yml +++ b/.github/workflows/request-reviewer.yml @@ -5,7 +5,6 @@ permissions: read-all on: pull_request_target: types: - - edited - opened - ready_for_review - reopened From 982d61acdf6e6c50f428a843d96a651400e71f7f Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 20 Mar 2024 09:16:10 -0700 Subject: [PATCH 166/200] Pinned versions for GitHub Actions (#10239) --- .github/workflows/build-downstream.yml | 10 +++++----- .github/workflows/changelog-checker.yml | 2 +- .github/workflows/membership-checker.yml | 4 ++-- .github/workflows/mmv1-lint-product-yaml.yml | 2 +- .github/workflows/mmv1-rake-tests.yml | 2 +- .github/workflows/repository-documentation-deploy.yml | 2 +- .github/workflows/repository-documentation-test.yml | 2 +- .github/workflows/request-reviewer.yml | 4 ++-- .../workflows/teamcity-services-diff-check-weekly.yml | 2 +- .github/workflows/teamcity-services-diff-check.yml | 4 ++-- .github/workflows/test-tgc.yml | 6 +++--- .github/workflows/test-tpg.yml | 4 ++-- .github/workflows/unit-test-tgc.yml | 8 ++++---- .github/workflows/unit-test-tpg.yml | 4 ++-- .github/workflows/unit-tests-diff-processor.yml | 4 ++-- 15 files changed, 30 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build-downstream.yml b/.github/workflows/build-downstream.yml index 10fcc1c768da..4cfa5aa2bac1 100644 --- a/.github/workflows/build-downstream.yml +++ b/.github/workflows/build-downstream.yml @@ -21,7 +21,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: fetch-depth: 0 @@ -31,7 +31,7 @@ jobs: ruby-version: '3.1' - name: Cache Bundler gems - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: mmv1/vendor/bundle key: ${{ runner.os }}-gems-${{ hashFiles('mmv1/**/Gemfile.lock') }} @@ -45,13 +45,13 @@ jobs: working-directory: mmv1 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' # Cache Go modules - name: Cache Go modules - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} @@ -108,7 +108,7 @@ jobs: (current_dir=$(pwd) && cd $OUTPUT_PATH && zip -r "$current_dir/output.zip" .) - name: Upload built artifacts - uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3 with: name: artifact-${{ inputs.repo }} path: output.zip \ No newline at end of file diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index 4e546f0e05e5..5d36340b23e6 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: path: repo - name: Check Changelog diff --git a/.github/workflows/membership-checker.yml b/.github/workflows/membership-checker.yml index 6650f101acc2..3a873917bce9 100644 --- a/.github/workflows/membership-checker.yml +++ b/.github/workflows/membership-checker.yml @@ -11,9 +11,9 @@ jobs: build-and-unit-tests: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' - name: Run membership checker unit tests diff --git a/.github/workflows/mmv1-lint-product-yaml.yml b/.github/workflows/mmv1-lint-product-yaml.yml index 7a732c6c7402..a857f40c3a7a 100644 --- a/.github/workflows/mmv1-lint-product-yaml.yml +++ b/.github/workflows/mmv1-lint-product-yaml.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: path: repo fetch-depth: 0 diff --git a/.github/workflows/mmv1-rake-tests.yml b/.github/workflows/mmv1-rake-tests.yml index e6d1ecb5ea1f..0c52a40890da 100644 --- a/.github/workflows/mmv1-rake-tests.yml +++ b/.github/workflows/mmv1-rake-tests.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: path: repo fetch-depth: 2 diff --git a/.github/workflows/repository-documentation-deploy.yml b/.github/workflows/repository-documentation-deploy.yml index f94df4ce4ffd..c21bc900150d 100644 --- a/.github/workflows/repository-documentation-deploy.yml +++ b/.github/workflows/repository-documentation-deploy.yml @@ -13,7 +13,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: submodules: true # Fetch Hugo themes (true OR recursive) fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod diff --git a/.github/workflows/repository-documentation-test.yml b/.github/workflows/repository-documentation-test.yml index f2952926ef2a..b425ecb58ca7 100644 --- a/.github/workflows/repository-documentation-test.yml +++ b/.github/workflows/repository-documentation-test.yml @@ -11,7 +11,7 @@ jobs: deploy: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: submodules: true # Fetch Hugo themes (true OR recursive) fetch-depth: 0 # Fetch all history for .GitInfo and .Lastmod diff --git a/.github/workflows/request-reviewer.yml b/.github/workflows/request-reviewer.yml index 2fbedea0d6a4..870abb2b57d6 100644 --- a/.github/workflows/request-reviewer.yml +++ b/.github/workflows/request-reviewer.yml @@ -23,9 +23,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' # Disable caching for now due to issues with large provider dependency caches diff --git a/.github/workflows/teamcity-services-diff-check-weekly.yml b/.github/workflows/teamcity-services-diff-check-weekly.yml index 355501e14d51..d9c257b1aca6 100644 --- a/.github/workflows/teamcity-services-diff-check-weekly.yml +++ b/.github/workflows/teamcity-services-diff-check-weekly.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: TeamCity Google Provider Generate uses: ./.github/actions/build-downstream with: diff --git a/.github/workflows/teamcity-services-diff-check.yml b/.github/workflows/teamcity-services-diff-check.yml index 9ffee2130bdb..a5ff3e1bc3a7 100644 --- a/.github/workflows/teamcity-services-diff-check.yml +++ b/.github/workflows/teamcity-services-diff-check.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: fetch-depth: 0 - name: "Check for New Services" @@ -48,7 +48,7 @@ jobs: run: echo "GOOGLE_BETA_REPO_PATH=${{ env.OUTPUT_PATH}}" >> $GITHUB_ENV - name: Checkout Repository if: steps.generate.outcome == 'success' - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: Check that new services have been added to the TeamCity configuration code if: steps.generate.outcome == 'success' run: | diff --git a/.github/workflows/test-tgc.yml b/.github/workflows/test-tgc.yml index 1edfa5b9399a..0b04641cbfd3 100644 --- a/.github/workflows/test-tgc.yml +++ b/.github/workflows/test-tgc.yml @@ -53,13 +53,13 @@ jobs: "state": "pending" }' - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} ref: ${{ github.event.inputs.branch }} fetch-depth: 2 - name: Cache Go modules and build cache - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/pkg/mod @@ -78,7 +78,7 @@ jobs: fi - name: Set up Go if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' - name: Build Terraform Google Conversion diff --git a/.github/workflows/test-tpg.yml b/.github/workflows/test-tpg.yml index c59f4355f19d..9c8900c019f8 100644 --- a/.github/workflows/test-tpg.yml +++ b/.github/workflows/test-tpg.yml @@ -52,7 +52,7 @@ jobs: "state": "pending" }' - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 with: repository: ${{ github.event.inputs.owner }}/${{ github.event.inputs.repo }} ref: ${{ github.event.inputs.branch }} @@ -68,7 +68,7 @@ jobs: fi - name: Set up Go if: ${{ !failure() && steps.pull_request.outputs.has_changes == 'true' }} - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' - name: Build Provider diff --git a/.github/workflows/unit-test-tgc.yml b/.github/workflows/unit-test-tgc.yml index 34011a802bed..51bbfaee3193 100644 --- a/.github/workflows/unit-test-tgc.yml +++ b/.github/workflows/unit-test-tgc.yml @@ -9,13 +9,13 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Download built artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: artifact-terraform-google-conversion path: artifacts-tgc - name: Download built artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: artifact-terraform-provider-google-beta path: artifacts-tpgb @@ -28,12 +28,12 @@ jobs: rm artifacts-tpgb/output.zip - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' - name: Cache Go modules and build cache - uses: actions/cache@v3 + uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 with: path: | ~/go/pkg/mod diff --git a/.github/workflows/unit-test-tpg.yml b/.github/workflows/unit-test-tpg.yml index e394fd9ab8d4..b1e84004a364 100644 --- a/.github/workflows/unit-test-tpg.yml +++ b/.github/workflows/unit-test-tpg.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Download built artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 with: name: artifact-${{ inputs.repo }} path: artifacts @@ -26,7 +26,7 @@ jobs: rm artifacts/output.zip - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21' diff --git a/.github/workflows/unit-tests-diff-processor.yml b/.github/workflows/unit-tests-diff-processor.yml index 8718b49b7e61..b3a1b80e189a 100644 --- a/.github/workflows/unit-tests-diff-processor.yml +++ b/.github/workflows/unit-tests-diff-processor.yml @@ -11,10 +11,10 @@ jobs: test: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 - name: Set up Go - uses: actions/setup-go@v4 + uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: '^1.21.0' From da6130d6b8b9cddca1bd59bcf21429d4865a59ed Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Wed, 20 Mar 2024 09:19:52 -0700 Subject: [PATCH 167/200] Switched from diff-processor adding labels to just computing and returning them as JSON (#10211) * Switched diff-processor from add-labels command to changed-schema-labels command * Force update to redis cluster * Revert "Force update to redis cluster" This reverts commit 750c39ddf7f30d8a448fb775b86711ecbf3830f0. --- .ci/magician/cmd/generate_comment.go | 99 +++-- .ci/magician/cmd/generate_comment_test.go | 8 +- .ci/magician/cmd/interfaces.go | 2 +- .ci/magician/cmd/membership_checker.go | 2 +- .ci/magician/cmd/membership_checker_test.go | 4 +- .ci/magician/cmd/mock_github_test.go | 4 +- .ci/magician/cmd/mock_runner_test.go | 2 +- .ci/magician/github/set.go | 6 +- .ci/magician/source/repo.go | 14 +- tools/diff-processor/cmd/add_labels.go | 103 ----- tools/diff-processor/cmd/add_labels_test.go | 294 -------------- .../cmd/changed_schema_labels.go | 62 +++ .../cmd/changed_schema_labels_test.go | 162 ++++++++ tools/diff-processor/cmd/root.go | 2 +- tools/diff-processor/go.mod | 105 ++--- tools/diff-processor/go.sum | 379 ++++++++---------- tools/diff-processor/labels/get_issue.go | 46 --- tools/issue-labeler/labeler/labels.go | 3 +- 18 files changed, 550 insertions(+), 747 deletions(-) delete mode 100644 tools/diff-processor/cmd/add_labels.go delete mode 100644 tools/diff-processor/cmd/add_labels_test.go create mode 100644 tools/diff-processor/cmd/changed_schema_labels.go create mode 100644 tools/diff-processor/cmd/changed_schema_labels_test.go delete mode 100644 tools/diff-processor/labels/get_issue.go diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index d1d5cd2936b4..78dcbc7b1347 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -16,11 +16,8 @@ package cmd import ( + "encoding/json" "fmt" - "magician/exec" - "magician/github" - "magician/provider" - "magician/source" "os" "path/filepath" "sort" @@ -28,6 +25,11 @@ import ( "strings" "text/template" + "magician/exec" + "magician/github" + "magician/provider" + "magician/source" + "github.com/spf13/cobra" "golang.org/x/exp/maps" @@ -141,6 +143,14 @@ func listGCEnvironmentVariables() string { } func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, projectId, commitSha string, gh GithubClient, rnr ExecRunner, ctlr *source.Controller) { + errors := map[string][]string{"Other": []string{}} + + pullRequest, err := gh.GetPullRequest(strconv.Itoa(prNumber)) + if err != nil { + fmt.Printf("Error getting pull request: %v\n", err) + errors["Other"] = append(errors["Other"], "Failed to fetch PR data") + } + newBranch := fmt.Sprintf("auto-pr-%d", prNumber) oldBranch := fmt.Sprintf("auto-pr-%d-old", prNumber) wd := rnr.GetCWD() @@ -174,8 +184,6 @@ func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, data := diffCommentData{ PrNumber: prNumber, } - errors := map[string][]string{"Other": []string{}} - var err error for _, repo := range []*source.Repo{&tpgRepo, &tpgbRepo, &tgcRepo, &tfoicsRepo} { errors[repo.Title] = []string{} repo.Branch = newBranch @@ -210,6 +218,7 @@ func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, // The breaking changes are unique across both provider versions uniqueBreakingChanges := map[string]struct{}{} + uniqueServiceLabels := map[string]struct{}{} diffProcessorPath := filepath.Join(mmLocalPath, "tools", "diff-processor") diffProcessorEnv := map[string]string{ "OLD_REF": oldBranch, @@ -240,14 +249,20 @@ func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, uniqueBreakingChanges[breakingChange] = struct{}{} } - addLabelsEnv := map[string]string{ - "GITHUB_TOKEN_MAGIC_MODULES": ghTokenMagicModules, + // If fetching the PR failed, Labels will be empty + labels := make([]string, len(pullRequest.Labels)) + for i, label := range pullRequest.Labels { + labels[i] = label.Name } - err = addLabels(prNumber, diffProcessorPath, addLabelsEnv, rnr) + serviceLabels, err := changedSchemaLabels(prNumber, labels, diffProcessorPath, gh, rnr) if err != nil { - fmt.Println("adding service labels: ", err) - errors[repo.Title] = append(errors[repo.Title], "The diff processor crashed while adding labels.") + fmt.Println("computing changed schema labels: ", err) + errors[repo.Title] = append(errors[repo.Title], "The diff processor crashed while computing changed schema labels.") + } + for _, serviceLabel := range serviceLabels { + uniqueServiceLabels[serviceLabel] = struct{}{} } + err = cleanDiffProcessor(diffProcessorPath, rnr) if err != nil { fmt.Println("cleaning up diff processor: ", err) @@ -258,21 +273,25 @@ func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, sort.Strings(breakingChangesSlice) data.BreakingChanges = breakingChangesSlice + // Add service labels to PR + if len(uniqueServiceLabels) > 0 { + serviceLabelsSlice := maps.Keys(uniqueServiceLabels) + sort.Strings(serviceLabelsSlice) + if err = gh.AddLabels(strconv.Itoa(prNumber), serviceLabelsSlice); err != nil { + fmt.Printf("Error posting new service labels %q: %s", serviceLabelsSlice, err) + errors["Other"] = append(errors["Other"], "Failed to update service labels") + } + } + // Update breaking changes status on PR breakingState := "success" if len(uniqueBreakingChanges) > 0 { breakingState = "failure" - - pullRequest, err := gh.GetPullRequest(strconv.Itoa(prNumber)) - if err != nil { - fmt.Printf("Error getting pull request: %v\n", err) - errors["Other"] = append(errors["Other"], "Failed to check for `override-breaking-change` label") - } else { - for _, label := range pullRequest.Labels { - if label.Name == allowBreakingChangesLabel { - breakingState = "success" - break - } + // If fetching the PR failed, Labels will be empty + for _, label := range pullRequest.Labels { + if label.Name == allowBreakingChangesLabel { + breakingState = "success" + break } } } @@ -387,16 +406,40 @@ func computeBreakingChanges(diffProcessorPath string, rnr ExecRunner) ([]string, return strings.Split(strings.TrimSuffix(output, "\n"), "\n"), rnr.PopDir() } -func addLabels(prNumber int, diffProcessorPath string, env map[string]string, rnr ExecRunner) error { +func changedSchemaLabels(prNumber int, currentLabels []string, diffProcessorPath string, gh GithubClient, rnr ExecRunner) ([]string, error) { if err := rnr.PushDir(diffProcessorPath); err != nil { - return err + return nil, err + } + + // short-circuit if service labels have already been added to the PR + hasServiceLabels := false + oldLabels := make(map[string]struct{}, len(currentLabels)) + for _, label := range currentLabels { + oldLabels[label] = struct{}{} + if strings.HasPrefix(label, "service/") { + hasServiceLabels = true + } } - output, err := rnr.Run("bin/diff-processor", []string{"add-labels", strconv.Itoa(prNumber)}, env) - fmt.Println(output) + if hasServiceLabels { + return nil, nil + } + + output, err := rnr.Run("bin/diff-processor", []string{"changed-schema-labels"}, nil) if err != nil { - return err + return nil, err } - return rnr.PopDir() + + fmt.Println("Labels for changed schema: " + output) + + var labels []string + if err = json.Unmarshal([]byte(output), &labels); err != nil { + return nil, err + } + + if err = rnr.PopDir(); err != nil { + return nil, err + } + return labels, nil } func cleanDiffProcessor(diffProcessorPath string, rnr ExecRunner) error { diff --git a/.ci/magician/cmd/generate_comment_test.go b/.ci/magician/cmd/generate_comment_test.go index 456267619bb8..f8055e165b06 100644 --- a/.ci/magician/cmd/generate_comment_test.go +++ b/.ci/magician/cmd/generate_comment_test.go @@ -37,9 +37,6 @@ func TestExecGenerateComment(t *testing.T) { "GOPATH": os.Getenv("GOPATH"), "HOME": os.Getenv("HOME"), } - addLabelsEnv := map[string]string{ - "GITHUB_TOKEN_MAGIC_MODULES": "*******", - } execGenerateComment( 123456, "*******", @@ -83,10 +80,10 @@ func TestExecGenerateComment(t *testing.T) { {"/mock/dir/tfoics", "git", []string{"diff", "origin/auto-pr-123456-old", "origin/auto-pr-123456", "--shortstat"}, map[string]string(nil)}, {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "123456"}, addLabelsEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"changed-schema-labels"}, map[string]string(nil)}, {"/mock/dir/magic-modules/tools/diff-processor", "make", []string{"build"}, diffProcessorEnv}, {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"breaking-changes"}, map[string]string(nil)}, - {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"add-labels", "123456"}, addLabelsEnv}, + {"/mock/dir/magic-modules/tools/diff-processor", "bin/diff-processor", []string{"changed-schema-labels"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "git", []string{"checkout", "origin/auto-pr-123456-old"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "find", []string{".", "-type", "f", "-name", "*.go", "-exec", "sed", "-i.bak", "s~github.com/hashicorp/terraform-provider-google-beta~google/provider/old~g", "{}", "+"}, map[string]string(nil)}, {"/mock/dir/tpgbold", "sed", []string{"-i.bak", "s|github.com/hashicorp/terraform-provider-google-beta|google/provider/old|g", "go.mod"}, map[string]string(nil)}, @@ -117,6 +114,7 @@ func TestExecGenerateComment(t *testing.T) { for method, expectedCalls := range map[string][][]any{ "PostBuildStatus": {{"123456", "terraform-provider-breaking-change-test", "success", "https://console.cloud.google.com/cloud-build/builds;region=global/build1;step=17?project=project1", "sha1"}}, "PostComment": {{"123456", "Hi there, I'm the Modular magician. I've detected the following information about your changes:\n\n## Diff report\n\nYour PR generated some diffs in downstreams - here they are.\n\n`google` provider: [Diff](https://github.com/modular-magician/terraform-provider-google/compare/auto-pr-123456-old..auto-pr-123456) ( 2 files changed, 40 insertions(+))\n`google-beta` provider: [Diff](https://github.com/modular-magician/terraform-provider-google-beta/compare/auto-pr-123456-old..auto-pr-123456) ( 2 files changed, 40 insertions(+))\n`terraform-google-conversion`: [Diff](https://github.com/modular-magician/terraform-google-conversion/compare/auto-pr-123456-old..auto-pr-123456) ( 1 file changed, 10 insertions(+))\n\n## Missing test report\nYour PR includes resource fields which are not covered by any test.\n\nResource: `google_folder_access_approval_settings` (3 total tests)\nPlease add an acceptance test which includes these fields. The test should include the following:\n\n```hcl\nresource \"google_folder_access_approval_settings\" \"primary\" {\n uncovered_field = # value needed\n}\n\n```\n"}}, + "AddLabels": {{"123456", []string{"service/google-x"}}}, } { if actualCalls, ok := gh.calledMethods[method]; !ok { t.Fatalf("Found no calls for %s", method) diff --git a/.ci/magician/cmd/interfaces.go b/.ci/magician/cmd/interfaces.go index 879f4a70a5c8..9d4c6dd2dcd6 100644 --- a/.ci/magician/cmd/interfaces.go +++ b/.ci/magician/cmd/interfaces.go @@ -30,7 +30,7 @@ type GithubClient interface { PostBuildStatus(prNumber, title, state, targetURL, commitSha string) error PostComment(prNumber, comment string) error RequestPullRequestReviewer(prNumber, assignee string) error - AddLabel(prNumber, label string) error + AddLabels(prNumber string, labels []string) error RemoveLabel(prNumber, label string) error CreateWorkflowDispatchEvent(workflowFileName string, inputs map[string]any) error } diff --git a/.ci/magician/cmd/membership_checker.go b/.ci/magician/cmd/membership_checker.go index a91ce77c5fca..3efb65b3b99d 100644 --- a/.ci/magician/cmd/membership_checker.go +++ b/.ci/magician/cmd/membership_checker.go @@ -83,7 +83,7 @@ func execMembershipChecker(prNumber, commitSha string, gh GithubClient, cb Cloud os.Exit(1) } } else { - gh.AddLabel(prNumber, "awaiting-approval") + gh.AddLabels(prNumber, []string{"awaiting-approval"}) targetUrl, err := cb.GetAwaitingApprovalBuildLink(prNumber, commitSha) if err != nil { fmt.Println(err) diff --git a/.ci/magician/cmd/membership_checker_test.go b/.ci/magician/cmd/membership_checker_test.go index 81074230ec56..11e0c1918bdf 100644 --- a/.ci/magician/cmd/membership_checker_test.go +++ b/.ci/magician/cmd/membership_checker_test.go @@ -92,8 +92,8 @@ func TestExecMembershipChecker_AmbiguousUserFlow(t *testing.T) { execMembershipChecker("pr1", "sha1", gh, cb) - method := "AddLabel" - expected := [][]any{{"pr1", "awaiting-approval"}} + method := "AddLabels" + expected := [][]any{{"pr1", []string{"awaiting-approval"}}} if calls, ok := gh.calledMethods[method]; !ok { t.Fatal("Label wasn't posted to pull request") } else if !reflect.DeepEqual(calls, expected) { diff --git a/.ci/magician/cmd/mock_github_test.go b/.ci/magician/cmd/mock_github_test.go index 5a836ff602f0..edd8554b21c5 100644 --- a/.ci/magician/cmd/mock_github_test.go +++ b/.ci/magician/cmd/mock_github_test.go @@ -73,8 +73,8 @@ func (m *mockGithub) PostComment(prNumber string, comment string) error { return nil } -func (m *mockGithub) AddLabel(prNumber string, label string) error { - m.calledMethods["AddLabel"] = append(m.calledMethods["AddLabel"], []any{prNumber, label}) +func (m *mockGithub) AddLabels(prNumber string, labels []string) error { + m.calledMethods["AddLabels"] = append(m.calledMethods["AddLabels"], []any{prNumber, labels}) return nil } diff --git a/.ci/magician/cmd/mock_runner_test.go b/.ci/magician/cmd/mock_runner_test.go index 72587c26b418..5ff069afa9d9 100644 --- a/.ci/magician/cmd/mock_runner_test.go +++ b/.ci/magician/cmd/mock_runner_test.go @@ -70,7 +70,7 @@ func NewMockRunner() MockRunner { "/mock/dir/magic-modules git [diff HEAD origin/main tools/missing-test-detector] map[]": "", "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [breaking-changes] map[]": "", "/mock/dir/magic-modules/tools/diff-processor make [build] " + sortedEnvString(diffProcessorEnv): "", - "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [add-labels 123456] map[GITHUB_TOKEN_MAGIC_MODULES:*******]": "", + "/mock/dir/magic-modules/tools/diff-processor bin/diff-processor [changed-schema-labels] map[]": "[\"service/google-x\"]", "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/new=/mock/dir/tpgb] map[]": "", "/mock/dir/magic-modules/tools/missing-test-detector go [mod edit -replace google/provider/old=/mock/dir/tpgbold] map[]": "", "/mock/dir/magic-modules/tools/missing-test-detector go [mod tidy] map[]": "", diff --git a/.ci/magician/github/set.go b/.ci/magician/github/set.go index 698781c6d667..7f517d66e1f0 100644 --- a/.ci/magician/github/set.go +++ b/.ci/magician/github/set.go @@ -74,16 +74,16 @@ func (gh *Client) RequestPullRequestReviewer(prNumber, assignee string) error { return nil } -func (gh *Client) AddLabel(prNumber, label string) error { +func (gh *Client) AddLabels(prNumber string, labels []string) error { url := fmt.Sprintf("https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/%s/labels", prNumber) body := map[string][]string{ - "labels": {label}, + "labels": labels, } err := utils.RequestCall(url, "POST", gh.token, nil, body) if err != nil { - return fmt.Errorf("failed to add %s label: %s", label, err) + return fmt.Errorf("failed to add %q labels: %s", labels, err) } return nil diff --git a/.ci/magician/source/repo.go b/.ci/magician/source/repo.go index 529cf97200ee..0c53cd40695c 100644 --- a/.ci/magician/source/repo.go +++ b/.ci/magician/source/repo.go @@ -8,13 +8,13 @@ import ( ) type Repo struct { - Name string // Name in GitHub (e.g. magic-modules) - Title string // Title for display (e.g. Magic Modules) - Branch string // Branch to clone, optional - Owner string // Owner of repo, optional - Path string // local Path once cloned, including Name - Version provider.Version - Cloned bool + Name string // Name in GitHub (e.g. magic-modules) + Title string // Title for display (e.g. Magic Modules) + Branch string // Branch to clone, optional + Owner string // Owner of repo, optional + Path string // local Path once cloned, including Name + Version provider.Version + Cloned bool } type Controller struct { diff --git a/tools/diff-processor/cmd/add_labels.go b/tools/diff-processor/cmd/add_labels.go deleted file mode 100644 index 1280898d823e..000000000000 --- a/tools/diff-processor/cmd/add_labels.go +++ /dev/null @@ -1,103 +0,0 @@ -package cmd - -import ( - newProvider "google/provider/new/google/provider" - oldProvider "google/provider/old/google/provider" - - "fmt" - "strconv" - "strings" - - "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/diff" - "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/labels" - "github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler/labeler" - "github.com/spf13/cobra" - "golang.org/x/exp/maps" -) - -const addLabelsDesc = `Add labels to a PR based on changed resources.` - -type addLabelsOptions struct { - rootOptions *rootOptions - computeSchemaDiff func() diff.SchemaDiff - enrolledTeamsYaml []byte - getIssue func(repository string, id uint64) (labeler.Issue, error) - updateIssues func(repository string, issueUpdates []labeler.IssueUpdate, dryRun bool) - dryRun bool -} - -func newAddLabelsCmd(rootOptions *rootOptions) *cobra.Command { - o := &addLabelsOptions{ - rootOptions: rootOptions, - computeSchemaDiff: func() diff.SchemaDiff { - return diff.ComputeSchemaDiff(oldProvider.ResourceMap(), newProvider.ResourceMap()) - }, - enrolledTeamsYaml: labeler.EnrolledTeamsYaml, - getIssue: labels.GetIssue, - updateIssues: labeler.UpdateIssues, - } - cmd := &cobra.Command{ - Use: "add-labels PR_ID [--dry-run]", - Short: addLabelsDesc, - Long: addLabelsDesc, - Args: cobra.ExactArgs(1), - RunE: func(c *cobra.Command, args []string) error { - return o.run(args) - }, - } - cmd.Flags().BoolVar(&o.dryRun, "dry-run", false, "Do a dry run without updating labels") - return cmd -} -func (o *addLabelsOptions) run(args []string) error { - prId, err := strconv.ParseUint(args[0], 10, 0) - if err != nil { - return fmt.Errorf("PR_ID must be an unsigned integer: %w", err) - } - - repository := "GoogleCloudPlatform/magic-modules" - issue, err := o.getIssue(repository, prId) - - if err != nil { - return fmt.Errorf("Error retrieving PR data: %w", err) - } - - hasServiceLabels := false - oldLabels := make(map[string]struct{}, len(issue.Labels)) - for _, label := range issue.Labels { - oldLabels[label.Name] = struct{}{} - if strings.HasPrefix(label.Name, "service/") { - hasServiceLabels = true - } - } - if hasServiceLabels { - return nil - } - - schemaDiff := o.computeSchemaDiff() - affectedResources := maps.Keys(schemaDiff) - regexpLabels, err := labeler.BuildRegexLabels(o.enrolledTeamsYaml) - if err != nil { - return fmt.Errorf("Error building regex labels: %w", err) - } - - newLabels := make(map[string]struct{}, len(oldLabels)) - for label, _ := range oldLabels { - newLabels[label] = struct{}{} - } - for _, label := range labeler.ComputeLabels(affectedResources, regexpLabels) { - newLabels[label] = struct{}{} - } - - // Only update the issue if new labels should be added - if len(newLabels) != len(oldLabels) { - issueUpdate := labeler.IssueUpdate{ - Number: prId, - Labels: maps.Keys(newLabels), - OldLabels: maps.Keys(oldLabels), - } - - o.updateIssues(repository, []labeler.IssueUpdate{issueUpdate}, o.dryRun) - } - - return nil -} diff --git a/tools/diff-processor/cmd/add_labels_test.go b/tools/diff-processor/cmd/add_labels_test.go deleted file mode 100644 index f9bda99a5ecc..000000000000 --- a/tools/diff-processor/cmd/add_labels_test.go +++ /dev/null @@ -1,294 +0,0 @@ -package cmd - -import ( - _ "embed" - "errors" - "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/diff" - "github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler/labeler" - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "testing" -) - -var enrolledTeamsYaml = []byte(` -service/google-x: - resources: - - google_x_resource`) - -func TestAddLabelsCmdRun(t *testing.T) { - cases := map[string]struct { - args []string - oldResourceMap map[string]*schema.Resource - newResourceMap map[string]*schema.Resource - githubIssue *labeler.Issue - updateErrors bool - expectedLabels []string - expectError bool - }{ - "empty resource map": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{}, - newResourceMap: map[string]*schema.Resource{}, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: nil, - }, - "resource changed that doesn't match mapping": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_y_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_y_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: nil, - }, - "resource matches mapping but isn't changed": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: nil, - }, - "resource changed that matches mapping": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: []string{"service/google-x"}, - }, - "service labels are deduped": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - "google_x_resource2": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - "google_x_resource2": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{}, - PullRequest: map[string]any{}, - }, - expectedLabels: []string{"service/google-x"}, - }, - "existing labels are preserved": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{{Name: "override-breaking-change"}}, - PullRequest: map[string]any{}, - }, - expectedLabels: []string{"override-breaking-change", "service/google-x"}, - }, - "existing service label prevents new service labels": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{{Name: "service/google-z"}}, - PullRequest: map[string]any{}, - }, - // nil indicates that the issue won't be updated at all (preserving existing labels) - expectedLabels: nil, - }, - "error fetching issue": { - args: []string{"12345"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: nil, - expectError: true, - }, - "error parsing PR id": { - args: []string{"foobar"}, - oldResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Optional: true}, - "field_b": {Description: "beep", Optional: true}, - }, - }, - }, - newResourceMap: map[string]*schema.Resource{ - "google_x_resource": { - Schema: map[string]*schema.Schema{ - "field_a": {Description: "beep", Required: true}, - }, - }, - }, - githubIssue: &labeler.Issue{ - Number: 12345, - Body: "Unused", - Labels: []labeler.Label{{Name: "service/google-z"}}, - PullRequest: map[string]any{}, - }, - expectError: true, - }, - } - - for tn, tc := range cases { - tc := tc - t.Run(tn, func(t *testing.T) { - t.Parallel() - - var gotLabels []string - o := addLabelsOptions{ - computeSchemaDiff: func() diff.SchemaDiff { - return diff.ComputeSchemaDiff(tc.oldResourceMap, tc.newResourceMap) - }, - enrolledTeamsYaml: enrolledTeamsYaml, - getIssue: func(repository string, id uint64) (labeler.Issue, error) { - if tc.githubIssue != nil { - return *tc.githubIssue, nil - } - var issue labeler.Issue - return issue, errors.New("Error getting issue") - }, - updateIssues: func(repository string, issueUpdates []labeler.IssueUpdate, dryRun bool) { - gotLabels = issueUpdates[0].Labels - }, - } - - err := o.run([]string{"1"}) - if err != nil { - if tc.expectError { - return - } - t.Errorf("Error running command: %s", err) - } - - if tc.expectedLabels == nil { - if gotLabels != nil { - t.Errorf("Expected updateIssues to not run. Got %v as new labels", gotLabels) - } - } - - less := func(a, b string) bool { return a < b } - if (len(tc.expectedLabels) > 0 || len(gotLabels) > 0) && !cmp.Equal(tc.expectedLabels, gotLabels, cmpopts.SortSlices(less)) { - t.Errorf("Unexpected final labels. Want %v, got %v", tc.expectedLabels, gotLabels) - } - }) - } -} diff --git a/tools/diff-processor/cmd/changed_schema_labels.go b/tools/diff-processor/cmd/changed_schema_labels.go new file mode 100644 index 000000000000..fcfcc64971e7 --- /dev/null +++ b/tools/diff-processor/cmd/changed_schema_labels.go @@ -0,0 +1,62 @@ +package cmd + +import ( + newProvider "google/provider/new/google/provider" + oldProvider "google/provider/old/google/provider" + + "encoding/json" + "fmt" + "io" + "os" + + "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/diff" + "github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler/labeler" + "github.com/spf13/cobra" + "golang.org/x/exp/maps" +) + +const changedSchemaLabelsDesc = `Compute service labels based on schema changes.` + +type changedSchemaLabelsOptions struct { + rootOptions *rootOptions + computeSchemaDiff func() diff.SchemaDiff + enrolledTeamsYaml []byte + stdout io.Writer +} + +func newChangedSchemaLabelsCmd(rootOptions *rootOptions) *cobra.Command { + o := &changedSchemaLabelsOptions{ + rootOptions: rootOptions, + computeSchemaDiff: func() diff.SchemaDiff { + return diff.ComputeSchemaDiff(oldProvider.ResourceMap(), newProvider.ResourceMap()) + }, + enrolledTeamsYaml: labeler.EnrolledTeamsYaml, + stdout: os.Stdout, + } + cmd := &cobra.Command{ + Use: "changed-schema-labels", + Short: changedSchemaLabelsDesc, + Long: changedSchemaLabelsDesc, + Args: cobra.NoArgs, + RunE: func(c *cobra.Command, args []string) error { + return o.run() + }, + } + return cmd +} +func (o *changedSchemaLabelsOptions) run() error { + schemaDiff := o.computeSchemaDiff() + affectedResources := maps.Keys(schemaDiff) + regexpLabels, err := labeler.BuildRegexLabels(o.enrolledTeamsYaml) + if err != nil { + return fmt.Errorf("Error building regex labels: %w", err) + } + + labels := labeler.ComputeLabels(affectedResources, regexpLabels) + + if err = json.NewEncoder(o.stdout).Encode(labels); err != nil { + return fmt.Errorf("Error encoding json: %w", err) + } + + return nil +} diff --git a/tools/diff-processor/cmd/changed_schema_labels_test.go b/tools/diff-processor/cmd/changed_schema_labels_test.go new file mode 100644 index 000000000000..3e0067488efc --- /dev/null +++ b/tools/diff-processor/cmd/changed_schema_labels_test.go @@ -0,0 +1,162 @@ +package cmd + +import ( + "bytes" + _ "embed" + "encoding/json" + "testing" + + "github.com/GoogleCloudPlatform/magic-modules/tools/diff-processor/diff" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +var enrolledTeamsYaml = []byte(` +service/google-x: + resources: + - google_x_resource +service/google-z: + resources: + - google_z_resource`) + +func TestChangedSchemaLabelsCmdRun(t *testing.T) { + cases := map[string]struct { + args []string + oldResourceMap map[string]*schema.Resource + newResourceMap map[string]*schema.Resource + expectedLabels []string + expectError bool + }{ + "empty resource map": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{}, + newResourceMap: map[string]*schema.Resource{}, + expectedLabels: nil, + }, + "resource changed that doesn't match mapping": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{ + "google_y_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_y_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Required: true}, + }, + }, + }, + expectedLabels: nil, + }, + "resource matches mapping but isn't changed": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + expectedLabels: nil, + }, + "resource changed that matches mapping": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Required: true}, + }, + }, + }, + expectedLabels: []string{"service/google-x"}, + }, + "resources changed that match multiple mappings": { + args: []string{"12345"}, + oldResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + "google_z_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Optional: true}, + "field_b": {Description: "beep", Optional: true}, + }, + }, + }, + newResourceMap: map[string]*schema.Resource{ + "google_x_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Required: true}, + }, + }, + "google_z_resource": { + Schema: map[string]*schema.Schema{ + "field_a": {Description: "beep", Required: true}, + }, + }, + }, + expectedLabels: []string{"service/google-x", "service/google-z"}, + }, + } + + for tn, tc := range cases { + tc := tc + t.Run(tn, func(t *testing.T) { + t.Parallel() + + var buf bytes.Buffer + o := changedSchemaLabelsOptions{ + computeSchemaDiff: func() diff.SchemaDiff { + return diff.ComputeSchemaDiff(tc.oldResourceMap, tc.newResourceMap) + }, + enrolledTeamsYaml: enrolledTeamsYaml, + stdout: &buf, + } + + err := o.run() + if err != nil { + if tc.expectError { + return + } + t.Errorf("Error running command: %s", err) + } + + out := make([]byte, buf.Len()) + buf.Read(out) + var gotLabels []string + if err = json.Unmarshal(out, &gotLabels); err != nil { + t.Fatalf("Unable to unmarshal labels (%q): %s", out, err) + } + + less := func(a, b string) bool { return a < b } + if (len(tc.expectedLabels) > 0 || len(gotLabels) > 0) && !cmp.Equal(tc.expectedLabels, gotLabels, cmpopts.SortSlices(less)) { + t.Errorf("Unexpected final labels. Want %q, got %q", tc.expectedLabels, gotLabels) + } + }) + } +} diff --git a/tools/diff-processor/cmd/root.go b/tools/diff-processor/cmd/root.go index 1a3674921745..4de264aa5357 100644 --- a/tools/diff-processor/cmd/root.go +++ b/tools/diff-processor/cmd/root.go @@ -21,7 +21,7 @@ func newRootCmd() (*cobra.Command, *rootOptions, error) { SilenceErrors: true, } cmd.AddCommand(newBreakingChangesCmd(o)) - cmd.AddCommand(newAddLabelsCmd(o)) + cmd.AddCommand(newChangedSchemaLabelsCmd(o)) return cmd, o, nil } diff --git a/tools/diff-processor/go.mod b/tools/diff-processor/go.mod index f740f857b9cf..d89297e03fe9 100644 --- a/tools/diff-processor/go.mod +++ b/tools/diff-processor/go.mod @@ -13,11 +13,11 @@ replace github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler => ../i require ( github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler v0.0.0-00010101000000-000000000000 github.com/davecgh/go-spew v1.1.1 - github.com/google/go-cmp v0.5.9 + github.com/google/go-cmp v0.6.0 github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 github.com/spf13/cobra v1.7.0 - github.com/stretchr/testify v1.8.3 + github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 google/provider/new v0.0.0-00010101000000-000000000000 google/provider/old v0.0.0-00010101000000-000000000000 @@ -25,56 +25,61 @@ require ( require ( bitbucket.org/creachadair/stringset v0.0.8 // indirect - cloud.google.com/go v0.110.4 // indirect + cloud.google.com/go v0.112.0 // indirect cloud.google.com/go/bigtable v1.19.0 // indirect - cloud.google.com/go/compute v1.20.1 // indirect + cloud.google.com/go/compute v1.23.4 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v1.1.0 // indirect - cloud.google.com/go/longrunning v0.5.1 // indirect - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 // indirect + cloud.google.com/go/iam v1.1.6 // indirect + cloud.google.com/go/longrunning v0.5.5 // indirect + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-cidr v1.1.0 // indirect - github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/apparentlymart/go-textseg/v15 v15.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/cloudflare/circl v1.3.3 // 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/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f // indirect - github.com/envoyproxy/protoc-gen-validate v0.10.1 // indirect + github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 // 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/felixge/httpsnoop v1.0.4 // indirect github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 // indirect github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 // indirect - github.com/golang/glog v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // 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-cpy v0.0.0-20211218193943-a9c933c06932 // indirect - github.com/google/s2a-go v0.1.4 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.2.1 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.4.8 // indirect + github.com/hashicorp/go-plugin v1.6.0 // 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/hc-install v0.6.2 // indirect + github.com/hashicorp/hcl/v2 v2.19.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-exec v0.19.0 // indirect + github.com/hashicorp/terraform-json v0.18.0 // indirect + github.com/hashicorp/terraform-plugin-framework v1.5.0 // 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-provider-google v1.20.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/hashicorp/terraform-plugin-go v0.20.0 // indirect + github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect + github.com/hashicorp/terraform-provider-google-beta v1.20.0 // indirect + github.com/hashicorp/terraform-registry-address v0.2.3 // indirect + github.com/hashicorp/terraform-svchost v0.1.1 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect @@ -91,24 +96,30 @@ require ( github.com/sirupsen/logrus v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // 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 + github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/zclconf/go-cty v1.14.1 // indirect go.opencensus.io v0.24.0 // indirect - golang.org/x/crypto v0.11.0 // indirect - golang.org/x/net v0.12.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.11.0 // indirect - golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.135.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230726155614-23370e0ffb3e // indirect - google.golang.org/grpc v1.57.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 // indirect + go.opentelemetry.io/otel v1.23.0 // indirect + go.opentelemetry.io/otel/metric v1.23.0 // indirect + go.opentelemetry.io/otel/trace v1.23.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/oauth2 v0.17.0 // indirect + golang.org/x/sync v0.6.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect + google.golang.org/api v0.167.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/grpc v1.61.1 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tools/diff-processor/go.sum b/tools/diff-processor/go.sum index 8aea913951ea..372104100426 100644 --- a/tools/diff-processor/go.sum +++ b/tools/diff-processor/go.sum @@ -1,128 +1,122 @@ 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.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk= -cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= +cloud.google.com/go v0.112.0 h1:tpFCD7hpHFlQ8yPwT3x+QeXqc2T6+n6T+hmABHfDUSM= +cloud.google.com/go v0.112.0/go.mod h1:3jEEVwZ/MHU4djK5t5RHuKOA/GbLddgTdVubX1qnPD4= 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.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= 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.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94= -cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk= -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.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/longrunning v0.5.5 h1:GOE6pZFdSrTb4KAiKnXsJBtlE6mEyaW44oKyMILWnOg= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0 h1:YhWTPhOf6gVpA9mSfnLOuL8Y6j8W5pzmHE7flXjTke4= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.51.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= -github.com/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/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= 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/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= -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/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= +github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= 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.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 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/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 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-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/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/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 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/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 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/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 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.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA= -github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +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 v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= -github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +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/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4 h1:R+19WKQClnfMXS60cP5BmMe1wjZ4u0evY2p2Ar0ZTXo= github.com/gammazero/deque v0.0.0-20180920172122-f6adf94963e4/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI= github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92 h1:EipXK6U05IQ2wtuFRn4k3h0+2lXypzItoXGVyf4r9Io= github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -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-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git/v5 v5.10.1 h1:tu8/D8i+TWxgKpzQ3Vc43e+kkhXqtsZCKI/egajKnxk= +github.com/go-git/go-git/v5 v5.10.1/go.mod h1:uEuHjxkHap8kAl//V5F/nNWwqIYtP/402ddd05mp0wg= 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-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 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/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 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.1 h1:jxpi2eWoU84wbX9iIEyAeeoac3FLuifZpY9tcNUD9kw= -github.com/golang/glog v1.1.1/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +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= 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.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 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= @@ -130,100 +124,90 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ 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 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -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.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc= -github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +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.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= -github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= -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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.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.1 h1:9F8GV9r9ztXyAi00gsMQHNoF51xPZm8uj1dpYt2ZETM= +github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= 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/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 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-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/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-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= 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/hc-install v0.6.2 h1:V1k+Vraqz4olgZ9UzKiAcbman9i9scg9GgSt/U3mw/M= +github.com/hashicorp/hc-install v0.6.2/go.mod h1:2JBpd+NCFKiHiu/yYCGaPyPHhZLxXTpz8oreHa/a3Ps= +github.com/hashicorp/hcl/v2 v2.19.1 h1://i05Jqznmb2EXqa39Nsvyan2o5XyMowW5fnCKW5RPI= +github.com/hashicorp/hcl/v2 v2.19.1/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE= 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-exec v0.19.0 h1:FpqZ6n50Tk95mItTSS9BjeOVUb4eg81SpgVtZNNtFSM= +github.com/hashicorp/terraform-exec v0.19.0/go.mod h1:tbxUpe3JKruE9Cuf65mycSIT8KiNPZ0FkuTE3H4urQg= +github.com/hashicorp/terraform-json v0.18.0 h1:pCjgJEqqDESv4y0Tzdqfxr/edOIGkjs8keY42xfNBwU= +github.com/hashicorp/terraform-json v0.18.0/go.mod h1:qdeBs11ovMzo5puhrRibdD6d2Dq6TyE/28JiU4tIQxk= +github.com/hashicorp/terraform-plugin-framework v1.5.0 h1:8kcvqJs/x6QyOFSdeAyEgsenVOUeC/IyKpi2ul4fjTg= +github.com/hashicorp/terraform-plugin-framework v1.5.0/go.mod h1:6waavirukIlFpVpthbGd2PUNYaFedB0RwW3MDzJ/rtc= 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.0 h1:dVzBoqMHZA4PDAJaH3ztIey2cxFx6e+kRDAr3bMSrmI= -github.com/hashicorp/terraform-provider-google v1.20.0/go.mod h1:19QAcvJTh1z3BfW6cxR5MQd89aIurcIIur99oJGbv/E= -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/hashicorp/terraform-plugin-go v0.20.0 h1:oqvoUlL+2EUbKNsJbIt3zqqZ7wi6lzn4ufkn/UA51xQ= +github.com/hashicorp/terraform-plugin-go v0.20.0/go.mod h1:Rr8LBdMlY53a3Z/HpP+ZU3/xCDqtKNCkeI9qOyT10QE= +github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= +github.com/hashicorp/terraform-plugin-log v0.9.0/go.mod h1:rKL8egZQ/eXSyDqzLUuwUYLVdlYeamldAHSxjUFADow= +github.com/hashicorp/terraform-plugin-mux v0.13.0 h1:79U401/3nd8CWwDGtTHc8F3miSCAS9XGtVarxSTDgwA= +github.com/hashicorp/terraform-plugin-mux v0.13.0/go.mod h1:Ndv0FtwDG2ogzH59y64f2NYimFJ6I0smRgFUKfm6dyQ= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 h1:Bl3e2ei2j/Z3Hc2HIS15Gal2KMKyLAZ2om1HCEvK6es= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0/go.mod h1:i2C41tszDjiWfziPQDL5R/f3Zp0gahXe5No/MIO9rCE= +github.com/hashicorp/terraform-provider-google-beta v1.20.0 h1:rxZwjTPOQgmSaBINGCRhGTf9svsFU3n1iaF5i3rYIbo= +github.com/hashicorp/terraform-provider-google-beta v1.20.0/go.mod h1:t8+8q1zjjAREhGZHvwPU35evEHk9FqNvCpP8+HwJ3Cw= +github.com/hashicorp/terraform-registry-address v0.2.3 h1:2TAiKJ1A3MAkZlH1YI/aTVcLZRu7JseiXNRHbOAyoTI= +github.com/hashicorp/terraform-registry-address v0.2.3/go.mod h1:lFHA76T8jfQteVfT7caREqguFrW3c4MFSPhZB7HHgUM= +github.com/hashicorp/terraform-svchost v0.1.1 h1:EZZimZ1GxdqFRinZ1tpJwVxxt49xc/S52uzrw4x0jKQ= +github.com/hashicorp/terraform-svchost v0.1.1/go.mod h1:mNsjQfZyf/Jhz35v6/0LWcv26+X7JPS+buii2c9/ctc= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 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/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/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 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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= @@ -244,24 +228,23 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua 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/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= 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/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -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/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 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/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -271,52 +254,52 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -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/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 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/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= +github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -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= +github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA= +github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 h1:P+/g8GpuJGYbOp2tAdKrIPUX9JO02q8Q0YNlHolpibA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= +go.opentelemetry.io/otel v1.23.0 h1:Df0pqjqExIywbMCMTxkAwzjLZtRf+bBKLbUcpxO2C9E= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= +go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= +go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= 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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= @@ -326,79 +309,75 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl 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/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 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.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= 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.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= 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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.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= 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-20200323222414-85ca7c5b95cd/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-20210423082822-04245dca01da/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.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= 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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +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= @@ -408,41 +387,37 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn 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/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 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.135.0 h1:6Vgfj6uPMXcyy66waYWBwmkeNB+9GmUlJDOzkukPQYQ= -google.golang.org/api v0.135.0/go.mod h1:Bp77uRFgwsSKI0BWH573F5Q6wSlznwI2NFayLOp/7mQ= +google.golang.org/api v0.167.0 h1:CKHrQD1BLRii6xdkatBDXyKzM0mkawt2QP+H3LtPmSE= +google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= 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/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= 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-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8= -google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= -google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230726155614-23370e0ffb3e h1:S83+ibolgyZ0bqz7KEsUOPErxcv4VzlszxY+31OfB/E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 h1:g/4bk7P6TPMkAUbUhquq98xey1slwvuVJPosdBqYJlU= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1:x9PwdEgd11LgK+orcck69WVRo7DezSO4VUMPI4xpc8A= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9 h1:hZB7eLIaYlW9qXRfCq/qDaPdbeY3757uARz5Vvfv+cY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk= 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.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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= @@ -454,20 +429,15 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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.3/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.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -476,3 +446,4 @@ 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= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= diff --git a/tools/diff-processor/labels/get_issue.go b/tools/diff-processor/labels/get_issue.go deleted file mode 100644 index c9d756892a48..000000000000 --- a/tools/diff-processor/labels/get_issue.go +++ /dev/null @@ -1,46 +0,0 @@ -package labels - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - - labeler "github.com/GoogleCloudPlatform/magic-modules/tools/issue-labeler/labeler" -) - -func GetIssue(repository string, id uint64) (labeler.Issue, error) { - var issue labeler.Issue - client := &http.Client{} - url := fmt.Sprintf("https://api.github.com/repos/%s/issues/%d", repository, id) - - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return issue, fmt.Errorf("Error creating request: %w", err) - } - req.Header.Add("Accept", "application/vnd.github+json") - req.Header.Add("Authorization", "Bearer "+os.Getenv("GITHUB_TOKEN_MAGIC_MODULES")) - req.Header.Add("X-GitHub-Api-Version", "2022-11-28") - resp, err := client.Do(req) - if err != nil { - return issue, fmt.Errorf("Error getting issue: %w", err) - } - defer resp.Body.Close() - body, err := io.ReadAll(resp.Body) - if err != nil { - return issue, fmt.Errorf("Error reading response body: %w", err) - } - - err = json.Unmarshal(body, &issue) - if err != nil { - var errorResponse labeler.ErrorResponse - err = json.Unmarshal(body, &errorResponse) - if err != nil { - return issue, fmt.Errorf("Error unmarshalling response body: %w", err) - } - return issue, fmt.Errorf("Error from API: %s", errorResponse.Message) - } - - return issue, nil -} diff --git a/tools/issue-labeler/labeler/labels.go b/tools/issue-labeler/labeler/labels.go index 6fa5e10e1810..d702b081dd65 100644 --- a/tools/issue-labeler/labeler/labels.go +++ b/tools/issue-labeler/labeler/labels.go @@ -76,8 +76,7 @@ func ComputeLabels(resources []string, regexpLabels []RegexpLabel) []string { } } - var labels []string - + labels := []string{} for label := range labelSet { labels = append(labels, label) } From 2aafbc049f9e84f2e9766c3660d5ff3e0b4eeed3 Mon Sep 17 00:00:00 2001 From: liferoad Date: Wed, 20 Mar 2024 13:01:58 -0400 Subject: [PATCH 168/200] change the dataflow zone from us-central1-f to us-east5-b (#10205) --- .../dataflow/resource_dataflow_job_test.go.erb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_test.go.erb b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_test.go.erb index ac9624cd3bc5..2454f99892c3 100644 --- a/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_test.go.erb +++ b/mmv1/third_party/terraform/services/dataflow/resource_dataflow_job_test.go.erb @@ -37,7 +37,7 @@ func TestAccDataflowJob_basic(t *testing.T) { randStr := acctest.RandString(t, 10) bucket := "tf-test-dataflow-gcs-" + randStr job := "tf-test-dataflow-job-" + randStr - zone := "us-central1-f" + zone := "us-east5-b" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -69,7 +69,7 @@ func TestAccDataflowJobSkipWait_basic(t *testing.T) { randStr := acctest.RandString(t, 10) bucket := "tf-test-dataflow-gcs-" + randStr job := "tf-test-dataflow-job-" + randStr - zone := "us-central1-f" + zone := "us-east5-b" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -259,14 +259,14 @@ func TestAccDataflowJob_withLabels(t *testing.T) { func TestAccDataflowJob_withProviderDefaultLabels(t *testing.T) { // The test failed if VCR testing is enabled, because the cached provider config is used. - // With the cached provider config, any changes in the provider default labels will not be applied. + // With the cached provider config, any changes in the provider default labels will not be applied. acctest.SkipIfVcr(t) t.Parallel() randStr := acctest.RandString(t, 10) bucket := "tf-test-dataflow-gcs-" + randStr job := "tf-test-dataflow-job-" + randStr - zone := "us-central1-f" + zone := "us-east5-b" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -420,7 +420,7 @@ func TestAccDataflowJob_withKmsKey(t *testing.T) { crypto_key := "tf-test-dataflow-kms-key-" + randStr bucket := "tf-test-dataflow-gcs-" + randStr job := "tf-test-dataflow-job-" + randStr - zone := "us-central1-f" + zone := "us-east5-b" if acctest.BootstrapPSARole(t, "service-", "compute-system", "roles/cloudkms.cryptoKeyEncrypterDecrypter") { t.Fatal("Stopping the test because a role was added to the policy.") @@ -870,7 +870,7 @@ resource "google_storage_bucket" "temp" { resource "google_dataflow_job" "big_data" { name = "%s" - + zone = "%s" machine_type = "e2-standard-2" @@ -895,7 +895,7 @@ resource "google_storage_bucket" "temp" { resource "google_dataflow_job" "big_data" { name = "%s" - + zone = "%s" machine_type = "e2-standard-2" @@ -1029,7 +1029,7 @@ resource "google_project_iam_member" "dataflow-worker" { resource "google_dataflow_job" "big_data" { name = "%s" depends_on = [ - google_storage_bucket_iam_member.dataflow-gcs, + google_storage_bucket_iam_member.dataflow-gcs, google_project_iam_member.dataflow-worker ] @@ -1226,7 +1226,7 @@ resource "google_storage_bucket" "temp" { resource "google_dataflow_job" "big_data" { name = "%s" - + zone = "%s" machine_type = "e2-standard-2" From 7b41c4afa4f77c38bc1b72ed97bbd8b1aeb22352 Mon Sep 17 00:00:00 2001 From: Xuran Liu Date: Wed, 20 Mar 2024 11:20:47 -0700 Subject: [PATCH 169/200] Added `CloudQuotas` service and Create `QuotaPreference` Resource (#10019) * setup resoruce config and add create tests * add create and update test * fix lint error * fix lint error * update yaml config * remove trailing spaces * modify update test * update acceptance test and cleanup * add upsert scenario for testing * update acceptance test syntax * remove allow-missing flag & fix update test failure * add import and id format * teamcity test failure - manually add cloudquotas service * teamcity test failure - manually add cloudquotas service for beta * add field 'validate_only' to tests * address comments & fix test failure * remove unused import * remove `validate_only` field, add ignore read feature to `annotations` field * add input only fields to ImportStateVerifyIgnore * update field name * VCR test failure: remove batch service creation * fix formatting --- .../products/cloudquotas/QuotaPreference.yaml | 158 +++++++++++++++ ...quotas_quota_preference_annotations.go.erb | 4 + .../cloudquotas_quota_preference_basic.tf.erb | 11 ++ .../provider/provider_mmv1_resources.go.erb | 3 - ...urce_cloud_quotas_quota_preference_test.go | 180 ++++++++++++++++++ 5 files changed, 353 insertions(+), 3 deletions(-) create mode 100644 mmv1/products/cloudquotas/QuotaPreference.yaml create mode 100644 mmv1/templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb create mode 100644 mmv1/templates/terraform/examples/cloudquotas_quota_preference_basic.tf.erb create mode 100644 mmv1/third_party/terraform/services/cloudquotas/resource_cloud_quotas_quota_preference_test.go diff --git a/mmv1/products/cloudquotas/QuotaPreference.yaml b/mmv1/products/cloudquotas/QuotaPreference.yaml new file mode 100644 index 000000000000..9ac2a049bc54 --- /dev/null +++ b/mmv1/products/cloudquotas/QuotaPreference.yaml @@ -0,0 +1,158 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'QuotaPreference' +description: | + QuotaPreference represents the preferred quota configuration specified for a project, folder or organization. There is only one QuotaPreference resource for a quota value targeting a unique set of dimensions. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Cloud Quotas Overview': 'https://cloud.google.com/docs/quotas/overview' + api: 'https://cloud.google.com/docs/quotas/reference/rest/v1/projects.locations.quotaPreferences' +base_url: '{{parent}}/locations/global/quotaPreferences' +self_link: '{{parent}}/locations/global/quotaPreferences/{{name}}' +create_url: '{{parent}}/locations/global/quotaPreferences?quotaPreferenceId={{name}}&ignoreSafetyChecks={{ignore_safety_checks}}' +update_url: '{{parent}}/locations/global/quotaPreferences/{{name}}?ignoreSafetyChecks={{ignore_safety_checks}}' +update_verb: :PATCH +update_mask: true +skip_delete: true +autogen_async: false +import_format: ['{{%parent}}/locations/global/quotaPreferences/{{name}}'] +id_format: '{{parent}}/locations/global/quotaPreferences/{{name}}' + +examples: + - !ruby/object:Provider::Terraform::Examples + name: "cloudquotas_quota_preference_basic" + primary_resource_id: "preference" + skip_test: true + vars: + name: "compute_googleapis_com-CPUS-per-project_us-east1" + test_env_vars: + project: :PROJECT_NAME + +parameters: + - !ruby/object:Api::Type::String + name: 'parent' + immutable: true + url_param_only: true + required: true + default_from_api: true + description: The parent of the quota preference. Allowed parents are "projects/[project-id / number]" or "folders/[folder-id / number]" or "organizations/[org-id / number]". + - !ruby/object:Api::Type::Enum + name: 'ignore_safety_checks' + url_param_only: true + default_value: :QUOTA_SAFETY_CHECK_UNSPECIFIED + description: The list of quota safety checks to be ignored. + values: + - :QUOTA_SAFETY_CHECK_UNSPECIFIED + - :QUOTA_DECREASE_BELOW_USAGE + - :QUOTA_DECREASE_PERCENTAGE_TOO_HIGH + +properties: + - !ruby/object:Api::Type::String + name: 'name' + default_from_api: true + pattern: '{{parent}}/locations/global/quotaPreferences/{{name}}' + description: | + The resource name of the quota preference. Required except in the CREATE requests. + diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' + custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb + custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb + - !ruby/object:Api::Type::String + name: 'service' + required: true + default_from_api: true + description: The name of the service to which the quota preference is applied. + - !ruby/object:Api::Type::String + name: 'quotaId' + required: true + default_from_api: true + description: | + The id of the quota to which the quota preference is applied. A quota id is unique in the service. + Example: `CPUS-per-project-region`. + - !ruby/object:Api::Type::NestedObject + name: 'quotaConfig' + required: true + description: The preferred quota configuration. + properties: + - !ruby/object:Api::Type::String + name: 'preferredValue' + required: true + description: | + The preferred value. Must be greater than or equal to -1. If set to -1, it means the value is "unlimited". + - !ruby/object:Api::Type::String + name: 'stateDetail' + output: true + description: Optional details about the state of this quota preference. + - !ruby/object:Api::Type::String + name: 'grantedValue' + output: true + description: Granted quota value. + - !ruby/object:Api::Type::String + name: 'traceId' + output: true + description: | + The trace id that the Google Cloud uses to provision the requested quota. This trace id may be used by the client to contact Cloud support to track the state of a quota preference request. The trace id is only produced for increase requests and is unique for each request. The quota decrease requests do not have a trace id. + - !ruby/object:Api::Type::KeyValuePairs + name: 'annotations' + custom_flatten: 'templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb' + description: |- + The annotations map for clients to store small amounts of arbitrary data. Do not put PII or other sensitive information here. See https://google.aip.dev/128#annotations. + + An object containing a list of "key: value" pairs. Example: `{ "name": "wrench", "mass": "1.3kg", "count": "3" }`. + - !ruby/object:Api::Type::String + name: 'requestOrigin' + output: true + description: The origin of the quota preference request. + - !ruby/object:Api::Type::KeyValuePairs + name: 'dimensions' + default_from_api: true + description: |- + The dimensions that this quota preference applies to. The key of the map entry is the name of a dimension, such as "region", "zone", "network_id", and the value of the map entry is the dimension value. If a dimension is missing from the map of dimensions, the quota preference applies to all the dimension values except for those that have other quota preferences configured for the specific value. + + NOTE: QuotaPreferences can only be applied across all values of "user" and "resource" dimension. Do not set values for "user" or "resource" in the dimension map. + + Example: `{"provider": "Foo Inc"}` where "provider" is a service specific dimension. + - !ruby/object:Api::Type::String + name: 'etag' + output: true + description: | + The current etag of the quota preference. If an etag is provided on update and does not match the current server's etag of the quota preference, the request will be blocked and an ABORTED error will be returned. See https://google.aip.dev/134#etags for more details on etags. + - !ruby/object:Api::Type::String + name: 'createTime' + output: true + description: | + Create time stamp. + 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: 'updateTime' + output: true + description: | + Update time stamp. + 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::Boolean + name: 'reconciling' + output: true + description: | + Is the quota preference pending Google Cloud approval and fulfillment. + - !ruby/object:Api::Type::String + name: 'justification' + ignore_read: true + description: The reason / justification for this quota preference. + - !ruby/object:Api::Type::String + name: 'contactEmail' + ignore_read: true + description: |- + An email address that can be used for quota related communication between the Google Cloud and the user in case the Google Cloud needs further information to make a decision on whether the user preferred quota can be granted. + + The Google account for the email address must have quota update permission for the project, folder or organization this quota preference is for. diff --git a/mmv1/templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb b/mmv1/templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb new file mode 100644 index 000000000000..6ace95aae077 --- /dev/null +++ b/mmv1/templates/terraform/custom_flatten/cloudquotas_quota_preference_annotations.go.erb @@ -0,0 +1,4 @@ +func flatten<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // ignore read on this field + return d.Get("quota_config.0.annotations") +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/cloudquotas_quota_preference_basic.tf.erb b/mmv1/templates/terraform/examples/cloudquotas_quota_preference_basic.tf.erb new file mode 100644 index 000000000000..af168e050e95 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudquotas_quota_preference_basic.tf.erb @@ -0,0 +1,11 @@ +resource "google_cloud_quotas_quota_preference" "<%= ctx[:primary_resource_id] %>" { + parent = "projects/<%= ctx[:test_env_vars]['project'] %>" + name = "<%= ctx[:vars]['name'] %>" + dimensions = { region = "us-east1" } + service = "compute.googleapis.com" + quota_id = "CPUS-per-project-region" + contact_email = "testuser@gmail.com" + quota_config { + preferred_value = 200 + } +} 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 f828b8c13ff2..40e1cabde402 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -15,9 +15,6 @@ import ( "github.com/hashicorp/terraform-provider-google/google/services/dataflow" "github.com/hashicorp/terraform-provider-google/google/services/servicenetworking" "github.com/hashicorp/terraform-provider-google/google/tpgiamresource" - <% if version == 'ga' -%> // https://github.com/hashicorp/terraform-provider-google/issues/15633 for details - "github.com/hashicorp/terraform-provider-google/google/services/cloudquotas" - <% end -%> ) // Datasources diff --git a/mmv1/third_party/terraform/services/cloudquotas/resource_cloud_quotas_quota_preference_test.go b/mmv1/third_party/terraform/services/cloudquotas/resource_cloud_quotas_quota_preference_test.go new file mode 100644 index 000000000000..35ea4107eae9 --- /dev/null +++ b/mmv1/third_party/terraform/services/cloudquotas/resource_cloud_quotas_quota_preference_test.go @@ -0,0 +1,180 @@ +package cloudquotas_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 TestAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_account": envvar.GetTestBillingAccountFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_basic(context), + }, + { + ResourceName: "google_cloud_quotas_quota_preference.my_preference", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "quota_preference_id", "ignore_safety_checks", "contact_email"}, + }, + { + Config: testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_increaseQuota(context), + }, + { + ResourceName: "google_cloud_quotas_quota_preference.my_preference", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "quota_preference_id", "ignore_safety_checks", "contact_email", "justification", "quota_config.0.annotations"}, + }, + { + Config: testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_decreaseQuota(context), + }, + { + ResourceName: "google_cloud_quotas_quota_preference.my_preference", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"parent", "quota_preference_id", "ignore_safety_checks", "contact_email", "justification", "quota_config.0.annotations"}, + }, + }, + }) +} + +func testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_project" "new_project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + } + + resource "google_project_service" "cloudquotas" { + project = google_project.new_project.project_id + service = "cloudquotas.googleapis.com" + } + + resource "google_project_service" "compute" { + project = google_project.new_project.project_id + service = "compute.googleapis.com" + depends_on = [google_project_service.cloudquotas] + } + + resource "google_project_service" "billing" { + project = google_project.new_project.project_id + service = "cloudbilling.googleapis.com" + depends_on = [google_project_service.compute] + } + + resource "time_sleep" "wait_120_seconds" { + create_duration = "120s" + depends_on = [google_project_service.billing] + } + + resource "google_cloud_quotas_quota_preference" "my_preference"{ + parent = "projects/${google_project.new_project.project_id}" + name = "compute_googleapis_com-CPUS-per-project_us-central1" + dimensions = { region = "us-central1" } + service = "compute.googleapis.com" + quota_id = "CPUS-per-project-region" + contact_email = "testuser@gmail.com" + quota_config { + preferred_value = 70 + } + ignore_safety_checks = "QUOTA_DECREASE_PERCENTAGE_TOO_HIGH" + depends_on = [ + time_sleep.wait_120_seconds + ] + } + `, context) +} + +func testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_increaseQuota(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_project" "new_project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + } + + resource "google_project_service" "cloudquotas" { + project = google_project.new_project.project_id + service = "cloudquotas.googleapis.com" + } + + resource "google_project_service" "compute" { + project = google_project.new_project.project_id + service = "compute.googleapis.com" + depends_on = [google_project_service.cloudquotas] + } + + resource "google_project_service" "billing" { + project = google_project.new_project.project_id + service = "cloudbilling.googleapis.com" + depends_on = [google_project_service.compute] + } + + resource "google_cloud_quotas_quota_preference" "my_preference"{ + contact_email = "testinguser2@google.com" + justification = "Ignore. Increase quota for Terraform testing." + quota_config { + preferred_value = 72 + annotations = { label = "terraform" } + } + depends_on = [google_project_service.billing] + } + `, context) +} + +func testAccCloudQuotasQuotaPreference_cloudquotasQuotaPreferenceBasicExample_decreaseQuota(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_project" "new_project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_account}" + } + + resource "google_project_service" "cloudquotas" { + project = google_project.new_project.project_id + service = "cloudquotas.googleapis.com" + } + + resource "google_project_service" "compute" { + project = google_project.new_project.project_id + service = "compute.googleapis.com" + depends_on = [google_project_service.cloudquotas] + } + + resource "google_project_service" "billing" { + project = google_project.new_project.project_id + service = "cloudbilling.googleapis.com" + depends_on = [google_project_service.compute] + } + + resource "google_cloud_quotas_quota_preference" "my_preference"{ + ignore_safety_checks = "QUOTA_DECREASE_PERCENTAGE_TOO_HIGH" + quota_config { + preferred_value = 65 + } + depends_on = [google_project_service.billing] + } + `, context) +} From be112dab93e82eb1d95b1da7b4095ae2c5ed0c00 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Wed, 20 Mar 2024 11:22:11 -0700 Subject: [PATCH 170/200] Magician tgc integration (#9907) * Add command for tgc integration tests * Use magician for TGC integration tests * Fix variable name * Remove owner * Fix go mod tidy command * Use new github token --- .ci/gcb-generate-diffs-new.yml | 15 +-- .ci/magician/cmd/test_tgc_integration.go | 114 +++++++++++++++++++++++ 2 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 .ci/magician/cmd/test_tgc_integration.go diff --git a/.ci/gcb-generate-diffs-new.yml b/.ci/gcb-generate-diffs-new.yml index e775b5a37d39..70e5f88d5a8b 100644 --- a/.ci/gcb-generate-diffs-new.yml +++ b/.ci/gcb-generate-diffs-new.yml @@ -208,7 +208,7 @@ steps: - name: 'gcr.io/graphite-docker-images/go-plus' id: tgc-test-integration - entrypoint: '/workspace/.ci/scripts/go-plus/tgc-tester-integration/test_tgc_integration.sh' + entrypoint: '/workspace/.ci/scripts/go-plus/magician/exec.sh' allowFailure: true secretEnv: ["GITHUB_TOKEN_MAGIC_MODULES"] waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] @@ -218,12 +218,13 @@ steps: - TEST_ANCESTRY=$_VALIDATOR_TEST_ANCESTRY - TEST_ORG_ID=$_VALIDATOR_TEST_ORG args: - - $_PR_NUMBER - - $COMMIT_SHA - - $BUILD_ID - - $PROJECT_ID - - "18" # Build step - - terraform-google-conversion + - 'test-tgc-integration' + - $_PR_NUMBER + - $COMMIT_SHA + - $BUILD_ID + - $PROJECT_ID + - "18" # Build step + - terraform-google-conversion - name: 'gcr.io/graphite-docker-images/go-plus' id: tpgb-test diff --git a/.ci/magician/cmd/test_tgc_integration.go b/.ci/magician/cmd/test_tgc_integration.go new file mode 100644 index 000000000000..04881ff62d23 --- /dev/null +++ b/.ci/magician/cmd/test_tgc_integration.go @@ -0,0 +1,114 @@ +package cmd + +import ( + "fmt" + "magician/exec" + "magician/github" + "magician/source" + "os" + "strings" + + "github.com/spf13/cobra" +) + +var testTGCIntegrationCmd = &cobra.Command{ + Use: "test-tgc-integration", + Short: "Run tgc integration tests via workflow dispatch", + Long: `This command runs tgc unit tests via workflow dispatch + + The following PR details are expected as environment variables: + 1. GOPATH + 2. GITHUB_TOKEN_MAGIC_MODULES + `, + Run: func(cmd *cobra.Command, args []string) { + goPath, ok := os.LookupEnv("GOPATH") + if !ok { + fmt.Println("Did not provide GOPATH environment variable") + os.Exit(1) + } + + githubToken, ok := lookupGithubTokenOrFallback("GITHUB_TOKEN_MAGIC_MODULES") + if !ok { + fmt.Println("Did not provide GITHUB_TOKEN_MAGIC_MODULES or GITHUB_TOKEN environment variables") + os.Exit(1) + } + + rnr, err := exec.NewRunner() + if err != nil { + fmt.Println("Error creating runner: ", err) + os.Exit(1) + } + + ctlr := source.NewController(goPath, "modular-magician", githubToken, rnr) + + gh := github.NewClient(githubToken) + + execTestTGCIntegration(args[0], args[1], args[2], args[3], args[4], args[5], "modular-magician", rnr, ctlr, gh) + }, +} + +func execTestTGCIntegration(prNumber, mmCommit, buildID, projectID, buildStep, ghRepo, githubUsername string, rnr ExecRunner, ctlr *source.Controller, gh GithubClient) { + newBranch := "auto-pr-" + prNumber + repo := &source.Repo{ + Name: ghRepo, + Branch: newBranch, + } + ctlr.SetPath(repo) + if err := ctlr.Clone(repo); err != nil { + fmt.Println("Error cloning repo: ", err) + os.Exit(1) + } + if err := rnr.PushDir(repo.Path); err != nil { + fmt.Println("Error changing to repo dir: ", err) + os.Exit(1) + } + diffs, err := rnr.Run("git", []string{"diff", "--name-only", "HEAD~1"}, nil) + if err != nil { + fmt.Println("Error diffing repo: ", err) + os.Exit(1) + } + hasGoFiles := false + for _, diff := range strings.Split(diffs, "\n") { + if strings.HasSuffix(diff, ".go") { + hasGoFiles = true + break + } + } + if !hasGoFiles { + fmt.Println("Skipping tests: No go files changed") + os.Exit(0) + } + + fmt.Println("Running tests: Go files changed") + + 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(prNumber, ghRepo+"-test-integration", "pending", targetURL, mmCommit); err != nil { + fmt.Println("Error posting build status: ", err) + os.Exit(1) + } + + if _, err := rnr.Run("go", []string{"mod", "edit", "-replace", fmt.Sprintf("github.com/hashicorp/terraform-provider-google-beta=github.com/%s/terraform-provider-google-beta@%s", githubUsername, newBranch)}, nil); err != nil { + fmt.Println("Error running go mod edit: ", err) + } + if _, err := rnr.Run("go", []string{"mod", "tidy"}, nil); err != nil { + fmt.Println("Error running go mod tidy: ", err) + } + + if _, err := rnr.Run("make", []string{"build"}, nil); err != nil { + fmt.Println("Error running make build: ", err) + } + state := "success" + if _, err := rnr.Run("make", []string{"test-integration"}, nil); err != nil { + fmt.Println("Error running make test-integration: ", err) + state = "failure" + } + + if err := gh.PostBuildStatus(prNumber, ghRepo+"-test-integration", state, targetURL, mmCommit); err != nil { + fmt.Println("Error posting build status: ", err) + os.Exit(1) + } +} + +func init() { + rootCmd.AddCommand(testTGCIntegrationCmd) +} From 18fd6b4edb626b23e7ee70e761716bd152a15099 Mon Sep 17 00:00:00 2001 From: Lingkai Shen Date: Wed, 20 Mar 2024 15:31:38 -0400 Subject: [PATCH 171/200] Fix https://github.com/hashicorp/terraform-provider-google/issues/17389 (#10206) --- .../firebaseappcheck/ServiceConfig.yaml | 4 +- ..._firebase_app_check_service_config_test.go | 55 ------- ...ebase_app_check_service_config_test.go.erb | 135 ++++++++++++++++++ 3 files changed, 137 insertions(+), 57 deletions(-) delete mode 100644 mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go create mode 100644 mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb diff --git a/mmv1/products/firebaseappcheck/ServiceConfig.yaml b/mmv1/products/firebaseappcheck/ServiceConfig.yaml index d1c0cdc5a561..d016ba8d2609 100644 --- a/mmv1/products/firebaseappcheck/ServiceConfig.yaml +++ b/mmv1/products/firebaseappcheck/ServiceConfig.yaml @@ -58,9 +58,9 @@ examples: name: "firebase_app_check_service_config_unenforced" primary_resource_id: "default" vars: - service_id: "firebasedatabase.googleapis.com" + service_id: "identitytoolkit.googleapis.com" test_vars_overrides: - service_id: '"firebasedatabase.googleapis.com"' + service_id: '"identitytoolkit.googleapis.com"' test_env_vars: project_id: :PROJECT_NAME parameters: diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go deleted file mode 100644 index aba5a807434f..000000000000 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package firebaseappcheck_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 TestAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(t *testing.T) { - t.Parallel() - - context := map[string]interface{}{ - "project_id": envvar.GetTestProjectFromEnv(), - "service_id": "identitytoolkit.googleapis.com", - "random_suffix": acctest.RandString(t, 10), - } - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckFirebaseAppCheckServiceConfigDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUnenforcedExample(context), - }, - { - ResourceName: "google_firebase_app_check_service_config.default", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_id"}, - }, - { - Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigOffExample(context), - }, - { - ResourceName: "google_firebase_app_check_service_config.default", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_id"}, - }, - { - Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigEnforcedExample(context), - }, - { - ResourceName: "google_firebase_app_check_service_config.default", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"service_id"}, - }, - }, - }) -} diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb new file mode 100644 index 000000000000..70a34c0c4b76 --- /dev/null +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb @@ -0,0 +1,135 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +<% autogen_exception -%> +package firebaseappcheck_test +<% unless version == 'ga' -%> + +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 TestAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(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.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckFirebaseAppCheckServiceConfigDestroyProducer(t), + ExternalProviders: map[string]resource.ExternalProvider{ + "random": {}, + "time": {}, + }, + Steps: []resource.TestStep{ + { + Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(context, "UNENFORCED"), + }, + { + ResourceName: "google_firebase_app_check_service_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_id"}, + }, + { + Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(context, "ENFORCED"), + }, + { + ResourceName: "google_firebase_app_check_service_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_id"}, + }, + { + Config: testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(context, ""), + }, + { + ResourceName: "google_firebase_app_check_service_config.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_id"}, + }, + }, + }) +} + +func testAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(context map[string]interface{}, enforcementMode string) string { + context["enforcement_mode"] = enforcementMode + return acctest.Nprintf(` +resource "google_project" "default" { + provider = google-beta + project_id = "tf-test-appcheck%{random_suffix}" + name = "tf-test-appcheck%{random_suffix}" + org_id = "%{org_id}" + labels = { + "firebase" = "enabled" + } +} + +resource "google_project_service" "firebase" { + provider = google-beta + project = google_project.default.project_id + service = "firebase.googleapis.com" + disable_on_destroy = false +} + +resource "google_project_service" "database" { + provider = google-beta + project = google_project.default.project_id + service = "firebasedatabase.googleapis.com" + disable_on_destroy = false +} + +resource "google_project_service" "appcheck" { + provider = google-beta + project = google_project.default.project_id + service = "firebaseappcheck.googleapis.com" + disable_on_destroy = false +} + +resource "google_firebase_project" "default" { + provider = google-beta + project = google_project.default.project_id + + depends_on = [ + google_project_service.firebase, + google_project_service.database, + google_project_service.appcheck, + ] +} + +# It takes a while for the new project to be ready for a database +resource "time_sleep" "wait_30s" { + depends_on = [google_firebase_project.default] + create_duration = "30s" +} + +resource "google_firebase_database_instance" "default" { + provider = google-beta + project = google_firebase_project.default.project + region = "us-central1" + instance_id = "tf-test-appcheck%{random_suffix}-default-rtdb" + type = "DEFAULT_DATABASE" + + depends_on = [time_sleep.wait_30s] +} + +resource "google_firebase_app_check_service_config" "default" { + provider = google-beta + project = google_firebase_project.default.project + service_id = "firebasedatabase.googleapis.com" + enforcement_mode = "%{enforcement_mode}" + + depends_on = [google_firebase_database_instance.default] +} +`, context) +} +<% end -%> From 31e31a13ab2a930666d83604e6d30d990170ebe7 Mon Sep 17 00:00:00 2001 From: Pawel Jasinski <56267784+pawelJas@users.noreply.github.com> Date: Wed, 20 Mar 2024 21:45:33 +0100 Subject: [PATCH 172/200] generated_id added to compute_region_backend_service (#10243) --- mmv1/products/compute/RegionBackendService.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/mmv1/products/compute/RegionBackendService.yaml b/mmv1/products/compute/RegionBackendService.yaml index 7647541c16ae..28bb3c23928f 100644 --- a/mmv1/products/compute/RegionBackendService.yaml +++ b/mmv1/products/compute/RegionBackendService.yaml @@ -744,6 +744,13 @@ properties: set_hash_func: 'tpgresource.SelfLinkRelativePathHash' custom_flatten: templates/terraform/custom_flatten/guard_self_link_array.go.erb item_type: Api::Type::String + - !ruby/object:Api::Type::Integer + name: 'generated_id' + api_name: 'id' + description: + 'The unique identifier for the resource. This identifier is defined by the + server.' + output: true - !ruby/object:Api::Type::NestedObject name: 'iap' description: Settings for enabling Cloud Identity Aware Proxy From 846a01a2aa3266b8d01d3d1bbf71c2d48bdc87a9 Mon Sep 17 00:00:00 2001 From: Riley Karson Date: Wed, 20 Mar 2024 13:50:19 -0700 Subject: [PATCH 173/200] Clarify CI README a bit (#10245) --- .ci/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.ci/README.md b/.ci/README.md index e156ca5be35e..f9495f605c4b 100644 --- a/.ci/README.md +++ b/.ci/README.md @@ -42,18 +42,17 @@ Don't panic - this is all quite safe and we have fixed it before. We store the It's possible for a job to be cancelled or fail in the middle of pushing downstreams in a transient way. The sorts of failures that happen at scale - lightning strikes a datacenter (ours or GitHub's!) or some other unlikely misfortune happens. This has a chance to cause a hiccup in the downstream history, but isn't dangerous. If that happens, the sync tags may need to be manually updated to sit at the same commit, just before the commit which needs to be generated, or some failed tasks might need to be run by hand. -Updating the sync tags is done like this: -First, check their state: `git fetch origin && git rev-parse origin/tpg-sync origin/tpgb-sync origin/tf-oics-sync origin/tgc-sync` will list the commits for each of the sync tags. -(If you have changed the name of the `googlecloudplatform/magic-modules` remote from `origin`, substitute that name instead) +First, check their state: `git fetch origin && git rev-parse origin/tpg-sync origin/tpgb-sync origin/tf-oics-sync origin/tgc-sync` will list the commits for each of the sync tags. (If you have changed the name of the `GoogleCloudPlatform/magic-modules` remote from `origin`, substitute that name instead, such as `git fetch upstream && git rev-parse upstream/tpg-sync upstream/tpgb-sync upstream/tf-oics-sync upstream/tgc-sync`) + In normal, steady-state operation, these tags will all be identical. When a failure occurs, some of them may be one commit ahead of the others. It is rare for any of them to be 2 or more commits ahead of any other. If some of them are one commit ahead of the others, and there is no pusher task currently running, this means you need to reset them by hand and rerun the failed jobs. If they diverge by more than one commit, or a pusher task is currently running, you will need to manually run missing tasks. ### Divergence by zero commits -Just click retry on the failed job in Cloud Build. Yay! +Just click retry on the failed job in Cloud Build. This is fairly rare, as most failures involve a step failing after another has already succeeded. ### Divergence by exactly one commit. -Find which commit caused the error. This will usually be easy - cloud build lists the commit which triggered a build, so you can probably just use that one. You need to set all the sync tags to the parent of that commit. Say the commit which caused the error is `12345abc`. You can find the parent of that commit with `git rev-parse 12345abc~` (note the `~` suffix). Some of the sync tags are likely set to this value already. For the remainder, simply perform a git push. Assuming that the parent commit is `98765fed`, that would be, e.g. `git push origin 98765fed:tf-validator-sync`. +Find which commit caused the error. This will usually be easy - cloud build lists the commit which triggered a build, so you can probably just use that one. You need to set all the sync tags to the parent of that commit. Say the commit which caused the error is `12345abc`. You can find the parent of that commit with `git rev-parse 12345abc~` (note the `~` suffix). Some of the sync tags are likely set to this value already. For the remainder, simply perform a git push. Assuming that the parent commit is `98765fed`, that would be, e.g. `git push -f origin 98765fed:tf-validator-sync`. If you are unlucky, there may be open PRs - this only happens if the failure occurred during the ~5 second period surrounding the merging of one of the downstreams. Close those PRs before proceeding to the final step. From d874e11de524dddb932b70f4ef1bc7905fb41846 Mon Sep 17 00:00:00 2001 From: Rohit Jangid Date: Thu, 21 Mar 2024 03:25:51 +0530 Subject: [PATCH 174/200] Add integrations product. Create Client resource. (#10186) Co-authored-by: Cameron Thornton --- mmv1/products/integrations/Client.yaml | 112 ++++++++++++++++++ mmv1/products/integrations/product.yaml | 22 ++++ .../decoders/integrations_client.go.erb | 4 + .../integrations_client_advance.tf.erb | 34 ++++++ .../examples/integrations_client_basic.tf.erb | 3 + .../components/inputs/services_beta.kt | 5 + .../components/inputs/services_ga.kt | 5 + 7 files changed, 185 insertions(+) create mode 100644 mmv1/products/integrations/Client.yaml create mode 100644 mmv1/products/integrations/product.yaml create mode 100644 mmv1/templates/terraform/decoders/integrations_client.go.erb create mode 100644 mmv1/templates/terraform/examples/integrations_client_advance.tf.erb create mode 100644 mmv1/templates/terraform/examples/integrations_client_basic.tf.erb diff --git a/mmv1/products/integrations/Client.yaml b/mmv1/products/integrations/Client.yaml new file mode 100644 index 000000000000..b6f538e38d06 --- /dev/null +++ b/mmv1/products/integrations/Client.yaml @@ -0,0 +1,112 @@ +# Copyright 2024 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Resource +name: 'Client' +description: | + Application Integration Client. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': 'https://cloud.google.com/application-integration/docs/overview' + 'Set up Application Integration': 'https://cloud.google.com/application-integration/docs/setup-application-integration' + api: 'https://cloud.google.com/application-integration/docs/reference/rest/v1/projects.locations.clients' +base_url: 'projects/{{project}}/locations/{{location}}/clients' +self_link: 'projects/{{project}}/locations/{{location}}/clients' +immutable: true +create_url: 'projects/{{project}}/locations/{{location}}/clients:provision' +autogen_async: false +skip_delete: true +import_format: + [ + 'projects/{{project}}/locations/{{location}}/clients', + ] +mutex: Client/{{location}} +custom_code: !ruby/object:Provider::Terraform::CustomCode + decoder: templates/terraform/decoders/integrations_client.go.erb +parameters: + - !ruby/object:Api::Type::String + name: 'location' + required: true + immutable: true + url_param_only: true + description: | + Location in which client needs to be provisioned. +properties: + - !ruby/object:Api::Type::NestedObject + name: 'cloudKmsConfig' + description: | + Cloud KMS config for AuthModule to encrypt/decrypt credentials. + immutable: true + url_param_only: true + properties: + - !ruby/object:Api::Type::String + name: "kmsLocation" + required: true + description: | + Location name of the key ring, e.g. "us-west1". + - !ruby/object:Api::Type::String + name: "kmsRing" + required: true + description: | + A key ring organizes keys in a specific Google Cloud location and allows you to + manage access control on groups of keys. A key ring's name does not need to be + unique across a Google Cloud project, but must be unique within a given location. + - !ruby/object:Api::Type::String + name: "key" + required: true + description: | + A Cloud KMS key is a named object containing one or more key versions, along + with metadata for the key. A key exists on exactly one key ring tied to a + specific location. + - !ruby/object:Api::Type::String + name: "keyVersion" + description: | + Each version of a key contains key material used for encryption or signing. + A key's version is represented by an integer, starting at 1. To decrypt data + or verify a signature, you must use the same key version that was used to + encrypt or sign the data. + - !ruby/object:Api::Type::String + name: "kmsProjectId" + description: | + The Google Cloud project id of the project where the kms key stored. If empty, + the kms key is stored at the same project as customer's project and ecrypted + with CMEK, otherwise, the kms key is stored in the tenant project and + encrypted with GMEK. + - !ruby/object:Api::Type::Boolean + name: 'createSampleWorkflows' + description: | + Indicates if sample workflow should be created along with provisioning. + immutable: true + url_param_only: true + - !ruby/object:Api::Type::Boolean + name: 'provisionGmek' + description: | + Indicates provision with GMEK or CMEK. + immutable: true + url_param_only: true + - !ruby/object:Api::Type::String + name: 'runAsServiceAccount' + description: | + User input run-as service account, if empty, will bring up a new default service account. + immutable: true + url_param_only: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "integrations_client_basic" + primary_resource_id: "example" + - !ruby/object:Provider::Terraform::Examples + name: "integrations_client_advance" + primary_resource_id: "example" + skip_vcr: true + vars: + key_ring_name: my-keyring diff --git a/mmv1/products/integrations/product.yaml b/mmv1/products/integrations/product.yaml new file mode 100644 index 000000000000..6c3e6a796e60 --- /dev/null +++ b/mmv1/products/integrations/product.yaml @@ -0,0 +1,22 @@ +# Copyright 2020 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +name: Integrations +display_name: Application Integration +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://integrations.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform diff --git a/mmv1/templates/terraform/decoders/integrations_client.go.erb b/mmv1/templates/terraform/decoders/integrations_client.go.erb new file mode 100644 index 000000000000..f0a1abfd8804 --- /dev/null +++ b/mmv1/templates/terraform/decoders/integrations_client.go.erb @@ -0,0 +1,4 @@ +// Since Client resource doesnt have any properties, +// Adding this decoder as placeholder else the linter will +// complain that the returned `res` is never used afterwards. +return res, nil \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/integrations_client_advance.tf.erb b/mmv1/templates/terraform/examples/integrations_client_advance.tf.erb new file mode 100644 index 000000000000..54e2de273ca9 --- /dev/null +++ b/mmv1/templates/terraform/examples/integrations_client_advance.tf.erb @@ -0,0 +1,34 @@ +data "google_project" "test_project" { +} + +resource "google_kms_key_ring" "keyring" { + name = "<%= ctx[:vars]['key_ring_name'] %>" + location = "us-central1" +} + +resource "google_kms_crypto_key" "cryptokey" { + name = "crypto-key-example" + key_ring = google_kms_key_ring.keyring.id + rotation_period = "7776000s" + depends_on = [google_kms_key_ring.keyring] +} + +resource "google_kms_crypto_key_version" "test_key" { + crypto_key = google_kms_crypto_key.cryptokey.id + depends_on = [google_kms_crypto_key.cryptokey] +} + +resource "google_integrations_client" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + create_sample_workflows = true + provision_gmek = true + run_as_service_account = "radndom-service-account" + cloud_kms_config { + kms_location = "us-central1" + kms_ring = google_kms_key_ring.keyring.id + key = google_kms_crypto_key.cryptokey.id + key_version = google_kms_crypto_key_version.test_key.id + kms_project_id = data.google_project.test_project.id + } + depends_on = [google_kms_crypto_key_version.test_key] +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/integrations_client_basic.tf.erb b/mmv1/templates/terraform/examples/integrations_client_basic.tf.erb new file mode 100644 index 000000000000..1fc724bcf539 --- /dev/null +++ b/mmv1/templates/terraform/examples/integrations_client_basic.tf.erb @@ -0,0 +1,3 @@ +resource "google_integrations_client" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index 13510630f136..613e795bf683 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -466,6 +466,11 @@ var ServicesListBeta = mapOf( "displayName" to "Integrationconnectors", "path" to "./google-beta/services/integrationconnectors" ), + "integrations" to mapOf( + "name" to "integrations", + "displayName" to "Applicationintegration", + "path" to "./google-beta/services/integrations" + ), "kms" to mapOf( "name" to "kms", "displayName" to "Kms", diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index f4b303eccc69..f3a3fe573889 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -461,6 +461,11 @@ var ServicesListGa = mapOf( "displayName" to "Integrationconnectors", "path" to "./google/services/integrationconnectors" ), + "integrations" to mapOf( + "name" to "integrations", + "displayName" to "Applicationintegration", + "path" to "./google/services/integrations" + ), "kms" to mapOf( "name" to "kms", "displayName" to "Kms", From de6caa4b08b78cd8f030da096a56e5535cd043b6 Mon Sep 17 00:00:00 2001 From: krishnangopal1810 <156300588+krishnangopal1810@users.noreply.github.com> Date: Thu, 21 Mar 2024 23:42:52 +0530 Subject: [PATCH 175/200] Add apphub.admin role for the organization in the test environment (#10152) * add apphub.admin role for the organizations that the CI runs the tests * Change to use org instead of billing id * Change to use org instead of billing id --------- Co-authored-by: Krishnan Gopal --- .ci/infra/terraform/main.tf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index 439d37f5e8b3..0567107882fd 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -135,6 +135,12 @@ resource "google_organization_iam_member" "sa_storage_admin" { member = google_service_account.sa.member } +resource "google_organization_iam_member" "apphub_admin" { + org_id = data.google_organization.org.org_id + role = "roles/apphub.admin" + member = google_service_account.sa.member +} + resource "google_billing_account_iam_member" "sa_master_billing_admin" { billing_account_id = data.google_billing_account.master_acct.id role = "roles/billing.admin" From d62cd8a0331b44a3f316d734be50a49fa8c200a1 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Thu, 21 Mar 2024 11:29:50 -0700 Subject: [PATCH 176/200] Change ItemType to object (#10249) --- mmv1/api/type.go | 2 +- mmv1/products/datafusion/go_instance.yaml | 35 ++++++++++++----------- mmv1/products/pubsub/go_Topic.yaml | 3 +- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/mmv1/api/type.go b/mmv1/api/type.go index 43afc0f77f8b..df9ab2c3e161 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -135,7 +135,7 @@ type Type struct { EnumValues []string `yaml:"enum_values"` - ItemType string `yaml:"item_type"` + ItemType *Type `yaml:"item_type"` Resource string diff --git a/mmv1/products/datafusion/go_instance.yaml b/mmv1/products/datafusion/go_instance.yaml index 729cf2079292..838891f4643b 100644 --- a/mmv1/products/datafusion/go_instance.yaml +++ b/mmv1/products/datafusion/go_instance.yaml @@ -279,20 +279,21 @@ able to access the public internet." If accelerators are enabled it is possible a permadiff will be created with the Options field. Users will need to either manually update their state file to include these diffed options, or include the field in a [lifecycle ignore changes block](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes)." - item_type: NestedObject - properties: - - name: 'acceleratorType' - type: Enum - description: "The type of an accelator for a CDF instance." - required: true - enum_values: - - 'CDC' - - 'HEALTHCARE' - - 'CCAI_INSIGHTS' - - name: 'state' - type: Enum - description: "The type of an accelator for a CDF instance." - required: true - enum_values: - - 'ENABLED' - - 'DISABLED' + item_type: + properties: + - name: 'acceleratorType' + type: Enum + description: "The type of an accelator for a CDF instance." + required: true + enum_values: + - 'CDC' + - 'HEALTHCARE' + - 'CCAI_INSIGHTS' + - name: 'state' + type: Enum + description: "The type of an accelator for a CDF instance." + required: true + enum_values: + - 'ENABLED' + - 'DISABLED' + type: NestedObject diff --git a/mmv1/products/pubsub/go_Topic.yaml b/mmv1/products/pubsub/go_Topic.yaml index 17cddf8c9ea7..aec7c9790c33 100644 --- a/mmv1/products/pubsub/go_Topic.yaml +++ b/mmv1/products/pubsub/go_Topic.yaml @@ -116,7 +116,8 @@ constraints are in effect." allowed regions. An empty list means that no regions are allowed, and is not a valid configuration." required: true - item_type: Api::Type::String + item_type: + type: String - name: 'schemaSettings' type: NestedObject description: "Settings for validating messages published against a schema." From 2089d74fe1ddf00362c76d82dbcebe95fafc9142 Mon Sep 17 00:00:00 2001 From: Jashan Sudan Date: Thu, 21 Mar 2024 11:48:36 -0700 Subject: [PATCH 177/200] Clarify usage of min/max throughput and instances (#10130) * Clarify usage of min/max throughput and instances * fix lint * fix snake casing --- mmv1/products/vpcaccess/Connector.yaml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/mmv1/products/vpcaccess/Connector.yaml b/mmv1/products/vpcaccess/Connector.yaml index c2034fc2bf3a..6237f8d680b5 100644 --- a/mmv1/products/vpcaccess/Connector.yaml +++ b/mmv1/products/vpcaccess/Connector.yaml @@ -106,19 +106,23 @@ properties: - !ruby/object:Api::Type::Integer name: minThroughput description: | - Minimum throughput of the connector in Mbps. Default and min is 200. + Minimum throughput of the connector in Mbps. Default and min is 200. Refers to the expected throughput when using an e2-micro machine type. + Value must be a multiple of 100 from 200 through 900. Must be lower than the value specified by max_throughput. If both min_throughput and + min_instances are provided, min_instances takes precedence over min_throughput. The use of min_throughput is discouraged in favor of min_instances. default_value: 200 validation: !ruby/object:Provider::Terraform::Validation function: 'validation.IntBetween(200, 1000)' - !ruby/object:Api::Type::Integer name: minInstances description: | - Minimum value of instances in autoscaling group underlying the connector. + Minimum value of instances in autoscaling group underlying the connector. Value must be between 2 and 9, inclusive. Must be + lower than the value specified by max_instances. default_from_api: true - !ruby/object:Api::Type::Integer name: maxInstances description: | - Maximum value of instances in autoscaling group underlying the connector. + Maximum value of instances in autoscaling group underlying the connector. Value must be between 3 and 10, inclusive. Must be + higher than the value specified by min_instances. default_from_api: true - !ruby/object:Api::Type::Integer name: maxThroughput @@ -126,7 +130,10 @@ properties: # throughput must be lower than the maximum. The console defaults to 1000, so I changed it to that. # API returns 300 if it is not sent description: | - Maximum throughput of the connector in Mbps, must be greater than `min_throughput`. Default is 300. + Maximum throughput of the connector in Mbps, must be greater than `min_throughput`. Default is 300. Refers to the expected throughput + when using an e2-micro machine type. Value must be a multiple of 100 from 300 through 1000. Must be higher than the value specified by + min_throughput. If both max_throughput and max_instances are provided, max_instances takes precedence over max_throughput. The use of + max_throughput is discouraged in favor of max_instances. default_value: 300 validation: !ruby/object:Provider::Terraform::Validation function: 'validation.IntBetween(200, 1000)' From 96be3399f6a67a00fc30a3dc08deefdcbcc71887 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Thu, 21 Mar 2024 13:41:53 -0700 Subject: [PATCH 178/200] Fixed issues with diff-processor caused by GA-only compilation errors (#10250) * Added file to trigger google-only failure * Check if cleaning the diff processor up properly solves the issue * Revert "Check if cleaning the diff processor up properly solves the issue" This reverts commit 85c358e4191d5e6115bfef0e02c819f92b45dfe0. * Clean up diff processor before building instead of after * Revert "Added file to trigger google-only failure" This reverts commit 0e4486080477902820ad282666d0c8f51e890076. --- .ci/magician/cmd/generate_comment.go | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/.ci/magician/cmd/generate_comment.go b/.ci/magician/cmd/generate_comment.go index 78dcbc7b1347..2ca1a7ec3ef0 100644 --- a/.ci/magician/cmd/generate_comment.go +++ b/.ci/magician/cmd/generate_comment.go @@ -262,12 +262,6 @@ func execGenerateComment(prNumber int, ghTokenMagicModules, buildId, buildStep, for _, serviceLabel := range serviceLabels { uniqueServiceLabels[serviceLabel] = struct{}{} } - - err = cleanDiffProcessor(diffProcessorPath, rnr) - if err != nil { - fmt.Println("cleaning up diff processor: ", err) - errors[repo.Title] = append(errors[repo.Title], "The diff processor failed to clean up properly.") - } } breakingChangesSlice := maps.Keys(uniqueBreakingChanges) sort.Strings(breakingChangesSlice) @@ -376,6 +370,11 @@ func computeDiff(repo *source.Repo, oldBranch string, ctlr *source.Controller) ( // Build the diff processor for tpg or tpgb func buildDiffProcessor(diffProcessorPath, providerLocalPath string, env map[string]string, rnr ExecRunner) error { + for _, path := range []string{"old", "new", "bin"} { + if err := rnr.RemoveAll(filepath.Join(diffProcessorPath, path)); err != nil { + return err + } + } if err := rnr.PushDir(diffProcessorPath); err != nil { return err } @@ -442,15 +441,6 @@ func changedSchemaLabels(prNumber int, currentLabels []string, diffProcessorPath return labels, nil } -func cleanDiffProcessor(diffProcessorPath string, rnr ExecRunner) error { - for _, path := range []string{"old", "new", "bin"} { - if err := rnr.RemoveAll(filepath.Join(diffProcessorPath, path)); err != nil { - return err - } - } - return nil -} - // 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. From 89267ec3216d345fd385cab8ed30b7af41a814a3 Mon Sep 17 00:00:00 2001 From: krishnangopal1810 <156300588+krishnangopal1810@users.noreply.github.com> Date: Fri, 22 Mar 2024 03:34:54 +0530 Subject: [PATCH 179/200] Consolidate Documentation for App Hub resources and data sources into one subcategory (#10238) * add apphub.admin role for the organizations that the CI runs the tests * Change to use org instead of billing id * Change to use org instead of billing id * Fix subcategory of data sources consistent with rest of AppHub product resources * This change is supposed to be a part of another feature --------- Co-authored-by: Krishnan Gopal --- .../website/docs/d/apphub_discovered_service.html.markdown | 4 ++-- .../website/docs/d/apphub_discovered_workload.html.markdown | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown index 272491b8d089..8f899ad1f20c 100644 --- a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_service.html.markdown @@ -1,5 +1,5 @@ --- -subcategory: "Apphub" +subcategory: "App Hub" description: |- Get information about a discovered service. --- @@ -49,4 +49,4 @@ In addition to the arguments listed above, the following computed attributes are * `location` - The location that the underlying resource resides in. -* `zone` - The location that the underlying resource resides in if it is zonal. \ No newline at end of file +* `zone` - The location that the underlying resource resides in if it is zonal. diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown index d9fc574eaff0..6dafead5393d 100644 --- a/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/apphub_discovered_workload.html.markdown @@ -1,5 +1,5 @@ --- -subcategory: "Apphub" +subcategory: "App Hub" description: |- Get information about a discovered workload. --- From ae121ddbe32876773ff3841419eddbb7b21ea9b5 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 22 Mar 2024 09:04:03 -0700 Subject: [PATCH 180/200] Corrected names of iam_workload resource and data source files (#10253) beta is not part of the resource name. This is important for https://github.com/GoogleCloudPlatform/magic-modules/pull/10248 --- ..._pool.go.erb => data_source_iam_workload_identity_pool.go.erb} | 0 ...erb => data_source_iam_workload_identity_pool_provider.go.erb} | 0 ...> data_source_iam_workload_identity_pool_provider_test.go.erb} | 0 ....go.erb => data_source_iam_workload_identity_pool_test.go.erb} | 0 ....go.erb => resource_iam_workload_identity_pool_id_test.go.erb} | 0 ...> resource_iam_workload_identity_pool_provider_id_test.go.erb} | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename mmv1/third_party/terraform/services/iambeta/{data_source_iam_beta_workload_identity_pool.go.erb => data_source_iam_workload_identity_pool.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{data_source_iam_beta_workload_identity_pool_provider.go.erb => data_source_iam_workload_identity_pool_provider.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{data_source_iam_beta_workload_identity_pool_provider_test.go.erb => data_source_iam_workload_identity_pool_provider_test.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{data_source_iam_beta_workload_identity_pool_test.go.erb => data_source_iam_workload_identity_pool_test.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{resource_iam_beta_workload_identity_pool_id_test.go.erb => resource_iam_workload_identity_pool_id_test.go.erb} (100%) rename mmv1/third_party/terraform/services/iambeta/{resource_iam_beta_workload_identity_pool_provider_id_test.go.erb => resource_iam_workload_identity_pool_provider_id_test.go.erb} (100%) diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool.go.erb rename to mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_provider.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider.go.erb rename to mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_provider.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider_test.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_provider_test.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_provider_test.go.erb rename to mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_provider_test.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_test.go.erb b/mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_test.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/data_source_iam_beta_workload_identity_pool_test.go.erb rename to mmv1/third_party/terraform/services/iambeta/data_source_iam_workload_identity_pool_test.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/resource_iam_beta_workload_identity_pool_id_test.go.erb b/mmv1/third_party/terraform/services/iambeta/resource_iam_workload_identity_pool_id_test.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/resource_iam_beta_workload_identity_pool_id_test.go.erb rename to mmv1/third_party/terraform/services/iambeta/resource_iam_workload_identity_pool_id_test.go.erb diff --git a/mmv1/third_party/terraform/services/iambeta/resource_iam_beta_workload_identity_pool_provider_id_test.go.erb b/mmv1/third_party/terraform/services/iambeta/resource_iam_workload_identity_pool_provider_id_test.go.erb similarity index 100% rename from mmv1/third_party/terraform/services/iambeta/resource_iam_beta_workload_identity_pool_provider_id_test.go.erb rename to mmv1/third_party/terraform/services/iambeta/resource_iam_workload_identity_pool_provider_id_test.go.erb From 60917c85e2f6645e21846fcf0197ff18244c747d Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 22 Mar 2024 09:33:14 -0700 Subject: [PATCH 181/200] Pin workflow dependency versions (#10256) * Pinned python yaml library versions * Pinned goimports version in build-downstreams * Force generation * Revert "Force generation" This reverts commit b2d876045277156ae2fd3a44194fe58164297186. --- .github/workflows/build-downstream.yml | 2 +- .github/workflows/mmv1-lint-product-yaml.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-downstream.yml b/.github/workflows/build-downstream.yml index 4cfa5aa2bac1..ab0dbd43dc13 100644 --- a/.github/workflows/build-downstream.yml +++ b/.github/workflows/build-downstream.yml @@ -58,7 +58,7 @@ jobs: restore-keys: | ${{ runner.os }}-go- - - run: go install golang.org/x/tools/cmd/goimports@latest + - run: go install golang.org/x/tools/cmd/goimports@7656c4c657688cae30795365d2a5f30d6f18be7f # v0.19.0 - name: Build ${{ inputs.repo }} run: | diff --git a/.github/workflows/mmv1-lint-product-yaml.yml b/.github/workflows/mmv1-lint-product-yaml.yml index a857f40c3a7a..c4d91e19371e 100644 --- a/.github/workflows/mmv1-lint-product-yaml.yml +++ b/.github/workflows/mmv1-lint-product-yaml.yml @@ -30,7 +30,7 @@ jobs: fi - name: Install yamllint if: ${{ !failure() && steps.pull_request.outputs.yamlfiles != '' }} - run: pip install yamllint + run: pip install yamllint==1.32.0 pyyaml==6.0.1 --no-deps - name: Lint YAML files if: ${{ !failure() && steps.pull_request.outputs.yamlfiles != '' }} run: yamllint -c repo/.yamllint ${{steps.pull_request.outputs.yamlfiles}} From 10868897184a36752a6ace53b8578d026f27a824 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Fri, 22 Mar 2024 09:42:38 -0700 Subject: [PATCH 182/200] Rewrite type functions (#10259) --- mmv1/api/type.go | 234 +++++++++++++++++++++++++++-------------------- mmv1/api/type.rb | 34 ------- 2 files changed, 135 insertions(+), 133 deletions(-) diff --git a/mmv1/api/type.go b/mmv1/api/type.go index df9ab2c3e161..b3923f1181fc 100644 --- a/mmv1/api/type.go +++ b/mmv1/api/type.go @@ -16,7 +16,6 @@ package api import ( "fmt" "log" - "reflect" "github.com/GoogleCloudPlatform/magic-modules/mmv1/api/product" "github.com/GoogleCloudPlatform/magic-modules/mmv1/google" @@ -135,9 +134,15 @@ type Type struct { EnumValues []string `yaml:"enum_values"` + // ==================== + // Array Fields + // ==================== ItemType *Type `yaml:"item_type"` + MinSize int `yaml:"min_size"` + MaxSize int `yaml:"max_size"` Resource string + Imports string // ==================== // Terraform Overrides @@ -190,6 +195,22 @@ type Type struct { // For a TypeMap, the DSF to apply to the key. KeyDiffSuppressFunc string `yaml:"key_diff_suppress_func"` + // ==================== + // Map Fields + // ==================== + // The type definition of the contents of the map. + ValueType *Type `yaml:"value_type"` + + // While the API doesn't give keys an explicit name, we specify one + // because in Terraform the key has to be a property of the object. + // + // The name of the key. Used in the Terraform schema as a field name. + KeyName string `yaml:"key_name` + + // A description of the key's format. Used in Terraform to describe + // the field in documentation. + KeyDescription string `yaml:"key_description` + // ==================== // Schema Modifications // ==================== @@ -313,7 +334,7 @@ const MAX_NAME = 20 // and at some points in the build this doesn't output a valid output. // def lineage -func (t *Type) Lineage() string { +func (t Type) Lineage() string { if t.ParentMetadata == nil { return google.Underscore(t.Name) } @@ -324,10 +345,13 @@ func (t *Type) Lineage() string { // Prints the access path of the field in the configration eg: metadata.0.labels // The only intended purpose is to get the value of the labes field by calling d.Get(). // func (t *Type) terraform_lineage() { -// return name&.underscore if __parent.nil? || __parent.flatten_object +func (t Type) TerraformLineage() string { + if t.ParentMetadata == nil || t.ParentMetadata.FlattenObject { + return google.Underscore(t.Name) + } -// "//{__parent.terraform_lineage}.0.//{name&.underscore}" -// } + return fmt.Sprintf("%s.0.%s", t.ParentMetadata.TerraformLineage(), google.Underscore(t.Name)) +} // func (t *Type) to_json(opts) { // ignore fields that will contain references to parent resources and @@ -394,10 +418,13 @@ func (t *Type) Lineage() string { // Returns list of properties that are in conflict with this property. // func (t *Type) conflicting() { -// return [] unless @__resource +func (t Type) Conflicting() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @conflicts -// } + return t.Conflicts +} // Checks that all properties that needs at least one of their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -410,10 +437,13 @@ func (t *Type) Lineage() string { // Returns list of properties that needs at least one of their fields set. // func (t *Type) at_least_one_of_list() { -// return [] unless @__resource +func (t Type) AtLeastOneOfList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @at_least_one_of -// } + return t.AtLeastOneOf +} // Checks that all properties that needs exactly one of their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -426,10 +456,13 @@ func (t *Type) Lineage() string { // Returns list of properties that needs exactly one of their fields set. // func (t *Type) exactly_one_of_list() { -// return [] unless @__resource +func (t Type) ExactlyOneOfList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// @exactly_one_of -// } + return t.ExactlyOneOf +} // Checks that all properties that needs required with their fields actually exist. // This currently just returns if empty, because we don't want to do the check, since @@ -442,21 +475,20 @@ func (t *Type) Lineage() string { // Returns list of properties that needs required with their fields set. // func (t *Type) required_with_list() { -// // return [] unless @__resource - -// // @required_with -// } +func (t Type) RequiredWithList() []string { + if t.ResourceMetadata == nil { + return []string{} + } -// func (t *Type) type() { -// // self.class.name.split('::').last -// } + return t.RequiredWith +} -// func (t *Type) parent() { -// // @__parent -// } +func (t Type) Parent() *Type { + return t.ParentMetadata +} // def min_version -func (t *Type) MinVersionObj() *product.Version { +func (t Type) MinVersionObj() *product.Version { if t.MinVersion != "" { return t.ResourceMetadata.ProductMetadata.versionObj(t.MinVersion) } else { @@ -484,6 +516,14 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { t.Exclude = version.CompareTo(t.MinVersionObj()) < 0 } } + + if t.IsA("NestedObject") { + for _, p := range t.Properties { + p.ExcludeIfNotInVersion(version) + } + } else if t.IsA("Array") && t.ItemType.IsA("NestedObject") { + t.ItemType.ExcludeIfNotInVersion(version) + } } // Overriding is_a? to enable class overrides. @@ -492,7 +532,7 @@ func (t *Type) ExcludeIfNotInVersion(version *product.Version) { // TODO Q1: check the type of superclasses of property t // func (t *Type) is_a?(clazz) { -func (t *Type) IsA(clazz string) bool { +func (t Type) IsA(clazz string) bool { if clazz == "" { log.Fatalf("class cannot be empty") } @@ -501,7 +541,7 @@ func (t *Type) IsA(clazz string) bool { return t.NewType == clazz } - return reflect.TypeOf(t).Name() == fmt.Sprintf("main.%s", clazz) + return t.Type == clazz // super(clazz) } @@ -514,13 +554,38 @@ func (t *Type) IsA(clazz string) bool { // // super // } -// func (t *Type) removed() { -// // !(@removed_message.nil? || @removed_message == '') -// } +// Returns nested properties for this property. +// def nested_properties +func (t Type) NestedProperties() []*Type { + props := make([]*Type, 0) -// func (t *Type) deprecated() { -// // !(@deprecation_message.nil? || @deprecation_message == '') -// } + switch { + case t.IsA("Array"): + if t.ItemType.IsA("NestedObject") { + props = google.Reject(t.ItemType.NestedProperties(), func(p *Type) bool { + return t.Exclude + }) + } + case t.IsA("NestedObject"): + props = t.UserProperties() + case t.IsA("Map"): + props = google.Reject(t.ValueType.NestedProperties(), func(p *Type) bool { + return t.Exclude + }) + default: + } + return props +} + +// def removed? +func (t Type) Removed() bool { + return t.RemovedMessage != "" +} + +// def deprecated? +func (t Type) Deprecated() bool { + return t.DeprecationMessage != "" +} // // private @@ -632,20 +697,6 @@ func (t *Type) IsA(clazz string) bool { // check :max_size, type: ::Integer // end -// func (t *Type) property_class -// case @item_type -// when NestedObject, ResourceRef -// type = @item_type.property_class -// when Enum -// raise 'aaaa' -// else -// type = property_ns_prefix -// type << get_type(@item_type).new(@name).type -// end -// type[-1] = "//{type[-1].camelize(:upper)}Array" -// type -// end - // func (t *Type) exclude_if_not_in_version!(version) // super // @item_type.exclude_if_not_in_version!(version) \ @@ -659,13 +710,15 @@ func (t *Type) IsA(clazz string) bool { // super // end -// func (t *Type) item_type_class -// return @item_type \ -// if @item_type.instance_of?(Class) +// This function is for array field +// def item_type_class +func (t Type) ItemTypeClass() string { + if !t.IsA("Array") { + return "" + } -// Object.const_get(@item_type) -// end -// end + return t.ItemType.Type +} // // Represents an enum, and store is valid values // class Enum < Primitive @@ -738,14 +791,12 @@ func (t *Type) IsA(clazz string) bool { // check_resource_ref_property_exists // end -// func (t *Type) property -// props = resource_ref.all_user_properties -// .select { |prop| prop.name == @imports } -// return props.first unless props.empty? -// end - // func (t *Type) resource_ref -func (t *Type) ResourceRef() *Resource { +func (t Type) ResourceRef() *Resource { + if !t.IsA("ResourceRef") { + return nil + } + product := t.ResourceMetadata.ProductMetadata resources := google.Select(product.Objects, func(obj *Resource) bool { return obj.Name == t.Resource @@ -754,13 +805,6 @@ func (t *Type) ResourceRef() *Resource { return resources[0] } -// func (t *Type) property_class -// type = property_ns_prefix -// type << [@resource, @imports, 'Ref'] -// type[-1] = type[-1].join('_').camelize(:upper) -// type -// end - // private // func (t *Type) check_resource_ref_property_exists @@ -791,33 +835,25 @@ func (t *Type) ResourceRef() *Resource { // check :properties, type: ::Array, item_type: Api::Type, required: true // end -// func (t *Type) property_class -// type = property_ns_prefix -// type << [@__resource.name, @name] -// type[-1] = type[-1].join('_').camelize(:upper) -// type -// end - -// // Returns all properties including the ones that are excluded -// // This is used for PropertyOverride validation -// func (t *Type) all_properties -// @properties -// end +// Returns all properties including the ones that are excluded +// This is used for PropertyOverride validation +// def all_properties +func (t Type) AllProperties() []*Type { + return t.Properties +} // func (t *Type) properties -func (t *Type) UserProperties() []*Type { - if t.Properties == nil { - log.Fatalf("Field '{%s}' properties are nil!", t.Lineage()) - } - - return google.Reject(t.Properties, func(p *Type) bool { - return p.Exclude - }) -} +func (t Type) UserProperties() []*Type { + if t.IsA("NestedObject") { + if t.Properties == nil { + log.Fatalf("Field '{%s}' properties are nil!", t.Lineage()) + } -// func (t *Type) nested_properties -func (t *Type) NestedProperties() []*Type { - return t.UserProperties() + return google.Reject(t.Properties, func(p *Type) bool { + return p.Exclude + }) + } + return nil } // Returns the list of top-level properties once any nested objects with @@ -1010,11 +1046,11 @@ func (t *Type) RootProperties() []*Type { // Module.const_get(type) // end -// func (t *Type) property_ns_prefix -// [ -// 'Google', -// @__resource.__product.name.camelize(:upper), -// 'Property' -// ] -// end -// end +// def property_ns_prefix +func (t Type) PropertyNsPrefix() []string { + return []string{ + "Google", + google.Camelize(t.ResourceMetadata.ProductMetadata.Name, "upper"), + "Property", + } +} diff --git a/mmv1/api/type.rb b/mmv1/api/type.rb index 291c03053af0..9bac441c0cc5 100644 --- a/mmv1/api/type.rb +++ b/mmv1/api/type.rb @@ -566,20 +566,6 @@ def validate check :max_size, type: ::Integer end - def property_class - case @item_type - when NestedObject, ResourceRef - type = @item_type.property_class - when Enum - raise 'aaaa' - else - type = property_ns_prefix - type << get_type(@item_type).new(@name).type - end - type[-1] = "#{type[-1].camelize(:upper)}Array" - type - end - def exclude_if_not_in_version!(version) super @item_type.exclude_if_not_in_version!(version) \ @@ -657,12 +643,6 @@ def validate check_resource_ref_property_exists end - def property - props = resource_ref.all_user_properties - .select { |prop| prop.name == @imports } - return props.first unless props.empty? - end - def resource_ref product = @__resource.__product resources = product.objects.select { |obj| obj.name == @resource } @@ -670,13 +650,6 @@ def resource_ref resources[0] end - def property_class - type = property_ns_prefix - type << [@resource, @imports, 'Ref'] - type[-1] = type[-1].join('_').camelize(:upper) - type - end - private def check_resource_ref_property_exists @@ -708,13 +681,6 @@ def validate check :properties, type: ::Array, item_type: Api::Type, required: true end - def property_class - type = property_ns_prefix - type << [@__resource.name, @name] - type[-1] = type[-1].join('_').camelize(:upper) - type - end - # Returns all properties including the ones that are excluded # This is used for PropertyOverride validation def all_properties From 97305d71d05cfc2a1fa9d4a494f4e09bb66e05f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleks=20Vuji=C4=87?= Date: Fri, 22 Mar 2024 18:24:13 +0100 Subject: [PATCH 183/200] Removed double quotes and typo in google_project_iam_member documentation (#9750) --- .../terraform/website/docs/r/google_project_iam.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown b/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown index 33ee748e341d..642b062ec3f5 100644 --- a/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/google_project_iam.html.markdown @@ -301,4 +301,4 @@ The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/c ``` terraform import google_project_iam_audit_config.default "{{project_id}} foo.googleapis.com" -``` \ No newline at end of file +``` From f9a432f23c7ecd3eb75806b3087e572e667dc65d Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 22 Mar 2024 10:27:35 -0700 Subject: [PATCH 184/200] Iniital setup for codeql scanning (#10254) --- .github/workflows/codeql.yml | 61 ++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000000..86b7a12ffe9e --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,61 @@ +name: "CodeQL" + +on: + push: + branches: [ "main", "FEATURE-BRANCH-*", "FEATURE-BRANCH-major-release-*" ] + # TODO: enable pull_request once behavior on main is confirmed + # pull_request: + # branches: [ "main", "FEATURE-BRANCH-*", "FEATURE-BRANCH-major-release-*" ] + schedule: + - cron: '26 13 * * 3' + +jobs: + analyze: + name: Analyze + runs-on: 'ubuntu-latest' + timeout-minutes: 360 + permissions: + # required for all workflows + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go', 'ruby', 'java-kotlin' ] + + steps: + - name: Checkout repository + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@05963f47d870e2cb19a537396c1f668a348c7d8f # v3.24.8 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: "/language:${{matrix.language}}" From c8f66220a0fcf8b12b12b1aa3a4f21bf766edbe2 Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 22 Mar 2024 13:00:40 -0700 Subject: [PATCH 185/200] Added permissions: read-all to codeql action (#10264) --- .github/workflows/codeql.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 86b7a12ffe9e..80b66c9dc520 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -1,4 +1,5 @@ name: "CodeQL" +permissions: read-all on: push: From 4b21578479e868444361b16bb627006eed66a4ee Mon Sep 17 00:00:00 2001 From: "Stephen Lewis (Burrows)" Date: Fri, 22 Mar 2024 13:00:59 -0700 Subject: [PATCH 186/200] Remove java-kotlin codeql scanning (#10263) --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 80b66c9dc520..c3f12b1d5d2c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -22,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'go', 'ruby', 'java-kotlin' ] + language: [ 'go', 'ruby' ] steps: - name: Checkout repository From bda80a6d813eec89cfdc796f16471acb702225f3 Mon Sep 17 00:00:00 2001 From: Cameron Thornton Date: Fri, 22 Mar 2024 16:26:06 -0500 Subject: [PATCH 187/200] Initial resource documentation templating (#10266) --- mmv1/api/product.go | 7 +++ mmv1/api/resource.go | 7 +++ mmv1/provider/template_data.go | 51 +++++++++---------- mmv1/provider/terraform.go | 10 ++-- .../terraform/resource.html.markdown.tmpl | 39 +++++++++++++- 5 files changed, 80 insertions(+), 34 deletions(-) diff --git a/mmv1/api/product.go b/mmv1/api/product.go index e3defe678c82..57aee0b50d54 100644 --- a/mmv1/api/product.go +++ b/mmv1/api/product.go @@ -211,6 +211,13 @@ func (p *Product) SetPropertiesBasedOnVersion(version *product.Version) { p.BaseUrl = version.BaseUrl } +func (p *Product) TerraformName() string { + if p.LegacyName != "" { + return google.Underscore(p.LegacyName) + } + return google.Underscore(p.Name) +} + // ==================== // Debugging Methods // ==================== diff --git a/mmv1/api/resource.go b/mmv1/api/resource.go index ad71a8eb23e8..b7a19a4df776 100644 --- a/mmv1/api/resource.go +++ b/mmv1/api/resource.go @@ -764,3 +764,10 @@ func (r Resource) HasZone() bool { func (r Resource) Lineage() string { return r.Name } + +func (r Resource) TerraformName() string { + if r.LegacyName != "" { + return r.LegacyName + } + return fmt.Sprintf("google_%s_%s", r.ProductMetadata.TerraformName(), google.Underscore(r.Name)) +} diff --git a/mmv1/provider/template_data.go b/mmv1/provider/template_data.go index 23ee5ebffd12..a52e6340d331 100644 --- a/mmv1/provider/template_data.go +++ b/mmv1/provider/template_data.go @@ -19,6 +19,7 @@ import ( "go/format" "log" "os" + "path/filepath" "strings" "text/template" @@ -74,40 +75,49 @@ func NewTemplateData(outputFolder string, version product.Version) *TemplateData } func (td *TemplateData) GenerateResourceFile(filePath string, resource api.Resource) { + td.GenerateFile(filePath, "templates/terraform/resource.go.tmpl", resource, true) +} + +func (td *TemplateData) GenerateDocumentationFile(filePath string, resource api.Resource) { + td.GenerateFile(filePath, "templates/terraform/resource.html.markdown.tmpl", resource, false) +} +func (td *TemplateData) GenerateFile(filePath, templatePath string, resource api.Resource, goFormat bool) { log.Printf("Generating %s", filePath) - tmpl, err := template.New("resource.go.tmpl").Funcs(TemplateFunctions).ParseFiles( - "templates/terraform/resource.go.tmpl", + templateFileName := filepath.Base(templatePath) + + tmpl, err := template.New(templateFileName).Funcs(TemplateFunctions).ParseFiles( + templatePath, ) if err != nil { glog.Exit(err) } contents := bytes.Buffer{} - if err = tmpl.ExecuteTemplate(&contents, "resource.go.tmpl", resource); err != nil { + if err = tmpl.ExecuteTemplate(&contents, templateFileName, resource); err != nil { glog.Exit(err) } - if err != nil { - glog.Exit(err) + sourceByte := contents.Bytes() + // Replace import path based on version (beta/alpha) + if td.TerraformResourceDirectory != "google" { + sourceByte = bytes.Replace(sourceByte, []byte("github.com/hashicorp/terraform-provider-google/google"), []byte(td.TerraformProviderModule+"/"+td.TerraformResourceDirectory), -1) } - formatted, err := td.FormatSource(&contents) - if err != nil { - glog.Error(fmt.Errorf("error formatting %s", filePath)) + if goFormat { + sourceByte, err = format.Source(sourceByte) + if err != nil { + glog.Error(fmt.Errorf("error formatting %s", filePath)) + } } - err = os.WriteFile(filePath, formatted, 0644) + err = os.WriteFile(filePath, sourceByte, 0644) if err != nil { glog.Exit(err) } } -func (td *TemplateData) GenerateDocumentationFile(filePath string, resource api.Resource) { - -} - // # path is the output name of the file // # template is used to determine metadata about the file based on how it is // # generated @@ -178,18 +188,3 @@ func (td *TemplateData) GenerateDocumentationFile(filePath string, resource api. // end // end // end - -func (td *TemplateData) FormatSource(source *bytes.Buffer) ([]byte, error) { - sourceByte := source.Bytes() - // Replace import path based on version (beta/alpha) - if td.TerraformResourceDirectory != "google" { - sourceByte = bytes.Replace(sourceByte, []byte("github.com/hashicorp/terraform-provider-google/google"), []byte(td.TerraformProviderModule+"/"+td.TerraformResourceDirectory), -1) - } - - output, err := format.Source(sourceByte) - if err != nil { - return []byte(source.String()), err - } - - return output, nil -} diff --git a/mmv1/provider/terraform.go b/mmv1/provider/terraform.go index 54a91b38f208..9c3acd229f05 100644 --- a/mmv1/provider/terraform.go +++ b/mmv1/provider/terraform.go @@ -127,18 +127,20 @@ func (t *Terraform) GenerateResource(object api.Resource, templateData TemplateD if generateCode { productName := t.Product.ApiName targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName) - if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) } - targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s.go", t.FullResourceName(object))) - templateData.GenerateResourceFile(targetFilePath, object) } if generateDocs { - templateData.GenerateDocumentationFile(outputFolder, object) + targetFolder := path.Join(outputFolder, "website", "docs", "r") + if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil { + log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err)) + } + targetFilePath := path.Join(targetFolder, fmt.Sprintf("%s.html.markdown", t.FullResourceName(object))) + templateData.GenerateDocumentationFile(targetFilePath, object) } } diff --git a/mmv1/templates/terraform/resource.html.markdown.tmpl b/mmv1/templates/terraform/resource.html.markdown.tmpl index 80a5c85d93dd..296092c6eba9 100644 --- a/mmv1/templates/terraform/resource.html.markdown.tmpl +++ b/mmv1/templates/terraform/resource.html.markdown.tmpl @@ -25,6 +25,41 @@ # .github/CONTRIBUTING.md. # # ---------------------------------------------------------------------------- - -{{$.ProductMetadata.Name}} {{$.Name}} +subcategory: "{{$.ProductMetadata.DisplayName}}" +description: |- + {{$.Description -}} --- + +# {{$.TerraformName}} +{{- if $.DeprecationMessage }} +~> **Warning:** {{$.DeprecationMessage}} +{{- end }} + +{{$.Description}} + +{{- if eq $.MinVersion "beta"}} +~> **Warning:** This resource 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. +{{- end }} +{{ if $.References}} +To get more information about {{$.Name}}, see: + + {{- if $.References.Api}} + +* [API documentation]({{$.References.Api}}) + {{- end }} + {{- if $.References.Guides}} +* How-to Guides + {{- range $title, $link := $.References.Guides }} + * [{{$title}}]({{$link}}) + {{- end }} + {{- end }} +{{- end }} +{{- if $.Docs.Warning}} + +~> **Warning:** {{$.Docs.Warning}} +{{- end }} +{{- if $.Docs.Note}} + +~> **Note:** {{$.Docs.Note}} +{{- end }} \ No newline at end of file From 50a42026b0f3eee1e020a22ecbb23e201d3c9575 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Fri, 22 Mar 2024 14:45:28 -0700 Subject: [PATCH 188/200] Add note about modifying yaml files (#10202) --- .ci/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.ci/README.md b/.ci/README.md index f9495f605c4b..c38c05cf2ca8 100644 --- a/.ci/README.md +++ b/.ci/README.md @@ -102,6 +102,9 @@ The best approach is * Build the `downstream-generator` container locally, with the new Gemfile and Gemfile.lock. This will involve hand-modifying the Dockerfile to use the local Gemfile/Gemfile.lock instead of wget from this repo's `main` branch. You don't need to check in those changes. * When that container is built, and while nothing else is running in GCB (wait, if you need to), push the container to GCR, and as soon as possible afterwards, merge the dependency-changing PR. +## Changes to cloud build yaml: +If changes are made to `gcb-contributor-membership-checker.yml` or `gcb-community-checker.yml` they will not be reflected in presubmit runs for existing PRs without a rebase. This is because these build triggers are linked to pull request creation and not pushes to the PR branch. If changes are needed to these build files they will need to be made in a backwards-compatible manner. Note that changes to other files used by these triggers will be immediately reflected in all PRs, leading to a possible disconnect between the yaml files and the rest of the CI code. + ## Historical Note: Design choices & tradeoffs * The downstream push doesn't wait for checks on its PRs against downstreams. This may inconvenience some existing workflows which rely on the downstream PR checks. This ensures that merge conflicts never come into play, since the downstreams never have dangling PRs, but it requires some up-front work to get those checks into the differ. If a new check is introduced into the downstream Travis, we will need to introduce it into the terraform-tester container. * The downstream push is disconnected from the output of the differ (but runs the same code). This means that the diff which is approved isn't guaranteed to be applied *exactly*, if for instance magic modules' behavior changes on main between diff generation and downstream push. This is also intended to avoid merge conflicts by, effectively, rebasing each commit on top of main before final generation is done. From 6c2de90ffeeb029b6c3a49bfdf52540e010b155c Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Sat, 23 Mar 2024 00:27:42 +0200 Subject: [PATCH 189/200] bq table - add geojson support (#10215) * bq table - add geojson support * bq table - add geojson support * CR comments --- .../services/bigquery/resource_bigquery_table.go | 15 +++++++++++++++ .../bigquery/resource_bigquery_table_test.go | 2 ++ .../website/docs/r/bigquery_table.html.markdown | 2 ++ 3 files changed, 19 insertions(+) diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go index c295af431850..4e584b9ed313 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -622,6 +622,13 @@ func ResourceBigQueryTable() *schema.Resource { }, }, + "json_extension": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"GEOJSON"}, false), + Description: `Load option to be used together with sourceFormat newline-delimited JSON to indicate that a variant of JSON is being loaded. To load newline-delimited GeoJSON, specify GEOJSON (and sourceFormat must be set to NEWLINE_DELIMITED_JSON).`, + }, + "parquet_options": { Type: schema.TypeList, Optional: true, @@ -1784,6 +1791,10 @@ func expandExternalDataConfiguration(cfg interface{}) (*bigquery.ExternalDataCon edc.Compression = v.(string) } + if v, ok := raw["json_extension"]; ok { + edc.JsonExtension = v.(string) + } + if v, ok := raw["csv_options"]; ok { edc.CsvOptions = expandCsvOptions(v) } @@ -1851,6 +1862,10 @@ func flattenExternalDataConfiguration(edc *bigquery.ExternalDataConfiguration) ( result["compression"] = edc.Compression } + if edc.JsonExtension != "" { + result["json_extension"] = edc.JsonExtension + } + if edc.CsvOptions != nil { result["csv_options"] = flattenCsvOptions(edc.CsvOptions) } diff --git a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go index cdecd09b2f6d..5cab9a250f87 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table_test.go @@ -2953,6 +2953,8 @@ resource "google_bigquery_table" "test" { encoding = "%s" } + json_extension = "GEOJSON" + hive_partitioning_options { mode = "CUSTOM" source_uri_prefix = "gs://${google_storage_bucket.test.name}/{key1:STRING}" diff --git a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown index 525f395d8a8d..dc0c5df595c4 100644 --- a/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/bigquery_table.html.markdown @@ -190,6 +190,8 @@ in Terraform state, a `terraform destroy` or `terraform apply` that would delete * `json_options` (Optional) - Additional properties to set if `source_format` is set to "JSON". Structure is [documented below](#nested_json_options). +* `json_extension` (Optional) - Used to indicate that a JSON variant, rather than normal JSON, is being used as the sourceFormat. This should only be used in combination with the `JSON` source format. Valid values are: `GEOJSON`. + * `parquet_options` (Optional) - Additional properties to set if `source_format` is set to "PARQUET". Structure is [documented below](#nested_parquet_options). From 77aabb05846837ebb1f50a590397267b6b38f107 Mon Sep 17 00:00:00 2001 From: Thomas Rodgers Date: Fri, 22 Mar 2024 16:04:24 -0700 Subject: [PATCH 190/200] Add logsBucket (#10267) --- .ci/gcb-community-checker.yml | 1 + .ci/gcb-contributor-membership-checker.yml | 1 + .ci/gcb-generate-diffs-new.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.ci/gcb-community-checker.yml b/.ci/gcb-community-checker.yml index 0eac9a4666e7..ba689d1307ff 100644 --- a/.ci/gcb-community-checker.yml +++ b/.ci/gcb-community-checker.yml @@ -72,6 +72,7 @@ steps: - $_HEAD_BRANCH - $_BASE_BRANCH +logsBucket: 'gs://cloudbuild-community-checker-logs' availableSecrets: secretManager: - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-magic-modules/versions/latest diff --git a/.ci/gcb-contributor-membership-checker.yml b/.ci/gcb-contributor-membership-checker.yml index 68219b034e4d..3f621bdf119e 100644 --- a/.ci/gcb-contributor-membership-checker.yml +++ b/.ci/gcb-contributor-membership-checker.yml @@ -69,6 +69,7 @@ steps: - $_PR_NUMBER - $COMMIT_SHA +logsBucket: 'gs://cloudbuild-membership-checker-logs' availableSecrets: secretManager: - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-magic-modules/versions/latest diff --git a/.ci/gcb-generate-diffs-new.yml b/.ci/gcb-generate-diffs-new.yml index 70e5f88d5a8b..400b796bdaa3 100644 --- a/.ci/gcb-generate-diffs-new.yml +++ b/.ci/gcb-generate-diffs-new.yml @@ -283,6 +283,7 @@ timeout: 20000s options: machineType: 'N1_HIGHCPU_32' +logsBucket: 'gs://cloudbuild-generate-diffs-logs' availableSecrets: secretManager: - versionName: projects/673497134629/secrets/github-magician-token-generate-diffs-downstreams/versions/latest From b38e6391e0261aa479b7f16fa23fad1c846b5db0 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Mon, 25 Mar 2024 16:15:53 +0100 Subject: [PATCH 191/200] Remove SarahFrench from vacation list (#10272) --- .ci/magician/github/membership.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.ci/magician/github/membership.go b/.ci/magician/github/membership.go index 112388d4a75a..908970d1b08f 100644 --- a/.ci/magician/github/membership.go +++ b/.ci/magician/github/membership.go @@ -46,9 +46,7 @@ var ( trustedContributors = []string{} // 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{ - "SarahFrench", - } + onVacationReviewers = []string{} ) type UserType int64 From 9aa4cbc7dfa2fe66f83b2a807d01e0eaddaeae7a Mon Sep 17 00:00:00 2001 From: Srevin Saju Date: Mon, 25 Mar 2024 21:22:25 +0530 Subject: [PATCH 192/200] ci: add missing pathspec dependency for yamllint pipeline (#10269) pipelines for YAML lints are failing due to: ``` Traceback (most recent call last): File "/home/runner/.local/bin/yamllint", line 5, in from yamllint.cli import run File "/home/runner/.local/lib/python3.10/site-packages/yamllint/cli.py", line 24, in from yamllint.config import YamlLintConfig, YamlLintConfigError File "/home/runner/.local/lib/python3.10/site-packages/yamllint/config.py", line 19, in import pathspec ModuleNotFoundError: No module named 'pathspec' ``` A fresh install in a virtual environment using the following command: ```bash $ pip install yamllint==1.32.0 pyyaml==6.0.1 $ pip freeze pathspec==0.12.1 PyYAML==6.0.1 yamllint==1.32.0 ``` Regression introduced by 60917c85e2f6645e21846fcf0197ff18244c747d --- .github/workflows/mmv1-lint-product-yaml.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/mmv1-lint-product-yaml.yml b/.github/workflows/mmv1-lint-product-yaml.yml index c4d91e19371e..41bdcfd65ace 100644 --- a/.github/workflows/mmv1-lint-product-yaml.yml +++ b/.github/workflows/mmv1-lint-product-yaml.yml @@ -30,7 +30,7 @@ jobs: fi - name: Install yamllint if: ${{ !failure() && steps.pull_request.outputs.yamlfiles != '' }} - run: pip install yamllint==1.32.0 pyyaml==6.0.1 --no-deps + run: pip install yamllint==1.32.0 pyyaml==6.0.1 pathspec==0.12.1 --no-deps - name: Lint YAML files if: ${{ !failure() && steps.pull_request.outputs.yamlfiles != '' }} run: yamllint -c repo/.yamllint ${{steps.pull_request.outputs.yamlfiles}} From 2dded45fb991e081bb4e22060382c4e6da22a594 Mon Sep 17 00:00:00 2001 From: Mauricio Alvarez Leon <65101411+BBBmau@users.noreply.github.com> Date: Mon, 25 Mar 2024 09:40:19 -0700 Subject: [PATCH 193/200] remove `pattern` field from `.yaml` files (#10227) * remove pattern field * fix lint yaml files --- mmv1/products/backupdr/ManagementServer.yaml | 1 - mmv1/products/certificatemanager/CertificateMap.yaml | 1 - mmv1/products/cloudfunctions/CloudFunction.yaml | 1 - mmv1/products/cloudfunctions2/Function.yaml | 1 - mmv1/products/cloudrunv2/Job.yaml | 1 - mmv1/products/cloudrunv2/Service.yaml | 1 - mmv1/products/cloudtasks/Queue.yaml | 1 - mmv1/products/datapipeline/Pipeline.yaml | 1 - mmv1/products/filestore/Backup.yaml | 1 - mmv1/products/filestore/Instance.yaml | 1 - mmv1/products/filestore/Snapshot.yaml | 1 - mmv1/products/firebaseappcheck/AppAttestConfig.yaml | 1 - mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml | 1 - mmv1/products/firebaseappcheck/ServiceConfig.yaml | 1 - mmv1/products/firebaseextensions/Instance.yaml | 4 ---- mmv1/products/firebasehosting/Channel.yaml | 1 - mmv1/products/firebasehosting/CustomDomain.yaml | 1 - mmv1/products/firebasestorage/Bucket.yaml | 1 - mmv1/products/memcache/Instance.yaml | 1 - mmv1/products/notebooks/Environment.yaml | 1 - mmv1/products/notebooks/Instance.yaml | 2 -- mmv1/products/notebooks/Runtime.yaml | 1 - mmv1/products/pubsub/Subscription.yaml | 2 -- mmv1/products/pubsub/Topic.yaml | 1 - mmv1/products/pubsub/go_Subscription.yaml | 2 -- mmv1/products/pubsub/go_Topic.yaml | 1 - mmv1/products/pubsublite/Subscription.yaml | 1 - mmv1/products/pubsublite/Topic.yaml | 1 - mmv1/products/runtimeconfig/Config.yaml | 1 - mmv1/products/sourcerepo/Repository.yaml | 1 - mmv1/products/vertexai/FeatureOnlineStore.yaml | 1 - mmv1/products/vertexai/Featurestore.yaml | 1 - mmv1/products/vertexai/FeaturestoreEntitytype.yaml | 1 - mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml | 1 - mmv1/products/vertexai/MetadataStore.yaml | 1 - mmv1/products/workbench/Instance.yaml | 2 -- 36 files changed, 43 deletions(-) diff --git a/mmv1/products/backupdr/ManagementServer.yaml b/mmv1/products/backupdr/ManagementServer.yaml index fc70378dae56..0b7329cea7f2 100644 --- a/mmv1/products/backupdr/ManagementServer.yaml +++ b/mmv1/products/backupdr/ManagementServer.yaml @@ -87,7 +87,6 @@ properties: description: | Network with format `projects/{{project_id}}/global/networks/{{network_id}}` required: true - pattern: projects/{{project}}/global/networks/{{network}} - !ruby/object:Api::Type::Enum name: 'peeringMode' description: | diff --git a/mmv1/products/certificatemanager/CertificateMap.yaml b/mmv1/products/certificatemanager/CertificateMap.yaml index 96df010f7666..b6c051317849 100644 --- a/mmv1/products/certificatemanager/CertificateMap.yaml +++ b/mmv1/products/certificatemanager/CertificateMap.yaml @@ -53,7 +53,6 @@ parameters: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/global/certificateMaps/{{name}} description: | A user-defined name of the Certificate Map. Certificate Map names must be unique globally and match the pattern `projects/*/locations/*/certificateMaps/*`. diff --git a/mmv1/products/cloudfunctions/CloudFunction.yaml b/mmv1/products/cloudfunctions/CloudFunction.yaml index 6ac2766e6ffe..03d28a182c84 100644 --- a/mmv1/products/cloudfunctions/CloudFunction.yaml +++ b/mmv1/products/cloudfunctions/CloudFunction.yaml @@ -77,7 +77,6 @@ properties: description: | A user-defined name of the function. Function names must be unique globally and match pattern `projects/*/locations/*/functions/*`. - pattern: projects/{{project}}/locations/{{location}}/functions/{{name}} - !ruby/object:Api::Type::String name: 'description' description: 'User-provided description of a function.' diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index 71fd0ef07e87..fda3a4ad014f 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -278,7 +278,6 @@ properties: description: | A user-defined name of the function. Function names must be unique globally and match pattern `projects/*/locations/*/functions/*`. - pattern: projects/{{project}}/locations/{{location}}/functions/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' custom_expand: 'templates/terraform/custom_expand/shortname_to_url.go.erb' - !ruby/object:Api::Type::String diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index 4daa40450fc6..d5f163f9483f 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -128,7 +128,6 @@ properties: url_param_only: true description: | Name of the Job. - pattern: projects/{{project}}/locations/{{location}}/jobs/{{name}} diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index 2568620c8fc7..b3d6477aedb8 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -139,7 +139,6 @@ properties: url_param_only: true description: | Name of the Service. - pattern: projects/{{project}}/locations/{{location}}/services/{{name}} diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb diff --git a/mmv1/products/cloudtasks/Queue.yaml b/mmv1/products/cloudtasks/Queue.yaml index a6b985f8db48..008f881cea49 100644 --- a/mmv1/products/cloudtasks/Queue.yaml +++ b/mmv1/products/cloudtasks/Queue.yaml @@ -57,7 +57,6 @@ properties: name: 'name' immutable: true description: The queue name. - pattern: projects/{{project}}/locations/{{location}}/queues/{{name}} custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb custom_expand: templates/terraform/custom_expand/qualify_queue_name.go.erb - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/datapipeline/Pipeline.yaml b/mmv1/products/datapipeline/Pipeline.yaml index 1bf821d94bff..c50ddd5c6382 100644 --- a/mmv1/products/datapipeline/Pipeline.yaml +++ b/mmv1/products/datapipeline/Pipeline.yaml @@ -51,7 +51,6 @@ properties: "PIPELINE_ID is the ID of the pipeline. Must be unique for the selected project and location." required: true immutable: true - pattern: projects/{{project}}/locations/{{region}}/functions/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' custom_expand: 'templates/terraform/custom_expand/shortname_to_url.go.erb' - !ruby/object:Api::Type::String diff --git a/mmv1/products/filestore/Backup.yaml b/mmv1/products/filestore/Backup.yaml index ae201770256e..828304be5c2f 100644 --- a/mmv1/products/filestore/Backup.yaml +++ b/mmv1/products/filestore/Backup.yaml @@ -57,7 +57,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/backups/{{backupId}} - !ruby/object:Api::Type::String name: 'description' description: | diff --git a/mmv1/products/filestore/Instance.yaml b/mmv1/products/filestore/Instance.yaml index bc8fd88cbd3f..fe5b9333000f 100644 --- a/mmv1/products/filestore/Instance.yaml +++ b/mmv1/products/filestore/Instance.yaml @@ -82,7 +82,6 @@ properties: The resource name of the instance. required: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/instances/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/products/filestore/Snapshot.yaml b/mmv1/products/filestore/Snapshot.yaml index 1ce5ea76bb50..944632d98583 100644 --- a/mmv1/products/filestore/Snapshot.yaml +++ b/mmv1/products/filestore/Snapshot.yaml @@ -70,7 +70,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/instances/{{instance}}/snapshots/{{name}} - !ruby/object:Api::Type::String name: 'description' description: | diff --git a/mmv1/products/firebaseappcheck/AppAttestConfig.yaml b/mmv1/products/firebaseappcheck/AppAttestConfig.yaml index 025e59fbcca9..9675f5c0bff1 100644 --- a/mmv1/products/firebaseappcheck/AppAttestConfig.yaml +++ b/mmv1/products/firebaseappcheck/AppAttestConfig.yaml @@ -78,7 +78,6 @@ properties: description: | The relative resource name of the App Attest configuration object output: true - pattern: projects/{{project}}/apps/{{app_id}}/appAttestConfig - !ruby/object:Api::Type::String name: tokenTtl description: | diff --git a/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml b/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml index 7631e64d1a4b..8794a0b0d3c8 100644 --- a/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml +++ b/mmv1/products/firebaseappcheck/PlayIntegrityConfig.yaml @@ -72,7 +72,6 @@ properties: description: | The relative resource name of the Play Integrity configuration object output: true - pattern: projects/{{project}}/apps/{{app_id}}/playIntegrityConfig - !ruby/object:Api::Type::String name: tokenTtl description: | diff --git a/mmv1/products/firebaseappcheck/ServiceConfig.yaml b/mmv1/products/firebaseappcheck/ServiceConfig.yaml index d016ba8d2609..2d673ca8d11c 100644 --- a/mmv1/products/firebaseappcheck/ServiceConfig.yaml +++ b/mmv1/products/firebaseappcheck/ServiceConfig.yaml @@ -81,7 +81,6 @@ properties: description: | The fully-qualified resource name of the service enforcement configuration. output: true - pattern: projects/{{project}}/services/{{service_id}} - !ruby/object:Api::Type::Enum name: enforcementMode description: | diff --git a/mmv1/products/firebaseextensions/Instance.yaml b/mmv1/products/firebaseextensions/Instance.yaml index 3e17c9fa1fd9..8950cb468ff4 100644 --- a/mmv1/products/firebaseextensions/Instance.yaml +++ b/mmv1/products/firebaseextensions/Instance.yaml @@ -78,7 +78,6 @@ properties: description: | The fully-qualified resource name of the Extension Instance. output: true - pattern: projects/{{project}}/instances/{{instance_id}} - !ruby/object:Api::Type::Time name: createTime description: The time at which the Extension Instance was created. @@ -104,7 +103,6 @@ properties: name: name description: The unique identifier for this configuration. output: true - pattern: projects/{{project}}/instances/{{instance_id}}/configs/{{config_id}} - !ruby/object:Api::Type::Time name: createTime description: The time at which the Extension Instance Config was created. @@ -143,7 +141,6 @@ properties: name: eventarcChannel description: | Fully qualified Eventarc resource name that consumers should use for event triggers. - pattern: projects/{{project}}/locations/{{location}}/channels/{{channel_id}} default_from_api: true - !ruby/object:Api::Type::String name: populatedPostinstallContent @@ -211,7 +208,6 @@ properties: description: | The name of the last operation that acted on this Extension Instance - pattern: projects/{{project}}/operations/{{operation_id}} - !ruby/object:Api::Type::String name: lastOperationType output: true diff --git a/mmv1/products/firebasehosting/Channel.yaml b/mmv1/products/firebasehosting/Channel.yaml index 5a1cc9648230..82295f516a56 100644 --- a/mmv1/products/firebasehosting/Channel.yaml +++ b/mmv1/products/firebasehosting/Channel.yaml @@ -65,7 +65,6 @@ parameters: properties: - !ruby/object:Api::Type::String name: name - pattern: sites/{{site_id}}/channels/{{channel_id}} description: | The fully-qualified resource name for the channel, in the format: sites/SITE_ID/channels/CHANNEL_ID diff --git a/mmv1/products/firebasehosting/CustomDomain.yaml b/mmv1/products/firebasehosting/CustomDomain.yaml index 104361a9c8e4..82e7a7575303 100644 --- a/mmv1/products/firebasehosting/CustomDomain.yaml +++ b/mmv1/products/firebasehosting/CustomDomain.yaml @@ -126,7 +126,6 @@ virtual_fields: properties: - !ruby/object:Api::Type::String name: name - pattern: projects/{{project}}/sites/{{site_id}}/customDomains/{{custom_domain}} description: | The fully-qualified name of the `CustomDomain`. output: true diff --git a/mmv1/products/firebasestorage/Bucket.yaml b/mmv1/products/firebasestorage/Bucket.yaml index 17fcd76af4ae..5ad4f967aa09 100644 --- a/mmv1/products/firebasestorage/Bucket.yaml +++ b/mmv1/products/firebasestorage/Bucket.yaml @@ -48,7 +48,6 @@ parameters: properties: - !ruby/object:Api::Type::String name: name - pattern: projects/{{project}}/buckets/{{bucket_id}} description: Resource name of the bucket in the format projects/PROJECT_IDENTIFIER/buckets/BUCKET_ID diff --git a/mmv1/products/memcache/Instance.yaml b/mmv1/products/memcache/Instance.yaml index 75fce1ee4293..fe277242b943 100644 --- a/mmv1/products/memcache/Instance.yaml +++ b/mmv1/products/memcache/Instance.yaml @@ -64,7 +64,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{region}}/instances/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' - !ruby/object:Api::Type::String name: 'displayName' diff --git a/mmv1/products/notebooks/Environment.yaml b/mmv1/products/notebooks/Environment.yaml index aca62cde53e1..bbafff8afe3d 100644 --- a/mmv1/products/notebooks/Environment.yaml +++ b/mmv1/products/notebooks/Environment.yaml @@ -38,7 +38,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/environments/{{name}} - !ruby/object:Api::Type::ResourceRef name: 'location' description: 'A reference to the zone where the machine resides.' diff --git a/mmv1/products/notebooks/Instance.yaml b/mmv1/products/notebooks/Instance.yaml index 613c50d70fab..7582475bbcc1 100644 --- a/mmv1/products/notebooks/Instance.yaml +++ b/mmv1/products/notebooks/Instance.yaml @@ -131,7 +131,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/instances/{{name}} custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' - !ruby/object:Api::Type::String name: 'machineType' @@ -143,7 +142,6 @@ properties: # TODO: Implement allow_stopping_for_update here and for acceleratorConfig # update_verb: :PATCH # update_url: 'projects/{{project}}/locations/{{location}}/instances/{{name}}:setMachineType' - 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::String diff --git a/mmv1/products/notebooks/Runtime.yaml b/mmv1/products/notebooks/Runtime.yaml index 1cadb0a2fa9d..df87dcf7169a 100644 --- a/mmv1/products/notebooks/Runtime.yaml +++ b/mmv1/products/notebooks/Runtime.yaml @@ -111,7 +111,6 @@ properties: required: true immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{location}}/runtimes/{{name}} - !ruby/object:Api::Type::NestedObject name: 'virtualMachine' exactly_one_of: diff --git a/mmv1/products/pubsub/Subscription.yaml b/mmv1/products/pubsub/Subscription.yaml index 80e33bb15edc..538c3212b9fa 100644 --- a/mmv1/products/pubsub/Subscription.yaml +++ b/mmv1/products/pubsub/Subscription.yaml @@ -92,7 +92,6 @@ properties: description: 'Name of the subscription.' required: true immutable: true - pattern: 'projects/{{project}}/subscriptions/{{name}}' custom_expand: templates/terraform/custom_expand/shortname_to_url.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::ResourceRef @@ -105,7 +104,6 @@ properties: the topic is in the same project as the subscription. required: true immutable: true - pattern: 'projects/{{project}}/topics/{{topic}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/computed_subscription_topic.erb - !ruby/object:Api::Type::KeyValueLabels diff --git a/mmv1/products/pubsub/Topic.yaml b/mmv1/products/pubsub/Topic.yaml index 275da6ceabca..5fff52cff69f 100644 --- a/mmv1/products/pubsub/Topic.yaml +++ b/mmv1/products/pubsub/Topic.yaml @@ -86,7 +86,6 @@ properties: required: true description: 'Name of the topic.' immutable: true - pattern: 'projects/{{project}}/topics/{{name}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/resource_from_self_link.go.erb custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb diff --git a/mmv1/products/pubsub/go_Subscription.yaml b/mmv1/products/pubsub/go_Subscription.yaml index ad7bd11d8ddd..a7d292465e54 100644 --- a/mmv1/products/pubsub/go_Subscription.yaml +++ b/mmv1/products/pubsub/go_Subscription.yaml @@ -97,7 +97,6 @@ properties: - name: 'name' type: String description: "Name of the subscription." - pattern: 'projects/{{project}}/subscriptions/{{name}}' required: true immutable: true custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' @@ -107,7 +106,6 @@ properties: description: "A reference to a Topic resource, of the form projects/{project}/topics/{{name}} (as in the id property of a google_pubsub_topic), or just a topic name if the topic is in the same project as the subscription." - pattern: 'projects/{{project}}/topics/{{topic}}' required: true immutable: true diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' diff --git a/mmv1/products/pubsub/go_Topic.yaml b/mmv1/products/pubsub/go_Topic.yaml index aec7c9790c33..2e4908dd8b54 100644 --- a/mmv1/products/pubsub/go_Topic.yaml +++ b/mmv1/products/pubsub/go_Topic.yaml @@ -79,7 +79,6 @@ properties: - name: 'name' type: String description: "Name of the topic." - pattern: 'projects/{{project}}/topics/{{name}}' required: true immutable: true diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' diff --git a/mmv1/products/pubsublite/Subscription.yaml b/mmv1/products/pubsublite/Subscription.yaml index d06980d55769..cdba3eedce81 100644 --- a/mmv1/products/pubsublite/Subscription.yaml +++ b/mmv1/products/pubsublite/Subscription.yaml @@ -62,7 +62,6 @@ properties: A reference to a Topic resource. required: true immutable: true - pattern: 'projects/{{project}}/locations/{{zone}}/topics/{{name}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/computed_lite_subscription_topic.erb - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/pubsublite/Topic.yaml b/mmv1/products/pubsublite/Topic.yaml index 50f68d7f83ec..3075cd5c92c6 100644 --- a/mmv1/products/pubsublite/Topic.yaml +++ b/mmv1/products/pubsublite/Topic.yaml @@ -112,6 +112,5 @@ properties: imports: 'name' description: | The Reservation to use for this topic's throughput capacity. - pattern: 'projects/{{project}}/locations/{{region}}/reservations/{{name}}' diff_suppress_func: 'tpgresource.CompareSelfLinkOrResourceName' custom_expand: templates/terraform/custom_expand/pubsublite_topic_reservation_config_throughput_reservation.go.erb diff --git a/mmv1/products/runtimeconfig/Config.yaml b/mmv1/products/runtimeconfig/Config.yaml index 8af2dff290f9..bd281ab85c89 100644 --- a/mmv1/products/runtimeconfig/Config.yaml +++ b/mmv1/products/runtimeconfig/Config.yaml @@ -42,7 +42,6 @@ parameters: The name of the runtime config. required: true immutable: true - pattern: projects/{{project}}/configs/{{name}} properties: - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/products/sourcerepo/Repository.yaml b/mmv1/products/sourcerepo/Repository.yaml index 1c17e3e20212..f0b38e288c0d 100644 --- a/mmv1/products/sourcerepo/Repository.yaml +++ b/mmv1/products/sourcerepo/Repository.yaml @@ -58,7 +58,6 @@ properties: description: | Resource name of the repository, of the form `{{repo}}`. The repo name may contain slashes. eg, `name/with/slash` - pattern: 'projects/{{project}}/repos/{{name}}' custom_expand: templates/terraform/custom_expand/shortname_to_url.go.erb custom_flatten: templates/terraform/custom_flatten/repository_short_name_from_name.go.erb - !ruby/object:Api::Type::String diff --git a/mmv1/products/vertexai/FeatureOnlineStore.yaml b/mmv1/products/vertexai/FeatureOnlineStore.yaml index 5880e31f4806..d74e81bcf129 100644 --- a/mmv1/products/vertexai/FeatureOnlineStore.yaml +++ b/mmv1/products/vertexai/FeatureOnlineStore.yaml @@ -88,7 +88,6 @@ properties: immutable: true required: true url_param_only: true - pattern: projects/{{project}}/locations/{{region}}/featureOnlineStores/{{name}} custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: createTime diff --git a/mmv1/products/vertexai/Featurestore.yaml b/mmv1/products/vertexai/Featurestore.yaml index 40bb998ec75f..daed16df66fc 100644 --- a/mmv1/products/vertexai/Featurestore.yaml +++ b/mmv1/products/vertexai/Featurestore.yaml @@ -128,7 +128,6 @@ properties: valid characters are [a-z0-9_]. The first character cannot be a number. immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{region}}/featurestores/{{name}} custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: 'etag' diff --git a/mmv1/products/vertexai/FeaturestoreEntitytype.yaml b/mmv1/products/vertexai/FeaturestoreEntitytype.yaml index 53fefc21ecfa..ab6dab427e70 100644 --- a/mmv1/products/vertexai/FeaturestoreEntitytype.yaml +++ b/mmv1/products/vertexai/FeaturestoreEntitytype.yaml @@ -112,7 +112,6 @@ properties: valid characters are [a-z0-9_]. The first character cannot be a number. immutable: true url_param_only: true - pattern: '{featurestore}}/entityTypes/{{name}}' custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml b/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml index b2379118329e..6c268cb8d8bb 100644 --- a/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml +++ b/mmv1/products/vertexai/FeaturestoreEntitytypeFeature.yaml @@ -88,7 +88,6 @@ properties: entity type. immutable: true url_param_only: true - pattern: '{{entitytype}}/features/{{name}}' custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: 'etag' diff --git a/mmv1/products/vertexai/MetadataStore.yaml b/mmv1/products/vertexai/MetadataStore.yaml index 8c441f1beecb..813fd2256b5a 100644 --- a/mmv1/products/vertexai/MetadataStore.yaml +++ b/mmv1/products/vertexai/MetadataStore.yaml @@ -67,7 +67,6 @@ properties: valid characters are [a-z0-9_]. The first character cannot be a number. immutable: true url_param_only: true - pattern: projects/{{project}}/locations/{{region}}/metadataStores/{{name}} custom_flatten: templates/terraform/custom_flatten/name_from_self_link.erb - !ruby/object:Api::Type::String name: 'description' diff --git a/mmv1/products/workbench/Instance.yaml b/mmv1/products/workbench/Instance.yaml index 7b3e0d2b47c0..0134ea3eb8eb 100644 --- a/mmv1/products/workbench/Instance.yaml +++ b/mmv1/products/workbench/Instance.yaml @@ -120,7 +120,6 @@ properties: 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 @@ -132,7 +131,6 @@ properties: 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 From 6f7d670e0f2e9da1ab3e562611c2a3ed25284ab3 Mon Sep 17 00:00:00 2001 From: Ilia Lazebnik Date: Mon, 25 Mar 2024 19:05:47 +0200 Subject: [PATCH 194/200] metastore - add support for scheduled backups (#10213) * add support for dataproc metastore scheduled backups * CR comments * CR comments * CR comments * CR comments * CR comments * Update mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb Co-authored-by: Zhenhua Li * Update mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb Co-authored-by: Zhenhua Li * CR comments --------- Co-authored-by: Zhenhua Li --- mmv1/products/metastore/Service.yaml | 29 +++++++++ ..._metastore_service_scheduled_backup.tf.erb | 31 +++++++++ ...rce_dataproc_metastore_service_test.go.erb | 64 +++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 mmv1/templates/terraform/examples/dataproc_metastore_service_scheduled_backup.tf.erb diff --git a/mmv1/products/metastore/Service.yaml b/mmv1/products/metastore/Service.yaml index 99fea8d11cbe..e85d012ae75b 100644 --- a/mmv1/products/metastore/Service.yaml +++ b/mmv1/products/metastore/Service.yaml @@ -138,6 +138,11 @@ examples: primary_resource_id: 'dpms2_scaling_factor_lt1' vars: metastore_service_name: 'ms-dpms2sflt1' + - !ruby/object:Provider::Terraform::Examples + name: 'dataproc_metastore_service_scheduled_backup' + primary_resource_id: 'backup' + vars: + metastore_service_name: 'backup' parameters: - !ruby/object:Api::Type::String name: 'serviceId' @@ -236,6 +241,30 @@ properties: description: | Scaling factor, in increments of 0.1 for values less than 1.0, and increments of 1.0 for values greater than 1.0. required: false + - !ruby/object:Api::Type::NestedObject + name: 'scheduledBackup' + description: | + The configuration of scheduled backup for the metastore service. + properties: + - !ruby/object:Api::Type::Boolean + name: 'enabled' + description: | + Defines whether the scheduled backup is enabled. The default value is false. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'cronSchedule' + description: | + The scheduled interval in Cron format, see https://en.wikipedia.org/wiki/Cron The default is empty: scheduled backup is not enabled. Must be specified to enable scheduled backups. + - !ruby/object:Api::Type::String + name: 'timeZone' + description: | + Specifies the time zone to be used when interpreting cronSchedule. Must be a time zone name from the time zone database (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones), e.g. America/Los_Angeles or Africa/Abidjan. If left unspecified, the default is UTC. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'backupLocation' + description: | + A Cloud Storage URI of a folder, in the format gs:///. A sub-folder containing backup files will be stored below it. + required: true - !ruby/object:Api::Type::NestedObject name: 'maintenanceWindow' description: | diff --git a/mmv1/templates/terraform/examples/dataproc_metastore_service_scheduled_backup.tf.erb b/mmv1/templates/terraform/examples/dataproc_metastore_service_scheduled_backup.tf.erb new file mode 100644 index 000000000000..fe4ada3fd0bc --- /dev/null +++ b/mmv1/templates/terraform/examples/dataproc_metastore_service_scheduled_backup.tf.erb @@ -0,0 +1,31 @@ +resource "google_dataproc_metastore_service" "<%= ctx[:primary_resource_id] %>" { + service_id = "<%= ctx[:vars]['metastore_service_name'] %>" + location = "us-central1" + port = 9080 + tier = "DEVELOPER" + + maintenance_window { + hour_of_day = 2 + day_of_week = "SUNDAY" + } + + hive_metastore_config { + version = "2.3.6" + } + + scheduled_backup { + enabled = true + cron_schedule = "0 0 * * *" + time_zone = "UTC" + backup_location = "gs://${google_storage_bucket.bucket.name}" + } + + labels = { + env = "test" + } +} + +resource "google_storage_bucket" "bucket" { + name = "<%= ctx[:vars]['metastore_service_name'] %>" + location = "us-central1" +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb b/mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb index 6e51622e1298..3d4460202d8c 100644 --- a/mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb +++ b/mmv1/third_party/terraform/services/dataprocmetastore/resource_dataproc_metastore_service_test.go.erb @@ -53,6 +53,34 @@ resource "google_dataproc_metastore_service" "my_metastore" { `, name, tier) } +func TestAccDataprocMetastoreService_dataprocMetastoreServiceScheduledBackupExampleUpdate(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: testAccCheckDataprocMetastoreServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataprocMetastoreService_dataprocMetastoreServiceScheduledBackupExample(context), + }, + { + ResourceName: "google_dataproc_metastore_service.backup", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"service_id", "location", "labels", "terraform_labels"}, + }, + { + Config: testAccDataprocMetastoreService_dataprocMetastoreServiceScheduledBackupExampleUpdate(context), + }, + }, + }) +} + func TestAccDataprocMetastoreService_PrivateServiceConnect(t *testing.T) { t.Skip("Skipping due to https://github.com/hashicorp/terraform-provider-google/issues/13710") t.Parallel() @@ -104,3 +132,39 @@ resource "google_dataproc_metastore_service" "default" { } `, context) } + +func testAccDataprocMetastoreService_dataprocMetastoreServiceScheduledBackupExampleUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_dataproc_metastore_service" "backup" { + service_id = "tf-test-backup%{random_suffix}" + location = "us-central1" + port = 9080 + tier = "DEVELOPER" + + maintenance_window { + hour_of_day = 2 + day_of_week = "SUNDAY" + } + + hive_metastore_config { + version = "2.3.6" + } + + scheduled_backup { + enabled = true + cron_schedule = "0 0 * * 0" + time_zone = "America/Los_Angeles" + backup_location = "gs://${google_storage_bucket.bucket.name}" + } + + labels = { + env = "test" + } +} + +resource "google_storage_bucket" "bucket" { + name = "tf-test-backup%{random_suffix}" + location = "us-central1" +} +`, context) +} \ No newline at end of file From bd8630001ab22816688040be47fc77facf554ca1 Mon Sep 17 00:00:00 2001 From: Sarah French <15078782+SarahFrench@users.noreply.github.com> Date: Mon, 25 Mar 2024 18:34:44 +0100 Subject: [PATCH 195/200] Update default TF version used in TeamCity to be `"1.8.0-rc1"` (#10276) * Update default TF version used in TeamCity to be 1.8.0-rc1 This will be updated to 1.8.0 after the GA release * Update pom.xml to pull in a hardcoded server-api dependency version : 2024.07-SNAPSHOT --- mmv1/third_party/terraform/.teamcity/components/constants.kt | 2 +- mmv1/third_party/terraform/.teamcity/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mmv1/third_party/terraform/.teamcity/components/constants.kt b/mmv1/third_party/terraform/.teamcity/components/constants.kt index ba1cd010f3ab..dd314e1f2cc9 100644 --- a/mmv1/third_party/terraform/.teamcity/components/constants.kt +++ b/mmv1/third_party/terraform/.teamcity/components/constants.kt @@ -16,7 +16,7 @@ const val DefaultStartHour = 4 const val DefaultParallelism = 6 // specifies the default version of Terraform Core which should be used for testing -const val DefaultTerraformCoreVersion = "1.2.5" +const val DefaultTerraformCoreVersion = "1.8.0-rc1" // TODO(SarahFrench) - update to 1.8.0 once it's gone GA // This represents a cron view of days of the week const val DefaultDaysOfWeek = "*" diff --git a/mmv1/third_party/terraform/.teamcity/pom.xml b/mmv1/third_party/terraform/.teamcity/pom.xml index bacb2965abc8..0a752451076c 100644 --- a/mmv1/third_party/terraform/.teamcity/pom.xml +++ b/mmv1/third_party/terraform/.teamcity/pom.xml @@ -136,7 +136,7 @@ org.jetbrains.teamcity server-api - ${teamcity.dsl.version} + 2024.07-SNAPSHOT test From 4abde8d7e72bb3aef0b8c40694ba6375b8cc629f Mon Sep 17 00:00:00 2001 From: Rohit Jangid Date: Tue, 26 Mar 2024 01:28:03 +0530 Subject: [PATCH 196/200] Add support to delete Client resource of Application Integration (#10280) --- mmv1/products/integrations/Client.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mmv1/products/integrations/Client.yaml b/mmv1/products/integrations/Client.yaml index b6f538e38d06..e9bb0e0d427d 100644 --- a/mmv1/products/integrations/Client.yaml +++ b/mmv1/products/integrations/Client.yaml @@ -24,8 +24,9 @@ base_url: 'projects/{{project}}/locations/{{location}}/clients' self_link: 'projects/{{project}}/locations/{{location}}/clients' immutable: true create_url: 'projects/{{project}}/locations/{{location}}/clients:provision' +delete_url: 'projects/{{project}}/locations/{{location}}/clients:deprovision' +delete_verb: :POST autogen_async: false -skip_delete: true import_format: [ 'projects/{{project}}/locations/{{location}}/clients', From 8a452f6ad41fb7d29c59d4516539589294d87e2f Mon Sep 17 00:00:00 2001 From: krishnangopal1810 <156300588+krishnangopal1810@users.noreply.github.com> Date: Tue, 26 Mar 2024 02:25:19 +0530 Subject: [PATCH 197/200] Add support for Application Data Source (#10154) Co-authored-by: Krishnan Gopal --- .../provider/provider_mmv1_resources.go.erb | 1 + .../apphub/data_source_apphub_application.go | 45 ++++++++++++ .../data_source_apphub_application_test.go | 70 +++++++++++++++++++ .../docs/d/apphub_application.html.markdown | 26 +++++++ 4 files changed, 142 insertions(+) create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_application.go create mode 100644 mmv1/third_party/terraform/services/apphub/data_source_apphub_application_test.go create mode 100644 mmv1/third_party/terraform/website/docs/d/apphub_application.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 40e1cabde402..7b9a37cebcf3 100644 --- a/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb +++ b/mmv1/third_party/terraform/provider/provider_mmv1_resources.go.erb @@ -29,6 +29,7 @@ var handwrittenDatasources = map[string]*schema.Resource{ "google_artifact_registry_repository": artifactregistry.DataSourceArtifactRegistryRepository(), "google_apphub_discovered_workload": apphub.DataSourceApphubDiscoveredWorkload(), "google_app_engine_default_service_account": appengine.DataSourceGoogleAppEngineDefaultServiceAccount(), + "google_apphub_application": apphub.DataSourceGoogleApphubApplication(), "google_apphub_discovered_service": apphub.DataSourceApphubDiscoveredService(), <% unless version == 'ga' -%> "google_backup_dr_management_server": backupdr.DataSourceGoogleCloudBackupDRService(), diff --git a/mmv1/third_party/terraform/services/apphub/data_source_apphub_application.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_application.go new file mode 100644 index 000000000000..7735cd81d41d --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_application.go @@ -0,0 +1,45 @@ +package apphub + +import ( + "fmt" + + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func DataSourceGoogleApphubApplication() *schema.Resource { + dsSchema := tpgresource.DatasourceSchemaFromResourceSchema(ResourceApphubApplication().Schema) + tpgresource.AddRequiredFieldsToSchema(dsSchema, "project") + tpgresource.AddRequiredFieldsToSchema(dsSchema, "application_id") + tpgresource.AddRequiredFieldsToSchema(dsSchema, "location") + + return &schema.Resource{ + Read: dataSourceGoogleApphubApplicationRead, + Schema: dsSchema, + } +} + +func dataSourceGoogleApphubApplicationRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*transport_tpg.Config) + + id, err := tpgresource.ReplaceVars(d, config, "projects/{{project}}/locations/{{location}}/applications/{{application_id}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + err = resourceApphubApplicationRead(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/apphub/data_source_apphub_application_test.go b/mmv1/third_party/terraform/services/apphub/data_source_apphub_application_test.go new file mode 100644 index 000000000000..a8c41f868b96 --- /dev/null +++ b/mmv1/third_party/terraform/services/apphub/data_source_apphub_application_test.go @@ -0,0 +1,70 @@ +package apphub_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestDataSourceApphubApplication_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: testAccCheckApphubApplicationDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testDataSourceApphubApplication_basic(context), + Check: resource.ComposeTestCheckFunc( + acctest.CheckDataSourceStateMatchesResourceState("data.google_apphub_application.example_data", "google_apphub_application.example"), + ), + }, + }, + }) +} + +func testDataSourceApphubApplication_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + +data "google_apphub_application" "example_data" { + project = google_apphub_application.example.project + application_id = google_apphub_application.example.application_id + location = google_apphub_application.example.location +} + +resource "google_apphub_application" "example" { + location = "us-central1" + application_id = "tf-test-example-application%{random_suffix}" + display_name = "Application Full New%{random_suffix}" + scope { + type = "REGIONAL" + } + attributes { + environment { + type = "STAGING" + } + criticality { + type = "MISSION_CRITICAL" + } + business_owners { + display_name = "Alice%{random_suffix}" + email = "alice@google.com%{random_suffix}" + } + developer_owners { + display_name = "Bob%{random_suffix}" + email = "bob@google.com%{random_suffix}" + } + operator_owners { + display_name = "Charlie%{random_suffix}" + email = "charlie@google.com%{random_suffix}" + } + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/website/docs/d/apphub_application.html.markdown b/mmv1/third_party/terraform/website/docs/d/apphub_application.html.markdown new file mode 100644 index 000000000000..3fd866b7f0c2 --- /dev/null +++ b/mmv1/third_party/terraform/website/docs/d/apphub_application.html.markdown @@ -0,0 +1,26 @@ +--- +subcategory: "App Hub" +description: |- + Application is a functional grouping of Services and Workloads that helps achieve a desired end-to-end business functionality. +--- + +# google\_apphub\_application + +Application is a functional grouping of Services and Workloads that helps achieve a desired end-to-end business functionality. Services and Workloads are owned by the Application. + + +## Example Usage + + +```hcl +data "google_apphub_application" "application" { + project = "project-id" + application_id = "application" + location = "location" +} +``` + +## Argument Reference + +See [google_resource_application](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/apphub_application#argument-reference) resource for details of the available attributes. + From 8410d877228030e7c97045bfe491c19c8b941a2b Mon Sep 17 00:00:00 2001 From: Kushagra Nigam Date: Mon, 25 Mar 2024 23:19:32 +0100 Subject: [PATCH 198/200] Fix test: TestAccContainer*_withInvalid* (#10277) * fix test TestAccContainerCluster_withInvalidAutoscalingProfile * fix test TestAccContainer*_withInvalid* --- .../services/container/resource_container_cluster_test.go.erb | 4 ++-- .../container/resource_container_node_pool_test.go.erb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 910fba9602b0..82074a6657cc 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 @@ -865,7 +865,7 @@ func TestAccContainerCluster_withInvalidReleaseChannel(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccContainerCluster_withReleaseChannelEnabled(clusterName, "CANARY", networkName, subnetworkName), - ExpectError: regexp.MustCompile(`expected release_channel\.0\.channel to be one of \[UNSPECIFIED RAPID REGULAR STABLE\], got CANARY`), + ExpectError: regexp.MustCompile(`expected release_channel\.0\.channel to be one of \["?UNSPECIFIED"? "?RAPID"? "?REGULAR"? "?STABLE"?\], got CANARY`), }, }, }) @@ -3355,7 +3355,7 @@ func TestAccContainerCluster_withInvalidAutoscalingProfile(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccContainerCluster_withAutoscalingProfile(clusterName, "AS_CHEAP_AS_POSSIBLE", networkName, subnetworkName), - ExpectError: regexp.MustCompile(`expected cluster_autoscaling\.0\.autoscaling_profile to be one of \[BALANCED OPTIMIZE_UTILIZATION\], got AS_CHEAP_AS_POSSIBLE`), + ExpectError: regexp.MustCompile(`expected cluster_autoscaling\.0\.autoscaling_profile to be one of \["?BALANCED"? "?OPTIMIZE_UTILIZATION"?\], got AS_CHEAP_AS_POSSIBLE`), }, }, }) 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 ac04e9501c21..bbe729bc766c 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 @@ -574,7 +574,7 @@ func TestAccContainerNodePool_withInvalidKubeletCpuManagerPolicy(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccContainerNodePool_withKubeletConfig(cluster, np, "dontexist", "100us", networkName, subnetworkName, true, 1024), - ExpectError: regexp.MustCompile(`.*to be one of \[static none \].*`), + ExpectError: regexp.MustCompile(`.*to be one of \["?static"? "?none"? "?"?\].*`), }, }, }) From f94fe593055da2139f372906aa54c5bcf07f9526 Mon Sep 17 00:00:00 2001 From: Zhenhua Li Date: Mon, 25 Mar 2024 16:34:06 -0700 Subject: [PATCH 199/200] Upgrade DCL to 1.64.0 (#10258) * Upgrade DCL to 1.64.0 * Fixed test randomness --- mmv1/third_party/terraform/go.mod.erb | 2 +- mmv1/third_party/terraform/go.sum | 4 ++-- ...esource_firebase_app_check_service_config_test.go.erb | 9 ++++++--- tpgtools/go.mod | 2 +- tpgtools/go.sum | 4 ++-- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/mmv1/third_party/terraform/go.mod.erb b/mmv1/third_party/terraform/go.mod.erb index 812e2da3e939..f6c84e1c5648 100644 --- a/mmv1/third_party/terraform/go.mod.erb +++ b/mmv1/third_party/terraform/go.mod.erb @@ -5,7 +5,7 @@ go 1.21 require ( cloud.google.com/go/bigtable v1.19.0 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.64.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 1cfc99eed33f..a34b9931b5c6 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -16,8 +16,8 @@ cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDn dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.64.0 h1:QA90iKudX8ijAW795f/jVbo0oEo7VoevwxLCNyi2qRc= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.64.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= diff --git a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb index 70a34c0c4b76..a4896985463e 100644 --- a/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb +++ b/mmv1/third_party/terraform/services/firebaseappcheck/resource_firebase_app_check_service_config_test.go.erb @@ -26,7 +26,6 @@ func TestAccFirebaseAppCheckServiceConfig_firebaseAppCheckServiceConfigUpdate(t ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), CheckDestroy: testAccCheckFirebaseAppCheckServiceConfigDestroyProducer(t), ExternalProviders: map[string]resource.ExternalProvider{ - "random": {}, "time": {}, }, Steps: []resource.TestStep{ @@ -86,6 +85,9 @@ resource "google_project_service" "database" { project = google_project.default.project_id service = "firebasedatabase.googleapis.com" disable_on_destroy = false + depends_on = [ + google_project_service.firebase, + ] } resource "google_project_service" "appcheck" { @@ -93,6 +95,9 @@ resource "google_project_service" "appcheck" { project = google_project.default.project_id service = "firebaseappcheck.googleapis.com" disable_on_destroy = false + depends_on = [ + google_project_service.database, + ] } resource "google_firebase_project" "default" { @@ -100,8 +105,6 @@ resource "google_firebase_project" "default" { project = google_project.default.project_id depends_on = [ - google_project_service.firebase, - google_project_service.database, google_project_service.appcheck, ] } diff --git a/tpgtools/go.mod b/tpgtools/go.mod index 370f45a397b2..62811783798b 100644 --- a/tpgtools/go.mod +++ b/tpgtools/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( bitbucket.org/creachadair/stringset v0.0.11 - github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 + github.com/GoogleCloudPlatform/declarative-resource-client-library v1.64.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 93cccba40a06..1f2bf8524869 100644 --- a/tpgtools/go.sum +++ b/tpgtools/go.sum @@ -6,8 +6,8 @@ cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdi cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0 h1:eSOBYPZVnU2fZul9sAJFGLVCgv6stNVKkmsogKF7UeY= -github.com/GoogleCloudPlatform/declarative-resource-client-library v1.63.0/go.mod h1:pL2Qt5HT+x6xrTd806oMiM3awW6kNIXB/iiuClz6m6k= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.64.0 h1:QA90iKudX8ijAW795f/jVbo0oEo7VoevwxLCNyi2qRc= +github.com/GoogleCloudPlatform/declarative-resource-client-library v1.64.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= From f073cd8fd59f8a16e357be3ea6fab0cc13b8d76f Mon Sep 17 00:00:00 2001 From: Sarah French Date: Tue, 26 Mar 2024 16:59:37 +0000 Subject: [PATCH 200/200] Run `go mod tidy` --- mmv1/third_party/terraform/go.sum | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 72e5bcae0171..1672ae714e55 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -196,7 +196,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI 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 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -293,8 +292,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -317,9 +314,6 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -331,7 +325,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ 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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -349,18 +342,12 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -368,9 +355,6 @@ 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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 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= @@ -384,7 +368,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn 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/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -429,7 +412,6 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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=