diff --git a/.ci/containers/bash-plus/Dockerfile b/.ci/containers/bash-plus/Dockerfile new file mode 100644 index 000000000000..1c370b3a4f57 --- /dev/null +++ b/.ci/containers/bash-plus/Dockerfile @@ -0,0 +1,5 @@ +FROM alpine/git + +RUN apk update && apk upgrade && \ + apk add --no-cache bash jq curl && \ + rm -rf /var/cache/apk/* diff --git a/.ci/containers/build-environment/Dockerfile b/.ci/containers/build-environment/Dockerfile new file mode 100644 index 000000000000..f30e774b9e36 --- /dev/null +++ b/.ci/containers/build-environment/Dockerfile @@ -0,0 +1,53 @@ +# Stage 1: Building Go dependencies +FROM golang:1.19-bullseye AS builder + +# Set working directory +WORKDIR /app + +# Download go.mod and go.sum from your repository +ADD "https://raw.githubusercontent.com/GoogleCloudPlatform/magic-modules/main/tpgtools/go.mod" go.mod +ADD "https://raw.githubusercontent.com/GoogleCloudPlatform/magic-modules/main/tpgtools/go.sum" go.sum + +# Install the go dependencies +RUN go mod download + +# Stage 2: Creating the final imag +FROM ruby:3.1-bullseye + +# golang +COPY --from=golang:1.19-bullseye /usr/local/go /usr/local/go +ENV GOPATH /go +ENV PATH /usr/local/go/bin:$PATH +ENV PATH $GOPATH/bin:$PATH +RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 1777 "$GOPATH" +WORKDIR $GOPATH + +# terraform binary used by tfv/tgc +COPY --from=hashicorp/terraform:1.4.2 /bin/terraform /bin/terraform + +SHELL ["/bin/bash", "-c"] + +ENV GO111MODULE "on" +ENV LC_ALL=C.UTF-8 +ENV LANG=C.UTF-8 + +RUN apt-get update && apt-get install -y --no-install-recommends git openssh-client apt-transport-https ca-certificates curl netbase wget gcc make jq libjq1 + +RUN git config --global user.name "Modular Magician" +RUN git config --global user.email "magic-modules@google.com" + +# Set up Github SSH cloning. +RUN ssh-keyscan github.com >> /known_hosts +RUN echo "UserKnownHostsFile /known_hosts" >> /etc/ssh/ssh_config + +RUN go install golang.org/x/tools/cmd/goimports@d088b475e3360caabc032aaee1dc66351d4e729a +RUN go install github.com/github/hub@v2.11.2+incompatible + +ADD "https://raw.githubusercontent.com/GoogleCloudPlatform/magic-modules/main/mmv1/Gemfile" Gemfile +ADD "https://raw.githubusercontent.com/GoogleCloudPlatform/magic-modules/main/mmv1/Gemfile.lock" Gemfile.lock +RUN bundle install +RUN rm Gemfile Gemfile.lock + +# Copy Go dependencies from builder stage +COPY --from=builder /go/pkg /go/pkg + diff --git a/.ci/containers/downstream-waiter/wait_for_commit.sh b/.ci/containers/downstream-waiter/wait_for_commit.sh index b59bde2a3698..f9e8315760cd 100755 --- a/.ci/containers/downstream-waiter/wait_for_commit.sh +++ b/.ci/containers/downstream-waiter/wait_for_commit.sh @@ -24,13 +24,21 @@ if git merge-base --is-ancestor $SHA origin/$SYNC_BRANCH; then fi while true; do - commits="$(git log --pretty=%H origin/$SYNC_BRANCH..origin/$BASE_BRANCH | tail -n 1)" - if [ "$commits" == "$SHA" ]; then - break - else - echo "git log says waiting on: $commits" - echo "command says waiting on $SHA" - git fetch origin $SYNC_BRANCH + if [ "$BASE_BRANCH" != "main" ]; then + SYNC_HEAD="$(git rev-parse --short origin/$SYNC_BRANCH)" + BASE_PARENT="$(git rev-parse --short origin/$BASE_BRANCH~)" + if [ "$SYNC_HEAD" == "$BASE_PARENT" ]; then + break; + fi + else + commits="$(git log --pretty=%H origin/$SYNC_BRANCH..origin/$BASE_BRANCH | tail -n 1)" + if [ "$commits" == "$SHA" ]; then + break + else + echo "git log says waiting on: $commits" + echo "command says waiting on $SHA" + git fetch origin $SYNC_BRANCH + fi fi sleep 5 done \ No newline at end of file diff --git a/.ci/containers/github-differ/Dockerfile b/.ci/containers/github-differ/Dockerfile deleted file mode 100644 index 9a93f71f3a55..000000000000 --- a/.ci/containers/github-differ/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -from golang:1.19-bullseye as resource -SHELL ["/bin/bash", "-c"] - -RUN apt-get update -RUN apt-get install -y curl jq -ADD generate_comment.sh /generate_comment.sh -ADD compare_breaking_changes.sh /compare_breaking_changes.sh -ADD test_tools.sh /test_tools.sh -ADD utils.sh /utils.sh -ENTRYPOINT ["/generate_comment.sh"] diff --git a/.ci/containers/go-plus/Dockerfile b/.ci/containers/go-plus/Dockerfile new file mode 100644 index 000000000000..6a6d48d9038f --- /dev/null +++ b/.ci/containers/go-plus/Dockerfile @@ -0,0 +1,32 @@ +from golang:1.19-bullseye as resource +SHELL ["/bin/bash", "-c"] +# Set up Github SSH cloning. +RUN ssh-keyscan github.com >> /known_hosts +RUN echo "UserKnownHostsFile /known_hosts" >> /etc/ssh/ssh_config + +RUN apt-get update && \ + apt-get install -y git jq unzip parallel curl && \ + echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ + curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && \ + apt-get update -y && \ + apt-get install google-cloud-sdk -y && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +RUN wget https://releases.hashicorp.com/terraform/1.2.5/terraform_1.2.5_linux_amd64.zip \ + && unzip terraform_1.2.5_linux_amd64.zip \ + && rm terraform_1.2.5_linux_amd64.zip \ + && mv ./terraform /bin/terraform + +### the following version of terraform are required for +### terraform-validator-tester-integration +RUN wget https://releases.hashicorp.com/terraform/0.13.7/terraform_0.13.7_linux_amd64.zip \ + && unzip terraform_0.13.7_linux_amd64.zip \ + && rm terraform_0.13.7_linux_amd64.zip \ + && mkdir /terraform \ + && mv terraform /terraform/0.13.7 + +RUN wget https://releases.hashicorp.com/terraform/0.12.31/terraform_0.12.31_linux_amd64.zip \ + && unzip terraform_0.12.31_linux_amd64.zip \ + && rm terraform_0.12.31_linux_amd64.zip \ + && mv terraform /terraform/0.12.31 \ No newline at end of file diff --git a/.ci/containers/membership-checker/membership.go b/.ci/containers/membership-checker/membership.go index 222e23b813e0..a3e728b14cf6 100644 --- a/.ci/containers/membership-checker/membership.go +++ b/.ci/containers/membership-checker/membership.go @@ -29,7 +29,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{"SarahFrench", "roaks3", "rileykarson"} ) // Check if a user is team member to not request a random reviewer diff --git a/.ci/containers/pre-build-validator/Dockerfile b/.ci/containers/pre-build-validator/Dockerfile deleted file mode 100644 index 9a806055d2c7..000000000000 --- a/.ci/containers/pre-build-validator/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -from golang:1.19-bullseye as resource -SHELL ["/bin/bash", "-c"] - -RUN apt-get update -RUN apt-get install -y git jq - -ADD validate.sh /validate.sh -ENTRYPOINT ["/validate.sh"] diff --git a/.ci/containers/terraform-tester/Dockerfile b/.ci/containers/terraform-tester/Dockerfile deleted file mode 100644 index 684c81f2659c..000000000000 --- a/.ci/containers/terraform-tester/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -from golang:1.19-bullseye as resource -SHELL ["/bin/bash", "-c"] - -RUN apt-get update -RUN apt-get install -y git jq - -ADD test_terraform.sh /test_terraform.sh -ENTRYPOINT ["/test_terraform.sh"] diff --git a/.ci/containers/terraform-triage-party/config.yaml b/.ci/containers/terraform-triage-party/config.yaml deleted file mode 100644 index e3134b42f330..000000000000 --- a/.ci/containers/terraform-triage-party/config.yaml +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright 2020 Google Inc. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -settings: - name: terraform - min_similarity: 0.65 - repos: - - https://github.com/terraform-providers/terraform-provider-google - -collections: - - id: untriaged - name: Untriaged - rules: - - untriaged - - missing-milestone - - missing-size - - id: priority - name: Priority - rules: - - p1 - - 30-reacts - - p2 - - 10-reacts - - id: blocked - name: Blocked - rules: - - upstream - - upstream-terraform - - waiting-response - - id: bugs - name: Bugs - rules: - - bug-unassigned - - bug-assigned - -rules: - # Untriaged - untriaged: - name: "Untriaged" - type: issue - filters: - - label: "!bug" - - label: "!upstream" - - label: "!upstream-terraform" - - label: "!waiting-response" - - label: "!question" - - label: "!size/.*" - - milestone: "^$" - missing-milestone: - name: "Missing Milestone" - type: issue - filters: - - label: "!bug" - - label: "!upstream" - - label: "!upstream-terraform" - - label: "!question" - - label: "size/.*" - - milestone: "^$" - missing-size: - name: "Missing Size" - type: issue - filters: - - label: "!bug" - - label: "!upstream" - - label: "!upstream-terraform" - - label: "!question" - - label: "!size/.*" - - milestone: "!^$" - - # Priority - p1: - name: "P1s" - type: issue - filters: - - label: "!bug" - - label: "!upstream" - - label: "!upstream-terraform" - - label: "priority/1" - 30-reacts: - name: "30+ reactions" - type: issue - filters: - - label: "!bug" - - label: "!upstream" - - label: "!upstream-terraform" - - reactions: ">=30" - p2: - name: "P2s" - type: issue - filters: - - label: "!bug" - - label: "!upstream" - - label: "!upstream-terraform" - - label: "priority/2" - - reactions: "<30" - 10-reacts: - name: "10+ reactions" - type: issue - filters: - - label: "!bug" - - label: "!upstream" - - label: "!upstream-terraform" - - reactions: ">=10" - - reactions: "<30" - - # Blocked - upstream: - name: "Blocked on GCP" - type: issue - filters: - - label: "upstream" - upstream-terraform: - name: "Blocked on Terraform" - type: issue - filters: - - label: "upstream-terraform" - waiting-response: - name: "Waiting for user response" - type: issue - filters: - - label: "waiting-response" - - # Bugs - bug-assigned: - name: "Assigned Bugs" - type: issue - filters: - - label: "bug" - - label: "!upstream" - - label: "!upstream-terraform" - - label: "!waiting-response" - - tag: "assigned" - bug-unassigned: - name: "Unassigned Bugs" - type: issue - filters: - - label: "bug" - - label: "!upstream" - - label: "!upstream-terraform" - - label: "!waiting-response" - - tag: "!assigned" diff --git a/.ci/containers/terraform-triage-party/deploy.sh b/.ci/containers/terraform-triage-party/deploy.sh deleted file mode 100755 index 614d0a7d4ca8..000000000000 --- a/.ci/containers/terraform-triage-party/deploy.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -# Copyright 2020 Google LLC -# -# 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. - -set -eu - -# Need to set GITHUB_TOKEN environment variable. Use one from the magician. -if [ -z "$GITHUB_TOKEN" ]; then - echo "Did not provide GITHUB_TOKEN environment variable." - exit 1 -fi - -set -x - -export PROJECT=terraform-triage -export IMAGE=gcr.io/terraform-triage/triage-party -export SERVICE_NAME=terraform-gcp-triage -export CONFIG_FILE=config.yaml -export TP_VERSION="v1.3.0" - -git clone --branch $TP_VERSION --depth 1 https://github.com/google/triage-party -cp $CONFIG_FILE triage-party/config/config.yaml - -docker build triage-party/ -t "${IMAGE}" - -rm -rf triage-party/ - -docker push "${IMAGE}" || exit 2 - -# TODO: add persistance to make it run faster: env vars PERSIST_BACKEND, PERSIST_PATH -gcloud beta run deploy "${SERVICE_NAME}" \ - --project "${PROJECT}" \ - --image "${IMAGE}" \ - --set-env-vars="GITHUB_TOKEN=${GITHUB_TOKEN}" \ - --allow-unauthenticated \ - --region us-central1 \ - --memory 384Mi \ - --platform managed diff --git a/.ci/containers/terraform-validator-tester-integration/Dockerfile b/.ci/containers/terraform-validator-tester-integration/Dockerfile deleted file mode 100644 index 8e385e7edecc..000000000000 --- a/.ci/containers/terraform-validator-tester-integration/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -from golang:1.19-bullseye as resource -SHELL ["/bin/bash", "-c"] -# Set up Github SSH cloning. -RUN ssh-keyscan github.com >> /known_hosts -RUN echo "UserKnownHostsFile /known_hosts" >> /etc/ssh/ssh_config - -RUN apt-get update -RUN apt-get install -y git jq unzip - -ADD test_terraform_validator_integration.sh /test_terraform_validator_integration.sh -ENTRYPOINT ["/test_terraform_validator_integration.sh"] - -RUN wget https://releases.hashicorp.com/terraform/0.13.7/terraform_0.13.7_linux_amd64.zip -RUN unzip terraform_0.13.7_linux_amd64.zip && rm terraform_0.13.7_linux_amd64.zip -RUN mkdir /terraform -RUN mv terraform /terraform/0.13.7 - -RUN wget https://releases.hashicorp.com/terraform/0.12.31/terraform_0.12.31_linux_amd64.zip -RUN unzip terraform_0.12.31_linux_amd64.zip && rm terraform_0.12.31_linux_amd64.zip -RUN mv terraform /terraform/0.12.31 \ No newline at end of file diff --git a/.ci/containers/terraform-validator-tester/Dockerfile b/.ci/containers/terraform-validator-tester/Dockerfile deleted file mode 100644 index 08f9bbba7d86..000000000000 --- a/.ci/containers/terraform-validator-tester/Dockerfile +++ /dev/null @@ -1,11 +0,0 @@ -from golang:1.19-bullseye as resource -SHELL ["/bin/bash", "-c"] -# Set up Github SSH cloning. -RUN ssh-keyscan github.com >> /known_hosts -RUN echo "UserKnownHostsFile /known_hosts" >> /etc/ssh/ssh_config - -RUN apt-get update -RUN apt-get install -y git jq - -ADD test_terraform_validator.sh /test_terraform_validator.sh -ENTRYPOINT ["/test_terraform_validator.sh"] \ No newline at end of file diff --git a/.ci/gcb-generate-diffs-new.yml b/.ci/gcb-generate-diffs-new.yml index b684c5e0a67c..a220bd33e3cd 100644 --- a/.ci/gcb-generate-diffs-new.yml +++ b/.ci/gcb-generate-diffs-new.yml @@ -64,17 +64,19 @@ steps: - --no-ff - head/$_HEAD_BRANCH - - name: 'gcr.io/graphite-docker-images/pre-build-validator' + - name: 'gcr.io/graphite-docker-images/bash-plus' id: pre-build-validate + entrypoint: '/workspace/.ci/scripts/bash-plus/pre-build-validator/validate.sh' secretEnv: ["GITHUB_TOKEN"] waitFor: ["merged"] env: - COMMIT_SHA=$COMMIT_SHA - PR_NUMBER=$_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/downstream-builder' - secretEnv: ["GITHUB_TOKEN"] + - name: 'gcr.io/graphite-docker-images/build-environment' + entrypoint: '/workspace/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh' id: tpg-head + secretEnv: ["GITHUB_TOKEN"] waitFor: ["merged"] env: - BASE_BRANCH=$_BASE_BRANCH @@ -84,7 +86,8 @@ steps: - 'ga' - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/downstream-builder' + - name: 'gcr.io/graphite-docker-images/build-environment' + entrypoint: '/workspace/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh' id: tpg-base secretEnv: ["GITHUB_TOKEN"] waitFor: ["merged"] @@ -96,7 +99,8 @@ steps: - 'ga' - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/downstream-builder' + - name: 'gcr.io/graphite-docker-images/build-environment' + entrypoint: '/workspace/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh' secretEnv: ["GITHUB_TOKEN"] id: tpgb-head waitFor: ["merged"] @@ -108,7 +112,8 @@ steps: - 'beta' - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/downstream-builder' + - name: 'gcr.io/graphite-docker-images/build-environment' + entrypoint: '/workspace/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh' id: tpgb-base secretEnv: ["GITHUB_TOKEN"] waitFor: ["merged"] @@ -120,10 +125,11 @@ steps: - 'beta' - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/downstream-builder' + - name: 'gcr.io/graphite-docker-images/build-environment' + entrypoint: '/workspace/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh' id: tgc-head secretEnv: ["GITHUB_TOKEN"] - waitFor: ["merged", "tpg-head"] + waitFor: ["merged"] env: - BASE_BRANCH=$_BASE_BRANCH args: @@ -132,10 +138,11 @@ steps: - 'beta' - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/downstream-builder' + - name: 'gcr.io/graphite-docker-images/build-environment' + entrypoint: '/workspace/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh' id: tgc-base secretEnv: ["GITHUB_TOKEN"] - waitFor: ["merged", "tpg-base"] + waitFor: ["merged"] env: - BASE_BRANCH=$_BASE_BRANCH args: @@ -144,7 +151,9 @@ steps: - 'beta' - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/downstream-builder' + - name: 'gcr.io/graphite-docker-images/build-environment' + entrypoint: '/workspace/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh' + id: tf-oics-head secretEnv: ["GITHUB_TOKEN"] waitFor: ["merged"] env: @@ -155,7 +164,9 @@ steps: - 'beta' - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/downstream-builder' + - name: 'gcr.io/graphite-docker-images/build-environment' + entrypoint: '/workspace/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh' + id: tf-oics-base secretEnv: ["GITHUB_TOKEN"] waitFor: ["merged"] env: @@ -166,23 +177,25 @@ steps: - 'beta' - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/github-differ' + - name: 'gcr.io/graphite-docker-images/go-plus' + entrypoint: '/workspace/.ci/scripts/go-plus/github-differ/generate_comment.sh' id: diff secretEnv: ["GITHUB_TOKEN"] env: - BUILD_ID=$BUILD_ID - PROJECT_ID=$PROJECT_ID - - BUILD_STEP="17" + - BUILD_STEP=17 - COMMIT_SHA=$COMMIT_SHA - PR_NUMBER=$_PR_NUMBER args: - $_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/terraform-validator-tester' + - name: 'gcr.io/graphite-docker-images/go-plus' + entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester/test_terraform_validator.sh' id: tgc-test allowFailure: true secretEnv: ["GITHUB_TOKEN"] - waitFor: ["tgc-head", "tgc-base"] + waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] env: - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT - TEST_FOLDER_ID=$_VALIDATOR_TEST_FOLDER @@ -196,11 +209,12 @@ steps: - "17" # Build step - terraform-google-conversion - - name: 'gcr.io/graphite-docker-images/terraform-validator-tester-integration' + - name: 'gcr.io/graphite-docker-images/go-plus' id: tgc-test-integration-0.12.31 + entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh' allowFailure: true secretEnv: ["GITHUB_TOKEN"] - waitFor: ["tgc-head", "tgc-base"] + waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] env: - TERRAFORM_VERSION=0.12.31 - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT @@ -215,11 +229,12 @@ steps: - "18" # Build step - terraform-google-conversion - - name: 'gcr.io/graphite-docker-images/terraform-validator-tester-integration' + - name: 'gcr.io/graphite-docker-images/go-plus' id: tgc-test-integration-0.13.7 + entrypoint: '/workspace/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh' allowFailure: true secretEnv: ["GITHUB_TOKEN"] - waitFor: ["tgc-head", "tgc-base"] + waitFor: ["tpgb-head", "tpgb-base", "tgc-head", "tgc-base"] env: - TERRAFORM_VERSION=0.13.7 - TEST_PROJECT=$_VALIDATOR_TEST_PROJECT @@ -234,25 +249,19 @@ steps: - "19" # Build step - terraform-google-conversion - - name: 'gcr.io/graphite-docker-images/terraform-tester' + - name: 'gcr.io/graphite-docker-images/bash-plus' id: tpgb-test + entrypoint: '/workspace/.ci/scripts/bash-plus/terraform-tester/test_terraform.sh' secretEnv: ["GITHUB_TOKEN"] waitFor: ["tpgb-head", "tpgb-base"] - args: - - 'beta' # remove after 07/2023 - - $_PR_NUMBER # remove after 07/2023 - - $COMMIT_SHA # remove after 07/2023 - - $BUILD_ID # remove after 07/2023 - - $PROJECT_ID # remove after 07/2023 - - GoogleCloudPlatform/magic-modules # remove after 07/2023 - - "20" # remove after 07/2023 env: - VERSION=beta - COMMIT_SHA=$COMMIT_SHA - PR_NUMBER=$_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/terraform-tester' + - name: 'gcr.io/graphite-docker-images/bash-plus' id: tpg-test + entrypoint: '/workspace/.ci/scripts/bash-plus/terraform-tester/test_terraform.sh' secretEnv: ["GITHUB_TOKEN"] waitFor: ["tpg-head", "tpg-base"] args: @@ -268,8 +277,9 @@ steps: - COMMIT_SHA=$COMMIT_SHA - PR_NUMBER=$_PR_NUMBER - - name: 'gcr.io/graphite-docker-images/gcb-terraform-vcr-tester' + - name: 'gcr.io/graphite-docker-images/go-plus' id: gcb-tpg-vcr-test + entrypoint: '/workspace/.ci/scripts/go-plus/gcb-terraform-vcr-tester/test_terraform_vcr.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"] waitFor: ["diff"] env: diff --git a/.ci/gcb-push-downstream.yml b/.ci/gcb-push-downstream.yml index 83a9849b095f..db3117cacd24 100644 --- a/.ci/gcb-push-downstream.yml +++ b/.ci/gcb-push-downstream.yml @@ -55,7 +55,7 @@ steps: - | if [ "$BRANCH_NAME" == "main" ]; then git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpg-sync - else + else git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpg-sync-$BRANCH_NAME fi @@ -90,7 +90,7 @@ steps: - | if [ "$BRANCH_NAME" == "main" ]; then git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpgb-sync - else + else git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tpgb-sync-$BRANCH_NAME fi @@ -107,7 +107,7 @@ steps: - name: 'gcr.io/graphite-docker-images/downstream-builder' secretEnv: ["GITHUB_TOKEN"] id: tgc-push - waitFor: ["tgc-sync", "tpg-push"] + waitFor: ["tgc-sync", "tpgb-push"] env: - BASE_BRANCH=$BRANCH_NAME args: @@ -125,7 +125,7 @@ steps: - | if [ "$BRANCH_NAME" == "main" ]; then git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tgc-sync - else + else git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tgc-sync-$BRANCH_NAME fi @@ -160,7 +160,7 @@ steps: - | if [ "$BRANCH_NAME" == "main" ]; then git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tf-oics-sync - else + else git push https://modular-magician:$$GITHUB_TOKEN@github.com/GoogleCloudPlatform/magic-modules $COMMIT_SHA:tf-oics-sync-$BRANCH_NAME fi diff --git a/.ci/infra/terraform/main.tf b/.ci/infra/terraform/main.tf index ded338e82a6c..fa6d3a584595 100644 --- a/.ci/infra/terraform/main.tf +++ b/.ci/infra/terraform/main.tf @@ -171,6 +171,7 @@ module "project-services" { "artifactregistry.googleapis.com", "assuredworkloads.googleapis.com", "autoscaling.googleapis.com", + "backupdr.googleapis.com", "beyondcorp.googleapis.com", "bigquery.googleapis.com", "bigqueryconnection.googleapis.com", @@ -204,6 +205,7 @@ module "project-services" { "containeranalysis.googleapis.com", "containerfilesystem.googleapis.com", "containerregistry.googleapis.com", + "contentwarehouse.googleapis.com", "daily-serviceconsumermanagement.sandbox.googleapis.com", "daily-serviceusage.sandbox.googleapis.com", "datacatalog.googleapis.com", diff --git a/.ci/scripts/bash-plus/downstream-waiter/wait_for_commit.sh b/.ci/scripts/bash-plus/downstream-waiter/wait_for_commit.sh new file mode 100755 index 000000000000..f9e8315760cd --- /dev/null +++ b/.ci/scripts/bash-plus/downstream-waiter/wait_for_commit.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +set -e +if [ $# -lt 3 ]; then + echo "Usage: $0 (sync-branch) (base-branch) (sha)" + exit 1 +fi + +SYNC_BRANCH_PREFIX=$1 +BASE_BRANCH=$2 +SHA=$3 + +if [ "$BASE_BRANCH" == "main" ]; then + SYNC_BRANCH=$SYNC_BRANCH_PREFIX +else + SYNC_BRANCH=$SYNC_BRANCH_PREFIX-$BASE_BRANCH +fi + +echo "SYNC_BRANCH: $SYNC_BRANCH" + +if git merge-base --is-ancestor $SHA origin/$SYNC_BRANCH; then + echo "Found $SHA in history of $SYNC_BRANCH - dying to avoid double-generating that commit." + exit 1 +fi + +while true; do + if [ "$BASE_BRANCH" != "main" ]; then + SYNC_HEAD="$(git rev-parse --short origin/$SYNC_BRANCH)" + BASE_PARENT="$(git rev-parse --short origin/$BASE_BRANCH~)" + if [ "$SYNC_HEAD" == "$BASE_PARENT" ]; then + break; + fi + else + commits="$(git log --pretty=%H origin/$SYNC_BRANCH..origin/$BASE_BRANCH | tail -n 1)" + if [ "$commits" == "$SHA" ]; then + break + else + echo "git log says waiting on: $commits" + echo "command says waiting on $SHA" + git fetch origin $SYNC_BRANCH + fi + fi + sleep 5 +done \ No newline at end of file diff --git a/.ci/containers/pre-build-validator/validate.sh b/.ci/scripts/bash-plus/pre-build-validator/validate.sh similarity index 100% rename from .ci/containers/pre-build-validator/validate.sh rename to .ci/scripts/bash-plus/pre-build-validator/validate.sh diff --git a/.ci/containers/terraform-tester/test_terraform.sh b/.ci/scripts/bash-plus/terraform-tester/test_terraform.sh similarity index 100% rename from .ci/containers/terraform-tester/test_terraform.sh rename to .ci/scripts/bash-plus/terraform-tester/test_terraform.sh diff --git a/.ci/scripts/bash-plus/vcr-cassette-merger/vcr_merge.sh b/.ci/scripts/bash-plus/vcr-cassette-merger/vcr_merge.sh new file mode 100755 index 000000000000..93d7be0a77a3 --- /dev/null +++ b/.ci/scripts/bash-plus/vcr-cassette-merger/vcr_merge.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -e + +REFERENCE=$1 + +# for backwards-compatibility +if [ -z "$BASE_BRANCH" ]; then + BASE_BRANCH=main +else + echo "BASE_BRANCH: $BASE_BRANCH" +fi + +PR_NUMBER=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \ + "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") + +set +e +gsutil ls gs://ci-vcr-cassettes/refs/heads/auto-pr-$PR_NUMBER/fixtures/ +if [ $? -eq 0 ]; then + # We have recorded new cassettes for this branch + if [ "$BASE_BRANCH" == "main" ]; then + gsutil -m cp gs://ci-vcr-cassettes/refs/heads/auto-pr-$PR_NUMBER/fixtures/* gs://ci-vcr-cassettes/fixtures/ + else + gsutil -m cp gs://ci-vcr-cassettes/refs/heads/auto-pr-$PR_NUMBER/fixtures/* gs://ci-vcr-cassettes/refs/branches/$BASE_BRANCH/fixtures/ + fi + gsutil -m rm -r gs://ci-vcr-cassettes/refs/heads/auto-pr-$PR_NUMBER/ +fi + +# Beta cassettes +gsutil ls gs://ci-vcr-cassettes/beta/refs/heads/auto-pr-$PR_NUMBER/fixtures/ +if [ $? -eq 0 ]; then + # We have recorded new cassettes for this branch + if [ "$BASE_BRANCH" == "main" ]; then + gsutil -m cp gs://ci-vcr-cassettes/beta/refs/heads/auto-pr-$PR_NUMBER/fixtures/* gs://ci-vcr-cassettes/beta/fixtures/ + else + gsutil -m cp gs://ci-vcr-cassettes/beta/refs/heads/auto-pr-$PR_NUMBER/fixtures/* gs://ci-vcr-cassettes/beta/refs/branches/$BASE_BRANCH/fixtures/ + fi + gsutil -m rm -r gs://ci-vcr-cassettes/beta/refs/heads/auto-pr-$PR_NUMBER/ +fi + + +set -e \ No newline at end of file diff --git a/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh b/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh new file mode 100755 index 000000000000..f1e054aa2558 --- /dev/null +++ b/.ci/scripts/build-environment/downstream-builder/generate_downstream.sh @@ -0,0 +1,216 @@ +#! /bin/bash + +set -e + +function clone_repo() { + SCRATCH_OWNER=modular-magician + UPSTREAM_BRANCH=$BASE_BRANCH + if [ "$REPO" == "terraform" ]; then + if [ "$VERSION" == "ga" ]; then + UPSTREAM_OWNER=hashicorp + GH_REPO=terraform-provider-google + LOCAL_PATH=$GOPATH/src/github.com/hashicorp/terraform-provider-google + elif [ "$VERSION" == "beta" ]; then + UPSTREAM_OWNER=hashicorp + GH_REPO=terraform-provider-google-beta + LOCAL_PATH=$GOPATH/src/github.com/hashicorp/terraform-provider-google-beta + else + echo "Unrecognized version $VERSION" + exit 1 + fi + elif [ "$REPO" == "tf-conversion" ]; then + # This is here for backwards compatibility and can be removed after Nov 15 2021 + UPSTREAM_OWNER=GoogleCloudPlatform + GH_REPO=terraform-google-conversion + LOCAL_PATH=$GOPATH/src/github.com/GoogleCloudPlatform/terraform-google-conversion + elif [ "$REPO" == "terraform-google-conversion" ]; then + UPSTREAM_OWNER=GoogleCloudPlatform + GH_REPO=terraform-google-conversion + LOCAL_PATH=$GOPATH/src/github.com/GoogleCloudPlatform/terraform-google-conversion + elif [ "$REPO" == "tf-oics" ]; then + if [ "$UPSTREAM_BRANCH" == "main" ]; then + UPSTREAM_BRANCH=master + fi + UPSTREAM_OWNER=terraform-google-modules + GH_REPO=docs-examples + LOCAL_PATH=$GOPATH/src/github.com/terraform-google-modules/docs-examples + elif [ "$REPO" == "tf-cloud-docs" ]; then + # backwards-compatability + echo "$REPO is no longer available." + exit 0 + else + echo "Unrecognized repo $REPO" + exit 1 + fi + + GITHUB_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/$UPSTREAM_OWNER/$GH_REPO + SCRATCH_PATH=https://modular-magician:$GITHUB_TOKEN@github.com/$SCRATCH_OWNER/$GH_REPO + mkdir -p "$(dirname $LOCAL_PATH)" + + echo "BASE_BRANCH: $BASE_BRANCH" + git clone $GITHUB_PATH $LOCAL_PATH --branch $UPSTREAM_BRANCH +} + +if [ $# -lt 4 ]; then + echo "Usage: $0 (build|diff|downstream) (terraform) (ga|beta) (pr number|sha)" + exit 1 +fi +if [ -z "$GITHUB_TOKEN" ]; then + echo "Did not provide GITHUB_TOKEN environment variable." + exit 1 +fi + + +COMMAND=$1 +REPO=$2 +VERSION=$3 +REFERENCE=$4 + +mkdir ../mm-$REPO-$VERSION-$COMMAND +cp -rp ./. ../mm-$REPO-$VERSION-$COMMAND +pushd ../mm-$REPO-$VERSION-$COMMAND + +# for backwards-compatibility +if [ -z "$BASE_BRANCH" ]; then + BASE_BRANCH=main +fi + + +clone_repo + +git config --local user.name "Modular Magician" +git config --local user.email "magic-modules@google.com" + +# MMv1 now lives inside a sub-folder +pushd mmv1 + +if [ "$COMMAND" == "head" ]; then + BRANCH=auto-pr-$REFERENCE + COMMIT_MESSAGE="New generated code for MM PR $REFERENCE." +elif [ "$COMMAND" == "base" ]; then + # In this case, there is guaranteed to be a merge commit, + # and the *left* side of it is the old main branch. + # the *right* side of it is the code to be merged. + git checkout HEAD~ + BRANCH=auto-pr-$REFERENCE-old + COMMIT_MESSAGE="Old generated code for MM PR $REFERENCE." +elif [ "$COMMAND" == "downstream" ]; then + BRANCH=downstream-pr-$REFERENCE + COMMIT_MESSAGE="$(git log -1 --pretty=%B "$REFERENCE")" +fi + +if [ "$REPO" == "terraform" ]; then + pushd $LOCAL_PATH + go mod download + find . -type f -not -wholename "./.git*" -not -wholename "./.changelog*" -not -name ".travis.yml" -not -name ".golangci.yml" -not -name "CHANGELOG.md" -not -name "GNUmakefile" -not -name "docscheck.sh" -not -name "LICENSE" -not -name "README.md" -not -wholename "./examples*" -not -name ".go-version" -not -name ".hashibot.hcl" -print0 | xargs -0 git rm + popd +fi + +if [ "$REPO" == "terraform-google-conversion" ]; then + pushd $LOCAL_PATH + # clear out the templates as they are copied during + # generation from mmv1/third_party/validator/tests/data + rm -rf ./tfplan2cai/testdata/templates/ + rm -rf ./tfplan2cai/testdata/generatedconvert/ + rm -rf ./tfplan2cai/converters/google/provider + rm -rf ./tfplan2cai/converters/google/resources + find ./tfplan2cai/test/** -type f -exec git rm {} \; + popd + + bundle exec compiler.rb -a -e terraform -f validator -o $LOCAL_PATH/tfplan2cai -v $VERSION + + if [ "$COMMAND" == "downstream" ]; then + pushd $LOCAL_PATH + go get -d github.com/hashicorp/terraform-provider-google-beta@$BASE_BRANCH + go mod tidy + set +e + make build + set -e + popd + fi +elif [ "$REPO" == "tf-oics" ]; then + # use terraform generator with oics override + bundle exec compiler.rb -a -e terraform -f oics -o $LOCAL_PATH -v $VERSION +else + if [ "$REPO" == "terraform" ]; then + if [ "$VERSION" == "ga" ]; then + bundle exec compiler.rb -a -e $REPO -o $LOCAL_PATH -v $VERSION --no-docs + bundle exec compiler.rb -a -e $REPO -o $LOCAL_PATH -v beta --no-code + else + bundle exec compiler.rb -a -e $REPO -o $LOCAL_PATH -v $VERSION + fi + pushd ../ + make tpgtools OUTPUT_PATH=$LOCAL_PATH VERSION=$VERSION + + # Only generate TeamCity-related file for TPG and TPGB + if [ "$VERSION" == "ga" ] || [ "$VERSION" == "beta" ]; then + make teamcity-servicemap-generate OUTPUT_PATH=$LOCAL_PATH VERSION=$VERSION + fi + popd + fi +fi + +popd + +pushd $LOCAL_PATH + +git config --local user.name "Modular Magician" +git config --local user.email "magic-modules@google.com" +git add . +git checkout -b $BRANCH + +COMMITTED=true +git commit --signoff -m "$COMMIT_MESSAGE" || COMMITTED=false + +CHANGELOG=false +if [ "$REPO" == "terraform" ]; then + CHANGELOG=true +fi + +PR_NUMBER=$(curl -L -s -H "Authorization: token ${GITHUB_TOKEN}" \ + "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") +if [ "$COMMITTED" == "true" ] && [ "$COMMAND" == "downstream" ] && [ "$CHANGELOG" == "true" ]; then + # Add the changelog entry! + mkdir -p .changelog/ + curl -L -s -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/$PR_NUMBER" | \ + jq -r .body | \ + sed -e '/```release-note/,/```/!d' \ + > .changelog/$PR_NUMBER.txt + git add .changelog + git commit --signoff --amend --no-edit +fi + +git push $SCRATCH_PATH $BRANCH -f + +if [ "$COMMITTED" == "true" ] && [ "$COMMAND" == "downstream" ]; then + PR_BODY=$(curl -L -s -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/$PR_NUMBER" | \ + jq -r .body) + PR_TITLE=$(curl -L -s -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/$PR_NUMBER" | \ + jq -r .title) + MM_PR_URL=$(curl -L -s -H "Authorization: token ${GITHUB_TOKEN}" \ + "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/pulls/$PR_NUMBER" | \ + jq -r .html_url) + + echo "Base: $UPSTREAM_OWNER:$UPSTREAM_BRANCH" + echo "Head: $SCRATCH_OWNER:$BRANCH" + NEW_PR_URL=$(hub pull-request -b $UPSTREAM_OWNER:$UPSTREAM_BRANCH -h $SCRATCH_OWNER:$BRANCH -m "$PR_TITLE" -m "$PR_BODY" -m "Derived from $MM_PR_URL") + if [ $? != 0 ]; then + exit $? + fi + echo "Created PR $NEW_PR_URL" + NEW_PR_NUMBER=$(echo $NEW_PR_URL | awk -F '/' '{print $NF}') + + # Wait a few seconds, then merge the PR. + sleep 5 + echo "Merging PR $NEW_PR_URL" + curl -L -H "Authorization: token ${GITHUB_TOKEN}" \ + -X PUT \ + -d '{"merge_method": "squash"}' \ + "https://api.github.com/repos/$UPSTREAM_OWNER/$GH_REPO/pulls/$NEW_PR_NUMBER/merge" +fi + +popd diff --git a/.ci/scripts/go-plus/gcb-terraform-vcr-tester/test_terraform_vcr.sh b/.ci/scripts/go-plus/gcb-terraform-vcr-tester/test_terraform_vcr.sh new file mode 100755 index 000000000000..0e0e5f0781da --- /dev/null +++ b/.ci/scripts/go-plus/gcb-terraform-vcr-tester/test_terraform_vcr.sh @@ -0,0 +1,322 @@ +#!/bin/bash + +set -e +pr_number=$1 +mm_commit_sha=$2 +build_id=$3 +project_id=$4 +build_step=$5 +echo "PR number: ${pr_number}" +echo "Commit SHA: ${mm_commit_sha}" +github_username=modular-magician +gh_repo=terraform-provider-google-beta +NEWLINE=$'\n' + +new_branch="auto-pr-$pr_number" +git_remote=https://github.com/$github_username/$gh_repo +local_path=$GOPATH/src/github.com/hashicorp/$gh_repo +mkdir -p "$(dirname $local_path)" +git clone $git_remote $local_path --branch $new_branch --depth 2 +pushd $local_path + +# Only skip tests if we can tell for sure that no go files were changed +echo "Checking for modified go files" +# get the names of changed files and look for go files +# (ignoring "no matches found" errors from grep) +gofiles=$(git diff --name-only HEAD~1 | { grep -e "\.go$" -e "go.mod$" -e "go.sum$" || test $? = 1; }) +if [[ -z $gofiles ]]; then + echo "Skipping tests: No go files changed" + exit 0 +else + echo "Running tests: Go files changed" +fi + +function add_comment { + curl -H "Authorization: token ${GITHUB_TOKEN}" \ + -d "$(jq -r --arg comment "${1}" -n "{body: \$comment}")" \ + "https://api.github.com/repos/GoogleCloudPlatform/magic-modules/issues/${pr_number}/comments" +} + +function update_status { + post_body=$( jq -n \ + --arg context "VCR-test" \ + --arg target_url "https://console.cloud.google.com/cloud-build/builds;region=global/${build_id};step=${build_step}?project=${project_id}" \ + --arg state "${1}" \ + '{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" +} + +update_status "pending" + +# for backwards-compatibility +if [ -z "$BASE_BRANCH" ]; then + BASE_BRANCH=main +else + echo "BASE_BRANCH: $BASE_BRANCH" +fi + +set +e +# cassette retrieval +mkdir fixtures +if [ "$BASE_BRANCH" != "FEATURE-BRANCH-major-release-5.0.0" ]; then + # pull main cassettes (major release uses branch specific casssettes as primary ones) + gsutil -m -q cp gs://ci-vcr-cassettes/beta/fixtures/* fixtures/ +fi +if [ "$BASE_BRANCH" != "main" ]; then + # copy feature branch specific cassettes over main. This might fail but that's ok if the folder doesnt exist + gsutil -m -q cp gs://ci-vcr-cassettes/beta/refs/branches/$BASE_BRANCH/fixtures/* fixtures/ +fi +# copy PR branch specific cassettes over main. This might fail but that's ok if the folder doesnt exist +gsutil -m -q cp gs://ci-vcr-cassettes/beta/refs/heads/auto-pr-$pr_number/fixtures/* fixtures/ + +echo $SA_KEY > sa_key.json +gcloud auth activate-service-account $GOOGLE_SERVICE_ACCOUNT --key-file=$local_path/sa_key.json --project=$GOOGLE_PROJECT + +mkdir testlog +mkdir testlog/replaying +mkdir testlog/recording +mkdir testlog/recording_build +mkdir testlog/replaying_after_recording +mkdir testlog/replaying_build_after_recording + +export GOOGLE_REGION=us-central1 +export GOOGLE_ZONE=us-central1-a +export VCR_PATH=$local_path/fixtures +export VCR_MODE=REPLAYING +export ACCTEST_PARALLELISM=32 +export GOOGLE_CREDENTIALS=$SA_KEY +export GOOGLE_APPLICATION_CREDENTIALS=$local_path/sa_key.json +export GOOGLE_TEST_DIRECTORY=$(go list ./... | grep -v github.com/hashicorp/terraform-provider-google-beta/scripts) + +echo "checking terraform version" +terraform version + + +TF_LOG=DEBUG TF_LOG_PATH_MASK=$local_path/testlog/replaying/%s.log TF_ACC=1 TF_SCHEMA_PANIC_ON_ERROR=1 go test $GOOGLE_TEST_DIRECTORY -parallel $ACCTEST_PARALLELISM -v -run=TestAcc -timeout 240m -ldflags="-X=github.com/hashicorp/terraform-provider-google-beta/version.ProviderVersion=acc" > replaying_test.log + +test_exit_code=$? + +TESTS_TERMINATED=$(grep "^cannot run Terraform provider tests" replaying_test.log) + +counter=1 +test_suffix="" + +while [[ -n $TESTS_TERMINATED ]]; do + # store the previous replaying build log + gsutil -h "Content-Type:text/plain" -q cp replaying_test$test_suffix.log gs://ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/ + + if [[ $counter -gt 3 ]]; then + comment="$\textcolor{red}{\textsf{Failed to run VCR tests in REPLAYING mode}}$ ${NEWLINE}" + comment+="View the [build log](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/replaying_test$test_suffix.log)${NEWLINE}" + comment+="If you believe the error is unrelated to your PR, please rerun the tests" + add_comment "${comment}" + update_status "failure" + exit 0 + fi + + comment="Rerun tests in REPLAYING mode" + add_comment "${comment}" + + test_suffix="$counter" + + # rerun the test + TF_LOG=DEBUG TF_LOG_PATH_MASK=$local_path/testlog/replaying/%s.log TF_ACC=1 TF_SCHEMA_PANIC_ON_ERROR=1 go test $GOOGLE_TEST_DIRECTORY -parallel $ACCTEST_PARALLELISM -v -run=TestAcc -timeout 240m -ldflags="-X=github.com/hashicorp/terraform-provider-google-beta/version.ProviderVersion=acc" > replaying_test$test_suffix.log + test_exit_code=$? + TESTS_TERMINATED=$(grep "^cannot run Terraform provider tests" replaying_test$test_suffix.log) + counter=$((counter + 1)) +done + +# store replaying build log +gsutil -h "Content-Type:text/plain" -q cp replaying_test$test_suffix.log gs://ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/ + +# store replaying test logs +gsutil -h "Content-Type:text/plain" -m -q cp testlog/replaying/* gs://ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/replaying/ + +# handle provider crash +TESTS_PANIC=$(grep "^panic: " replaying_test$test_suffix.log) + +if [[ -n $TESTS_PANIC ]]; then + comment="$\textcolor{red}{\textsf{The provider crashed while running the VCR tests in REPLAYING mode}}$ ${NEWLINE}" + comment+="$\textcolor{red}{\textsf{Please fix it to complete your PR}}$ ${NEWLINE}" + comment+="View the [build log](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/replaying_test$test_suffix.log)" + add_comment "${comment}" + update_status "failure" + exit 0 +fi + +FAILED_TESTS=$(grep "^--- FAIL: TestAcc" replaying_test$test_suffix.log) +PASSED_TESTS=$(grep "^--- PASS: TestAcc" replaying_test$test_suffix.log) +SKIPPED_TESTS=$(grep "^--- SKIP: TestAcc" replaying_test$test_suffix.log) + +if [[ -n $FAILED_TESTS ]]; then + FAILED_TESTS_COUNT=$(echo "$FAILED_TESTS" | wc -l) +else + FAILED_TESTS_COUNT=0 +fi + +if [[ -n $PASSED_TESTS ]]; then + PASSED_TESTS_COUNT=$(echo "$PASSED_TESTS" | wc -l) +else + PASSED_TESTS_COUNT=0 +fi + +if [[ -n $SKIPPED_TESTS ]]; then + SKIPPED_TESTS_COUNT=$(echo "$SKIPPED_TESTS" | wc -l) +else + SKIPPED_TESTS_COUNT=0 +fi + +FAILED_TESTS_PATTERN=$(grep "^--- FAIL: TestAcc" replaying_test$test_suffix.log | awk '{print $3}' | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + +comment="#### Tests analytics ${NEWLINE}" +comment+="Total tests: \`$(($FAILED_TESTS_COUNT+$PASSED_TESTS_COUNT+$SKIPPED_TESTS_COUNT))\` ${NEWLINE}" +comment+="Passed tests \`$PASSED_TESTS_COUNT\` ${NEWLINE}" +comment+="Skipped tests: \`$SKIPPED_TESTS_COUNT\` ${NEWLINE}" +comment+="Affected tests: \`$FAILED_TESTS_COUNT\` ${NEWLINE}${NEWLINE}" + +if [[ -n $FAILED_TESTS_PATTERN ]]; then + comment+="#### Action taken ${NEWLINE}" + comment+="
Found $FAILED_TESTS_COUNT affected test(s) by replaying old test recordings. Starting RECORDING based on the most recent commit. Click here to see the affected tests
$FAILED_TESTS_PATTERN
${NEWLINE}${NEWLINE}" + comment+="[Get to know how VCR tests work](https://googlecloudplatform.github.io/magic-modules/docs/getting-started/contributing/#general-contributing-steps)" + add_comment "${comment}" + # Clear fixtures folder + rm $VCR_PATH/* + + # Clear replaying-log folder + rm testlog/replaying/* + + # RECORDING mode + export VCR_MODE=RECORDING + FAILED_TESTS=$(grep "^--- FAIL: TestAcc" replaying_test$test_suffix.log | awk '{print $3}') + # test_exit_code=0 + parallel --jobs 16 TF_LOG=DEBUG TF_LOG_PATH_MASK=$local_path/testlog/recording/%s.log TF_ACC=1 TF_SCHEMA_PANIC_ON_ERROR=1 go test {1} -parallel 1 -v -run="{2}$" -timeout 240m -ldflags="-X=github.com/hashicorp/terraform-provider-google-beta/version.ProviderVersion=acc" ">>" testlog/recording_build/{2}_recording_test.log ::: $GOOGLE_TEST_DIRECTORY ::: $FAILED_TESTS + + test_exit_code=$? + + # Concatenate recording build logs to one file + # Note: build logs are different from debug logs + for failed_test in $FAILED_TESTS + do + cat testlog/recording_build/${failed_test}_recording_test.log >> recording_test.log + done + + # store cassettes + gsutil -m -q cp fixtures/* gs://ci-vcr-cassettes/beta/refs/heads/auto-pr-$pr_number/fixtures/ + + # store recording build log + gsutil -h "Content-Type:text/plain" -q cp recording_test.log gs://ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/ + + # store recording individual build logs + gsutil -h "Content-Type:text/plain" -m -q cp testlog/recording_build/* gs://ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/recording_build/ + + # store recording test logs + gsutil -h "Content-Type:text/plain" -m -q cp testlog/recording/* gs://ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/recording/ + + # handle provider crash + RECORDING_TESTS_PANIC=$(grep "^panic: " recording_test.log) + + if [[ -n $RECORDING_TESTS_PANIC ]]; then + + comment="$\textcolor{red}{\textsf{The provider crashed while running the VCR tests in RECORDING mode}}$ ${NEWLINE}" + comment+="$\textcolor{red}{\textsf{Please fix it to complete your PR}}$ ${NEWLINE}" + comment+="View the [build log](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/recording_test.log)" + add_comment "${comment}" + update_status "failure" + exit 0 + fi + + + RECORDING_FAILED_TESTS=$(grep "^--- FAIL: TestAcc" recording_test.log | awk -v pr_number=$pr_number -v build_id=$build_id '{print "`"$3"`[[Error message](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-"pr_number"/artifacts/"build_id"/build-log/recording_build/"$3"_recording_test.log)] [[Debug log](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-"pr_number"/artifacts/"build_id"/recording/"$3".log)]"}') + RECORDING_PASSED_TESTS=$(grep "^--- PASS: TestAcc" recording_test.log | awk -v pr_number=$pr_number -v build_id=$build_id '{print "`"$3"`[[Debug log](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-"pr_number"/artifacts/"build_id"/recording/"$3".log)]"}') + RECORDING_PASSED_TEST_LIST=$(grep "^--- PASS: TestAcc" recording_test.log | awk '{print $3}') + + comment="" + RECORDING_PASSED_TESTS_COUNT=0 + RECORDING_FAILED_TESTS_COUNT=0 + if [[ -n $RECORDING_PASSED_TESTS ]]; then + comment+="$\textcolor{green}{\textsf{Tests passed during RECORDING mode:}}$ ${NEWLINE} $RECORDING_PASSED_TESTS ${NEWLINE}${NEWLINE}" + RECORDING_PASSED_TESTS_COUNT=$(echo "$RECORDING_PASSED_TESTS" | wc -l) + comment+="##### Rerun these tests in REPLAYING mode to catch issues ${NEWLINE}${NEWLINE}" + + # Rerun passed tests in REPLAYING mode 3 times to catch issues + export VCR_MODE=REPLAYING + count=3 + parallel --jobs 16 TF_LOG=DEBUG TF_LOG_PATH_MASK=$local_path/testlog/replaying_after_recording/%s.log TF_ACC=1 TF_SCHEMA_PANIC_ON_ERROR=1 go test {1} -parallel 1 -count=$count -v -run="{2}$" -timeout 120m -ldflags="-X=github.com/hashicorp/terraform-provider-google-beta/version.ProviderVersion=acc" ">>" testlog/replaying_build_after_recording/{2}_replaying_test.log ::: $GOOGLE_TEST_DIRECTORY ::: $RECORDING_PASSED_TEST_LIST + + test_exit_code=$(($test_exit_code || $?)) + + # Concatenate recording build logs to one file + for test in $RECORDING_PASSED_TEST_LIST + do + cat testlog/replaying_build_after_recording/${test}_replaying_test.log >> replaying_build_after_recording.log + done + + # store replaying individual build logs + gsutil -h "Content-Type:text/plain" -m -q cp testlog/replaying_build_after_recording/* gs://ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/replaying_build_after_recording/ + + # store replaying test logs + gsutil -h "Content-Type:text/plain" -m -q cp testlog/replaying_after_recording/* gs://ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/replaying_after_recording/ + + REPLAYING_FAILED_TESTS=$(grep "^--- FAIL: TestAcc" replaying_build_after_recording.log | sort -u -t' ' -k3,3 | awk -v pr_number=$pr_number -v build_id=$build_id '{print "`"$3"`[[Error message](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-"pr_number"/artifacts/"build_id"/build-log/replaying_build_after_recording/"$3"_replaying_test.log)] [[Debug log](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-"pr_number"/artifacts/"build_id"/replaying_after_recording/"$3".log)]"}') + if [[ -n $REPLAYING_FAILED_TESTS ]]; then + comment+="$\textcolor{red}{\textsf{Tests failed when rerunning REPLAYING mode:}}$ ${NEWLINE} $REPLAYING_FAILED_TESTS ${NEWLINE}${NEWLINE}" + comment+="Tests failed due to non-determinism or randomness when the VCR replayed the response after the HTTP request was made.${NEWLINE}${NEWLINE}" + comment+="Please fix these to complete your PR. If you believe these test failures to be incorrect or unrelated to your change, or if you have any questions, please raise the concern with your reviewer.${NEWLINE}" + else + comment+="$\textcolor{green}{\textsf{No issues found for passed tests after REPLAYING rerun.}}$ ${NEWLINE}" + fi + comment+="${NEWLINE}---${NEWLINE}" + + # Clear replaying-log folder + rm testlog/replaying_after_recording/* + rm testlog/replaying_build_after_recording/* + fi + + if [[ -n $RECORDING_FAILED_TESTS ]]; then + comment+="$\textcolor{red}{\textsf{Tests failed during RECORDING mode:}}$ ${NEWLINE} $RECORDING_FAILED_TESTS ${NEWLINE}${NEWLINE}" + RECORDING_FAILED_TESTS_COUNT=$(echo "$RECORDING_FAILED_TESTS" | wc -l) + if [[ $RECORDING_PASSED_TESTS_COUNT+$RECORDING_FAILED_TESTS_COUNT -lt $FAILED_TESTS_COUNT ]]; then + comment+="$\textcolor{red}{\textsf{Several tests got terminated during RECORDING mode.}}$ ${NEWLINE}" + fi + comment+="$\textcolor{red}{\textsf{Please fix these to complete your PR.}}$ ${NEWLINE}" + else + if [[ $RECORDING_PASSED_TESTS_COUNT+$RECORDING_FAILED_TESTS_COUNT -lt $FAILED_TESTS_COUNT ]]; then + comment+="$\textcolor{red}{\textsf{Several tests got terminated during RECORDING mode.}}$ ${NEWLINE}" + elif [[ $test_exit_code -ne 0 ]]; then + # check for any uncaught errors in RECORDING mode + comment+="$\textcolor{red}{\textsf{Errors occurred during RECORDING mode. Please fix them to complete your PR.}}$ ${NEWLINE}" + else + comment+="$\textcolor{green}{\textsf{All tests passed!}} ${NEWLINE}" + fi + fi + + comment+="View the [build log](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/recording_test.log) or the [debug log](https://console.cloud.google.com/storage/browser/ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/recording) for each test" + add_comment "${comment}" + +else + if [[ $test_exit_code -ne 0 ]]; then + # check for any uncaught errors errors in REPLAYING mode + comment+="$\textcolor{red}{\textsf{Errors occurred during REPLAYING mode. Please fix them to complete your PR}}$ ${NEWLINE}" + else + comment+="$\textcolor{green}{\textsf{All tests passed in REPLAYING mode.}}$ ${NEWLINE}" + fi + comment+="View the [build log](https://storage.cloud.google.com/ci-vcr-logs/beta/refs/heads/auto-pr-$pr_number/artifacts/$build_id/build-log/replaying_test$test_suffix.log)" + add_comment "${comment}" +fi + + +if [[ $test_exit_code -ne 0 ]]; then + test_state="failure" +else + test_state="success" +fi + +set -e + +update_status ${test_state} \ No newline at end of file diff --git a/.ci/containers/github-differ/compare_breaking_changes.sh b/.ci/scripts/go-plus/github-differ/compare_breaking_changes.sh similarity index 100% rename from .ci/containers/github-differ/compare_breaking_changes.sh rename to .ci/scripts/go-plus/github-differ/compare_breaking_changes.sh diff --git a/.ci/containers/github-differ/generate_comment.sh b/.ci/scripts/go-plus/github-differ/generate_comment.sh similarity index 96% rename from .ci/containers/github-differ/generate_comment.sh rename to .ci/scripts/go-plus/github-differ/generate_comment.sh index 57003f08921d..8746867b291e 100755 --- a/.ci/containers/github-differ/generate_comment.sh +++ b/.ci/scripts/go-plus/github-differ/generate_comment.sh @@ -11,8 +11,11 @@ if [ -z "$GITHUB_TOKEN" ]; then exit 1 fi +# Get the directory of the current script +script_dir=$(dirname "$0") + # make utility functions avalible -source /utils.sh +source "$script_dir/utils.sh" PR_NUMBER=$1 NEW_BRANCH=auto-pr-$PR_NUMBER @@ -104,7 +107,7 @@ if [ $retVal -ne 0 ]; then export TPGB_BREAKING="" BREAKING_CHANGE_BUILD_FAILURE=$? fi -BREAKINGCHANGES="$(/compare_breaking_changes.sh)" +BREAKINGCHANGES="$($script_dir/compare_breaking_changes.sh)" set -e popd @@ -197,5 +200,5 @@ curl -H "Authorization: token ${GITHUB_TOKEN}" \ if ! git diff --exit-code origin/main tools || [ "$BREAKING_CHANGE_BUILD_FAILURE" -ne 0 ]; then ## Run unit tests for breaking change and missing test detector. - /test_tools.sh $MM_LOCAL_PATH $TPG_LOCAL_PATH $COMMIT_SHA $BUILD_ID $BUILD_STEP $PROJECT_ID + "$script_dir/test_tools.sh" "$MM_LOCAL_PATH" "$TPG_LOCAL_PATH" "$COMMIT_SHA" "$BUILD_ID" "$BUILD_STEP" "$PROJECT_ID" fi diff --git a/.ci/containers/github-differ/test_tools.sh b/.ci/scripts/go-plus/github-differ/test_tools.sh similarity index 100% rename from .ci/containers/github-differ/test_tools.sh rename to .ci/scripts/go-plus/github-differ/test_tools.sh diff --git a/.ci/containers/github-differ/utils.sh b/.ci/scripts/go-plus/github-differ/utils.sh similarity index 100% rename from .ci/containers/github-differ/utils.sh rename to .ci/scripts/go-plus/github-differ/utils.sh diff --git a/.ci/containers/terraform-validator-tester-integration/test_terraform_validator_integration.sh b/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh similarity index 94% rename from .ci/containers/terraform-validator-tester-integration/test_terraform_validator_integration.sh rename to .ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh index 5bad25285e75..30c54b36d454 100755 --- a/.ci/containers/terraform-validator-tester-integration/test_terraform_validator_integration.sh +++ b/.ci/scripts/go-plus/terraform-validator-tester-integration/test_terraform_validator_integration.sh @@ -66,6 +66,9 @@ curl \ set +e +go mod edit -replace github.com/hashicorp/terraform-provider-google-beta=github.com/$github_username/terraform-provider-google-beta@$new_branch +go mod tidy + make build make test-integration exit_code=$? diff --git a/.ci/containers/terraform-validator-tester/test_terraform_validator.sh b/.ci/scripts/go-plus/terraform-validator-tester/test_terraform_validator.sh similarity index 92% rename from .ci/containers/terraform-validator-tester/test_terraform_validator.sh rename to .ci/scripts/go-plus/terraform-validator-tester/test_terraform_validator.sh index e68b0aa0a945..d4023a2d79d4 100755 --- a/.ci/containers/terraform-validator-tester/test_terraform_validator.sh +++ b/.ci/scripts/go-plus/terraform-validator-tester/test_terraform_validator.sh @@ -44,6 +44,9 @@ curl \ set +e +go mod edit -replace github.com/hashicorp/terraform-provider-google-beta=github.com/$github_username/terraform-provider-google-beta@$new_branch +go mod tidy + make test exit_code=$? diff --git a/GNUmakefile b/GNUmakefile index 58f255cb87bc..788043d693aa 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -80,7 +80,7 @@ teamcity-servicemap-generate: tgc: cd mmv1;\ bundle;\ - bundle exec compiler -e terraform -f validator -v beta -o $(OUTPUT_PATH) $(mmv1_compile);\ + bundle exec compiler -e terraform -f tgc -v beta -o $(OUTPUT_PATH) $(mmv1_compile);\ test: cd mmv1; \ diff --git a/docs/content/develop/add-handwritten-test.md b/docs/content/develop/add-handwritten-test.md deleted file mode 100644 index 04765285c846..000000000000 --- a/docs/content/develop/add-handwritten-test.md +++ /dev/null @@ -1,221 +0,0 @@ ---- -title: "Add a handwritten test" -summary: "For handwritten resources and generated resources that need to test update, -handwritten tests must be added." -weight: 41 -aliases: - - /docs/how-to/add-handwritten-test - - /how-to/add-handwritten-test ---- - - -# Add a handwritten test - -For handwritten resources and generated resources that need to test update, -handwritten tests must be added. - -Tests are made up of a templated Terraform configuration where unique values -like GCE names are passed in as arguments, and boilerplate to exercise that -configuration. - -The test boilerplate effectively does the following: - -1. Run `terraform apply` on the configuration, waiting for it to succeed and - recording the results in Terraform state -2. Run `terraform plan`, and fail if Terraform detects any drift -3. Clear the resource from state and run `terraform import` on it -4. Deeply compare the original state from `terraform apply` and the `terraform - import` results, returning an error if any values are not identical -5. Destroy all resources in the configuration using `terraform destroy`, - waiting for the destroy command to succeed -6. Call `GET` on the resource, and fail the test if it is still present - -## Simple Tests - -Terraform configurations are stored as string constants wrapped in Go functions -like the following: - -```go -func testAccComputeFirewall_basic(network, firewall string) string { - return fmt.Sprintf(` -resource "google_compute_network" "foobar" { - name = "%s" - auto_create_subnetworks = false -} - -resource "google_compute_firewall" "foobar" { - name = "%s" - description = "Resource created for Terraform acceptance testing" - network = google_compute_network.foobar.name - source_tags = ["foo"] - allow { - protocol = "icmp" - } -} -`, network, firewall) -} -``` - -For the most part, you can copy and paste a preexisting test case and modify it. -For example, the following test case is a good reference: - -```go -func TestAccComputeFirewall_noSource(t *testing.T) { - t.Parallel() - - networkName := fmt.Sprintf("tf-test-firewall-%s", acctest.RandString(t, 10)) - firewallName := fmt.Sprintf("tf-test-firewall-%s", acctest.RandString(t, 10)) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckComputeFirewallDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccComputeFirewall_noSource(networkName, firewallName), - }, - { - ResourceName: "google_compute_firewall.foobar", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccComputeFirewall_noSource(network, firewall string) string { - return fmt.Sprintf(` -resource "google_compute_network" "foobar" { - name = "%s" - auto_create_subnetworks = false -} -resource "google_compute_firewall" "foobar" { - name = "%s" - description = "Resource created for Terraform acceptance testing" - network = google_compute_network.foobar.name - allow { - protocol = "tcp" - ports = [22] - } -} -`, network, firewall) -} -``` - -## Update tests - -Inside of a test, additional steps can be added in order to transition between -Terraform configurations, updating the stored state as it progresses. This -allows you to exercise update behaviour. This modifies the flow from before: - -1. Start with an empty Terraform state -1. For each `Config` and `ImportState` pair: - 1. Run `terraform apply` on the configuration, waiting for it to succeed - and recording the results in Terraform state - 1. Run `terraform plan`, and fail if Terraform detects any drift - 1. Clear the resource from state and run `terraform import` on it - 1. Deeply compare the original state from `terraform apply` and the - `terraform import` results, returning an error if any values are not - identical -1. Destroy all resources in the configuration using `terraform destroy`, - waiting for the destroy command to succeed -1. Call `GET` on the resource, and fail the test if it is still present - -For example: - -```go -func TestAccComputeFirewall_disabled(t *testing.T) { - t.Parallel() - - networkName := fmt.Sprintf("tf-test-firewall-%s", acctest.RandString(t, 10)) - firewallName := fmt.Sprintf("tf-test-firewall-%s", acctest.RandString(t, 10)) - - acctest.VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), - CheckDestroy: testAccCheckComputeFirewallDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccComputeFirewall_disabled(networkName, firewallName), - }, - { - ResourceName: "google_compute_firewall.foobar", - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccComputeFirewall_basic(networkName, firewallName), - }, - { - ResourceName: "google_compute_firewall.foobar", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccComputeFirewall_basic(network, firewall string) string { - return fmt.Sprintf(` -resource "google_compute_network" "foobar" { - name = "%s" - auto_create_subnetworks = false -} - -resource "google_compute_firewall" "foobar" { - name = "%s" - description = "Resource created for Terraform acceptance testing" - network = google_compute_network.foobar.name - source_tags = ["foo"] - allow { - protocol = "icmp" - } -} -`, network, firewall) -} - -func testAccComputeFirewall_disabled(network, firewall string) string { - return fmt.Sprintf(` -resource "google_compute_network" "foobar" { - name = "%s" - auto_create_subnetworks = false -} - -resource "google_compute_firewall" "foobar" { - name = "%s" - description = "Resource created for Terraform acceptance testing" - network = google_compute_network.foobar.name - source_tags = ["foo"] - allow { - protocol = "icmp" - } - disabled = true -} -`, network, firewall) -} -``` - -## Testing Beta Features - -If you worked with a beta feature and had to use beta version guards in a -handwritten resource or set `min_version: beta` in a generated resource, you'll -want to version guard both the test case and configuration by enclosing them in -ERB tags like below. Additionally, if the filename ends in `.go`, rename it to -end in `.go.erb`. - -``` -<% unless version == 'ga' -%> -// test case + config here -<% end -%> -``` - -Otherwise, tests using a beta feature are written exactly the same as tests -using a GA one. Normally to use the beta provider, it's necessary to specify -`provider = google-beta`, as Terraform maps any resources prefixed with -`google_` to the `google` provider by default. However, inside the test -framework, the `google-beta` provider has been aliased as the `google` provider -and that is not necessary. - -Note: You _may_ use version guards to test different configurations between the -GA and beta provider tests, but it's strongly recommended that you write -different test cases instead, even if they're slightly duplicative. \ No newline at end of file diff --git a/docs/content/develop/add-mmv1-test.md b/docs/content/develop/add-mmv1-test.md deleted file mode 100644 index e154a8745d89..000000000000 --- a/docs/content/develop/add-mmv1-test.md +++ /dev/null @@ -1,201 +0,0 @@ ---- -title: "Add an MMv1 test" -summary: "An example terraform configuration can be used to generate docs and tests for a resource." -weight: 40 -aliases: - - /docs/how-to/add-mmv1-test - - /how-to/add-mmv1-test ---- - -# Add an MMv1 test - -For generated resources, you can add an example to the -[`mmv1/templates/terraform/examples`](https://github.com/GoogleCloudPlatform/magic-modules/tree/master/mmv1/templates/terraform/examples) -directory, which contains a set of templated Terraform configurations. - -After writing out the example and filling out some metadata, Magic Modules will -insert it into the resource documentation page, and generate a test case -stepping through the following stages: - -1. Run `terraform apply` on the configuration, waiting for it to succeed and - recording the results in Terraform state -1. Run `terraform plan`, and fail if Terraform detects any drift -1. Clear the resource from state and run `terraform import` on it -1. Deeply compare the original state from `terraform apply` and the `terraform - import` results, returning an error if any values are not identical -1. Destroy all resources in the configuration using `terraform destroy`, - waiting for the destroy command to succeed -1. Call `GET` on the resource, and fail the test if it is still present - -## Example Configuration File - -First, you'll want to add the example file. It needs to end in the filename -`.tf.erb`, and is typically named `service_resource_descriptive_name`. For -example, `pubsub_topic_geo_restricted.tf.erb`. Inside, you'll write a complete -Terraform configuration that provisions the resource and all of the required -dependencies. For example, in -[`mmv1/templates/terraform/examples/pubsub_subscription_dead_letter.tf.erb`](https://github.com/GoogleCloudPlatform/magic-modules/blob/e7ef590f6007796f446b2d41875b3d26f4469ff4/mmv1/templates/terraform/examples/pubsub_subscription_dead_letter.tf.erb): - -```tf -resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['topic_name'] %>" -} - -resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>_dead_letter" { - name = "<%= ctx[:vars]['topic_name'] %>-dead-letter" -} - -resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { - name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name - - dead_letter_policy { - dead_letter_topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>_dead_letter.id - max_delivery_attempts = 10 - } -} -``` - -The `ctx` variable provides metadata at generation time, and should be used in -two ways: - -* The Terraform ID of a single instance of the primary resource should be - supplied through `<%= ctx[:primary_resource_id] %>` (in this example - multiple resources use the value, although only the first - `google_pubsub_topic` requires it). The resource kind you are testing with - an id equal to `<%= ctx[:primary_resource_id] %>` is the one that will be - imported. -* Unique values can be supplied through `<%= ctx[:vars]['{{var}}'] %>`, where - `{{var}}` is an arbitrary key you define. These values are created by - appending suffixes to them, and are typically only used for names- most - values should be constant within the configuration. - -## `Topic.yaml` metadata - -Once your configuration is written, go in `Topic.yaml` and find the -`examples` block for the resource. Generally it'll be above the `properties` -block. In there, append an entry such as the -[following](https://github.com/GoogleCloudPlatform/magic-modules/blob/67cef91ee76fc4871566f03e7caee1ef664f8aa0/mmv1/products/pubsub/Topic.yaml#L45-L73): - -```yaml - - !ruby/object:Provider::Terraform::Examples - name: "pubsub_subscription_dead_letter" - primary_resource_id: "example" - vars: - topic_name: "example-topic" - subscription_name: "example-subscription" -``` - -The `name` should match the base name of your example file, -`primary_resource_id` is an arbitrary snake_cased string that describes the -resource, and the `vars` map should contain each key you defined previously. - -{{< hint danger >}} -**Important**: Any vars that are part of the resource's id should include at -least one hyphen or underscore; this -[triggers addition of a `tf-test` or `tf_test` prefix](https://github.com/GoogleCloudPlatform/magic-modules/blob/6858338f013f5dc57729ec037883a3594441ea62/mmv1/provider/terraform/examples.rb#L244), -which is what we use to detect and delete stray resources that are sometimes -left over during test runs. -{{< /hint >}} - -## Results - -Your configuration will ultimately generate a Go test case similar to the -[following](https://github.com/hashicorp/terraform-provider-google/blob/38e2913cb102225f9f9bda9f04b5498d3386a79c/google/resource_pubsub_subscription_generated_test.go#L135-L180) -based on the snippets above: - -```go -func TestAccPubsubSubscription_pubsubSubscriptionDeadLetterExample(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: testAccCheckPubsubSubscriptionDestroyProducer(t), - Steps: []resource.TestStep{ - { - Config: testAccPubsubSubscription_pubsubSubscriptionDeadLetterExample(context), - }, - { - ResourceName: "google_pubsub_subscription.example", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"topic"}, - }, - }, - }) -} - -func testAccPubsubSubscription_pubsubSubscriptionDeadLetterExample(context map[string]interface{}) string { - return acctest.Nprintf(` -resource "google_pubsub_topic" "example" { - name = "tf-test-example-topic%{random_suffix}" -} -resource "google_pubsub_topic" "example_dead_letter" { - name = "tf-test-example-topic%{random_suffix}-dead-letter" -} -resource "google_pubsub_subscription" "example" { - name = "tf-test-example-subscription%{random_suffix}" - topic = google_pubsub_topic.example.name - dead_letter_policy { - dead_letter_topic = google_pubsub_topic.example_dead_letter.id - max_delivery_attempts = 10 - } -} -`, context) -} -``` - -## Update tests - -Update tests can only be [added as handwritten tests]({{< ref "/develop/add-handwritten-test#update-tests" >}}). - -## Tests that use beta features - -For tests that use beta features, you'll need to perform two additional steps: - -1. Add `provider = google-beta` to every resource in the test (even resources - that aren't being tested and/or are also in the GA provider) -1. Add `min_version: beta` to the `Provider::Terraform::Examples` block - -For example, modifying the snippets above: - -```tf -resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta - - name = "<%= ctx[:vars]['topic_name'] %>" -} - -resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>_dead_letter" { - provider = google-beta - - name = "<%= ctx[:vars]['topic_name'] %>-dead-letter" -} - -resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { - provider = google-beta - - name = "<%= ctx[:vars]['subscription_name'] %>" - topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name - - dead_letter_policy { - dead_letter_topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>_dead_letter.id - max_delivery_attempts = 10 - } -} -``` - -```yaml - - !ruby/object:Provider::Terraform::Examples - name: "pubsub_subscription_dead_letter" - min_version: beta - primary_resource_id: "example" - vars: - topic_name: "example-topic" - subscription_name: "example-subscription" -``` \ No newline at end of file diff --git a/docs/content/develop/resource.md b/docs/content/develop/resource.md index 527e475a4fe7..89ed8e7248b8 100644 --- a/docs/content/develop/resource.md +++ b/docs/content/develop/resource.md @@ -193,16 +193,21 @@ For more information about types of resources and the generation process overall 3. From the beta provider, copy the files generated for the resource to the following locations: - Resource: Copy to the appropriate service folder inside [`magic-modules/mmv1/third_party/terraform/services`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/services) - Documentation: [`magic-modules/mmv1/third_party/terraform/website/docs/r`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/website/docs/r) - - Tests: [`magic-modules/mmv1/third_party/terraform/tests`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/tests) + - Tests: [`magic-modules/mmv1/third_party/terraform/tests`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/tests), and remove `_generated` from the filename - Sweepers: [`magic-modules/mmv1/third_party/terraform/utils`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/utils) 4. Modify the Go code as needed. + - Remove the `Example` suffix from all test function names. - Replace the comments at the top of the file with the following: ``` <% autogen_exception -%> ``` - - If any of the added Go code (including any imports) is beta-only, change the file suffix to `.go.erb` and wrap the beta-only code in a version guard: `<% unless version = 'ga' -%>...<% else -%>...<% end -%>`. + - If any of the added Go code (including any imports) is beta-only, change the file suffix to `.go.erb` and wrap the beta-only code in a version guard: `<% unless version == 'ga' -%>...<% else -%>...<% end -%>`. 5. Register the resource in [`magic-modules/mmv1/third_party/terraform/utils/provider.go.erb`](https://github.com/GoogleCloudPlatform/magic-modules/blob/main/mmv1/third_party/terraform/utils/provider.go.erb) under "START handwritten resources" - Add a version guard for any beta-only resources. +6. Optional: Complete other handwritten tasks that require the MMv1 configuration file. + - [Add resource tests]({{< ref "/develop/test.md" >}}) + - [Add IAM support]({{}}) +7. Delete the MMv1 configuration file. {{< /tab >}} {{< /tabs >}} @@ -343,7 +348,7 @@ For more information about types of resources and the generation process overall - "Flatteners" convert API response data to Terraform resource data. - For top level fields, add a flattener. Call `d.Set()` on the flattened API response value to store it in Terraform state. - For other fields, add logic to the parent field's flattener to convert the value from the API response to the Terraform state value. Use a nested flattener for complex logic. -4. If any of the added Go code (including any imports) is beta-only, change the file suffix to `.go.erb` and wrap the beta-only code in a version guard: `<% unless version = 'ga' -%>...<% else -%>...<% end -%>`. +4. If any of the added Go code (including any imports) is beta-only, change the file suffix to `.go.erb` and wrap the beta-only code in a version guard: `<% unless version == 'ga' -%>...<% else -%>...<% end -%>`. - Add a new guard rather than adding the field to an existing guard; it is easier to read. {{< /tab >}} {{< /tabs >}} @@ -422,7 +427,7 @@ iam_policy: !ruby/object:Api::Resource::IamPolicy ``` <% autogen_exception -%> ``` - - If any of the added Go code (including any imports) is beta-only, change the file suffix to `.go.erb` and wrap the beta-only code in a version guard: `<% unless version = 'ga' -%>...<% else -%>...<% end -%>`. + - If any of the added Go code (including any imports) is beta-only, change the file suffix to `.go.erb` and wrap the beta-only code in a version guard: `<% unless version == 'ga' -%>...<% else -%>...<% end -%>`. 4. Register the binding, member, and policy resources in [`magic-modules/mmv1/third_party/terraform/utils/provider.go.erb`](https://github.com/GoogleCloudPlatform/magic-modules/blob/main/mmv1/third_party/terraform/utils/provider.go.erb) under "START non-generated IAM resources" - Add a version guard for any beta-only resources. {{< /tab >}} @@ -459,6 +464,5 @@ Documentation is autogenerated based on the resource and field configurations. T ## What's next? -- [Add MMv1 tests]({{< ref "/develop/add-mmv1-test.md" >}}) -- [Add handwritten tests]({{< ref "/develop/add-handwritten-test.md" >}}) +- [Add tests]({{< ref "/develop/test.md" >}}) - [Test your changes]({{< ref "/develop/run-tests.md" >}}) diff --git a/docs/content/develop/test.md b/docs/content/develop/test.md new file mode 100644 index 000000000000..c195ed43f66a --- /dev/null +++ b/docs/content/develop/test.md @@ -0,0 +1,220 @@ +--- +title: "Add resource tests" +weight: 40 +aliases: + - /docs/how-to/add-mmv1-test + - /how-to/add-mmv1-test + - /develop/add-mmv1-test + - /docs/how-to/add-handwritten-test + - /how-to/add-handwritten-test + - /develop/add-handwritten-test +--- + +# Add resource tests + +This page describes how to add tests to a new resource in the `google` or `google-beta` Terraform provider. + +For more information about testing, see the [official Terraform documentation](https://developer.hashicorp.com/terraform/plugin/sdkv2/testing/acceptance-tests). + +## Before you begin + +1. Determine whether your resources is using [MMv1 generation or handwritten]({{}}). +2. If you are not adding tests to an in-progress PR, ensure that your `magic-modules`, `terraform-provider-google`, and `terraform-provider-google-beta` repositories are up to date. + ```bash + cd ~/magic-modules + git checkout main && git clean -f . && git checkout -- . && git pull + cd $GOPATH/src/github.com/hashicorp/terraform-provider-google + git checkout main && git clean -f . && git checkout -- . && git pull + cd $GOPATH/src/github.com/hashicorp/terraform-provider-google-beta + git checkout main && git clean -f . && git checkout -- . && git pull + ``` + +## Add a create test + +A create test is a test that creates the target resource and immediately destroys it. + +> **Note:** All resources should have a "basic" create test, which uses the smallest possible number of fields. Additional create tests can be used to ensure all fields on the resource are used in at least one test. + +{{< tabs "create" >}} +{{< tab "MMv1" >}} +1. Using an editor of your choice, create a `*.tf.erb` file in [`mmv1/templates/terraform/examples/`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/templates/terraform/examples). The name of the file should include the service name, resource name, and a descriptor. For example, `compute_subnetwork_basic.tf.erb`. +2. Write the Terraform configuration for your test. This should include all of the required dependencies. For example, `google_compute_subnetwork` has a dependency on `google_compute_network`: + ```tf + resource "google_compute_subnetwork" "primary" { + name = "my-subnet" + ip_cidr_range = "10.1.0.0/16" + region = "us-central1" + network = google_compute_network.network.name + } + + resource "google_compute_network" "network" { + name = "my-network" + auto_create_subnetworks = false + } + ``` +3. If beta-only fields are being tested: + - Add `provider = google-beta` to every resource in the file. +4. Modify the configuration to use templated values. + - Replace the id of the primary resource you are testing with `<%= ctx[:primary_resource_id] %>`. + - Replace fields that are identifiers, like `id` or `name`, with an appropriately named variable. For example, `<%= ctx[:vars]['subnetwork_name'] %>`. + - The resulting configuration for the above example would look like this: + ```tf + resource "google_compute_subnetwork" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['subnetwork_name'] %>" + ip_cidr_range = "10.1.0.0/16" + region = "us-central1" + network = google_compute_network.network.name + } + + resource "google_compute_network" "network" { + name = "<%= ctx[:vars]['network_name'] %>" + auto_create_subnetworks = false + } + ``` +5. Modify the relevant `RESOURCE_NAME.yaml` file under [magic-modules/mmv1/products](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/products) to include an [`examples`](https://github.com/GoogleCloudPlatform/magic-modules/blob/main/mmv1/provider/terraform/examples.rb) block with your test. The `name` must match the name of your `*.tf.erb` file. For example: + ```yaml + examples: + - !ruby/object:Provider::Terraform::Examples + name: "compute_subnetwork_basic" + primary_resource_id: "example" + vars: + subnetwork_name: "example-subnet" + network_name: "example-network" + ``` +{{< hint warning >}} +**Warning:** Values in `vars` must include a `-` (or `_`). They [trigger the addition of a `tf-test` prefix](https://github.com/GoogleCloudPlatform/magic-modules/blob/6858338f013f5dc57729ec037883a3594441ea62/mmv1/provider/terraform/examples.rb#L244), which the sweeper uses to clean them up after tests run. +{{< /hint >}} +6. If beta-only fields are being tested: + - Add `min_version: beta` to the `examples` block in `RESOURCE_NAME.yaml`. +{{< /tab >}} +{{< tab "Handwritten" >}} +This section assumes you've used the [Add a resource]({{< ref "/develop/resource.md" >}}) guide to create your handwritten resource, and you have a working MMv1 config. + +> **Note:** If not, you can create one now, or skip this guide and construct the test by hand. Writing tests by hand can sometimes be a better option if there is a similar test you can copy from. + +1. Add the test in MMv1. Repeat for all the create tests you will need. +2. [Generate the providers]({{< ref "/get-started/generate-providers.md" >}}). +3. From the provider, copy and paste the generated `*_generated_test.go` file into [`magic-modules/mmv1/third_party/terraform/tests`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/tests) as a new file call `*_test.go`. +4. Modify the tests as needed. + - Remove the comments at the top of the file. + - Remove the `Example` suffix from all function names. + - If beta-only fields are being tested, do the following: + - Change the file suffix to `.go.erb`. + - Add `<% autogen_exception -%>` to the top of the file. + - Wrap the beta-only tests in a version guard: `<% unless version == 'ga' -%>...<% else -%>...<% end -%>`. +{{< /tab >}} +{{< /tabs >}} + +## Add an update test + +An update test is a test that creates the target resource and then makes updates to fields that are updatable. Updatable fields are fields that can be updated without recreating the entire resource; that is, they are not marked `immutable` in MMv1 or `ForceNew` in handwritten code. + +> **Note:** All updatable fields must be covered by at least one update test. In most cases, only a single update test is needed to test all fields at once. + +{{< tabs "update" >}} +{{< tab "MMv1" >}} +1. [Generate the providers]({{< ref "/get-started/generate-providers.md" >}}). +2. From the provider, copy and paste the generated `*_generated_test.go` file into [`magic-modules/mmv1/third_party/terraform/tests`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/tests) as a new file call `*_test.go`. +3. Using an editor of your choice, delete the `*DestroyProducer` function, and all but one test. The remaining test should be the "full" test, or if there is no "full" test, the "basic" test. This will be the starting point for your new update test. +4. Modify the `TestAcc*` *test function* to support updates. + - Change the suffix of the test function to `_update`. + - Copy the 2 `TestStep` blocks and paste them immediately after, so that there are 4 total test steps. + - Change the suffix of the first `Config` value to `_full` (or `_basic`). + - Change the suffix of the second `Config` value to `_update`. + - The resulting test function would look similar to this: + ```go + func TestAccPubsubTopic_update(t *testing.T) { + ... + acctest.VcrTest(t, resource.TestCase{ + ... + Steps: []resource.TestStep{ + { + Config: testAccPubsubTopic_full(...), + }, + { + ... + }, + { + Config: testAccPubsubTopic_update(...), + }, + { + ... + }, + }, + }) + } + ``` +5. Modify the `testAcc*` Terraform *template function* to support updates. + - Copy the template function and paste it immediately after so that there are 2 template functions. + - Change the suffix of the first template function to `_full` (or `_basic`). + - Change the suffix of the second template function to `_update`. + - The resulting template functions would look similar to this: + ```go + func testAccPubsubTopic_full(...) string { + ... + } + + func testAccPubsubTopic_update(...) string { + ... + } + ``` +6. Modify the test as needed. + - Modify the template function ending in `_update` so that updatable fields are changed or removed. This may require additions to the `context` map in the test function. + - Remove the comments at the top of the file. + - If beta-only fields are being tested, do the following: + - Change the file suffix to `.go.erb`. + - Add `<% autogen_exception -%>` to the top of the file. + - Wrap the beta-only tests in a version guard: `<% unless version == 'ga' -%>...<% else -%>...<% end -%>`. +{{< /tab >}} +{{< tab "Handwritten" >}} +1. Using an editor of your choice, open the existing `*_test.go` or `*_test.go.erb` file in [`magic-modules/mmv1/third_party/terraform/tests`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/tests) which contains your create tests. +2. Copy the `TestAcc*` *test function* for the existing "full" test. If there is no "full" test, use the "basic" test. This will be the starting point for your new update test. +3. Modify the test function to support updates. + - Change the suffix of the test function to `_update`. + - Copy the 2 `TestStep` blocks and paste them immediately after, so that there are 4 total test steps. + - Change the suffix of the second `Config` value to `_update`. + - The resulting test function would look similar to this: + ```go + func TestAccPubsubTopic_update(t *testing.T) { + ... + acctest.VcrTest(t, resource.TestCase{ + ... + Steps: []resource.TestStep{ + { + Config: testAccPubsubTopic_full(...), + }, + { + ... + }, + { + Config: testAccPubsubTopic_update(...), + }, + { + ... + }, + }, + }) + } + ``` +4. Add a Terraform *template function* to support updates. + - Copy the full (or basic) `testAcc*` template function. + - Change the suffix of the new template function to `_update`. + - The new template function would look similar to this: + ```go + func testAccPubsubTopic_update(...) string { + ... + } + ``` +5. Modify the test as needed. + - Modify the new template function so that updatable fields are changed or removed. This may require additions to the `context` map in the test function. + - Remove the comments at the top of the file. + - If beta-only fields are being tested, do the following: + - Change the file suffix to `.go.erb`. + - Add `<% autogen_exception -%>` to the top of the file. + - Wrap the beta-only tests in a version guard: `<% unless version == 'ga' -%>...<% else -%>...<% end -%>`. +{{< /tab >}} +{{< /tabs >}} + +## What's next? + +- [Run your tests]({{< ref "/develop/run-tests.md" >}}) diff --git a/docs/content/get-started/contributing.md b/docs/content/get-started/contributing.md index d077b5112764..0156630f91ae 100644 --- a/docs/content/get-started/contributing.md +++ b/docs/content/get-started/contributing.md @@ -19,7 +19,7 @@ aliases: If it exists, check the header of the downstream file to identify the type of tools used to generate the resource. For some resources, the code file, the test file and the documentation file might not be generated via the same tools. - * Generated resources like [`google_compute_address`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_address) can be identified by looking in their [`Go source`](https://github.com/hashicorp/terraform-provider-google/blob/main/google/resource_compute_address.go) for an `AUTO GENERATED CODE` header as well as a `Type`. "Generated resources" typically refers to just the `MMv1` type, and `DCL` type resources are considered "DCL-based". (Currently DCL-related contribution are not supported) + * Generated resources like [`google_compute_address`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_address) can be identified by looking in their [`Go source`](https://github.com/hashicorp/terraform-provider-google/blob/main/google/services/compute/resource_compute_address.go) for an `AUTO GENERATED CODE` header as well as a `Type`. "Generated resources" typically refers to just the `MMv1` type, and `DCL` type resources are considered "DCL-based". (Currently DCL-related contribution are not supported) * Handwritten resources like [`google_container_cluster`](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_cluster) can be identified if they have source code present under the [`mmv1/third_party/terraform/resources`](https://github.com/GoogleCloudPlatform/magic-modules/tree/main/mmv1/third_party/terraform/resources) folder or by the absence of the `AUTO GENERATED CODE header` in their [`Go source`](https://github.com/hashicorp/terraform-provider-google/blob/main/google/resource_container_cluster.go). If not, decide which tool you would like to use to implement the resource: @@ -30,7 +30,7 @@ aliases: 1. [Generate the providers]({{< ref "/get-started/generate-providers" >}}) that include your change. 1. [Run provider tests locally]({{< ref "/develop/run-tests" >}}) that are relevant to the change you made. (Testing the PR locally and pushing the commit to the PR only after the tests pass locally may significantly reduce back-and-forth in review.) 1. Push your changes to your `magic-modules` repo fork and send a pull request from that branch to the main branch on `magic-modules`. A reviewer will be assigned automatically to your PR. -1. Get approval to start Clould Builder jobs from the reviewer if you're an community contributor +1. Get approval to start Cloud Builder jobs from the reviewer if you're an community contributor 1. Wait for the the modules magician to generate downstream diff (which should take about 15 mins after creating the PR) to make sure all changes are generated correctly in downstream repos. 1. Wait for the VCR test results. {{< details "Get to know general workflow for VCR tests" >}} diff --git a/mmv1/compiler.rb b/mmv1/compiler.rb index 150839d0899a..00a414c0552a 100755 --- a/mmv1/compiler.rb +++ b/mmv1/compiler.rb @@ -31,7 +31,7 @@ require 'provider/terraform' require 'provider/terraform_kcc' require 'provider/terraform_oics' -require 'provider/terraform_validator' +require 'provider/terraform_tgc' products_to_generate = nil all_products = false @@ -275,7 +275,8 @@ else override_providers = { 'oics' => Provider::TerraformOiCS, - 'validator' => Provider::TerraformValidator, + 'validator' => Provider::TerraformGoogleConversion, + 'tgc' => Provider::TerraformGoogleConversion, 'kcc' => Provider::TerraformKCC } @@ -291,7 +292,7 @@ unless products_to_generate.include?(product_name) Google::LOGGER.info "#{product_name}: Not specified, skipping generation" - next + next { definitions: product_api, overrides: provider_config, provider: provider } # rubocop:disable Style/HashSyntax end Google::LOGGER.info \ diff --git a/mmv1/products/alloydb/Cluster.yaml b/mmv1/products/alloydb/Cluster.yaml index 9eed5e54bbf6..0f59b2d751f3 100644 --- a/mmv1/products/alloydb/Cluster.yaml +++ b/mmv1/products/alloydb/Cluster.yaml @@ -121,6 +121,44 @@ properties: description: | Output only. Cloud KMS key versions that are being used to protect the database or the backup. output: true + - !ruby/object:Api::Type::NestedObject + name: 'continuousBackupInfo' + description: | + ContinuousBackupInfo describes the continuous backup properties of a cluster. + output: true + properties: + - !ruby/object:Api::Type::String + name: enabledTime + description: | + When ContinuousBackup was most recently enabled. Set to null if ContinuousBackup is not enabled. + output: true + - !ruby/object:Api::Type::Array + name: schedule + item_type: Api::Type::String + description: | + Days of the week on which a continuous backup is taken. Output only field. Ignored if passed into the request. + output: true + - !ruby/object:Api::Type::String + name: earliestRestorableTime + description: | + The earliest restorable time that can be restored to. Output only field. + output: true + - !ruby/object:Api::Type::NestedObject + name: 'encryptionInfo' + description: | + Output only. The encryption information for the WALs and backups required for ContinuousBackup. + output: true + properties: + - !ruby/object:Api::Type::String + name: 'encryptionType' + description: 'Output only. Type of encryption.' + output: true + - !ruby/object:Api::Type::Array + name: kmsKeyVersions + item_type: Api::Type::String + description: | + Output only. Cloud KMS key versions that are being used to protect the database or the backup. + output: true - !ruby/object:Api::Type::String name: 'network' required: true @@ -156,11 +194,39 @@ properties: required: true sensitive: true - !ruby/object:Api::Type::NestedObject - name: 'automatedBackupPolicy' + name: 'continuousBackupConfig' + default_from_api: true description: | - The automated backup policy for this cluster. + The continuous backup config for this cluster. + + If no policy is provided then the default policy will be used. The default policy takes one backup a day and retains backups for 14 days. + properties: + - !ruby/object:Api::Type::Boolean + name: enabled + send_empty_value: true + default_value: true + description: | + Whether continuous backup recovery is enabled. If not set, defaults to true. + - !ruby/object:Api::Type::Integer + name: recoveryWindowDays + default_from_api: true + description: | + The numbers of days that are eligible to restore from using PITR. To support the entire recovery window, backups and logs are retained for one day more than the recovery window. - If no policy is provided then the default policy will be used. The default policy takes one backup a day, has a backup window of 1 hour, and retains backups for 14 days. + If not set, defaults to 14 days. + - !ruby/object:Api::Type::NestedObject + name: 'encryptionConfig' + description: | + EncryptionConfig describes the encryption config of a cluster or a backup that is encrypted with a CMEK (customer-managed encryption key). + properties: + - !ruby/object:Api::Type::String + name: 'kmsKeyName' + description: | + The fully-qualified resource name of the KMS key. Each Cloud KMS key is regionalized and has the following format: projects/[PROJECT]/locations/[REGION]/keyRings/[RING]/cryptoKeys/[KEY_NAME]. + - !ruby/object:Api::Type::NestedObject + name: 'automatedBackupPolicy' + description: | + The automated backup policy for this cluster. AutomatedBackupPolicy is disabled by default. default_from_api: true properties: - !ruby/object:Api::Type::String diff --git a/mmv1/products/alloydb/Instance.yaml b/mmv1/products/alloydb/Instance.yaml index 6a77c87b7258..8877e850eda0 100644 --- a/mmv1/products/alloydb/Instance.yaml +++ b/mmv1/products/alloydb/Instance.yaml @@ -56,6 +56,9 @@ examples: vars: alloydb_cluster_name: 'alloydb-cluster' alloydb_instance_name: 'alloydb-instance' + network_name: 'alloydb-network' + test_vars_overrides: + network_name: 'acctest.BootstrapSharedTestNetwork(t, "alloydb-instance-basic")' ignore_read_extra: - 'reconciling' - 'update_time' diff --git a/mmv1/products/appengine/FirewallRule.yaml b/mmv1/products/appengine/FirewallRule.yaml index ab7851a668fe..a83d1a2dd91b 100644 --- a/mmv1/products/appengine/FirewallRule.yaml +++ b/mmv1/products/appengine/FirewallRule.yaml @@ -39,6 +39,7 @@ examples: project_id: 'ae-project' test_env_vars: org_id: :ORG_ID + billing_account: :BILLING_ACCT parameters: - !ruby/object:Api::Type::Integer name: 'priority' diff --git a/mmv1/products/bigquerydatatransfer/Config.yaml b/mmv1/products/bigquerydatatransfer/Config.yaml index ce05f0c38480..a7fe1c6880a5 100644 --- a/mmv1/products/bigquerydatatransfer/Config.yaml +++ b/mmv1/products/bigquerydatatransfer/Config.yaml @@ -15,9 +15,8 @@ name: 'Config' base_url: projects/{{project}}/locations/{{location}}/transferConfigs?serviceAccountName={{service_account_name}} self_link: '{{name}}' -update_url: "{{name}}?serviceAccountName={{service_account_name}}" +update_url: "{{name}}?serviceAccountName={{service_account_name}}&updateMask=serviceAccountName,displayName,destinationDatasetId,schedule,scheduleOptions,emailPreferences,notificationPubsubTopic,dataRefreshWindowDays,disabled,params" update_verb: :PATCH -update_mask: true description: | Represents a data transfer configuration. A transfer configuration contains all metadata needed to perform a data transfer. diff --git a/mmv1/products/billing/ProjectInfo.yaml b/mmv1/products/billing/ProjectInfo.yaml new file mode 100644 index 000000000000..b55634709d98 --- /dev/null +++ b/mmv1/products/billing/ProjectInfo.yaml @@ -0,0 +1,46 @@ +# 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: ProjectInfo +base_url: 'projects/{{project}}/billingInfo' +create_verb: :PUT +delete_verb: :PUT +description: | + Billing information for a project. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Enable, disable, or change billing for a project': 'https://cloud.google.com/billing/docs/how-to/modify-project' + api: 'https://cloud.google.com/billing/docs/reference/rest/v1/projects' +id_format: 'projects/{{project}}/billingInfo' +custom_code: !ruby/object:Provider::Terraform::CustomCode + decoder: templates/terraform/decoders/billing_project_info.go.erb + encoder: templates/terraform/encoders/billing_project_info.go.erb + test_check_destroy: templates/terraform/custom_check_destroy/billing_project_info.go.erb +import_format: + ['projects/{{project}}', '{{project}}'] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'billing_project_info_basic' + primary_resource_id: 'default' + test_env_vars: + billing_account: :BILLING_ACCT + org_id: :ORG_ID +properties: + - !ruby/object:Api::Type::String + name: billing_account + description: | + The ID of the billing account associated with the project, if + any. Set to empty string to disable billing for the project. + For example, `"012345-567890-ABCDEF"` or `""`. + required: true diff --git a/mmv1/products/billing/product.yaml b/mmv1/products/billing/product.yaml new file mode 100644 index 000000000000..6b0711b6282c --- /dev/null +++ b/mmv1/products/billing/product.yaml @@ -0,0 +1,30 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +# "Billing" is already used by the Billing Budgets product, so we're +# forced to use a fake name and to specify `legacy_name` to have all +# resources in the `billing` namespace +name: CoreBilling +display_name: Cloud Billing +legacy_name: billing +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://cloudbilling.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform +apis_required: + - !ruby/object:Api::Product::ApiReference + name: Cloud Billing + url: https://console.cloud.google.com/apis/library/cloudbilling.googleapis.com/ diff --git a/mmv1/products/billingbudget/Budget.yaml b/mmv1/products/billingbudget/Budget.yaml index bdc0a76e7f9e..6b2cf52aaf72 100644 --- a/mmv1/products/billingbudget/Budget.yaml +++ b/mmv1/products/billingbudget/Budget.yaml @@ -59,6 +59,7 @@ examples: display_name: 'Example Billing Budget' test_env_vars: billing_acct: :MASTER_BILLING_ACCT + org_id: :ORG_ID - !ruby/object:Provider::Terraform::Examples name: 'billing_budget_notify' primary_resource_id: 'budget' @@ -112,6 +113,7 @@ properties: default_from_api: true update_mask_fields: - 'budgetFilter.projects' + - 'budgetFilter.resourceAncestors' - 'budgetFilter.labels' - 'budgetFilter.calendarPeriod' - 'budgetFilter.customPeriod' @@ -124,6 +126,7 @@ properties: name: projects at_least_one_of: - budget_filter.0.projects + - budget_filter.0.resource_ancestors - budget_filter.0.credit_types_treatment - budget_filter.0.services - budget_filter.0.subaccounts @@ -138,6 +141,24 @@ properties: the usage occurred on. is_set: true item_type: Api::Type::String + - !ruby/object:Api::Type::Array + name: resourceAncestors + at_least_one_of: + - budget_filter.0.projects + - budget_filter.0.resource_ancestors + - budget_filter.0.credit_types_treatment + - budget_filter.0.services + - budget_filter.0.subaccounts + - budget_filter.0.labels + - budget_filter.0.calendarPeriod + - budget_filter.0.customPeriod + description: | + A set of folder and organization names of the form folders/{folderId} or organizations/{organizationId}, + specifying that usage from only this set of folders and organizations should be included in the budget. + If omitted, the budget includes all usage that the billing account pays for. If the folder or organization + contains projects that are paid for by a different Cloud Billing account, the budget doesn't apply to those projects. + is_set: true + item_type: Api::Type::String - !ruby/object:Api::Type::Enum name: creditTypesTreatment description: | @@ -150,6 +171,7 @@ properties: - :INCLUDE_SPECIFIED_CREDITS at_least_one_of: - budget_filter.0.projects + - budget_filter.0.resource_ancestors - budget_filter.0.credit_types_treatment - budget_filter.0.services - budget_filter.0.subaccounts @@ -167,6 +189,7 @@ properties: https://cloud.google.com/billing/v1/how-tos/catalog-api. at_least_one_of: - budget_filter.0.projects + - budget_filter.0.resource_ancestors - budget_filter.0.credit_types_treatment - budget_filter.0.services - budget_filter.0.subaccounts @@ -185,6 +208,7 @@ properties: **Note:** If the field has a value in the config and needs to be removed, the field has to be an emtpy array in the config. at_least_one_of: - budget_filter.0.projects + - budget_filter.0.resource_ancestors - budget_filter.0.credit_types_treatment - budget_filter.0.services - budget_filter.0.subaccounts @@ -206,6 +230,7 @@ properties: **Note:** If the field has a value in the config and needs to be removed, the field has to be an emtpy array in the config. at_least_one_of: - budget_filter.0.projects + - budget_filter.0.resource_ancestors - budget_filter.0.credit_types_treatment - budget_filter.0.services - budget_filter.0.subaccounts @@ -221,6 +246,7 @@ properties: this set of labeled resources should be included in the budget. at_least_one_of: - budget_filter.0.projects + - budget_filter.0.resource_ancestors - budget_filter.0.credit_types_treatment - budget_filter.0.services - budget_filter.0.subaccounts @@ -234,6 +260,7 @@ properties: name: calendarPeriod at_least_one_of: - budget_filter.0.projects + - budget_filter.0.resource_ancestors - budget_filter.0.credit_types_treatment - budget_filter.0.services - budget_filter.0.subaccounts @@ -258,6 +285,7 @@ properties: name: customPeriod at_least_one_of: - budget_filter.0.projects + - budget_filter.0.resource_ancestors - budget_filter.0.credit_types_treatment - budget_filter.0.services - budget_filter.0.subaccounts diff --git a/mmv1/products/cloudbuild/Trigger.yaml b/mmv1/products/cloudbuild/Trigger.yaml index 4ca2f4ed6b9c..ea7bf11df3c7 100644 --- a/mmv1/products/cloudbuild/Trigger.yaml +++ b/mmv1/products/cloudbuild/Trigger.yaml @@ -52,12 +52,20 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'cloudbuild_trigger_pubsub_config' primary_resource_id: 'pubsub-config-trigger' + vars: + pubsub_topic_name: 'my-topic' + cloudbuild_trigger_name: 'pubsub-trigger' - !ruby/object:Provider::Terraform::Examples name: 'cloudbuild_trigger_webhook_config' primary_resource_id: 'webhook-config-trigger' + vars: + cloudbuild_trigger_name: 'webhook-trigger' + secret_id: "webhook-trigger-secret-key" - !ruby/object:Provider::Terraform::Examples name: 'cloudbuild_trigger_manual' primary_resource_id: 'manual-trigger' + vars: + cloudbuild_trigger_name: 'manual-trigger' - !ruby/object:Provider::Terraform::Examples name: 'cloudbuild_trigger_manual_github_enterprise' primary_resource_id: 'manual-ghe-trigger' @@ -69,6 +77,8 @@ examples: installation_id: '123123' pat_secret: 'projects/my-project/secrets/github-pat-secret/versions/latest' repo_uri: 'https://github.com/myuser/my-repo.git' + cloudbuildv2_connection_name: "my-connection" + cloudbuildv2_repo_name: "my-repo" test_vars_overrides: installation_id: 31300675 pat_secret: '"projects/gcb-terraform-creds/secrets/github-pat/versions/latest"' @@ -76,12 +86,18 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'cloudbuild_trigger_bitbucket_server_push' primary_resource_id: 'bbs-push-trigger' + vars: + cloudbuild_trigger_name: 'bbs-push-trigger' - !ruby/object:Provider::Terraform::Examples name: 'cloudbuild_trigger_bitbucket_server_pull_request' primary_resource_id: 'bbs-pull-request-trigger' + vars: + cloudbuild_trigger_name: 'ghe-trigger' - !ruby/object:Provider::Terraform::Examples name: 'cloudbuild_trigger_github_enterprise' primary_resource_id: 'ghe-trigger' + vars: + cloudbuild_trigger_name: 'ghe-trigger' skip_test: true - !ruby/object:Provider::Terraform::Examples name: 'cloudbuild_trigger_allow_failure' @@ -96,6 +112,10 @@ examples: installation_id: "123123" pat_secret: "projects/my-project/secrets/github-pat-secret/versions/latest" repo_uri: "https://github.com/myuser/my-repo.git" + cloudbuildv2_connection_name: "my-connection" + cloudbuildv2_repo_name: "my-repo" + pubsub_topic_name: "my-topic" + cloudbuild_trigger_name: "pubsub-with-repo-trigger" test_vars_overrides: installation_id: 31300675 pat_secret: '"projects/gcb-terraform-creds/secrets/github-pat/versions/latest"' @@ -1108,16 +1128,10 @@ properties: values: - :NOT_VERIFIED - :VERIFIED - - !ruby/object:Api::Type::Enum + - !ruby/object:Api::Type::String name: 'machineType' description: | Compute Engine machine type on which to run the build. - values: - - :UNSPECIFIED - - :N1_HIGHCPU_8 - - :N1_HIGHCPU_32 - - :E2_HIGHCPU_8 - - :E2_HIGHCPU_32 - !ruby/object:Api::Type::Integer name: 'diskSizeGb' description: | diff --git a/mmv1/products/cloudfunctions2/Function.yaml b/mmv1/products/cloudfunctions2/Function.yaml index 7cad1ba4d3f1..28fa8810372b 100644 --- a/mmv1/products/cloudfunctions2/Function.yaml +++ b/mmv1/products/cloudfunctions2/Function.yaml @@ -49,6 +49,7 @@ async: !ruby/object:Api::OpAsync id_format: 'projects/{{project}}/locations/{{location}}/functions/{{name}}' import_format: ['projects/{{project}}/locations/{{location}}/functions/{{name}}'] +taint_resource_on_failed_create: true autogen_async: true examples: - !ruby/object:Provider::Terraform::Examples @@ -215,6 +216,29 @@ examples: ignore_read_extra: - 'build_config.0.source.0.storage_source.0.object' - 'build_config.0.source.0.storage_source.0.bucket' + - !ruby/object:Provider::Terraform::Examples + name: 'cloudfunctions2_cmek' + primary_resource_id: 'function' + min_version: beta + vars: + function: 'function-cmek' + bucket_name: 'gcf-source' + zip_path: 'function-source.zip' + kms_service_name: 'cloudkms.googleapis.com' + cmek-repo: 'cmek-repo' + unencoded-ar-repo: 'ar-repo' + kms_key_name: 'cmek-key' + test_env_vars: + project: :PROJECT_NAME + test_vars_overrides: + kms_key_name: 'BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' + zip_path: '"./test-fixtures/cloudfunctions2/function-source.zip"' + location: + '"us-central1"' + # ignore these fields during import step + ignore_read_extra: + - 'build_config.0.source.0.storage_source.0.object' + - 'build_config.0.source.0.storage_source.0.bucket' iam_policy: !ruby/object:Api::Resource::IamPolicy parent_resource_attribute: 'cloud_function' method_name_separator: ':' @@ -315,6 +339,7 @@ properties: custom_flatten: 'templates/terraform/custom_flatten/cloudfunctions2_function_source_object.go.erb' - !ruby/object:Api::Type::Integer name: 'generation' + default_from_api: true description: | Google Cloud Storage generation for the object. If the generation is omitted, the latest generation will be used. @@ -608,3 +633,8 @@ properties: name: 'labels' description: | A set of key/value label pairs associated with this Cloud Function. + - !ruby/object:Api::Type::String + name: 'kmsKeyName' + description: | + 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}. diff --git a/mmv1/products/compute/Address.yaml b/mmv1/products/compute/Address.yaml index 0aeb95ac33df..59a26cd3b1bd 100644 --- a/mmv1/products/compute/Address.yaml +++ b/mmv1/products/compute/Address.yaml @@ -111,9 +111,8 @@ properties: - !ruby/object:Api::Type::String name: 'address' description: | - The static external IP address represented by this resource. Only - IPv4 is supported. An address may only be specified for INTERNAL - address types. The IP address must be inside the specified subnetwork, + The static external IP address represented by this resource. + The IP address must be inside the specified subnetwork, if any. Set by the API if undefined. default_from_api: true - !ruby/object:Api::Type::Enum @@ -223,3 +222,21 @@ properties: name: prefixLength description: | The prefix length if the resource represents an IP range. + default_from_api: true + - !ruby/object:Api::Type::Enum + name: 'ipVersion' + description: | + The IP Version that will be used by this address. The default value is `IPV4`. + values: + - :IPV4 + - :IPV6 + diff_suppress_func: 'tpgresource.EmptyOrDefaultStringSuppress("IPV4")' + - !ruby/object:Api::Type::Enum + name: 'ipv6EndpointType' + description: | + The endpoint type of this address, which should be VM or NETLB. This is + used for deciding which type of endpoint this address can be used after + the external IPv6 address reservation. + values: + - :VM + - :NETLB diff --git a/mmv1/products/compute/BackendService.yaml b/mmv1/products/compute/BackendService.yaml index ef24870db9bf..de689673f7d8 100644 --- a/mmv1/products/compute/BackendService.yaml +++ b/mmv1/products/compute/BackendService.yaml @@ -775,6 +775,7 @@ properties: values: - :EXTERNAL - :INTERNAL_SELF_MANAGED + - :INTERNAL_MANAGED - :EXTERNAL_MANAGED - !ruby/object:Api::Type::Enum name: 'localityLbPolicy' @@ -1210,7 +1211,9 @@ properties: description: | The protocol this BackendService uses to communicate with backends. The default is HTTP. **NOTE**: HTTP2 is only valid for beta HTTP/2 load balancer - types and may result in errors if used with the GA API. + types and may result in errors if used with the GA API. **NOTE**: With protocol “UNSPECIFIED”, + the backend service can be used by Layer 4 Internal Load Balancing or Network Load Balancing + with TCP/UDP/L3_DEFAULT Forwarding Rule protocol. values: - :HTTP - :HTTPS @@ -1218,6 +1221,7 @@ properties: - :TCP - :SSL - :GRPC + - :UNSPECIFIED # TODO: make a ResourceRef to Security Policy default_from_api: true - !ruby/object:Api::Type::String diff --git a/mmv1/products/compute/ForwardingRule.yaml b/mmv1/products/compute/ForwardingRule.yaml index 63d7ca4ec017..15acdafc7c78 100644 --- a/mmv1/products/compute/ForwardingRule.yaml +++ b/mmv1/products/compute/ForwardingRule.yaml @@ -203,6 +203,17 @@ examples: ip_name: 'website-ip' backend_name: 'service-backend' external_forwarding_rule_name: 'external-forwarding-rule' + - !ruby/object:Provider::Terraform::Examples + name: "forwarding_rule_internallb_ipv6" + primary_resource_id: "default" + vars: + forwarding_rule_name: "ilb-ipv6-forwarding-rule" + backend_name: "ilb-ipv6-backend" + network_name: "net-ipv6" + subnet_name: "subnet-internal-ipv6" + ignore_read_extra: + - "port_range" + - "target" custom_code: !ruby/object:Provider::Terraform::CustomCode post_create: templates/terraform/post_create/labels.erb parameters: @@ -307,6 +318,10 @@ properties: The valid IP protocols are different for different load balancing products as described in [Load balancing features](https://cloud.google.com/load-balancing/docs/features#protocols_from_the_load_balancer_to_the_backends). + + A Forwarding Rule with protocol L3_DEFAULT can attach with target instance or + backend service with UNSPECIFIED protocol. + A forwarding rule with "L3_DEFAULT" IPProtocal cannot be attached to a backend service with TCP or UDP. values: - :TCP - :UDP @@ -416,7 +431,7 @@ properties: * If `IPProtocol` is one of TCP, UDP, or SCTP. * By internal TCP/UDP load balancers, backend service-based network load - balancers, and internal protocol forwarding. + balancers, internal protocol forwarding and when protocol is not L3_DEFAULT. You can specify a list of up to five ports by number, separated by commas. @@ -509,6 +524,8 @@ properties: * By internal TCP/UDP load balancers, backend service-based network load balancers, and internal and external protocol forwarding. + This option should be set to TRUE when the Forwarding Rule + IPProtocol is set to L3_DEFAULT. Set this field to true to allow packets addressed to any port or packets lacking destination port information (for example, UDP fragments after the @@ -617,3 +634,15 @@ properties: send_empty_value: true immutable: true ignore_read: true + - !ruby/object:Api::Type::Enum + name: 'ipVersion' + description: | + The IP address version that will be used by this forwarding rule. + Valid options are IPV4 and IPV6. + + If not set, the IPv4 address will be used by default. + values: + - :IPV4 + - :IPV6 + immutable: true + default_from_api: true diff --git a/mmv1/products/compute/GlobalAddress.yaml b/mmv1/products/compute/GlobalAddress.yaml index 16a0497a6cdd..b5cd3bd89ca5 100644 --- a/mmv1/products/compute/GlobalAddress.yaml +++ b/mmv1/products/compute/GlobalAddress.yaml @@ -115,8 +115,9 @@ properties: The prefix length of the IP range. If not present, it means the address field is a single IP address. - This field is not applicable to addresses with addressType=EXTERNAL, - or addressType=INTERNAL when purpose=PRIVATE_SERVICE_CONNECT + This field is not applicable to addresses with addressType=INTERNAL + when purpose=PRIVATE_SERVICE_CONNECT + default_from_api: true - !ruby/object:Api::Type::Enum name: 'addressType' description: | @@ -148,5 +149,3 @@ properties: This should only be set when using an Internal address. custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' - # status is not useful for state convergence - # users[] is not useful for state convergence diff --git a/mmv1/products/compute/GlobalForwardingRule.yaml b/mmv1/products/compute/GlobalForwardingRule.yaml index 13567a3083b7..ee6df3585dfd 100644 --- a/mmv1/products/compute/GlobalForwardingRule.yaml +++ b/mmv1/products/compute/GlobalForwardingRule.yaml @@ -156,6 +156,27 @@ examples: ignore_read_extra: - 'port_range' - 'target' + - !ruby/object:Provider::Terraform::Examples + name: 'global_internal_http_lb_with_mig_backend' + primary_resource_id: 'google_compute_forwarding_rule' + vars: + gilb_network_name: 'l7-gilb-network' + proxy_subnet_name: 'l7-gilb-proxy-subnet' + backend_subnet_name: 'l7-gilb-subnet' + forwarding_rule_name: 'l7-gilb-forwarding-rule' + target_http_proxy_name: 'l7-gilb-target-http-proxy' + url_map_name: 'l7-gilb-url-map' + backend_service_name: 'l7-gilb-backend-subnet' + mig_template_name: 'l7-gilb-mig-template' + hc_name: 'l7-gilb-hc' + mig_name: 'l7-gilb-mig1' + fw_allow_iap_hc_name: 'l7-gilb-fw-allow-iap-hc' + fw_allow_gilb_to_backends_name: 'l7-gilb-fw-allow-gilb-to-backends' + vm_test_name: 'l7-gilb-test-vm' + min_version: beta + ignore_read_extra: + - 'port_range' + - 'target' - !ruby/object:Provider::Terraform::Examples name: 'private_service_connect_google_apis' min_version: beta @@ -299,6 +320,7 @@ properties: values: - :EXTERNAL - :EXTERNAL_MANAGED + - :INTERNAL_MANAGED - :INTERNAL_SELF_MANAGED - !ruby/object:Api::Type::Array name: 'metadataFilters' @@ -423,6 +445,23 @@ properties: # This is a multi-resource resource reference (TargetHttp(s)Proxy, # TargetSslProxy, TargetTcpProxy, TargetVpnGateway, TargetPool, # TargetInstance) + - !ruby/object:Api::Type::ResourceRef + name: 'subnetwork' + resource: 'Subnetwork' + imports: 'selfLink' + description: | + This field identifies the subnetwork that the load balanced IP should + belong to for this Forwarding Rule, used in internal load balancing and + network load balancing with IPv6. + + If the network specified is in auto subnet mode, this field is optional. + However, a subnetwork must be specified if the network is in custom subnet + mode or when creating external forwarding rule with IPv6. + # This is a multi-resource resource reference (TargetHttp(s)Proxy, + # TargetSslProxy, TargetTcpProxy, TargetVpnGateway, TargetPool, + # TargetInstance) + default_from_api: true + custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.erb' - !ruby/object:Api::Type::String name: 'target' required: true diff --git a/mmv1/products/compute/RegionBackendService.yaml b/mmv1/products/compute/RegionBackendService.yaml index fd0068cba262..e89d609a731b 100644 --- a/mmv1/products/compute/RegionBackendService.yaml +++ b/mmv1/products/compute/RegionBackendService.yaml @@ -1208,6 +1208,9 @@ properties: - :DEFAULT_FOR_PROTOCOL - :NEVER_PERSIST - :ALWAYS_PERSIST + - !ruby/object:Api::Type::Boolean + name: enableStrongAffinity + description: Enable Strong Session Affinity for Network Load Balancing. This option is not available publicly. - !ruby/object:Api::Type::Integer name: 'timeoutSec' description: | diff --git a/mmv1/products/compute/Subnetwork.yaml b/mmv1/products/compute/Subnetwork.yaml index 4461876ff554..bc262149ffca 100644 --- a/mmv1/products/compute/Subnetwork.yaml +++ b/mmv1/products/compute/Subnetwork.yaml @@ -165,12 +165,13 @@ properties: name: 'purpose' immutable: true description: | - The purpose of the resource. This field can be either `PRIVATE_RFC_1918`, `INTERNAL_HTTPS_LOAD_BALANCER`, `REGIONAL_MANAGED_PROXY`, or `PRIVATE_SERVICE_CONNECT`. + The purpose of the resource. This field can be either `PRIVATE_RFC_1918`, `INTERNAL_HTTPS_LOAD_BALANCER`, `REGIONAL_MANAGED_PROXY`, `GLOBAL_MANAGED_PROXY` or `PRIVATE_SERVICE_CONNECT`. A subnetwork with purpose set to `INTERNAL_HTTPS_LOAD_BALANCER` is a user-created subnetwork that is reserved for Internal HTTP(S) Load Balancing. A subnetwork in a given region with purpose set to `REGIONAL_MANAGED_PROXY` is a proxy-only subnet and is shared between all the regional Envoy-based load balancers. + A subnetwork in a given region with purpose set to `GLOBAL_MANAGED_PROXY` is a proxy-only subnet and is shared between all the cross-regional Envoy-based load balancers. A subnetwork with purpose set to `PRIVATE_SERVICE_CONNECT` reserves the subnet for hosting a Private Service Connect published service. If unspecified, the purpose defaults to `PRIVATE_RFC_1918`. - The enableFlowLogs field isn't supported with the purpose field set to `INTERNAL_HTTPS_LOAD_BALANCER`. + The enableFlowLogs field isn't supported with the purpose field set to `INTERNAL_HTTPS_LOAD_BALANCER` or `REGIONAL_MANAGED_PROXY` or `GLOBAL_MANAGED_PROXY`. default_from_api: true - !ruby/object:Api::Type::Enum name: 'role' @@ -267,7 +268,7 @@ properties: description: | Denotes the logging options for the subnetwork flow logs. If logging is enabled logs will be exported to Stackdriver. This field cannot be set if the `purpose` of this - subnetwork is `INTERNAL_HTTPS_LOAD_BALANCER` + subnetwork is `INTERNAL_HTTPS_LOAD_BALANCER` or `REGIONAL_MANAGED_PROXY` or `GLOBAL_MANAGED_PROXY` send_empty_value: true custom_expand: 'templates/terraform/custom_expand/subnetwork_log_config.go.erb' custom_flatten: 'templates/terraform/custom_flatten/subnetwork_log_config.go.erb' @@ -366,7 +367,7 @@ properties: or the first time the subnet is updated into IPV4_IPV6 dual stack. If the ipv6_type is EXTERNAL then this subnet cannot enable direct path. - !ruby/object:Api::Type::String - name: 'internalIpv6Prefix' + name: 'ipv6CidrRange' output: true description: | The range of internal IPv6 addresses that are owned by this subnetwork. diff --git a/mmv1/products/compute/TargetHttpsProxy.yaml b/mmv1/products/compute/TargetHttpsProxy.yaml index 65202ce55a3b..aa255fe48128 100644 --- a/mmv1/products/compute/TargetHttpsProxy.yaml +++ b/mmv1/products/compute/TargetHttpsProxy.yaml @@ -106,16 +106,15 @@ properties: - !ruby/object:Api::Type::Array name: 'sslCertificates' description: | - A list of SslCertificate resources that are used to authenticate - connections between users and the load balancer. At least one SSL - certificate must be specified. + A list of SslCertificate resource URLs or Certificate Manager certificate URLs that are used to authenticate + connections between users and the load balancer. At least one resource must be specified. update_verb: :POST update_url: 'projects/{{project}}/targetHttpsProxies/{{name}}/setSslCertificates' item_type: !ruby/object:Api::Type::ResourceRef name: 'sslCertificate' resource: 'SslCertificate' imports: 'selfLink' - description: 'The SSL certificates used by this TargetHttpsProxy' + description: 'The SSL certificate URL or Certificate Manager certificate resource URL used by this TargetHttpsProxy' custom_expand: 'templates/terraform/custom_expand/array_resourceref_with_validation.go.erb' - !ruby/object:Api::Type::String name: 'certificateMap' diff --git a/mmv1/products/databasemigrationservice/connectionprofile.yaml b/mmv1/products/databasemigrationservice/connectionprofile.yaml index 2e6de7032da0..86351ff654be 100644 --- a/mmv1/products/databasemigrationservice/connectionprofile.yaml +++ b/mmv1/products/databasemigrationservice/connectionprofile.yaml @@ -87,6 +87,8 @@ examples: profile: 'my-profileid' global_address_name: 'private-ip-alloc' network_name: 'vpc-network' + test_vars_overrides: + network_name: 'acctest.BootstrapSharedTestNetwork(t, "profile-alloydb")' parameters: - !ruby/object:Api::Type::String name: 'connectionProfileId' diff --git a/mmv1/products/dataform/ReleaseConfig.yaml b/mmv1/products/dataform/ReleaseConfig.yaml new file mode 100644 index 000000000000..6d11d9196b74 --- /dev/null +++ b/mmv1/products/dataform/ReleaseConfig.yaml @@ -0,0 +1,145 @@ +# 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: RepositoryReleaseConfig +base_url: projects/{{project}}/locations/{{region}}/repositories/{{repository}}/releaseConfigs +create_url: projects/{{project}}/locations/{{region}}/repositories/{{repository}}/releaseConfigs?releaseConfigId={{name}} +create_verb: :POST +update_verb: :PATCH +min_version: beta +description: |- + A resource represents a Dataform release configuration +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': 'https://cloud.google.com/dataform/docs/release-configurations' + api: 'https://cloud.google.com/dataform/reference/rest/v1beta1/projects.locations.repositories.releaseConfigs' +id_format: projects/{{project}}/locations/{{region}}/repositories/{{repository}}/releaseConfigs/{{name}} +import_format: + ['projects/{{project}}/locations/{{region}}/repositories/{{repository}}/releaseConfigs/{{name}}'] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'dataform_repository_release_config' + primary_resource_id: release + min_version: beta + vars: + release_name: 'my_release' + git_repository_name: 'my/repository' + dataform_repository_name: 'dataform_repository' + data: secret-data +parameters: + - !ruby/object:Api::Type::String + name: 'region' + description: 'A reference to the region' + immutable: true + url_param_only: true + - !ruby/object:Api::Type::String + name: 'repository' + description: 'A reference to the Dataform repository' + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::String + name: 'name' + description: The release's name. + immutable: true + required: true + custom_flatten: 'templates/terraform/custom_flatten/name_from_self_link.erb' + - !ruby/object:Api::Type::String + name: 'gitCommitish' + required: true + description: + Git commit/tag/branch name at which the repository should be compiled. + Must exist in the remote repository. + - !ruby/object:Api::Type::String + name: 'cronSchedule' + description: + Optional. Optional schedule (in cron format) for automatic creation of compilation results. + - !ruby/object:Api::Type::String + name: 'timeZone' + description: + Optional. 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). + If left unspecified, the default is UTC. + - !ruby/object:Api::Type::NestedObject + name: 'codeCompilationConfig' + description: + Optional. If set, fields of codeCompilationConfig override the default compilation + settings that are specified in dataform.json. + properties: + - !ruby/object:Api::Type::String + name: 'defaultDatabase' + description: Optional. The default database (Google Cloud project ID). + - !ruby/object:Api::Type::String + name: 'defaultSchema' + description: Optional. The default schema (BigQuery dataset ID). + - !ruby/object:Api::Type::String + name: 'defaultLocation' + description: |- + Optional. The default BigQuery location to use. Defaults to "US". + See the BigQuery docs for a full list of locations: https://cloud.google.com/bigquery/docs/locations. + - !ruby/object:Api::Type::String + name: 'assertionSchema' + description: Optional. The default schema (BigQuery dataset ID) for assertions. + - !ruby/object:Api::Type::KeyValuePairs + name: 'vars' + description: |- + Optional. User-defined variables that are made available to project code during compilation. + An object containing a list of "key": value pairs. + Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. + - !ruby/object:Api::Type::String + name: 'databaseSuffix' + description: Optional. The suffix that should be appended to all database (Google Cloud project ID) names. + - !ruby/object:Api::Type::String + name: 'schemaSuffix' + description: Optional. The suffix that should be appended to all schema (BigQuery dataset ID) names. + - !ruby/object:Api::Type::String + name: 'tablePrefix' + description: Optional. The prefix that should be prepended to all table names. + - !ruby/object:Api::Type::Array + name: 'recentScheduledReleaseRecords' + description: + Records of the 10 most recent scheduled release attempts, + ordered in in descending order of releaseTime. + Updated whenever automatic creation of a compilation result is triggered by cronSchedule. + output: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'releaseTime' + output: true + description: The timestamp of this release attempt. + - !ruby/object:Api::Type::String + name: 'compilationResult' + output: true + description: + The name of the created compilation result, if one was successfully created. + Must be in the format projects/*/locations/*/repositories/*/compilationResults/*. + - !ruby/object:Api::Type::NestedObject + name: 'errorStatus' + output: true + description: + The error status encountered upon this attempt to create the compilation + result, if the attempt was unsuccessful. + properties: + - !ruby/object:Api::Type::Integer + name: 'code' + output: true + description: The status code, which should be an enum value of google.rpc.Code. + - !ruby/object:Api::Type::String + name: 'message' + output: true + description: + A developer-facing error message, which should be in English. + Any user-facing error message should be localized and sent in + the google.rpc.Status.details field, or localized by the client. diff --git a/mmv1/products/documentaiwarehouse/DocumentSchema.yaml b/mmv1/products/documentaiwarehouse/DocumentSchema.yaml new file mode 100644 index 000000000000..9c8746f6b72e --- /dev/null +++ b/mmv1/products/documentaiwarehouse/DocumentSchema.yaml @@ -0,0 +1,346 @@ +# 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: 'DocumentSchema' +base_url: 'projects/{{project_number}}/locations/{{location}}/documentSchemas' +self_link: '{{name}}' +delete_url: '{{name}}' +immutable: true +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': 'https://cloud.google.com/document-warehouse/docs/manage-document-schemas' + api: 'https://cloud.google.com/document-warehouse/docs/reference/rest/v1/projects.locations.documentSchemas' +description: | + A document schema is used to define document structure. +custom_code: !ruby/object:Provider::Terraform::CustomCode + custom_import: templates/terraform/custom_import/document_ai_warehouse_document_schema.go.erb +examples: + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_text" + primary_resource_id: "example_text" + vars: + document_schema_name: "schema-name-text" + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_integer" + primary_resource_id: "example_integer" + vars: + document_schema_name: "schema-name-integer" + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_float" + primary_resource_id: "example_float" + vars: + document_schema_name: "schema-name-float" + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_property" + primary_resource_id: "example_property" + vars: + document_schema_name: "schema-name-property" + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_property_enum" + primary_resource_id: "example_property_enum" + vars: + document_schema_name: "schema-name-property-enum" + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_enum" + primary_resource_id: "example_enum" + vars: + document_schema_name: "schema-name-enum" + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_map" + primary_resource_id: "example_map" + vars: + document_schema_name: "schema-name-map" + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_datetime" + primary_resource_id: "example_datetime" + vars: + document_schema_name: "schema-name-datetime" + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_document_schema_timestamp" + primary_resource_id: "example_timestamp" + vars: + document_schema_name: "schema-name-timestamp" +parameters: + - !ruby/object:Api::Type::String + name: 'project_number' + url_param_only: true + required: true + immutable: true + description: | + The unique identifier of the project. + - !ruby/object:Api::Type::String + name: 'location' + url_param_only: true + immutable: true + required: true + description: | + The location of the resource. +properties: + - !ruby/object:Api::Type::String + name: 'name' + output: true + description: | + The resource name of the document schema. + - !ruby/object:Api::Type::String + name: 'displayName' + required: true + description: | + Name of the schema given by the user. + - !ruby/object:Api::Type::Boolean + name: 'documentIsFolder' + description: | + Tells whether the document is a folder or a typical document. + - !ruby/object:Api::Type::Array + name: 'propertyDefinitions' + description: | + Defines the metadata for a schema property. + required: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + description: | + The name of the metadata property. + - !ruby/object:Api::Type::String + name: 'displayName' + description: | + The display-name for the property, used for front-end. + - !ruby/object:Api::Type::Boolean + name: 'isRepeatable' + description: | + Whether the property can have multiple values. + - !ruby/object:Api::Type::Boolean + name: 'isFilterable' + description: | + Whether the property can be filtered. If this is a sub-property, all the parent properties must be marked filterable. + - !ruby/object:Api::Type::Boolean + name: 'isSearchable' + description: | + Indicates that the property should be included in a global search. + - !ruby/object:Api::Type::Boolean + name: 'isMetadata' + description: | + Whether the property is user supplied metadata. + - !ruby/object:Api::Type::Boolean + name: 'isRequired' + description: | + Whether the property is mandatory. + - !ruby/object:Api::Type::Enum + name: 'retrievalImportance' + description: | + Stores the retrieval importance. + values: + - :HIGHEST + - :HIGHER + - :HIGH + - :MEDIUM + - :LOW + - :LOWEST + - !ruby/object:Api::Type::Array + name: 'schemaSources' + description: | + The schema source information. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'name' + description: | + The schema name in the source. + - !ruby/object:Api::Type::String + name: 'processorType' + description: | + The Doc AI processor type name. + # select any one of the property types (integer, float, text, property, enum, dateTime, map, timestamp) + - !ruby/object:Api::Type::NestedObject + name: 'integerTypeOptions' + description: | + Integer property. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'floatTypeOptions' + description: | + Float property. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'textTypeOptions' + description: | + Text/string property. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'propertyTypeOptions' + description: | + Nested structured data property. + properties: + - !ruby/object:Api::Type::Array + name: 'propertyDefinitions' + description: | + Defines the metadata for a schema property. + required: true + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'name' + required: true + description: | + The name of the metadata property. + - !ruby/object:Api::Type::String + name: 'displayName' + description: | + The display-name for the property, used for front-end. + - !ruby/object:Api::Type::Boolean + name: 'isRepeatable' + description: | + Whether the property can have multiple values. + - !ruby/object:Api::Type::Boolean + name: 'isFilterable' + description: | + Whether the property can be filtered. If this is a sub-property, all the parent properties must be marked filterable. + - !ruby/object:Api::Type::Boolean + name: 'isSearchable' + description: | + Indicates that the property should be included in a global search. + - !ruby/object:Api::Type::Boolean + name: 'isMetadata' + description: | + Whether the property is user supplied metadata. + - !ruby/object:Api::Type::Boolean + name: 'isRequired' + description: | + Whether the property is mandatory. + - !ruby/object:Api::Type::Enum + name: 'retrievalImportance' + description: | + Stores the retrieval importance. + values: + - :HIGHEST + - :HIGHER + - :HIGH + - :MEDIUM + - :LOW + - :LOWEST + - !ruby/object:Api::Type::Array + name: 'schemaSources' + description: | + The schema source information. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'name' + description: | + The schema name in the source. + - !ruby/object:Api::Type::String + name: 'processorType' + description: | + The Doc AI processor type name. + - !ruby/object:Api::Type::NestedObject + name: 'integerTypeOptions' + description: | + Integer property. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'floatTypeOptions' + description: | + Float property. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'textTypeOptions' + description: | + Text property. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'enumTypeOptions' + description: | + Enum/categorical property. + properties: + - !ruby/object:Api::Type::Array + name: 'possibleValues' + required: true + description: | + List of possible enum values. + item_type: Api::Type::String + - !ruby/object:Api::Type::Boolean + name: 'validationCheckDisabled' + description: | + Make sure the enum property value provided in the document is in the possile value list during document creation. The validation check runs by default. + - !ruby/object:Api::Type::NestedObject + name: 'dateTimeTypeOptions' + description: | + Date time property. Not supported by CMEK compliant deployment. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'mapTypeOptions' + description: | + Map property. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'timestampTypeOptions' + description: | + Timestamp property. Not supported by CMEK compliant deployment. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'enumTypeOptions' + description: | + Enum/categorical property. + properties: + - !ruby/object:Api::Type::Array + name: 'possibleValues' + required: true + description: | + List of possible enum values. + item_type: Api::Type::String + - !ruby/object:Api::Type::Boolean + name: 'validationCheckDisabled' + description: | + Make sure the enum property value provided in the document is in the possile value list during document creation. The validation check runs by default. + - !ruby/object:Api::Type::NestedObject + name: 'dateTimeTypeOptions' + description: | + Date time property. Not supported by CMEK compliant deployment. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'mapTypeOptions' + description: | + Map property. + send_empty_value: true + allow_empty_object: true + properties: [] + - !ruby/object:Api::Type::NestedObject + name: 'timestampTypeOptions' + description: | + Timestamp property. Not supported by CMEK compliant deployment. + send_empty_value: true + allow_empty_object: true + properties: [] + diff --git a/mmv1/products/documentaiwarehouse/Location.yaml b/mmv1/products/documentaiwarehouse/Location.yaml new file mode 100644 index 000000000000..cbf1a999e150 --- /dev/null +++ b/mmv1/products/documentaiwarehouse/Location.yaml @@ -0,0 +1,104 @@ +# 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: 'Location' +base_url: 'projects/{{project_number}}/locations/{{location}}:initialize' +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': 'https://cloud.google.com/document-warehouse/docs/overview' + api: 'https://cloud.google.com/document-warehouse/docs/reference/rest/v1/projects.locations' +description: | + A location is used to initialize a project. +id_format: 'projects/{{project_number}}/locations/{{location}}' +autogen_async: true +async: !ruby/object:Api::OpAsync + actions: ['create'] + operation: !ruby/object:Api::OpAsync::Operation + path: 'name' + base_url: '{{op_id}}' + wait_ms: + 1000 + result: !ruby/object:Api::OpAsync::Result + path: 'response' + resource_inside_response: true + status: !ruby/object:Api::OpAsync::Status + path: 'done' + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: 'error' + message: 'message' +immutable: true +skip_read: true +skip_delete: true +skip_sweeper: true +exclude_import: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: "document_ai_warehouse_location" + primary_resource_id: "example" + skip_import_test: true +timeouts: !ruby/object:Api::Timeouts + insert_minutes: 30 + update_minutes: 30 + delete_minutes: 30 +parameters: + - !ruby/object:Api::Type::String + name: 'project_number' + url_param_only: true + required: true + description: | + The unique identifier of the project. + - !ruby/object:Api::Type::String + name: 'location' + url_param_only: true + required: true + description: | + The location in which the instance is to be provisioned. It takes the form projects/{projectNumber}/locations/{location}. +properties: + - !ruby/object:Api::Type::Enum + name: 'databaseType' + description: | + The type of database used to store customer data. + required: true + values: + - :DB_INFRA_SPANNER + - :DB_CLOUD_SQL_POSTGRES + - !ruby/object:Api::Type::Enum + name: 'accessControlMode' + description: | + The access control mode for accessing the customer data. + required: true + values: + - :ACL_MODE_DOCUMENT_LEVEL_ACCESS_CONTROL_GCI + - :ACL_MODE_DOCUMENT_LEVEL_ACCESS_CONTROL_BYOID + - :ACL_MODE_UNIVERSAL_ACCESS + - !ruby/object:Api::Type::String + name: 'kmsKey' + description: | + The KMS key used for CMEK encryption. It is required that + the kms key is in the same region as the endpoint. The + same key will be used for all provisioned resources, if + encryption is available. If the kmsKey is left empty, no + encryption will be enforced. + - !ruby/object:Api::Type::Enum + name: 'documentCreatorDefaultRole' + description: | + The default role for the person who create a document. + values: + - :DOCUMENT_ADMIN + - :DOCUMENT_EDITOR + - :DOCUMENT_VIEWER \ No newline at end of file diff --git a/mmv1/products/documentaiwarehouse/product.yaml b/mmv1/products/documentaiwarehouse/product.yaml new file mode 100644 index 000000000000..5493a6660cb2 --- /dev/null +++ b/mmv1/products/documentaiwarehouse/product.yaml @@ -0,0 +1,26 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +name: DocumentAIWarehouse +display_name: Document AI Warehouse +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://contentwarehouse.googleapis.com/v1/ +scopes: + - https://www.googleapis.com/auth/cloud-platform +apis_required: + - !ruby/object:Api::Product::ApiReference + name: Document AI Warehouse API + url: https://console.cloud.google.com/apis/library/contentwarehouse.googleapis.com/ diff --git a/mmv1/products/firebasedatabase/Instance.yaml b/mmv1/products/firebasedatabase/Instance.yaml index 7bdf1f8d09ee..2ab209c0c2dc 100644 --- a/mmv1/products/firebasedatabase/Instance.yaml +++ b/mmv1/products/firebasedatabase/Instance.yaml @@ -97,7 +97,7 @@ properties: Learn more about using project identifiers in Google's [AIP 2510 standard](https://google.aip.dev/cloud/2510). output: true - !ruby/object:Api::Type::String - name: database_url + name: databaseUrl description: | The database URL in the form of https://{instance-id}.firebaseio.com for us-central1 instances or https://{instance-id}.{region}.firebasedatabase.app in other regions. diff --git a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml index 04a24d7e73ea..9b0bd897af7a 100644 --- a/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalAdminCluster.yaml @@ -23,6 +23,11 @@ update_mask: true autogen_async: false id_format: "projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}" import_format: ["projects/{{project}}/locations/{{location}}/bareMetalAdminClusters/{{name}}"] +taint_resource_on_failed_create: true +timeouts: !ruby/object:Api::Timeouts + insert_minutes: 60 + delete_minutes: 60 + update_minutes: 60 description: "A Google Bare Metal Admin Cluster." examples: - !ruby/object:Provider::Terraform::Examples diff --git a/mmv1/products/gkeonprem/BareMetalCluster.yaml b/mmv1/products/gkeonprem/BareMetalCluster.yaml index 73581496c25a..82decdfc41db 100644 --- a/mmv1/products/gkeonprem/BareMetalCluster.yaml +++ b/mmv1/products/gkeonprem/BareMetalCluster.yaml @@ -25,6 +25,10 @@ autogen_async: false id_format: "projects/{{project}}/locations/{{location}}/bareMetalClusters/{{name}}" import_format: ["projects/{{project}}/locations/{{location}}/bareMetalClusters/{{name}}"] taint_resource_on_failed_create: true +timeouts: !ruby/object:Api::Timeouts + insert_minutes: 60 + delete_minutes: 60 + update_minutes: 60 examples: - !ruby/object:Provider::Terraform::Examples name: "gkeonprem_bare_metal_cluster_basic" diff --git a/mmv1/products/healthcare/FhirStore.yaml b/mmv1/products/healthcare/FhirStore.yaml index 821a774fe476..4ab3ee1d1042 100644 --- a/mmv1/products/healthcare/FhirStore.yaml +++ b/mmv1/products/healthcare/FhirStore.yaml @@ -309,3 +309,11 @@ properties: full FHIR resource. When a resource change is too large or during heavy traffic, only the resource name will be sent. Clients should always check the "payloadType" label from a Pub/Sub message to determine whether it needs to fetch the full resource as a separate operation. + - !ruby/object:Api::Type::Boolean + name: sendPreviousResourceOnDelete + description: | + Whether to send full FHIR resource to this Pub/Sub topic for deleting FHIR resource. Note that setting this to + true does not guarantee that all previous resources will be sent in the format of full FHIR resource. When a + resource change is too large or during heavy traffic, only the resource name will be sent. Clients should always + check the "payloadType" label from a Pub/Sub message to determine whether it needs to fetch the full previous + resource as a separate operation. diff --git a/mmv1/products/iap/WebTypeAppEngine.yaml b/mmv1/products/iap/WebTypeAppEngine.yaml index 282a51945b18..b3cdb21bd07e 100644 --- a/mmv1/products/iap/WebTypeAppEngine.yaml +++ b/mmv1/products/iap/WebTypeAppEngine.yaml @@ -40,6 +40,7 @@ examples: primary_resource_name: 'context["project_id"]' test_env_vars: org_id: :ORG_ID + billing_account: :BILLING_ACCT properties: - !ruby/object:Api::Type::String name: 'appId' diff --git a/mmv1/products/identityplatform/Config.yaml b/mmv1/products/identityplatform/Config.yaml index bd95547ce0da..09f298d8c999 100644 --- a/mmv1/products/identityplatform/Config.yaml +++ b/mmv1/products/identityplatform/Config.yaml @@ -46,6 +46,9 @@ examples: billing_acct: :BILLING_ACCT # Resource creation race + test_vars_overrides: + # Set quota start time for the following day. + quota_start_time: 'time.Now().AddDate(0, 0, 1).Format(time.RFC3339)' skip_vcr: true custom_code: !ruby/object:Provider::Terraform::CustomCode custom_create: 'templates/terraform/custom_create/identity_platform_config.go' @@ -59,3 +62,70 @@ properties: name: 'autodeleteAnonymousUsers' description: | Whether anonymous users will be auto-deleted after a period of 30 days + - !ruby/object:Api::Type::NestedObject + name: 'blockingFunctions' + description: | + Configuration related to blocking functions. + properties: + - !ruby/object:Api::Type::Map + name: 'triggers' + required: true + description: | + Map of Trigger to event type. Key should be one of the supported event types: "beforeCreate", "beforeSignIn". + key_name: event_type + value_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'functionUri' + required: true + description: | + HTTP URI trigger for the Cloud Function. + - !ruby/object:Api::Type::Time + name: 'updateTime' + output: true + description: | + When the trigger was changed. + - !ruby/object:Api::Type::NestedObject + name: 'forwardInboundCredentials' + description: | + The user credentials to include in the JWT payload that is sent to the registered Blocking Functions. + properties: + - !ruby/object:Api::Type::Boolean + name: 'idToken' + description: | + Whether to pass the user's OIDC identity provider's ID token. + - !ruby/object:Api::Type::Boolean + name: 'accessToken' + description: | + Whether to pass the user's OAuth identity provider's access token. + - !ruby/object:Api::Type::Boolean + name: 'refreshToken' + description: | + Whether to pass the user's OAuth identity provider's refresh token. + - !ruby/object:Api::Type::NestedObject + name: 'quota' + description: | + Configuration related to quotas. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'signUpQuotaConfig' + description: | + Quota for the Signup endpoint, if overwritten. Signup quota is measured in sign ups per project per hour per IP. + properties: + - !ruby/object:Api::Type::Integer + name: 'quota' + description: | + A sign up APIs quota that customers can override temporarily. + - !ruby/object:Api::Type::Time + name: 'startTime' + description: | + When this quota will take affect. + - !ruby/object:Api::Type::String + name: 'quotaDuration' + description: | + How long this quota will be active for. It is measurred in seconds, e.g., Example: "9.615s". + - !ruby/object:Api::Type::Array + name: authorizedDomains + description: | + List of domains authorized for OAuth redirects. + item_type: Api::Type::String diff --git a/mmv1/products/looker/Instance.yaml b/mmv1/products/looker/Instance.yaml index b830b54c7ac8..7e645702f776 100644 --- a/mmv1/products/looker/Instance.yaml +++ b/mmv1/products/looker/Instance.yaml @@ -57,6 +57,7 @@ examples: client_id: 'my-client-id' client_secret: 'my-client-secret' test_vars_overrides: + network_name: 'acctest.BootstrapSharedTestNetwork(t, "looker-instance-enterprise")' kms_key_name: 'acctest.BootstrapKMSKeyInLocation(t, "us-central1").CryptoKey.Name' parameters: - !ruby/object:Api::Type::String diff --git a/mmv1/products/monitoring/AlertPolicy.yaml b/mmv1/products/monitoring/AlertPolicy.yaml index 6d1f9deb45f2..6ec4e791e16f 100644 --- a/mmv1/products/monitoring/AlertPolicy.yaml +++ b/mmv1/products/monitoring/AlertPolicy.yaml @@ -852,7 +852,6 @@ properties: default value is zero. Must be zero or positive. - !ruby/object:Api::Type::String name: evaluationInterval - required: true description: | How often this rule should be evaluated. Must be a positive multiple of 30 seconds or missing. The default value is 30 seconds. If this diff --git a/mmv1/products/monitoring/UptimeCheckConfig.yaml b/mmv1/products/monitoring/UptimeCheckConfig.yaml index 96bb8aebe4d7..155e522159ba 100644 --- a/mmv1/products/monitoring/UptimeCheckConfig.yaml +++ b/mmv1/products/monitoring/UptimeCheckConfig.yaml @@ -83,7 +83,6 @@ properties: - !ruby/object:Api::Type::String name: period default_value: '300s' - immutable: true description: How often, in seconds, the uptime check is performed. Currently, the only supported values are 60s (1 minute), 300s (5 minutes), 600s (10 minutes), diff --git a/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml b/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml new file mode 100644 index 000000000000..28bd092b254d --- /dev/null +++ b/mmv1/products/networkconnectivity/ServiceConnectionPolicies.yaml @@ -0,0 +1,139 @@ +# 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: 'ServiceConnectionPolicy' +base_url: 'projects/{{project}}/locations/{{location}}/serviceConnectionPolicies' +create_url: 'projects/{{project}}/locations/{{location}}/serviceConnectionPolicies?serviceConnectionPolicyId={{name}}' +self_link: 'projects/{{project}}/locations/{{location}}/serviceConnectionPolicies/{{name}}' +update_verb: :PATCH +update_mask: true +description: + 'Manage Service Connection Policies.' +references: !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/secure-web-proxy/docs/reference/networkconnectivity/rest/v1/projects.locations.networkConnectionPolicies' + guides: + 'About Service Connection Policies': 'https://cloud.google.com/vpc/docs/about-service-connection-policies#service-policies' +async: !ruby/object:Api::OpAsync + operation: !ruby/object:Api::OpAsync::Operation + path: 'name' + base_url: '{{op_id}}' + wait_ms: 1000 + timeouts: !ruby/object:Api::Timeouts + insert_minutes: 30 + update_minutes: 30 + delete_minutes: 30 + result: !ruby/object:Api::OpAsync::Result + path: 'response' + status: !ruby/object:Api::OpAsync::Status + path: 'done' + complete: true + allowed: + - true + - false + error: !ruby/object:Api::OpAsync::Error + path: 'error' + message: 'message' +autogen_async: true +import_format: + ['projects/{{project}}/locations/{{location}}/serviceConnectionPolicies/{{name}}'] +examples: + - !ruby/object:Provider::Terraform::Examples + name: 'network_connectivity_policy_basic' + primary_resource_id: 'default' + vars: + resource_name: 'my-network-connectivity-policy' + producer_network_name: 'producer-net' + producer_subnetwork_name: 'producer-subnet' + service_class_name: 'my-basic-service-class' + test_vars_overrides: + service_class_name: '"gcp-memorystore-redis"' +custom_code: !ruby/object:Provider::Terraform::CustomCode + update_encoder: templates/terraform/encoders/service_connection_policy.go.erb +parameters: + - !ruby/object:Api::Type::String + name: 'name' + required: true + immutable: true + url_param_only: true + description: | + The name of a ServiceConnectionPolicy. Format: projects/{project}/locations/{location}/serviceConnectionPolicies/{service_connection_policy} See: https://google.aip.dev/122#fields-representing-resource-names + - !ruby/object:Api::Type::String + name: 'location' + required: true + immutable: true + url_param_only: true + description: | + The location of the ServiceConnectionPolicy. +properties: + - !ruby/object:Api::Type::Time + name: 'createTime' + description: | + The timestamp when the resource was created. + output: true + - !ruby/object:Api::Type::Time + name: 'updateTime' + description: | + The timestamp when the resource was updated. + output: true + - !ruby/object:Api::Type::String + name: 'serviceClass' + required: true + immutable: true + description: | + The service class identifier for which this ServiceConnectionPolicy is for. The service class identifier is a unique, symbolic representation of a ServiceClass. + It is provided by the Service Producer. Google services have a prefix of gcp. For example, gcp-cloud-sql. 3rd party services do not. For example, test-service-a3dfcx. + - !ruby/object:Api::Type::String + name: 'description' + description: | + Free-text description of the resource. + - !ruby/object:Api::Type::String + name: 'network' + required: true + immutable: true + description: | + The resource path of the consumer network. Example: - projects/{projectNumOrId}/global/networks/{resourceId}. + - !ruby/object:Api::Type::NestedObject + name: 'pscConfig' + description: | + Configuration used for Private Service Connect connections. Used when Infrastructure is PSC. + properties: + - !ruby/object:Api::Type::Array + name: 'subnetworks' + required: true + item_type: Api::Type::String + description: | + IDs of the subnetworks or fully qualified identifiers for the subnetworks + - !ruby/object:Api::Type::String + name: 'limit' + description: | + Max number of PSC connections for this policy. + - !ruby/object:Api::Type::Fingerprint + name: 'etag' + description: | + The etag is computed by the server, and may be sent on update and delete requests to ensure the client has an up-to-date value before proceeding. + - !ruby/object:Api::Type::Array + name: 'pscConnections' + output: true + item_type: Api::Type::String + description: | + Information about each Private Service Connect connection. + - !ruby/object:Api::Type::String + name: 'infrastructure' + output: true + description: | + The type of underlying resources used to create the connection. + - !ruby/object:Api::Type::KeyValuePairs + name: "labels" + description: | + User-defined labels. diff --git a/mmv1/products/networkconnectivity/product.yaml b/mmv1/products/networkconnectivity/product.yaml new file mode 100644 index 000000000000..210044bd2cf8 --- /dev/null +++ b/mmv1/products/networkconnectivity/product.yaml @@ -0,0 +1,27 @@ +# Copyright 2023 Google Inc. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +--- !ruby/object:Api::Product +name: NetworkConnectivity +display_name: Network Connectivity +scopes: + - https://www.googleapis.com/auth/cloud-platform +versions: + - !ruby/object:Api::Product::Version + name: ga + base_url: https://networkconnectivity.googleapis.com/v1/ +apis_required: + - !ruby/object:Api::Product::ApiReference + name: Network Connectivity API + url: https://console.cloud.google.com/apis/library/networkconnectivity.googleapis.com/ + \ No newline at end of file diff --git a/mmv1/products/privateca/Certificate.yaml b/mmv1/products/privateca/Certificate.yaml index 84327602ada3..2d8b63d41544 100644 --- a/mmv1/products/privateca/Certificate.yaml +++ b/mmv1/products/privateca/Certificate.yaml @@ -31,11 +31,16 @@ examples: - !ruby/object:Provider::Terraform::Examples name: 'privateca_certificate_config' primary_resource_id: 'default' + skip_docs: true vars: ca_pool_id: 'my-pool' certificate_name: 'my-certificate' test_env_vars: project: :PROJECT_NAME + - !ruby/object:Provider::Terraform::Examples + name: 'privateca_certificate_generated_key' + primary_resource_id: 'default' + skip_test: true - !ruby/object:Provider::Terraform::Examples name: 'privateca_certificate_with_template' primary_resource_id: 'default' diff --git a/mmv1/products/pubsub/Subscription.yaml b/mmv1/products/pubsub/Subscription.yaml index 5cb4fe561fa2..027504a2cd95 100644 --- a/mmv1/products/pubsub/Subscription.yaml +++ b/mmv1/products/pubsub/Subscription.yaml @@ -65,6 +65,20 @@ examples: subscription_name: 'example-subscription' dataset_id: 'example_dataset' table_id: 'example_table' + - !ruby/object:Provider::Terraform::Examples + name: 'pubsub_subscription_push_cloudstorage' + primary_resource_id: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + bucket_name: 'example-bucket' + - !ruby/object:Provider::Terraform::Examples + name: 'pubsub_subscription_push_cloudstorage_avro' + primary_resource_id: 'example' + vars: + topic_name: 'example-topic' + subscription_name: 'example-subscription' + bucket_name: 'example-bucket' docs: !ruby/object:Provider::Terraform::Docs note: | You can retrieve the email of the Google Managed Pub/Sub Service Account used for forwarding @@ -101,10 +115,11 @@ properties: name: 'bigqueryConfig' conflicts: - push_config + - cloud_storage_config description: | If delivery to BigQuery is used with this subscription, this field is used to configure it. - Either pushConfig or bigQueryConfig can be set, but not both. - If both are empty, then the subscriber will pull and ack messages using API methods. + 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. properties: - !ruby/object:Api::Type::String name: 'table' @@ -125,10 +140,66 @@ properties: description: | When true and useTopicSchema is true, any fields that are a part of the topic 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. + - !ruby/object:Api::Type::NestedObject + name: 'cloudStorageConfig' + conflicts: + - push_config + - bigquery_config + 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. + properties: + - !ruby/object:Api::Type::String + name: 'bucket' + 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 + - !ruby/object:Api::Type::String + name: 'filenamePrefix' + description: | + User-provided prefix for Cloud Storage filename. + - !ruby/object:Api::Type::String + name: 'filenameSuffix' + description: | + User-provided suffix for Cloud Storage filename. Must not end in "/". + - !ruby/object:Api::Type::String + name: 'maxDuration' + 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' + - !ruby/object:Api::Type::Integer + name: 'maxBytes' + 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. + validation: !ruby/object:Provider::Terraform::Validation + function: 'validation.IntBetween(1000, 10737418240)' + - !ruby/object:Api::Type::Enum + name: 'state' + description: | + An output-only field that indicates whether or not the subscription can receive messages. + output: true + values: + - :ACTIVE + - :PERMISSION_DENIED + - :NOT_FOUND + - !ruby/object:Api::Type::NestedObject + name: 'avroConfig' + description: | + If set, message data will be written to Cloud Storage in Avro format. + properties: + - !ruby/object:Api::Type::Boolean + name: 'writeMetadata' + description: | + When true, write the subscription name, messageId, publishTime, attributes, and orderingKey as additional fields in the output. - !ruby/object:Api::Type::NestedObject name: 'pushConfig' conflicts: - bigquery_config + - cloud_storage_config description: | If push delivery is used with this subscription, this field is used to configure it. An empty pushConfig signifies that the subscriber will @@ -191,6 +262,19 @@ properties: - 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")' + - !ruby/object:Api::Type::NestedObject + name: 'noWrapper' + description: | + When set, the payload to the push endpoint is not wrapped.Sets the + `data` field as the HTTP body for delivery. + properties: + - !ruby/object:Api::Type::Boolean + name: 'writeMetadata' + required: true + 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. - !ruby/object:Api::Type::Integer name: 'ackDeadlineSeconds' description: | diff --git a/mmv1/products/secretmanager/Secret.yaml b/mmv1/products/secretmanager/Secret.yaml index cb4dee6b7ecf..35ab01cfc2ff 100644 --- a/mmv1/products/secretmanager/Secret.yaml +++ b/mmv1/products/secretmanager/Secret.yaml @@ -33,6 +33,11 @@ examples: primary_resource_name: 'fmt.Sprintf("secret%s", context["random_suffix"])' vars: secret_id: 'secret' + - !ruby/object:Provider::Terraform::Examples + name: 'secret_with_annotations' + primary_resource_id: 'secret-with-annotations' + vars: + secret_id: 'secret' import_format: ['projects/{{project}}/secrets/{{secret_id}}'] parameters: - !ruby/object:Api::Type::String @@ -67,6 +72,23 @@ properties: No more than 64 labels can be assigned to a given resource. + An object containing a list of "key": value pairs. Example: + { "name": "wrench", "mass": "1.3kg", "count": "3" }. + - !ruby/object:Api::Type::KeyValuePairs + name: annotations + description: | + Custom metadata about the secret. + + Annotations are distinct from various forms of labels. Annotations exist to allow + client tools to store their own state information without requiring a database. + + Annotation keys must be between 1 and 63 characters long, have a UTF-8 encoding of + maximum 128 bytes, begin and end with an alphanumeric character ([a-z0-9A-Z]), and + may have dashes (-), underscores (_), dots (.), and alphanumerics in between these + symbols. + + The total size of annotation keys and values must be less than 16KiB. + An object containing a list of "key": value pairs. Example: { "name": "wrench", "mass": "1.3kg", "count": "3" }. - !ruby/object:Api::Type::NestedObject diff --git a/mmv1/products/workstations/WorkstationCluster.yaml b/mmv1/products/workstations/WorkstationCluster.yaml index 097ba4493285..ed0f940c896d 100644 --- a/mmv1/products/workstations/WorkstationCluster.yaml +++ b/mmv1/products/workstations/WorkstationCluster.yaml @@ -11,67 +11,68 @@ # See the License for the specific language governing permissions and # limitations under the License. ---- !ruby/object:Api::Resource -name: 'WorkstationCluster' -self_link: 'projects/{{project}}/locations/{{location}}/workstationClusters/{{workstation_cluster_id}}' -base_url: 'projects/{{project}}/locations/{{location}}/workstationClusters' -create_url: 'projects/{{project}}/locations/{{location}}/workstationClusters?workstationClusterId={{workstation_cluster_id}}' +--- +!ruby/object:Api::Resource +name: "WorkstationCluster" +self_link: "projects/{{project}}/locations/{{location}}/workstationClusters/{{workstation_cluster_id}}" +base_url: "projects/{{project}}/locations/{{location}}/workstationClusters" +create_url: "projects/{{project}}/locations/{{location}}/workstationClusters?workstationClusterId={{workstation_cluster_id}}" update_verb: :PATCH update_mask: true min_version: beta -description: 'A grouping of workstation configurations and the associated workstations in that region.' +description: "A grouping of workstation configurations and the associated workstations in that region." references: !ruby/object:Api::Resource::ReferenceLinks guides: - 'Workstations': 'https://cloud.google.com/workstations/docs/' - api: 'https://cloud.google.com/workstations/docs/reference/rest/v1beta/projects.locations.workstationClusters/create' + "Workstations": "https://cloud.google.com/workstations/docs/" + api: "https://cloud.google.com/workstations/docs/reference/rest/v1beta/projects.locations.workstationClusters/create" async: !ruby/object:Api::OpAsync operation: !ruby/object:Api::OpAsync::Operation - path: 'name' - base_url: '{{op_id}}' + path: "name" + base_url: "{{op_id}}" wait_ms: 1000 timeouts: !ruby/object:Api::Timeouts insert_minutes: 60 update_minutes: 60 delete_minutes: 60 result: !ruby/object:Api::OpAsync::Result - path: 'response' + path: "response" status: !ruby/object:Api::OpAsync::Status - path: 'done' + path: "done" complete: true allowed: - true - false error: !ruby/object:Api::OpAsync::Error - path: 'error' - message: 'message' + path: "error" + message: "message" import_format: [ - 'projects/{{project}}/locations/{{location}}/workstationClusters/{{workstation_cluster_id}}', + "projects/{{project}}/locations/{{location}}/workstationClusters/{{workstation_cluster_id}}", ] autogen_async: true examples: - !ruby/object:Provider::Terraform::Examples - name: 'workstation_cluster_basic' + name: "workstation_cluster_basic" min_version: beta - primary_resource_id: 'default' + primary_resource_id: "default" vars: - workstation_cluster_name: 'workstation-cluster' + workstation_cluster_name: "workstation-cluster" - !ruby/object:Provider::Terraform::Examples - name: 'workstation_cluster_private' + name: "workstation_cluster_private" min_version: beta - primary_resource_id: 'default' + primary_resource_id: "default" vars: - workstation_cluster_name: 'workstation-cluster-private' + workstation_cluster_name: "workstation-cluster-private" parameters: - !ruby/object:Api::Type::String - name: 'workstationClusterId' + name: "workstationClusterId" required: true immutable: true url_param_only: true description: | ID to use for the workstation cluster. - !ruby/object:Api::Type::String - name: 'location' + name: "location" # TODO(esu): Change to required, as it's not possible for this field to be omitted on the API side. immutable: true url_param_only: true @@ -79,101 +80,108 @@ parameters: The location where the workstation cluster should reside. properties: - !ruby/object:Api::Type::String - name: 'name' + name: "name" output: true description: | The name of the cluster resource. - !ruby/object:Api::Type::String - name: 'uid' + name: "uid" output: true description: | The system-generated UID of the resource. - !ruby/object:Api::Type::KeyValuePairs - name: 'labels' + name: "labels" description: - 'Client-specified labels that are applied to the resource and that are - also propagated to the underlying Compute Engine resources.' + "Client-specified labels that are applied to the resource and that are + also propagated to the underlying Compute Engine resources." - !ruby/object:Api::Type::String - name: 'network' + name: "network" required: true immutable: true description: | The relative resource name of the VPC network on which the instance can be accessed. It is specified in the following form: "projects/{projectNumber}/global/networks/{network_id}". - !ruby/object:Api::Type::String - name: 'subnetwork' + name: "subnetwork" required: true immutable: true description: | Name of the Compute Engine subnetwork in which instances associated with this cluster will be created. Must be part of the subnetwork specified for this cluster. - !ruby/object:Api::Type::String - name: 'displayName' + name: "displayName" description: | Human-readable name for this resource. - !ruby/object:Api::Type::Boolean - name: 'degraded' + name: "degraded" description: | Whether this resource is in degraded mode, in which case it may require user action to restore full functionality. Details can be found in the conditions field. output: true - !ruby/object:Api::Type::KeyValuePairs - name: 'annotations' - description: 'Client-specified annotations. This is distinct from labels.' + name: "annotations" + description: "Client-specified annotations. This is distinct from labels." - !ruby/object:Api::Type::Fingerprint - name: 'etag' + name: "etag" description: | Checksum computed by the server. May be sent on update and delete requests to ensure that the client has an up-to-date value before proceeding. - !ruby/object:Api::Type::Time - name: 'createTime' + name: "createTime" description: | Time when this resource was created. output: true - !ruby/object:Api::Type::NestedObject - name: 'privateClusterConfig' + name: "privateClusterConfig" description: | Configuration for private cluster. properties: - !ruby/object:Api::Type::Boolean - name: 'enablePrivateEndpoint' + name: "enablePrivateEndpoint" immutable: true required: true description: | Whether Workstations endpoint is private. - !ruby/object:Api::Type::String - name: 'clusterHostname' + name: "clusterHostname" description: | Hostname for the workstation cluster. This field will be populated only when private endpoint is enabled. To access workstations in the cluster, create a new DNS zone mapping this domain name to an internal IP address and a forwarding rule mapping that address to the service attachment. output: true - !ruby/object:Api::Type::String - name: 'serviceAttachmentUri' + name: "serviceAttachmentUri" description: | Service attachment URI for the workstation cluster. The service attachment is created when private endpoint is enabled. To access workstations in the cluster, configure access to the managed service using (Private Service Connect)[https://cloud.google.com/vpc/docs/configure-private-service-connect-services]. output: true + - !ruby/object:Api::Type::Array + name: "allowedProjects" + item_type: Api::Type::String + default_from_api: true + description: | + Additional project IDs that are allowed to attach to the workstation cluster's service attachment. + By default, the workstation cluster's project and the VPC host project (if different) are allowed. - !ruby/object:Api::Type::Array - name: 'conditions' + name: "conditions" description: |- Status conditions describing the current resource state. output: true item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::Integer - name: 'code' + name: "code" output: true description: |- The status code, which should be an enum value of google.rpc.Code. - !ruby/object:Api::Type::String - name: 'message' + name: "message" output: true description: |- Human readable message indicating details about the current status. - !ruby/object:Api::Type::Array - name: 'details' + name: "details" description: | A list of messages that carry the error details. item_type: Api::Type::KeyValuePairs diff --git a/mmv1/products/workstations/WorkstationConfig.yaml b/mmv1/products/workstations/WorkstationConfig.yaml index f0d1fa929559..79e7a3544772 100644 --- a/mmv1/products/workstations/WorkstationConfig.yaml +++ b/mmv1/products/workstations/WorkstationConfig.yaml @@ -101,6 +101,13 @@ examples: vars: workstation_cluster_name: 'workstation-cluster' workstation_config_name: 'workstation-config' + - !ruby/object:Provider::Terraform::Examples + name: 'workstation_config_accelerators' + 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 @@ -263,6 +270,22 @@ properties: description: | Whether the instance has confidential compute enabled. send_empty_value: true + - !ruby/object:Api::Type::Array + name: 'accelerators' + description: | + An accelerator card attached to the 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/provider/terraform_validator.rb b/mmv1/provider/terraform_tgc.rb similarity index 85% rename from mmv1/provider/terraform_validator.rb rename to mmv1/provider/terraform_tgc.rb index 74d19393d0e5..0491ae0fcdbe 100644 --- a/mmv1/provider/terraform_validator.rb +++ b/mmv1/provider/terraform_tgc.rb @@ -16,7 +16,7 @@ module Provider # Code generator for a library converting terraform state to gcp objects. - class TerraformValidator < Provider::Terraform + class TerraformGoogleConversion < Provider::Terraform def generating_hashicorp_repo? # This code is not used when generating TPG/TPGB false @@ -56,7 +56,7 @@ def generate_resource(pwd, data, _generate_code, _generate_docs) object_name = data.object.name.underscore target = "#{product_name}_#{object_name}.go" data.generate(pwd, - 'templates/validator/resource_converter.go.erb', + 'templates/tgc/resource_converter.go.erb', File.join(output_folder, target), self) replace_import_path(output_folder, target) @@ -70,11 +70,11 @@ def retrieve_list_of_manually_defined_tests_from_file(file) def retrieve_list_of_manually_defined_tests m1 = retrieve_list_of_manually_defined_tests_from_file( - 'third_party/validator/tests/source/cli_test.go.erb' + 'third_party/tgc/tests/source/cli_test.go.erb' ) m2 = retrieve_list_of_manually_defined_tests_from_file( - 'third_party/validator/tests/source/read_test.go.erb' + 'third_party/tgc/tests/source/read_test.go.erb' ) m1 | m2 # union of manually defined tests end @@ -94,7 +94,7 @@ def validate_non_defined_tests(file_set, non_defined_tests) end def retrieve_full_list_of_test_files - files = Dir['third_party/validator/tests/data/*'] + files = Dir['third_party/tgc/tests/data/*'] files = files.map { |file| file.split('/')[-1] } files.sort end @@ -102,7 +102,7 @@ def retrieve_full_list_of_test_files def retrieve_full_list_of_test_files_with_location files = retrieve_full_list_of_test_files files.map do |file| - ["testdata/templates/#{file}", "third_party/validator/tests/data/#{file}"] + ["testdata/templates/#{file}", "third_party/tgc/tests/data/#{file}"] end end @@ -124,7 +124,7 @@ def retrieve_test_source_files(path, suffix) end def retrieve_test_source_code_with_location(suffix) - path = 'third_party/validator/tests/source/' + path = 'third_party/tgc/tests/source/' files = retrieve_test_source_files(path, suffix) files.map do |file| ["test/#{file}", path + file] @@ -176,9 +176,9 @@ def compile_common_files(output_folder, products, _common_compile_file) ['converters/google/resources/transport/provider_handwritten_endpoint.go', 'third_party/terraform/transport/provider_handwritten_endpoint.go.erb'], ['converters/google/resources/resource_converters.go', - 'templates/validator/resource_converters.go.erb'], + 'templates/tgc/resource_converters.go.erb'], ['converters/google/resources/mappers.go', - 'templates/validator/mappers/mappers.go.erb'], + 'templates/tgc/mappers/mappers.go.erb'], ['converters/google/resources/services/kms/iam_kms_key_ring.go', 'third_party/terraform/services/kms/iam_kms_key_ring.go.erb'], ['converters/google/resources/services/kms/iam_kms_crypto_key.go', @@ -186,7 +186,7 @@ def compile_common_files(output_folder, products, _common_compile_file) ['converters/google/resources/services/compute/metadata.go', 'third_party/terraform/services/compute/metadata.go.erb'], ['converters/google/resources/services/compute/compute_instance.go', - 'third_party/validator/compute_instance.go.erb'] + 'third_party/tgc/compute_instance.go.erb'] ], file_template ) @@ -208,71 +208,71 @@ def copy_common_files(output_folder, generate_code, _generate_docs) copy_file_list(output_folder, [ ['converters/google/resources/tpgresource/constants.go', - 'third_party/validator/tpgresource/constants.go'], + 'third_party/tgc/tpgresource/constants.go'], ['converters/google/resources/constants.go', - 'third_party/validator/constants.go'], + 'third_party/tgc/constants.go'], ['converters/google/resources/cai.go', - 'third_party/validator/cai.go'], + 'third_party/tgc/cai.go'], ['converters/google/resources/tpgresource/cai.go', - 'third_party/validator/tpgresource/cai.go'], + 'third_party/tgc/tpgresource/cai.go'], ['converters/google/resources/tpgresource/cai_test.go', - 'third_party/validator/tpgresource/cai_test.go'], + 'third_party/tgc/tpgresource/cai_test.go'], ['converters/google/resources/org_policy_policy.go', - 'third_party/validator/org_policy_policy.go'], + 'third_party/tgc/org_policy_policy.go'], ['converters/google/resources/getconfig.go', - 'third_party/validator/getconfig.go'], + 'third_party/tgc/getconfig.go'], ['converters/google/resources/folder.go', - 'third_party/validator/folder.go'], + 'third_party/tgc/folder.go'], ['converters/google/resources/getconfig_test.go', - 'third_party/validator/getconfig_test.go'], + 'third_party/tgc/getconfig_test.go'], ['converters/google/resources/transport/config_test_utils.go', 'third_party/terraform/transport/config_test_utils.go'], ['converters/google/resources/tpgresource/json_map.go', - 'third_party/validator/tpgresource/json_map.go'], + 'third_party/tgc/tpgresource/json_map.go'], ['converters/google/resources/json_map.go', - 'third_party/validator/json_map.go'], + 'third_party/tgc/json_map.go'], ['converters/google/resources/project.go', - 'third_party/validator/project.go'], + 'third_party/tgc/project.go'], ['converters/google/resources/sql_database_instance.go', - 'third_party/validator/sql_database_instance.go'], + 'third_party/tgc/sql_database_instance.go'], ['converters/google/resources/storage_bucket.go', - 'third_party/validator/storage_bucket.go'], + 'third_party/tgc/storage_bucket.go'], ['converters/google/resources/cloudfunctions_function.go', - 'third_party/validator/cloudfunctions_function.go'], + 'third_party/tgc/cloudfunctions_function.go'], ['converters/google/resources/transport/dcl.go', - 'third_party/validator/dcl.go'], + 'third_party/tgc/dcl.go'], ['converters/google/resources/cloudfunctions_cloud_function.go', - 'third_party/validator/cloudfunctions_cloud_function.go'], + 'third_party/tgc/cloudfunctions_cloud_function.go'], ['converters/google/resources/bigquery_table.go', - 'third_party/validator/bigquery_table.go'], + 'third_party/tgc/bigquery_table.go'], ['converters/google/resources/bigtable_cluster.go', - 'third_party/validator/bigtable_cluster.go'], + 'third_party/tgc/bigtable_cluster.go'], ['converters/google/resources/bigtable_instance.go', - 'third_party/validator/bigtable_instance.go'], + 'third_party/tgc/bigtable_instance.go'], ['converters/google/resources/tpgiamresource/iam_helpers.go', - 'third_party/validator/tpgiamresource/iam_helpers.go'], + 'third_party/tgc/tpgiamresource/iam_helpers.go'], ['converters/google/resources/iam_helpers.go', - 'third_party/validator/iam_helpers.go'], + 'third_party/tgc/iam_helpers.go'], ['converters/google/resources/tpgiamresource/iam_helpers_test.go', - 'third_party/validator/tpgiamresource/iam_helpers_test.go'], + 'third_party/tgc/tpgiamresource/iam_helpers_test.go'], ['converters/google/resources/organization_iam.go', - 'third_party/validator/organization_iam.go'], + 'third_party/tgc/organization_iam.go'], ['converters/google/resources/project_iam.go', - 'third_party/validator/project_iam.go'], + 'third_party/tgc/project_iam.go'], ['converters/google/resources/project_organization_policy.go', - 'third_party/validator/project_organization_policy.go'], + 'third_party/tgc/project_organization_policy.go'], ['converters/google/resources/folder_organization_policy.go', - 'third_party/validator/folder_organization_policy.go'], + 'third_party/tgc/folder_organization_policy.go'], ['converters/google/resources/folder_iam.go', - 'third_party/validator/folder_iam.go'], + 'third_party/tgc/folder_iam.go'], ['converters/google/resources/container.go', - 'third_party/validator/container.go'], + 'third_party/tgc/container.go'], ['converters/google/resources/project_service.go', - 'third_party/validator/project_service.go'], + 'third_party/tgc/project_service.go'], ['converters/google/resources/services/monitoring/monitoring_slo_helper.go', - 'third_party/validator/monitoring_slo_helper.go'], + 'third_party/tgc/monitoring_slo_helper.go'], ['converters/google/resources/service_account.go', - 'third_party/validator/service_account.go'], + 'third_party/tgc/service_account.go'], ['converters/google/resources/services/compute/image.go', 'third_party/terraform/services/compute/image.go'], ['converters/google/resources/import.go', @@ -366,7 +366,7 @@ def copy_common_files(output_folder, generate_code, _generate_docs) ['converters/google/resources/utils.go', 'third_party/terraform/utils/utils.go'], ['converters/google/resources/acctest/test_utils.go', - 'third_party/validator/test_utils.go'], + 'third_party/tgc/test_utils.go'], ['converters/google/resources/tpgresource/utils.go', 'third_party/terraform/tpgresource/utils.go'], ['converters/google/resources/iam_bigquery_dataset.go', @@ -374,35 +374,35 @@ def copy_common_files(output_folder, generate_code, _generate_docs) ['converters/google/resources/services/bigquery/iam_bigquery_dataset.go', 'third_party/terraform/services/bigquery/iam_bigquery_dataset.go'], ['converters/google/resources/bigquery_dataset_iam.go', - 'third_party/validator/bigquery_dataset_iam.go'], + 'third_party/tgc/bigquery_dataset_iam.go'], ['converters/google/resources/compute_security_policy.go', - 'third_party/validator/compute_security_policy.go'], + 'third_party/tgc/compute_security_policy.go'], ['converters/google/resources/kms_key_ring_iam.go', - 'third_party/validator/kms_key_ring_iam.go'], + 'third_party/tgc/kms_key_ring_iam.go'], ['converters/google/resources/kms_crypto_key_iam.go', - 'third_party/validator/kms_crypto_key_iam.go'], + 'third_party/tgc/kms_crypto_key_iam.go'], ['converters/google/resources/project_iam_custom_role.go', - 'third_party/validator/project_iam_custom_role.go'], + 'third_party/tgc/project_iam_custom_role.go'], ['converters/google/resources/organization_iam_custom_role.go', - 'third_party/validator/organization_iam_custom_role.go'], + 'third_party/tgc/organization_iam_custom_role.go'], ['converters/google/resources/services/pubsub/iam_pubsub_subscription.go', 'third_party/terraform/services/pubsub/iam_pubsub_subscription.go'], ['converters/google/resources/services/pubsub/pubsub_subscription_iam.go', - 'third_party/validator/pubsub_subscription_iam.go'], + 'third_party/tgc/pubsub_subscription_iam.go'], ['converters/google/resources/services/spanner/iam_spanner_database.go', 'third_party/terraform/services/spanner/iam_spanner_database.go'], ['converters/google/resources/services/spanner/spanner_database_iam.go', - 'third_party/validator/spanner_database_iam.go'], + 'third_party/tgc/spanner_database_iam.go'], ['converters/google/resources/services/spanner/iam_spanner_instance.go', 'third_party/terraform/services/spanner/iam_spanner_instance.go'], ['converters/google/resources/services/spanner/spanner_instance_iam.go', - 'third_party/validator/spanner_instance_iam.go'], + 'third_party/tgc/spanner_instance_iam.go'], ['converters/google/resources/storage_bucket_iam.go', - 'third_party/validator/storage_bucket_iam.go'], + 'third_party/tgc/storage_bucket_iam.go'], ['converters/google/resources/organization_policy.go', - 'third_party/validator/organization_policy.go'], + 'third_party/tgc/organization_policy.go'], ['converters/google/resources/iam_storage_bucket.go', - 'third_party/validator/iam_storage_bucket.go'] + 'third_party/tgc/iam_storage_bucket.go'] ]) end @@ -421,7 +421,7 @@ def generate_resource_tests(pwd, data) FileUtils.mkpath folder_name(data.version) data.generate( pwd, - 'templates/validator/examples/base_configs/test_file.go.erb', + 'templates/tgc/examples/base_configs/test_file.go.erb', "test/resource_#{full_resource_name(data)}_generated_test.go", self ) @@ -446,7 +446,7 @@ def generate_iam_policy(pwd, data, generate_code, _generate_docs) FileUtils.mkpath output_folder target = "#{product_name_underscore}_#{name}_iam.go" data.generate(pwd, - 'templates/validator/resource_converter_iam.go.erb', + 'templates/tgc/resource_converter_iam.go.erb', File.join(output_folder, target), self) replace_import_path(output_folder, target) diff --git a/mmv1/templates/terraform/constants/agent_pool.go.erb b/mmv1/templates/terraform/constants/agent_pool.go.erb index 76afc811cca2..3fc74c542878 100644 --- a/mmv1/templates/terraform/constants/agent_pool.go.erb +++ b/mmv1/templates/terraform/constants/agent_pool.go.erb @@ -1,4 +1,4 @@ -<% unless compiler == "terraformvalidator-codegen" -%> +<% unless compiler == "terraformgoogleconversion-codegen" -%> // waitForAgentPoolReady waits for an agent pool to leave the // "CREATING" state and become "CREATED", to indicate that it's ready. func waitForAgentPoolReady(d *schema.ResourceData, config *transport_tpg.Config, timeout time.Duration) error { @@ -19,4 +19,4 @@ func waitForAgentPoolReady(d *schema.ResourceData, config *transport_tpg.Config, } }) } -<% end -%> \ No newline at end of file +<% end -%> diff --git a/mmv1/templates/terraform/constants/datastream_stream.go.erb b/mmv1/templates/terraform/constants/datastream_stream.go.erb index d81ec0d71de0..3470e6a67940 100644 --- a/mmv1/templates/terraform/constants/datastream_stream.go.erb +++ b/mmv1/templates/terraform/constants/datastream_stream.go.erb @@ -43,7 +43,7 @@ func resourceDatastreamStreamCustomDiff(_ context.Context, diff *schema.Resource return resourceDatastreamStreamCustomDiffFunc(diff) } -<% unless compiler == "terraformvalidator-codegen" -%> +<% unless compiler == "terraformgoogleconversion-codegen" -%> // waitForDatastreamStreamReady waits for an agent pool to reach a stable state to indicate that it's ready. func waitForDatastreamStreamReady(d *schema.ResourceData, config *transport_tpg.Config, timeout time.Duration) error { return resource.Retry(timeout, func() *resource.RetryError { diff --git a/mmv1/templates/terraform/constants/disk.erb b/mmv1/templates/terraform/constants/disk.erb index 25a44ca4e622..52cc7aecd070 100644 --- a/mmv1/templates/terraform/constants/disk.erb +++ b/mmv1/templates/terraform/constants/disk.erb @@ -1,5 +1,5 @@ -<% unless compiler == "terraformvalidator-codegen" -%> +<% unless compiler == "terraformgoogleconversion-codegen" -%> // diffsupress for hyperdisk provisioned_iops func hyperDiskIopsUpdateDiffSupress(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { if !strings.Contains(d.Get("type").(string), "hyperdisk") { diff --git a/mmv1/templates/terraform/constants/interconnect_attachment.go.erb b/mmv1/templates/terraform/constants/interconnect_attachment.go.erb index cfd526af2576..f8d4ad8baa46 100644 --- a/mmv1/templates/terraform/constants/interconnect_attachment.go.erb +++ b/mmv1/templates/terraform/constants/interconnect_attachment.go.erb @@ -1,4 +1,4 @@ -<% unless compiler == "terraformvalidator-codegen" -%> +<% unless compiler == "terraformgoogleconversion-codegen" -%> // waitForAttachmentToBeProvisioned waits for an attachment to leave the // "UNPROVISIONED" state, to indicate that it's either ready or awaiting partner // activity. diff --git a/mmv1/templates/terraform/constants/private_connection.go.erb b/mmv1/templates/terraform/constants/private_connection.go.erb index 1f0e9beedf9e..79812d25b564 100644 --- a/mmv1/templates/terraform/constants/private_connection.go.erb +++ b/mmv1/templates/terraform/constants/private_connection.go.erb @@ -1,4 +1,4 @@ -<% unless compiler == "terraformvalidator-codegen" -%> +<% unless compiler == "terraformgoogleconversion-codegen" -%> func extractError(d *schema.ResourceData) error { // Casts are not safe since the logic that populate it is type deterministic. diff --git a/mmv1/templates/terraform/constants/secret_version.go.erb b/mmv1/templates/terraform/constants/secret_version.go.erb index eddaf950713a..0881353f43ca 100644 --- a/mmv1/templates/terraform/constants/secret_version.go.erb +++ b/mmv1/templates/terraform/constants/secret_version.go.erb @@ -1,4 +1,4 @@ -<% unless compiler == "terraformvalidator-codegen" -%> +<% unless compiler == "terraformgoogleconversion-codegen" -%> func resourceSecretManagerSecretVersionUpdate(d *schema.ResourceData, meta interface{}) error { config := meta.(*transport_tpg.Config) @@ -9,4 +9,4 @@ func resourceSecretManagerSecretVersionUpdate(d *schema.ResourceData, meta inter return resourceSecretManagerSecretVersionRead(d, meta) } -<% end -%> \ No newline at end of file +<% end -%> diff --git a/mmv1/templates/terraform/custom_check_destroy/billing_project_info.go.erb b/mmv1/templates/terraform/custom_check_destroy/billing_project_info.go.erb new file mode 100644 index 000000000000..68a1438af056 --- /dev/null +++ b/mmv1/templates/terraform/custom_check_destroy/billing_project_info.go.erb @@ -0,0 +1,27 @@ +// After deleting a project, you can still query its billing account +// (it will be empty). We change the destroy check to ensure the +// project has no billing account linked after destroying the +// google_billing_project_info resource + +config := GoogleProviderConfig(t) + +url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{CoreBillingBasePath}}projects/{{project}}/billingInfo") +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 nil +} + +if ba := res["billingAccountName"]; ba == "" { + return nil +} + +return fmt.Errorf("Billing account still linked at %s", url) diff --git a/mmv1/templates/terraform/custom_expand/subnetwork_log_config.go.erb b/mmv1/templates/terraform/custom_expand/subnetwork_log_config.go.erb index 4e69ad7a2c8a..ba30a64eb5c7 100644 --- a/mmv1/templates/terraform/custom_expand/subnetwork_log_config.go.erb +++ b/mmv1/templates/terraform/custom_expand/subnetwork_log_config.go.erb @@ -18,8 +18,8 @@ func expand<%= prefix -%><%= titlelize_property(property) -%>(v interface{}, d t if len(l) == 0 || l[0] == nil { purpose, ok := d.GetOkExists("purpose") - if ok &&(purpose.(string) == "REGIONAL_MANAGED_PROXY" || purpose.(string) == "INTERNAL_HTTPS_LOAD_BALANCER") { - // Subnetworks for regional L7 ILB/XLB do not accept any values for logConfig + if ok &&(purpose.(string) == "REGIONAL_MANAGED_PROXY" || purpose.(string) == "GLOBAL_MANAGED_PROXY" || purpose.(string) == "INTERNAL_HTTPS_LOAD_BALANCER") { + // Subnetworks for regional L7 ILB/XLB or cross-regional L7 ILB do not accept any values for logConfig return nil, nil } // send enable = false to ensure logging is disabled if there is no config diff --git a/mmv1/templates/terraform/custom_import/document_ai_warehouse_document_schema.go.erb b/mmv1/templates/terraform/custom_import/document_ai_warehouse_document_schema.go.erb new file mode 100644 index 000000000000..f24c80976052 --- /dev/null +++ b/mmv1/templates/terraform/custom_import/document_ai_warehouse_document_schema.go.erb @@ -0,0 +1,17 @@ +config := meta.(*transport_tpg.Config) + +if err := tpgresource.ParseImportId([]string{ + "projects/(?P[^/]+)/locations/(?P[^/]+)/documentSchemas/(?P[^/]+)"}, d, config); err != nil { + return nil, err +} + +originalName := d.Get("name").(string) +originalLocation := d.Get("location").(string) +originalProject := d.Get("project_number").(string) +name := fmt.Sprintf("projects/%s/locations/%s/documentSchemas/%s", originalProject, originalLocation, originalName) + +if err := d.Set("name", name); err != nil { + return nil, fmt.Errorf("Error setting name: %s", err) +} +d.SetId(name) +return []*schema.ResourceData{d}, nil diff --git a/mmv1/templates/terraform/decoders/billing_project_info.go.erb b/mmv1/templates/terraform/decoders/billing_project_info.go.erb new file mode 100644 index 000000000000..1d00154311e8 --- /dev/null +++ b/mmv1/templates/terraform/decoders/billing_project_info.go.erb @@ -0,0 +1,2 @@ +res["billing_account"] = strings.TrimPrefix(res["billingAccountName"].(string), "billingAccounts/") +return res, nil diff --git a/mmv1/templates/terraform/encoders/billing_project_info.go.erb b/mmv1/templates/terraform/encoders/billing_project_info.go.erb new file mode 100644 index 000000000000..1928c246a990 --- /dev/null +++ b/mmv1/templates/terraform/encoders/billing_project_info.go.erb @@ -0,0 +1,8 @@ +ba := d.Get("billing_account").(string) +if ba == "" { + obj["billingAccountName"] = "" +} else { + obj["billingAccountName"] = "billingAccounts/" + ba +} +delete(obj, "billing_account") +return obj, nil diff --git a/mmv1/templates/terraform/encoders/service_connection_policy.go.erb b/mmv1/templates/terraform/encoders/service_connection_policy.go.erb new file mode 100644 index 000000000000..0a3866b9aca9 --- /dev/null +++ b/mmv1/templates/terraform/encoders/service_connection_policy.go.erb @@ -0,0 +1,2 @@ +obj["network"] = d.Get("network").(string) +return obj, nil diff --git a/mmv1/templates/terraform/encoders/spanner_database.go.erb b/mmv1/templates/terraform/encoders/spanner_database.go.erb index 05d4de9f2f8e..59cc52a59c32 100644 --- a/mmv1/templates/terraform/encoders/spanner_database.go.erb +++ b/mmv1/templates/terraform/encoders/spanner_database.go.erb @@ -11,9 +11,9 @@ log.Printf("[DEBUG] Preparing to create new Database. Any extra DDL statements w delete(obj, "name") delete(obj, "instance") <%# These are added back in post-create, but do not remove for Validator. %> -<% unless compiler == "terraformvalidator-codegen" -%> +<% unless compiler == "terraformgoogleconversion-codegen" -%> delete(obj, "versionRetentionPeriod") delete(obj, "extraStatements") delete(obj, "enableDropProtection") <% end -%> -return obj, nil \ No newline at end of file +return obj, nil diff --git a/mmv1/templates/terraform/examples/alloydb_cluster_full.tf.erb b/mmv1/templates/terraform/examples/alloydb_cluster_full.tf.erb index 2378c8e340b8..3d7ed2204076 100644 --- a/mmv1/templates/terraform/examples/alloydb_cluster_full.tf.erb +++ b/mmv1/templates/terraform/examples/alloydb_cluster_full.tf.erb @@ -8,6 +8,11 @@ resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { password = "<%= ctx[:vars]['alloydb_cluster_name'] %>" } + continuous_backup_config { + enabled = true + recovery_window_days = 14 + } + automated_backup_policy { location = "us-central1" backup_window = "1800s" diff --git a/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb b/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb index 2d3f52e2ebb5..f6907cd44237 100644 --- a/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb +++ b/mmv1/templates/terraform/examples/alloydb_instance_basic.tf.erb @@ -13,7 +13,7 @@ resource "google_alloydb_instance" "<%= ctx[:primary_resource_id] %>" { resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { cluster_id = "<%= ctx[:vars]['alloydb_cluster_name'] %>" location = "us-central1" - network = google_compute_network.default.id + network = data.google_compute_network.default.id initial_user { password = "<%= ctx[:vars]['alloydb_cluster_name'] %>" @@ -22,8 +22,8 @@ resource "google_alloydb_cluster" "<%= ctx[:primary_resource_id] %>" { data "google_project" "project" {} -resource "google_compute_network" "default" { - name = "<%= ctx[:vars]['alloydb_cluster_name'] %>" +data "google_compute_network" "default" { + name = "<%= ctx[:vars]['network_name'] %>" } resource "google_compute_global_address" "private_ip_alloc" { @@ -31,11 +31,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/app_engine_firewall_rule_basic.tf.erb b/mmv1/templates/terraform/examples/app_engine_firewall_rule_basic.tf.erb index d21956cd3191..057f23b2e268 100644 --- a/mmv1/templates/terraform/examples/app_engine_firewall_rule_basic.tf.erb +++ b/mmv1/templates/terraform/examples/app_engine_firewall_rule_basic.tf.erb @@ -2,6 +2,7 @@ resource "google_project" "my_project" { name = "tf-test-project" project_id = "<%= ctx[:vars]['project_id'] %>" org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" } resource "google_app_engine_application" "app" { diff --git a/mmv1/templates/terraform/examples/backend_service_unspecified_protocol_simple.tf.erb b/mmv1/templates/terraform/examples/backend_service_unspecified_protocol_simple.tf.erb new file mode 100644 index 000000000000..7eae6686236a --- /dev/null +++ b/mmv1/templates/terraform/examples/backend_service_unspecified_protocol_simple.tf.erb @@ -0,0 +1,15 @@ +resource "google_compute_backend_service" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['backend_service_name'] %>" + health_checks = [google_compute_http_health_check.default.id] + protocol = "UNSPECIFIED" + region = "us-central1" + load_balancing_scheme = "INTERNAL" + timeout_sec = 30 +} + +resource "google_compute_http_health_check" "default" { + name = "<%= ctx[:vars]['http_health_check_name'] %>" + request_path = "/" + check_interval_sec = 1 + timeout_sec = 1 +} diff --git a/mmv1/templates/terraform/examples/billing_budget_filter.tf.erb b/mmv1/templates/terraform/examples/billing_budget_filter.tf.erb index b5af323ed1c4..ef8c8877dde6 100644 --- a/mmv1/templates/terraform/examples/billing_budget_filter.tf.erb +++ b/mmv1/templates/terraform/examples/billing_budget_filter.tf.erb @@ -14,6 +14,7 @@ resource "google_billing_budget" "<%= ctx[:primary_resource_id] %>" { credit_types_treatment = "INCLUDE_SPECIFIED_CREDITS" services = ["services/24E6-581D-38E5"] # Bigquery credit_types = ["PROMOTION", "FREE_TIER"] + resource_ancestors = ["organizations/<%= ctx[:test_env_vars]['org_id'] %>"] } amount { diff --git a/mmv1/templates/terraform/examples/billing_project_info_basic.tf.erb b/mmv1/templates/terraform/examples/billing_project_info_basic.tf.erb new file mode 100644 index 000000000000..09eb8ed8334c --- /dev/null +++ b/mmv1/templates/terraform/examples/billing_project_info_basic.tf.erb @@ -0,0 +1,13 @@ +resource "google_project" "project" { + project_id = "tf-test%{random_suffix}" + name = "tf-test%{random_suffix}" + org_id = "<%= ctx[:test_env_vars]['org_id'] %>" + lifecycle { + ignore_changes = [billing_account] + } +} + +resource "google_billing_project_info" "<%= ctx[:primary_resource_id] %>" { + project = google_project.project.project_id + billing_account = "<%= ctx[:test_env_vars]['billing_account'] %>" +} diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_bitbucket_server_pull_request.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_bitbucket_server_pull_request.tf.erb index d3a60b89885d..e3966a739a68 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_bitbucket_server_pull_request.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_bitbucket_server_pull_request.tf.erb @@ -1,5 +1,5 @@ resource "google_cloudbuild_trigger" "<%= ctx[:primary_resource_id] %>" { - name = "terraform-bbs-pull-request-trigger" + name = "<%= ctx[:vars]['cloudbuild_trigger_name'] %>" location = "us-central1" bitbucket_server_trigger_config { diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_bitbucket_server_push.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_bitbucket_server_push.tf.erb index 5eda2de7b560..30b2d311b819 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_bitbucket_server_push.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_bitbucket_server_push.tf.erb @@ -1,9 +1,9 @@ resource "google_cloudbuild_trigger" "<%= ctx[:primary_resource_id] %>" { - name = "terraform-bbs-push-trigger" + name = "bbs-push-trigger" location = "us-central1" bitbucket_server_trigger_config { - repo_slug = "terraform-provider-google" + repo_slug = "<%= ctx[:vars]['cloudbuild_trigger_name'] %>" project_key = "STAG" bitbucket_server_config_resource = "projects/123456789/locations/us-central1/bitbucketServerConfigs/myBitbucketConfig" push { diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_github_enterprise.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_github_enterprise.tf.erb index dd69e7caa0bc..40bd7c400a8a 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_github_enterprise.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_github_enterprise.tf.erb @@ -1,5 +1,5 @@ resource "google_cloudbuild_trigger" "<%= ctx[:primary_resource_id] %>" { - name = "terraform-ghe-trigger" + name = "<%= ctx[:vars]['cloudbuild_trigger_name'] %>" location = "us-central1" github { diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_manual.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_manual.tf.erb index f702ab927f4b..636686010584 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_manual.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_manual.tf.erb @@ -1,6 +1,6 @@ resource "google_cloudbuild_trigger" "<%= ctx[:primary_resource_id] %>" { - name = "manual-build" + name = "<%= ctx[:vars]['cloudbuild_trigger_name'] %>" source_to_build { uri = "https://hashicorp/terraform-provider-google-beta" diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_manual_github_enterprise.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_manual_github_enterprise.tf.erb index 7e8450cc7af0..af6ab4cec3cb 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_manual_github_enterprise.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_manual_github_enterprise.tf.erb @@ -1,5 +1,5 @@ resource "google_cloudbuild_trigger" "<%= ctx[:primary_resource_id] %>" { - name = "terraform-manual-ghe-trigger" + name = "<%= ctx[:vars]['cloudbuild_trigger_name'] %>" source_to_build { uri = "https://hashicorp/terraform-provider-google-beta" diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_pubsub_config.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_pubsub_config.tf.erb index dcded0cd0ebb..6b34b0b2d739 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_pubsub_config.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_pubsub_config.tf.erb @@ -1,11 +1,11 @@ resource "google_pubsub_topic" "mytopic" { - name = "mytopic" + name = "<%= ctx[:vars]['pubsub_topic_name'] %>" } resource "google_cloudbuild_trigger" "<%= ctx[:primary_resource_id] %>" { location = "us-central1" - name = "pubsub-trigger" + name = "<%= ctx[:vars]['cloudbuild_trigger_name'] %>" description = "acceptance test example pubsub build trigger" pubsub_config { diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_pubsub_with_repo.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_pubsub_with_repo.tf.erb index 23bc2500e22f..795f2735d6a9 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_pubsub_with_repo.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_pubsub_with_repo.tf.erb @@ -1,6 +1,6 @@ resource "google_cloudbuildv2_connection" "my-connection" { location = "us-central1" - name = "my-connection" + name = "<%= ctx[:vars]['cloudbuildv2_connection_name'] %>" github_config { app_installation_id = <%= ctx[:vars]['installation_id'] %> @@ -11,17 +11,17 @@ resource "google_cloudbuildv2_connection" "my-connection" { } resource "google_cloudbuildv2_repository" "my-repository" { - name = "my-repo" + name = "<%= ctx[:vars]['cloudbuildv2_repo_name'] %>" parent_connection = google_cloudbuildv2_connection.my-connection.id remote_uri = "<%= ctx[:vars]['repo_uri'] %>" } resource "google_pubsub_topic" "mytopic" { - name = "mytopic" + name = "<%= ctx[:vars]['pubsub_topic_name'] %>" } resource "google_cloudbuild_trigger" "<%= ctx[:primary_resource_id] %>" { - name = "pubsub-with-repo-trigger" + name = "<%= ctx[:vars]['cloudbuild_trigger_name'] %>" location = "us-central1" pubsub_config { diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_repo.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_repo.tf.erb index bea577a37ccc..83628908bbaf 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_repo.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_repo.tf.erb @@ -1,6 +1,6 @@ resource "google_cloudbuildv2_connection" "my-connection" { location = "us-central1" - name = "my-connection" + name = "<%= ctx[:vars]['cloudbuildv2_connection_name'] %>" github_config { app_installation_id = <%= ctx[:vars]['installation_id'] %> @@ -11,7 +11,7 @@ resource "google_cloudbuildv2_connection" "my-connection" { } resource "google_cloudbuildv2_repository" "my-repository" { - name = "my-repo" + name = "<%= ctx[:vars]['cloudbuildv2_repo_name'] %>" parent_connection = google_cloudbuildv2_connection.my-connection.id remote_uri = "<%= ctx[:vars]['repo_uri'] %>" } diff --git a/mmv1/templates/terraform/examples/cloudbuild_trigger_webhook_config.tf.erb b/mmv1/templates/terraform/examples/cloudbuild_trigger_webhook_config.tf.erb index 85a47d08a25e..1f270b706fc6 100644 --- a/mmv1/templates/terraform/examples/cloudbuild_trigger_webhook_config.tf.erb +++ b/mmv1/templates/terraform/examples/cloudbuild_trigger_webhook_config.tf.erb @@ -1,6 +1,6 @@ resource "google_secret_manager_secret" "webhook_trigger_secret_key" { - secret_id = "webhook_trigger-secret-key-1" + secret_id = "<%= ctx[:vars]['secret_id'] %>" replication { user_managed { @@ -36,7 +36,7 @@ resource "google_secret_manager_secret_iam_policy" "policy" { resource "google_cloudbuild_trigger" "<%= ctx[:primary_resource_id] %>" { - name = "webhook-trigger" + name = "<%= ctx[:vars]['cloudbuild_trigger_name'] %>" description = "acceptance test example webhook build trigger" webhook_config { diff --git a/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb b/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb new file mode 100644 index 000000000000..9ad4af6978f4 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudfunctions2_cmek.tf.erb @@ -0,0 +1,113 @@ +locals { + project = "<%= ctx[:test_env_vars]['project'] %>" # Google Cloud Platform Project ID +} + +data "google_project" "project" { + provider = google-beta +} + +resource "google_storage_bucket" "bucket" { + provider = google-beta + + name = "${local.project}-<%= ctx[:vars]['bucket_name'] %>" # Every bucket name must be globally unique + location = "US" + uniform_bucket_level_access = true +} + +resource "google_storage_bucket_object" "object" { + provider = google-beta + + name = "function-source.zip" + bucket = google_storage_bucket.bucket.name + source = "<%= ctx[:vars]['zip_path'] %>" # Add path to the zipped function source code +} + +resource "google_project_service_identity" "ea_sa" { + provider = google-beta + + project = data.google_project.project.project_id + service = "eventarc.googleapis.com" +} + +resource "google_artifact_registry_repository" "unencoded-ar-repo" { + provider = google-beta + + repository_id = "<%= ctx[:vars]['unencoded-ar-repo'] %>" + location = "us-central1" + format = "DOCKER" +} + +resource "google_artifact_registry_repository_iam_binding" "binding" { + provider = google-beta + + location = google_artifact_registry_repository.encoded-ar-repo.location + repository = google_artifact_registry_repository.encoded-ar-repo.name + role = "roles/artifactregistry.admin" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", + ] +} + +resource "google_kms_crypto_key_iam_binding" "gcf_cmek_keyuser" { + provider = google-beta + + crypto_key_id = "<%= ctx[:vars]['kms_key_name'] %>" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcf-admin-robot.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-artifactregistry.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@gs-project-accounts.iam.gserviceaccount.com", + "serviceAccount:service-${data.google_project.project.number}@serverless-robot-prod.iam.gserviceaccount.com", + "serviceAccount:${google_project_service_identity.ea_sa.email}", + ] + + depends_on = [ + google_project_service_identity.ea_sa + ] +} + +resource "google_artifact_registry_repository" "encoded-ar-repo" { + provider = google-beta + + location = "us-central1" + repository_id = "<%= ctx[:vars]['cmek-repo'] %>" + format = "DOCKER" + kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" + depends_on = [ + google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + ] +} + +resource "google_cloudfunctions2_function" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + + name = "<%= ctx[:vars]['function'] %>" + location = "us-central1" + description = "CMEK function" + kms_key_name = "<%= ctx[:vars]['kms_key_name'] %>" + + build_config { + runtime = "nodejs16" + entry_point = "helloHttp" # Set the entry point + docker_repository = google_artifact_registry_repository.encoded-ar-repo.id + + source { + storage_source { + bucket = google_storage_bucket.bucket.name + object = google_storage_bucket_object.object.name + } + } + } + + service_config { + max_instance_count = 1 + available_memory = "256M" + timeout_seconds = 60 + } + + depends_on = [ + google_kms_crypto_key_iam_binding.gcf_cmek_keyuser + ] + +} diff --git a/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb b/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb index 96384e6e4b58..68a6ea686b57 100644 --- a/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb +++ b/mmv1/templates/terraform/examples/database_migration_service_connection_profile_alloydb.tf.erb @@ -1,7 +1,7 @@ data "google_project" "project" { } -resource "google_compute_network" "default" { +data "google_compute_network" "default" { name = "<%= ctx[:vars]['network_name'] %>" } @@ -10,11 +10,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -34,7 +34,7 @@ resource "google_database_migration_service_connection_profile" "<%= ctx[:primar user = "alloyuser%{random_suffix}" password = "alloypass%{random_suffix}" } - vpc_network = google_compute_network.default.id + vpc_network = data.google_compute_network.default.id labels = { alloyfoo = "alloybar" } diff --git a/mmv1/templates/terraform/examples/dataform_repository_release_config.tf.erb b/mmv1/templates/terraform/examples/dataform_repository_release_config.tf.erb new file mode 100644 index 000000000000..0f44c43374bc --- /dev/null +++ b/mmv1/templates/terraform/examples/dataform_repository_release_config.tf.erb @@ -0,0 +1,64 @@ +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 = "secret" + + replication { + automatic = true + } +} + +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" "repository" { + provider = google-beta + name = "<%= ctx[:vars]['dataform_repository_name'] %>" + region = "us-central1" + + 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_" + } +} + +resource "google_dataform_repository_release_config" "<%= ctx[:primary_resource_id] %>" { + provider = google-beta + + project = google_dataform_repository.repository.project + region = google_dataform_repository.repository.region + repository = google_dataform_repository.repository.name + + name = "<%= ctx[:vars]['release_name'] %>" + git_commitish = "main" + cron_schedule = "0 7 * * *" + time_zone = "America/New_York" + + code_compilation_config { + default_database = "gcp-example-project" + default_schema = "example-dataset" + default_location = "us-central1" + assertion_schema = "example-assertion-dataset" + database_suffix = "" + schema_suffix = "" + table_prefix = "" + vars = { + var1 = "value" + } + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_datetime.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_datetime.tf.erb new file mode 100644 index 000000000000..1e3e4f35b060 --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_datetime.tf.erb @@ -0,0 +1,24 @@ +resource "google_document_ai_warehouse_document_schema" "example_datetime" { + project_number = data.google_project.project.number + display_name = "test-property-date_time" + location = "us" + + property_definitions { + name = "prop7" + display_name = "propdisp7" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + date_time_type_options {} + } +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_enum.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_enum.tf.erb new file mode 100644 index 000000000000..b763f2fad385 --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_enum.tf.erb @@ -0,0 +1,31 @@ +resource "google_document_ai_warehouse_document_schema" "example_enum" { + project_number = data.google_project.project.number + display_name = "test-property-enum" + location = "us" + + property_definitions { + name = "prop6" + display_name = "propdisp6" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + enum_type_options { + possible_values = [ + "M", + "F", + "X" + ] + validation_check_disabled = false + } + } +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_float.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_float.tf.erb new file mode 100644 index 000000000000..96d30784152b --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_float.tf.erb @@ -0,0 +1,23 @@ +resource "google_document_ai_warehouse_document_schema" "example_float" { + project_number = data.google_project.project.number + display_name = "test-property-float" + location = "us" + + property_definitions { + name = "prop2" + display_name = "propdisp2" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + float_type_options {} + } +} +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_integer.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_integer.tf.erb new file mode 100644 index 000000000000..9c0ef30e6b4f --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_integer.tf.erb @@ -0,0 +1,24 @@ +resource "google_document_ai_warehouse_document_schema" "example_integer" { + project_number = data.google_project.project.number + display_name = "test-property-integer" + location = "us" + + property_definitions { + name = "prop1" + display_name = "propdisp1" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + integer_type_options {} + } +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_map.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_map.tf.erb new file mode 100644 index 000000000000..11796b01b0e8 --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_map.tf.erb @@ -0,0 +1,24 @@ +resource "google_document_ai_warehouse_document_schema" "example_map" { + project_number = data.google_project.project.number + display_name = "test-property-map" + location = "us" + + property_definitions { + name = "prop4" + display_name = "propdisp4" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + map_type_options {} + } +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_property.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_property.tf.erb new file mode 100644 index 000000000000..bd0ba6ee0976 --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_property.tf.erb @@ -0,0 +1,41 @@ +resource "google_document_ai_warehouse_document_schema" "example_property" { + project_number = data.google_project.project.number + display_name = "test-property-property" + location = "us" + document_is_folder = false + + property_definitions { + name = "prop8" + display_name = "propdisp8" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + property_type_options { + property_definitions { + name = "prop8_nested" + display_name = "propdisp8_nested" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source_nested" + processor_type = "dummy_processor_nested" + } + text_type_options {} + } + } + } +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_property_enum.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_property_enum.tf.erb new file mode 100644 index 000000000000..19eb0553b6c7 --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_property_enum.tf.erb @@ -0,0 +1,48 @@ +resource "google_document_ai_warehouse_document_schema" "example_property_enum" { + project_number = data.google_project.project.number + display_name = "test-property-property" + location = "us" + document_is_folder = false + + property_definitions { + name = "prop8" + display_name = "propdisp8" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + property_type_options { + property_definitions { + name = "prop8_nested" + display_name = "propdisp8_nested" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source_nested" + processor_type = "dummy_processor_nested" + } + enum_type_options { + possible_values = [ + "M", + "F", + "X" + ] + validation_check_disabled = false + } + } + } + } +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_text.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_text.tf.erb new file mode 100644 index 000000000000..d7f797fbe114 --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_text.tf.erb @@ -0,0 +1,25 @@ +resource "google_document_ai_warehouse_document_schema" "example_text" { + project_number = data.google_project.project.number + display_name = "test-property-text" + location = "us" + document_is_folder = false + + property_definitions { + name = "prop3" + display_name = "propdisp3" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + text_type_options {} + } +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_timestamp.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_timestamp.tf.erb new file mode 100644 index 000000000000..417d81fe70fa --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_document_schema_timestamp.tf.erb @@ -0,0 +1,24 @@ +resource "google_document_ai_warehouse_document_schema" "example_timestamp" { + project_number = data.google_project.project.number + display_name = "test-property-timestamp" + location = "us" + + property_definitions { + name = "prop5" + display_name = "propdisp5" + is_repeatable = false + is_filterable = true + is_searchable = true + is_metadata = false + is_required = false + retrieval_importance = "HIGHEST" + schema_sources { + name = "dummy_source" + processor_type = "dummy_processor" + } + timestamp_type_options {} + } +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/document_ai_warehouse_location.tf.erb b/mmv1/templates/terraform/examples/document_ai_warehouse_location.tf.erb new file mode 100644 index 000000000000..28ef1e3f8a78 --- /dev/null +++ b/mmv1/templates/terraform/examples/document_ai_warehouse_location.tf.erb @@ -0,0 +1,11 @@ +resource "google_document_ai_warehouse_location" "<%= ctx[:primary_resource_id] %>" { + location = "us" + project_number = data.google_project.project.number + access_control_mode = "ACL_MODE_DOCUMENT_LEVEL_ACCESS_CONTROL_GCI" + database_type = "DB_INFRA_SPANNER" + kms_key = "dummy_key" + document_creator_default_role = "DOCUMENT_ADMIN" +} + +data "google_project" "project" { +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/forwarding_rule_internallb.tf.erb b/mmv1/templates/terraform/examples/forwarding_rule_internallb.tf.erb index 886884b60af6..857de596a098 100644 --- a/mmv1/templates/terraform/examples/forwarding_rule_internallb.tf.erb +++ b/mmv1/templates/terraform/examples/forwarding_rule_internallb.tf.erb @@ -8,6 +8,7 @@ resource "google_compute_forwarding_rule" "<%= ctx[:primary_resource_id] %>" { all_ports = true network = google_compute_network.default.name subnetwork = google_compute_subnetwork.default.name + ip_version = "IPV4" } resource "google_compute_region_backend_service" "backend" { diff --git a/mmv1/templates/terraform/examples/forwarding_rule_internallb_ipv6.tf.erb b/mmv1/templates/terraform/examples/forwarding_rule_internallb_ipv6.tf.erb new file mode 100644 index 000000000000..c71af6b2132d --- /dev/null +++ b/mmv1/templates/terraform/examples/forwarding_rule_internallb_ipv6.tf.erb @@ -0,0 +1,43 @@ +// Forwarding rule for Internal Load Balancing +resource "google_compute_forwarding_rule" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['forwarding_rule_name'] %>" + region = "us-central1" + + load_balancing_scheme = "INTERNAL" + backend_service = google_compute_region_backend_service.backend.id + all_ports = true + network = google_compute_network.default.name + subnetwork = google_compute_subnetwork.default.name + ip_version = "IPV6" +} + +resource "google_compute_region_backend_service" "backend" { + name = "<%= ctx[:vars]['backend_name'] %>" + region = "us-central1" + health_checks = [google_compute_health_check.hc.id] +} + +resource "google_compute_health_check" "hc" { + name = "check-<%= ctx[:vars]['backend_name'] %>" + check_interval_sec = 1 + timeout_sec = 1 + + tcp_health_check { + port = "80" + } +} + +resource "google_compute_network" "default" { + name = "<%= ctx[:vars]['network_name'] %>" + auto_create_subnetworks = false + enable_ula_internal_ipv6 = true +} + +resource "google_compute_subnetwork" "default" { + name = "<%= ctx[:vars]['subnet_name'] %>" + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" + stack_type = "IPV4_IPV6" + ipv6_access_type = "INTERNAL" + network = google_compute_network.default.id +} diff --git a/mmv1/templates/terraform/examples/global_internal_http_lb_with_mig_backend.tf.erb b/mmv1/templates/terraform/examples/global_internal_http_lb_with_mig_backend.tf.erb new file mode 100644 index 000000000000..25a069dd2ea3 --- /dev/null +++ b/mmv1/templates/terraform/examples/global_internal_http_lb_with_mig_backend.tf.erb @@ -0,0 +1,185 @@ +# Global Internal HTTP load balancer with a managed instance group backend + +# [START cloudloadbalancing_int_http_gce] +# VPC network +resource "google_compute_network" "gilb_network" { + name = "<%= ctx[:vars]['gilb_network_name'] %>" + provider = google-beta + auto_create_subnetworks = false +} + +# proxy-only subnet +resource "google_compute_subnetwork" "proxy_subnet" { + name = "<%= ctx[:vars]['proxy_subnet_name'] %>" + provider = google-beta + ip_cidr_range = "10.0.0.0/24" + region = "europe-west1" + purpose = "GLOBAL_MANAGED_PROXY" + role = "ACTIVE" + network = google_compute_network.gilb_network.id +} + +# backend subnet +resource "google_compute_subnetwork" "gilb_subnet" { + name = "<%= ctx[:vars]['backend_subnet_name'] %>" + provider = google-beta + ip_cidr_range = "10.0.1.0/24" + region = "europe-west1" + network = google_compute_network.gilb_network.id +} + +# forwarding rule +resource "google_compute_global_forwarding_rule" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['forwarding_rule_name'] %>" + provider = google-beta + depends_on = [google_compute_subnetwork.proxy_subnet] + ip_protocol = "TCP" + load_balancing_scheme = "INTERNAL_MANAGED" + port_range = "80" + target = google_compute_target_http_proxy.default.id + network = google_compute_network.gilb_network.id + subnetwork = google_compute_subnetwork.gilb_subnet.id +} + +# HTTP target proxy +resource "google_compute_target_http_proxy" "default" { + name = "<%= ctx[:vars]['target_http_proxy_name'] %>" + provider = google-beta + url_map = google_compute_url_map.default.id +} + +# URL map +resource "google_compute_url_map" "default" { + name = "<%= ctx[:vars]['url_map_name'] %>" + provider = google-beta + default_service = google_compute_backend_service.default.id +} + +# backend service +resource "google_compute_backend_service" "default" { + name = "<%= ctx[:vars]['backend_service_name'] %>" + provider = google-beta + protocol = "HTTP" + load_balancing_scheme = "INTERNAL_MANAGED" + timeout_sec = 10 + health_checks = [google_compute_health_check.default.id] + backend { + group = google_compute_instance_group_manager.mig.instance_group + balancing_mode = "UTILIZATION" + capacity_scaler = 1.0 + } +} + +# instance template +resource "google_compute_instance_template" "instance_template" { + name = "<%= ctx[:vars]['mig_template_name'] %>" + provider = google-beta + machine_type = "e2-small" + tags = ["http-server"] + + network_interface { + network = google_compute_network.gilb_network.id + subnetwork = google_compute_subnetwork.gilb_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 + } +} + +# health check +resource "google_compute_health_check" "default" { + name = "<%= ctx[:vars]['hc_name'] %>" + provider = google-beta + http_health_check { + port_specification = "USE_SERVING_PORT" + } +} + +# MIG +resource "google_compute_instance_group_manager" "mig" { + name = "<%= ctx[:vars]['mig_name'] %>" + provider = google-beta + zone = "europe-west1-b" + version { + instance_template = google_compute_instance_template.instance_template.id + name = "primary" + } + base_instance_name = "vm" + target_size = 2 +} + +# allow all access from IAP and health check ranges +resource "google_compute_firewall" "fw-iap" { + name = "<%= ctx[:vars]['fw_allow_iap_hc_name'] %>" + provider = google-beta + direction = "INGRESS" + network = google_compute_network.gilb_network.id + source_ranges = ["130.211.0.0/22", "35.191.0.0/16", "35.235.240.0/20"] + allow { + protocol = "tcp" + } +} + +# allow http from proxy subnet to backends +resource "google_compute_firewall" "fw-gilb-to-backends" { + name = "<%= ctx[:vars]['fw_allow_gilb_to_backends_name'] %>" + provider = google-beta + direction = "INGRESS" + network = google_compute_network.gilb_network.id + source_ranges = ["10.0.0.0/24"] + target_tags = ["http-server"] + allow { + protocol = "tcp" + ports = ["80", "443", "8080"] + } +} + +# test instance +resource "google_compute_instance" "vm-test" { + name = "<%= ctx[:vars]['vm_test_name'] %>" + provider = google-beta + zone = "europe-west1-b" + machine_type = "e2-small" + network_interface { + network = google_compute_network.gilb_network.id + subnetwork = google_compute_subnetwork.gilb_subnet.id + } + boot_disk { + initialize_params { + image = "debian-cloud/debian-10" + } + } +} +# [END cloudloadbalancing_int_http_gce] diff --git a/mmv1/templates/terraform/examples/healthcare_fhir_store_notification_configs.tf.erb b/mmv1/templates/terraform/examples/healthcare_fhir_store_notification_configs.tf.erb index 16757174aa62..e773a5cc79e9 100644 --- a/mmv1/templates/terraform/examples/healthcare_fhir_store_notification_configs.tf.erb +++ b/mmv1/templates/terraform/examples/healthcare_fhir_store_notification_configs.tf.erb @@ -14,8 +14,9 @@ resource "google_healthcare_fhir_store" "default" { } notification_configs { - pubsub_topic = "${google_pubsub_topic.topic.id}" - send_full_resource = true + pubsub_topic = "${google_pubsub_topic.topic.id}" + send_full_resource = true + send_previous_resource_on_delete = true } } diff --git a/mmv1/templates/terraform/examples/iap_appengine.tf.erb b/mmv1/templates/terraform/examples/iap_appengine.tf.erb index 3623f62e9212..f63aa36038ea 100644 --- a/mmv1/templates/terraform/examples/iap_appengine.tf.erb +++ b/mmv1/templates/terraform/examples/iap_appengine.tf.erb @@ -2,6 +2,7 @@ resource "google_project" "project" { name = "%{project_id}" project_id = "%{project_id}" org_id = "%{org_id}" + billing_account = "%{billing_account}" } resource "time_sleep" "wait_60_seconds" { diff --git a/mmv1/templates/terraform/examples/identity_platform_config_basic.tf.erb b/mmv1/templates/terraform/examples/identity_platform_config_basic.tf.erb index cdbb3ee53984..9880802797c2 100644 --- a/mmv1/templates/terraform/examples/identity_platform_config_basic.tf.erb +++ b/mmv1/templates/terraform/examples/identity_platform_config_basic.tf.erb @@ -17,4 +17,27 @@ resource "google_project_service" "identitytoolkit" { resource "google_identity_platform_config" "default" { project = google_project.default.project_id autodelete_anonymous_users = true + blocking_functions { + triggers { + event_type = "beforeSignIn" + function_uri = "https://us-east1-<%= ctx[:vars]['project_id'] %>.cloudfunctions.net/before-sign-in" + } + forward_inbound_credentials { + refresh_token = true + access_token = true + id_token = true + } + } + quota { + sign_up_quota_config { + quota = 1000 + start_time = "<%= ctx[:vars]['quota_start_time'] %>" + quota_duration = "7200s" + } + } + authorized_domains = [ + "localhost", + "<%= ctx[:vars]['project_id'] %>.firebaseapp.com", + "<%= ctx[:vars]['project_id'] %>.web.app", + ] } diff --git a/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb b/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb index 1a0a8910f084..5a223f1e21db 100644 --- a/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb +++ b/mmv1/templates/terraform/examples/looker_instance_enterprise_full.tf.erb @@ -5,7 +5,7 @@ resource "google_looker_instance" "<%= ctx[:primary_resource_id] %>" { private_ip_enabled = true public_ip_enabled = false reserved_range = "${google_compute_global_address.looker_range.name}" - consumer_network = google_compute_network.looker_network.id + consumer_network = data.google_compute_network.looker_network.id admin_settings { allowed_email_domains = ["google.com"] } @@ -49,7 +49,7 @@ resource "google_looker_instance" "<%= ctx[:primary_resource_id] %>" { } resource "google_service_networking_connection" "looker_vpc_connection" { - network = google_compute_network.looker_network.id + network = data.google_compute_network.looker_network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.looker_range.name] } @@ -59,14 +59,13 @@ resource "google_compute_global_address" "looker_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 20 - network = google_compute_network.looker_network.id + network = data.google_compute_network.looker_network.id } data "google_project" "project" {} -resource "google_compute_network" "looker_network" { +data "google_compute_network" "looker_network" { name = "<%= ctx[:vars]["network_name"] %>" - auto_create_subnetworks = false } resource "google_kms_crypto_key_iam_member" "crypto_key" { diff --git a/mmv1/templates/terraform/examples/network_connectivity_policy_basic.tf.erb b/mmv1/templates/terraform/examples/network_connectivity_policy_basic.tf.erb new file mode 100644 index 000000000000..a51633e9170f --- /dev/null +++ b/mmv1/templates/terraform/examples/network_connectivity_policy_basic.tf.erb @@ -0,0 +1,23 @@ +resource "google_compute_network" "producer_net" { + name = "<%= ctx[:vars]['producer_network_name'] %>" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "producer_subnet" { + name = "<%= ctx[:vars]['producer_subnetwork_name'] %>" + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" + network = google_compute_network.producer_net.id +} + +resource "google_network_connectivity_service_connection_policy" "default" { + name = "<%= ctx[:vars]['resource_name'] %>" + location = "us-central1" + service_class = "<%= ctx[:vars]['service_class_name'] %>" + description = "my basic service connection policy" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.producer_subnet.id] + limit = 2 + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb index f01870f48b34..2b25835dc3a5 100644 --- a/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb +++ b/mmv1/templates/terraform/examples/privateca_certificate_config.tf.erb @@ -1,4 +1,5 @@ # [START privateca_create_certificate_config] + resource "google_privateca_ca_pool" "default" { location = "us-central1" name = "<%= ctx[:vars]["ca_pool_id"] %>" diff --git a/mmv1/templates/terraform/examples/privateca_certificate_generated_key.tf.erb b/mmv1/templates/terraform/examples/privateca_certificate_generated_key.tf.erb new file mode 100644 index 000000000000..23d870239f9f --- /dev/null +++ b/mmv1/templates/terraform/examples/privateca_certificate_generated_key.tf.erb @@ -0,0 +1,103 @@ +resource "google_privateca_ca_pool" "default" { + location = "us-central1" + name = "default" + tier = "ENTERPRISE" +} + +resource "google_privateca_certificate_authority" "default" { + location = "us-central1" + pool = google_privateca_ca_pool.default.name + certificate_authority_id = "my-authority" + config { + subject_config { + subject { + organization = "HashiCorp" + common_name = "my-certificate-authority" + } + subject_alt_name { + dns_names = ["hashicorp.com"] + } + } + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = true + } + } + } + } + key_spec { + algorithm = "RSA_PKCS1_4096_SHA256" + } + + // Disable CA deletion related safe checks for easier cleanup. + deletion_protection = false + skip_grace_period = true + ignore_active_certificates_on_deletion = true +} + +resource "tls_private_key" "cert_key" { + algorithm = "RSA" +} + +resource "google_privateca_certificate" "<%= ctx[:primary_resource_id] %>" { + location = "us-central1" + pool = google_privateca_ca_pool.default.name + certificate_authority = google_privateca_certificate_authority.default.certificate_authority_id + lifetime = "86000s" + name = "cert-1" + config { + subject_config { + subject { + common_name = "san1.example.com" + country_code = "us" + organization = "google" + organizational_unit = "enterprise" + locality = "mountain view" + province = "california" + street_address = "1600 amphitheatre parkway" + } + subject_alt_name { + email_addresses = ["email@example.com"] + ip_addresses = ["127.0.0.1"] + uris = ["http://www.ietf.org/rfc/rfc3986.txt"] + } + } + x509_config { + ca_options { + is_ca = true + } + key_usage { + base_key_usage { + cert_sign = true + crl_sign = true + } + extended_key_usage { + server_auth = false + } + } + name_constraints { + critical = true + permitted_dns_names = ["*.example.com"] + excluded_dns_names = ["*.deny.example.com"] + permitted_ip_ranges = ["10.0.0.0/8"] + excluded_ip_ranges = ["10.1.1.0/24"] + permitted_email_addresses = [".example.com"] + excluded_email_addresses = [".deny.example.com"] + permitted_uris = [".example.com"] + excluded_uris = [".deny.example.com"] + } + } + public_key { + format = "PEM" + key = base64encode(tls_private_key.cert_key.public_key_pem) + } + } +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage.tf.erb new file mode 100644 index 000000000000..5f89e82f2cb1 --- /dev/null +++ b/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage.tf.erb @@ -0,0 +1,37 @@ +resource "google_storage_bucket" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['bucket_name'] %>" + location = "US" + uniform_bucket_level_access = true +} + +resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['topic_name'] %>" +} + +resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['subscription_name'] %>" + topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name + + cloud_storage_config { + bucket = google_storage_bucket.<%= ctx[:primary_resource_id] %>.name + + filename_prefix = "pre-" + filename_suffix = "-%{random_suffix}" + + max_bytes = 1000 + max_duration = "300s" + } + depends_on = [ + google_storage_bucket.<%= ctx[:primary_resource_id] %>, + google_storage_bucket_iam_member.admin, + ] +} + +data "google_project" "project" { +} + +resource "google_storage_bucket_iam_member" "admin" { + bucket = google_storage_bucket.<%= ctx[:primary_resource_id] %>.name + role = "roles/storage.admin" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-pubsub.iam.gserviceaccount.com" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage_avro.tf.erb b/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage_avro.tf.erb new file mode 100644 index 000000000000..1692813943e5 --- /dev/null +++ b/mmv1/templates/terraform/examples/pubsub_subscription_push_cloudstorage_avro.tf.erb @@ -0,0 +1,41 @@ +resource "google_storage_bucket" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['bucket_name'] %>" + location = "US" + uniform_bucket_level_access = true +} + +resource "google_pubsub_topic" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['topic_name'] %>" +} + +resource "google_pubsub_subscription" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['subscription_name'] %>" + topic = google_pubsub_topic.<%= ctx[:primary_resource_id] %>.name + + cloud_storage_config { + bucket = google_storage_bucket.<%= ctx[:primary_resource_id] %>.name + + filename_prefix = "pre-" + filename_suffix = "-%{random_suffix}" + + max_bytes = 1000 + max_duration = "300s" + + avro_config { + write_metadata = true + } + } + depends_on = [ + google_storage_bucket.<%= ctx[:primary_resource_id] %>, + google_storage_bucket_iam_member.admin, + ] +} + +data "google_project" "project" { +} + +resource "google_storage_bucket_iam_member" "admin" { + bucket = google_storage_bucket.<%= ctx[:primary_resource_id] %>.name + role = "roles/storage.admin" + member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-pubsub.iam.gserviceaccount.com" +} \ No newline at end of file diff --git a/mmv1/templates/terraform/examples/region_backend_service_connection_tracking.tf.erb b/mmv1/templates/terraform/examples/region_backend_service_connection_tracking.tf.erb index c2646c1efa52..574f18bacc60 100644 --- a/mmv1/templates/terraform/examples/region_backend_service_connection_tracking.tf.erb +++ b/mmv1/templates/terraform/examples/region_backend_service_connection_tracking.tf.erb @@ -11,6 +11,7 @@ resource "google_compute_region_backend_service" "<%= ctx[:primary_resource_id] tracking_mode = "PER_SESSION" connection_persistence_on_unhealthy_backends = "NEVER_PERSIST" idle_timeout_sec = 60 + enable_strong_affinity = true } } diff --git a/mmv1/templates/terraform/examples/secret_with_annotations.tf.erb b/mmv1/templates/terraform/examples/secret_with_annotations.tf.erb new file mode 100644 index 000000000000..4ae910ae37e0 --- /dev/null +++ b/mmv1/templates/terraform/examples/secret_with_annotations.tf.erb @@ -0,0 +1,19 @@ +resource "google_secret_manager_secret" "<%= ctx[:primary_resource_id] %>" { + secret_id = "<%= ctx[:vars]['secret_id'] %>" + + labels = { + label = "my-label" + } + + annotations = { + key1 = "someval" + key2 = "someval2" + key3 = "someval3" + key4 = "someval4" + key5 = "someval5" + } + + replication { + automatic = true + } +} diff --git a/mmv1/templates/terraform/examples/workstation_config_accelerators.tf.erb b/mmv1/templates/terraform/examples/workstation_config_accelerators.tf.erb new file mode 100644 index 000000000000..35640b4a07b5 --- /dev/null +++ b/mmv1/templates/terraform/examples/workstation_config_accelerators.tf.erb @@ -0,0 +1,48 @@ +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 = "n1-standard-2" + boot_disk_size_gb = 35 + disable_public_ip_addresses = true + accelerators { + type = "nvidia-tesla-p100" + count = "1" + } + } + } +} diff --git a/mmv1/templates/validator/examples/base_configs/test_body.go.erb b/mmv1/templates/tgc/examples/base_configs/test_body.go.erb similarity index 100% rename from mmv1/templates/validator/examples/base_configs/test_body.go.erb rename to mmv1/templates/tgc/examples/base_configs/test_body.go.erb diff --git a/mmv1/templates/validator/examples/base_configs/test_file.go.erb b/mmv1/templates/tgc/examples/base_configs/test_file.go.erb similarity index 100% rename from mmv1/templates/validator/examples/base_configs/test_file.go.erb rename to mmv1/templates/tgc/examples/base_configs/test_file.go.erb diff --git a/mmv1/templates/validator/mappers/mappers.go.erb b/mmv1/templates/tgc/mappers/mappers.go.erb similarity index 100% rename from mmv1/templates/validator/mappers/mappers.go.erb rename to mmv1/templates/tgc/mappers/mappers.go.erb diff --git a/mmv1/templates/validator/resource_converter.go.erb b/mmv1/templates/tgc/resource_converter.go.erb similarity index 100% rename from mmv1/templates/validator/resource_converter.go.erb rename to mmv1/templates/tgc/resource_converter.go.erb diff --git a/mmv1/templates/validator/resource_converter_iam.go.erb b/mmv1/templates/tgc/resource_converter_iam.go.erb similarity index 100% rename from mmv1/templates/validator/resource_converter_iam.go.erb rename to mmv1/templates/tgc/resource_converter_iam.go.erb diff --git a/mmv1/templates/validator/resource_converters.go.erb b/mmv1/templates/tgc/resource_converters.go.erb similarity index 100% rename from mmv1/templates/validator/resource_converters.go.erb rename to mmv1/templates/tgc/resource_converters.go.erb diff --git a/mmv1/third_party/terraform/.teamcity/components/build_config_package.kt b/mmv1/third_party/terraform/.teamcity/components/build_config_package.kt index d6136cb22dc4..aa9f2f5000a1 100644 --- a/mmv1/third_party/terraform/.teamcity/components/build_config_package.kt +++ b/mmv1/third_party/terraform/.teamcity/components/build_config_package.kt @@ -1,3 +1,8 @@ +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is copied from mmv1, any changes made here will be overwritten import jetbrains.buildServer.configs.kotlin.* diff --git a/mmv1/third_party/terraform/.teamcity/components/build_google.kt b/mmv1/third_party/terraform/.teamcity/components/build_google.kt index d0209eb36cdd..9469c113a2d2 100644 --- a/mmv1/third_party/terraform/.teamcity/components/build_google.kt +++ b/mmv1/third_party/terraform/.teamcity/components/build_google.kt @@ -1,3 +1,8 @@ +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is copied from mmv1, any changes made here will be overwritten import jetbrains.buildServer.configs.kotlin.ParametrizedWithType diff --git a/mmv1/third_party/terraform/.teamcity/components/generated/build_components.erb b/mmv1/third_party/terraform/.teamcity/components/generated/build_components.erb index 5e8b2e035109..e39c0ff3dde8 100644 --- a/mmv1/third_party/terraform/.teamcity/components/generated/build_components.erb +++ b/mmv1/third_party/terraform/.teamcity/components/generated/build_components.erb @@ -1,4 +1,9 @@ <% autogen_exception -%> +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is auto-generated with mmv1, any changes made here will be overwritten import jetbrains.buildServer.configs.kotlin.* diff --git a/mmv1/third_party/terraform/.teamcity/components/generated/project.erb b/mmv1/third_party/terraform/.teamcity/components/generated/project.erb index 94997bbffcd5..ee351f9aa8a6 100644 --- a/mmv1/third_party/terraform/.teamcity/components/generated/project.erb +++ b/mmv1/third_party/terraform/.teamcity/components/generated/project.erb @@ -1,4 +1,9 @@ <% autogen_exception -%> +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is auto-generated with mmv1, any changes made here will be overwritten import jetbrains.buildServer.configs.kotlin.BuildType @@ -13,6 +18,7 @@ const val providerName = "google<%= "-" + version unless version == 'ga' -%>" fun Google<%= version.capitalize unless version == 'ga' -%>(environment: String, manualVcsRoot: AbsoluteId, branchRef: String, configuration: ClientConfiguration) : Project { return Project{ + // Create build configs for each package defined in packages.kt var buildConfigs = buildConfigurationsForPackages(packages, providerName, "google<%= "-" + version unless version == 'ga' -%>", environment, manualVcsRoot, branchRef, configuration) buildConfigs.forEach { buildConfiguration -> buildType(buildConfiguration) diff --git a/mmv1/third_party/terraform/.teamcity/components/generated/services.erb b/mmv1/third_party/terraform/.teamcity/components/generated/services.erb index f98a9fef637f..4d21594512ee 100644 --- a/mmv1/third_party/terraform/.teamcity/components/generated/services.erb +++ b/mmv1/third_party/terraform/.teamcity/components/generated/services.erb @@ -1,4 +1,9 @@ <% autogen_exception -%> +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is auto-generated with mmv1, any changes made here will be overwritten <% service_names = [] diff --git a/mmv1/third_party/terraform/.teamcity/components/generated/settings.erb b/mmv1/third_party/terraform/.teamcity/components/generated/settings.erb index 5ac811536355..658dc4d1d289 100644 --- a/mmv1/third_party/terraform/.teamcity/components/generated/settings.erb +++ b/mmv1/third_party/terraform/.teamcity/components/generated/settings.erb @@ -1,4 +1,9 @@ <% autogen_exception -%> +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is auto-generated with mmv1, any changes made here will be overwritten // specifies the default hour (UTC) at which tests should be triggered, if enabled diff --git a/mmv1/third_party/terraform/.teamcity/components/packages.kt b/mmv1/third_party/terraform/.teamcity/components/packages.kt index 415e33c47bc7..3b5d4de1596a 100644 --- a/mmv1/third_party/terraform/.teamcity/components/packages.kt +++ b/mmv1/third_party/terraform/.teamcity/components/packages.kt @@ -1,3 +1,8 @@ +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is copied from mmv1, any changes made here will be overwritten var packages = mapOf( diff --git a/mmv1/third_party/terraform/.teamcity/generated/settings.kts.erb b/mmv1/third_party/terraform/.teamcity/generated/settings.kts.erb index e3b810f86a41..93c458925bfc 100644 --- a/mmv1/third_party/terraform/.teamcity/generated/settings.kts.erb +++ b/mmv1/third_party/terraform/.teamcity/generated/settings.kts.erb @@ -1,4 +1,9 @@ <% autogen_exception -%> +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is auto-generated with mmv1, any changes made here will be overwritten import Google<%= version.capitalize unless version == 'ga' -%> diff --git a/mmv1/third_party/terraform/.teamcity/tests/generated/configuration.erb b/mmv1/third_party/terraform/.teamcity/tests/generated/configuration.erb index 13f45f0fb640..0b8f5b496a4d 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/generated/configuration.erb +++ b/mmv1/third_party/terraform/.teamcity/tests/generated/configuration.erb @@ -1,4 +1,9 @@ <% autogen_exception -%> +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is auto-generated with mmv1, any changes made here will be overwritten package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/generated/vcs_roots.erb b/mmv1/third_party/terraform/.teamcity/tests/generated/vcs_roots.erb index 9c8c01f5506d..a5068f007318 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/generated/vcs_roots.erb +++ b/mmv1/third_party/terraform/.teamcity/tests/generated/vcs_roots.erb @@ -1,4 +1,9 @@ <% autogen_exception -%> +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is auto-generated with mmv1, any changes made here will be overwritten package tests diff --git a/mmv1/third_party/terraform/.teamcity/tests/helpers.kt b/mmv1/third_party/terraform/.teamcity/tests/helpers.kt index 363a7a1b66cc..2ac12b7b0fa7 100644 --- a/mmv1/third_party/terraform/.teamcity/tests/helpers.kt +++ b/mmv1/third_party/terraform/.teamcity/tests/helpers.kt @@ -1,3 +1,8 @@ +/* + * Copyright (c) HashiCorp, Inc. + * SPDX-License-Identifier: MPL-2.0 + */ + // this file is copied from mmv1, any changes made here will be overwritten package tests diff --git a/mmv1/third_party/terraform/fwmodels/provider_model.go.erb b/mmv1/third_party/terraform/fwmodels/provider_model.go.erb index 1c58b26e1a74..f995a5c5db98 100644 --- a/mmv1/third_party/terraform/fwmodels/provider_model.go.erb +++ b/mmv1/third_party/terraform/fwmodels/provider_model.go.erb @@ -53,7 +53,6 @@ type ProviderModel struct { CloudResourceManagerCustomEndpoint types.String `tfsdk:"cloud_resource_manager_custom_endpoint"` EventarcCustomEndpoint types.String `tfsdk:"eventarc_custom_endpoint"` FirebaserulesCustomEndpoint types.String `tfsdk:"firebaserules_custom_endpoint"` - NetworkConnectivityCustomEndpoint types.String `tfsdk:"network_connectivity_custom_endpoint"` <% if version == "ga" -%> OrgPolicyCustomEndpoint types.String `tfsdk:"org_policy_custom_endpoint"` <% end -%> @@ -62,7 +61,6 @@ type ProviderModel struct { GkehubFeatureCustomEndpoint types.String `tfsdk:"gkehub_feature_custom_endpoint"` <% end -%> <% if version == "private" -%> - VmwareCustomEndpoint types.String `tfsdk:"vmware_custom_endpoint"` // artifact from a private internal fork- this one can be removed when the // internal definition is removed. RunCustomEndpoint types.String `tfsdk:"run_custom_endpoint"` diff --git a/mmv1/third_party/terraform/go.sum b/mmv1/third_party/terraform/go.sum index 1ffa419204b3..f885d00e815c 100644 --- a/mmv1/third_party/terraform/go.sum +++ b/mmv1/third_party/terraform/go.sum @@ -2,8 +2,6 @@ bitbucket.org/creachadair/stringset v0.0.8 h1:gQqe4vs8XWgMyijfyKE6K8o4TcyGGrRXe0 bitbucket.org/creachadair/stringset v0.0.8/go.mod h1:AgthVMyMxC/6FK1KBJ2ALdqkZObGN8hOetgpwXyMn34= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= cloud.google.com/go v0.110.2 h1:sdFPBr6xG9/wkBbfhmUz/JmZC7X6LavQgcrVINrKiVA= cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk= @@ -16,12 +14,8 @@ cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZN cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= 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.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= cloud.google.com/go/longrunning v0.5.0 h1:DK8BH0+hS+DIvc9a2TPnteUievsTCH4ORMAASSb7JcQ= cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= @@ -212,7 +206,6 @@ github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKL 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/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= 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= @@ -273,7 +266,6 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB 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/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= 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= @@ -328,7 +320,6 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL 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/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 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= @@ -494,4 +485,3 @@ gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 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 dafd68aa86be..701537b1198f 100644 --- a/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go +++ b/mmv1/third_party/terraform/services/bigquery/resource_bigquery_table.go @@ -455,6 +455,12 @@ func ResourceBigQueryTable() *schema.Resource { Description: `A list of the fully-qualified URIs that point to your data in Google Cloud.`, Elem: &schema.Schema{Type: schema.TypeString}, }, + // FileSetSpecType: [Optional] Specifies how source URIs are interpreted for constructing the file set to load. By default source URIs are expanded against the underlying storage. Other options include specifying manifest files. Only applicable to object storage systems. + "file_set_spec_type": { + Type: schema.TypeString, + Optional: true, + Description: `Specifies how source URIs are interpreted for constructing the file set to load. By default source URIs are expanded against the underlying storage. Other options include specifying manifest files. Only applicable to object storage systems.`, + }, // Compression: [Optional] The compression type of the data source. "compression": { Type: schema.TypeString, @@ -720,6 +726,13 @@ func ResourceBigQueryTable() *schema.Resource { Description: `A descriptive name for the table.`, }, + // max_staleness: [Optional] The maximum staleness of data that could be returned when the table (or stale MV) is queried. Staleness encoded as a string encoding of sql IntervalValue type. + "max_staleness": { + Type: schema.TypeString, + Optional: true, + Description: `The maximum staleness of data that could be returned when the table (or stale MV) is queried. Staleness encoded as a string encoding of sql IntervalValue type.`, + }, + // Labels: [Experimental] The labels associated with this table. You can // use these to organize and group your tables. Label keys and values // can be no longer than 63 characters, can only contain lowercase @@ -1078,6 +1091,10 @@ func resourceTable(d *schema.ResourceData, meta interface{}) (*bigquery.Table, e table.FriendlyName = v.(string) } + if v, ok := d.GetOk("max_staleness"); ok { + table.MaxStaleness = v.(string) + } + if v, ok := d.GetOk("encryption_configuration.0.kms_key_name"); ok { table.EncryptionConfiguration = &bigquery.EncryptionConfiguration{ KmsKeyName: v.(string), @@ -1216,6 +1233,9 @@ func resourceBigQueryTableRead(d *schema.ResourceData, meta interface{}) error { if err := d.Set("friendly_name", res.FriendlyName); err != nil { return fmt.Errorf("Error setting friendly_name: %s", err) } + if err := d.Set("max_staleness", res.MaxStaleness); err != nil { + return fmt.Errorf("Error setting max_staleness: %s", err) + } if err := d.Set("labels", res.Labels); err != nil { return fmt.Errorf("Error setting labels: %s", err) } @@ -1406,6 +1426,10 @@ func expandExternalDataConfiguration(cfg interface{}) (*bigquery.ExternalDataCon edc.SourceUris = sourceUris } + if v, ok := raw["file_set_spec_type"]; ok { + edc.FileSetSpecType = v.(string) + } + if v, ok := raw["compression"]; ok { edc.Compression = v.(string) } @@ -1468,6 +1492,10 @@ func flattenExternalDataConfiguration(edc *bigquery.ExternalDataConfiguration) ( result["autodetect"] = edc.Autodetect result["source_uris"] = edc.SourceUris + if edc.FileSetSpecType != "" { + result["file_set_spec_type"] = edc.FileSetSpecType + } + if edc.Compression != "" { result["compression"] = edc.Compression } diff --git a/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.erb b/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.erb index 14eb5dceb0d8..0035138b50d1 100644 --- a/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.erb +++ b/mmv1/third_party/terraform/services/cloudidentity/data_source_cloud_identity_group_memberships.go.erb @@ -73,6 +73,7 @@ func dataSourceGoogleCloudIdentityGroupMembershipsRead(d *schema.ResourceData, m for _, member := range resp.Memberships { result = append(result, map[string]interface{}{ "name": member.Name, + "type": member.Type, "roles": flattenCloudIdentityGroupMembershipsRoles(member.Roles), <% unless version == 'ga' -%> "member_key": flattenCloudIdentityGroupsEntityKey(member.MemberKey), diff --git a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.erb b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.erb index ca10fd62ffc6..bde469c3019a 100644 --- a/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.erb +++ b/mmv1/third_party/terraform/services/compute/compute_instance_helpers.go.erb @@ -4,6 +4,7 @@ package compute import ( "fmt" "reflect" + "strconv" "github.com/hashicorp/terraform-provider-google/google/tpgresource" transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" @@ -149,6 +150,14 @@ func expandScheduling(v interface{}) (*compute.Scheduling, error) { scheduling.MaintenanceInterval = v.(string) } <% end -%> + if v, ok := original["local_ssd_recovery_timeout"]; ok { + transformedLocalSsdRecoveryTimeout, err := expandComputeLocalSsdRecoveryTimeout(v) + if err != nil { + return nil, err + } + scheduling.LocalSsdRecoveryTimeout = transformedLocalSsdRecoveryTimeout + scheduling.ForceSendFields = append(scheduling.ForceSendFields, "LocalSsdRecoveryTimeout") + } return scheduling, nil } @@ -188,6 +197,38 @@ func expandComputeMaxRunDurationSeconds(v interface{}) (interface{}, error) { } <% end -%> +func expandComputeLocalSsdRecoveryTimeout(v interface{}) (*compute.Duration, error) { + l := v.([]interface{}) + duration := compute.Duration{} + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + + transformedNanos, err := expandComputeLocalSsdRecoveryTimeoutNanos(original["nanos"]) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNanos); val.IsValid() && !tpgresource.IsEmptyValue(val) { + duration.Nanos = int64(transformedNanos.(int)) + } + + transformedSeconds, err := expandComputeLocalSsdRecoveryTimeoutSeconds(original["seconds"]) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSeconds); val.IsValid() && !tpgresource.IsEmptyValue(val) { + duration.Seconds = int64(transformedSeconds.(int)) + } + return &duration, nil +} + +func expandComputeLocalSsdRecoveryTimeoutNanos(v interface{}) (interface{}, error) { + return v, nil +} + +func expandComputeLocalSsdRecoveryTimeoutSeconds(v interface{}) (interface{}, error) { + return v, nil +} func flattenScheduling(resp *compute.Scheduling) []map[string]interface{} { schedulingMap := map[string]interface{}{ @@ -211,6 +252,10 @@ func flattenScheduling(resp *compute.Scheduling) []map[string]interface{} { } <% end -%> + if resp.LocalSsdRecoveryTimeout != nil { + schedulingMap["local_ssd_recovery_timeout"] = flattenComputeLocalSsdRecoveryTimeout(resp.LocalSsdRecoveryTimeout) + } + nodeAffinities := schema.NewSet(schema.HashResource(instanceSchedulingNodeAffinitiesElemSchema()), nil) for _, na := range resp.NodeAffinities { nodeAffinities.Add(map[string]interface{}{ @@ -236,6 +281,16 @@ func flattenComputeMaxRunDuration(v *compute.Duration) []interface{} { } <% end -%> +func flattenComputeLocalSsdRecoveryTimeout(v *compute.Duration) []interface{} { + if v == nil { + return nil + } + transformed := make(map[string]interface{}) + transformed["nanos"] = v.Nanos + transformed["seconds"] = v.Seconds + return []interface{}{transformed} +} + func flattenAccessConfigs(accessConfigs []*compute.AccessConfig) ([]map[string]interface{}, string) { flattened := make([]map[string]interface{}, len(accessConfigs)) natIP := "" @@ -262,6 +317,8 @@ func flattenIpv6AccessConfigs(ipv6AccessConfigs []*compute.AccessConfig) []map[s } flattened[i]["public_ptr_domain_name"] = ac.PublicPtrDomainName flattened[i]["external_ipv6"] = ac.ExternalIpv6 + flattened[i]["external_ipv6_prefix_length"] = strconv.FormatInt(ac.ExternalIpv6PrefixLength, 10) + flattened[i]["name"] = ac.Name } return flattened } @@ -344,6 +401,19 @@ func expandIpv6AccessConfigs(configs []interface{}) []*compute.AccessConfig { if ptr, ok := data["public_ptr_domain_name"]; ok && ptr != "" { iacs[i].PublicPtrDomainName = ptr.(string) } + if eip, ok := data["external_ipv6"]; ok && eip != "" { + iacs[i].ExternalIpv6 = eip.(string) + } + if eipl, ok := data["external_ipv6_prefix_length"]; ok && eipl != "" { + if strVal, ok := eipl.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + iacs[i].ExternalIpv6PrefixLength = intVal + } + } + } + if name, ok := data["name"]; ok && name != "" { + iacs[i].Name = name.(string) + } iacs[i].Type = "DIRECT_IPV6" // Currently only type supported } } diff --git a/mmv1/third_party/terraform/services/compute/compute_operation.go.erb b/mmv1/third_party/terraform/services/compute/compute_operation.go.erb index db829aa2aed5..1c1cbc95d4d1 100644 --- a/mmv1/third_party/terraform/services/compute/compute_operation.go.erb +++ b/mmv1/third_party/terraform/services/compute/compute_operation.go.erb @@ -185,6 +185,13 @@ func writeOperationError(w io.StringWriter, opError *compute.OperationErrorError if opError.Code == "QUOTA_EXCEEDED" && ed.QuotaInfo != nil { w.WriteString("\tmetric name = " + ed.QuotaInfo.MetricName + "\n") w.WriteString("\tlimit name = " + ed.QuotaInfo.LimitName + "\n") + if ed.QuotaInfo.Limit != 0 { + w.WriteString("\tlimit = " + fmt.Sprint(ed.QuotaInfo.Limit) + "\n") + } + if ed.QuotaInfo.FutureLimit != 0 { + w.WriteString("\tfuture limit = " + fmt.Sprint(ed.QuotaInfo.FutureLimit) + "\n") + w.WriteString("\trollout status = in progress\n") + } if ed.QuotaInfo.Dimensions != nil { w.WriteString("\tdimensions = " + fmt.Sprint(ed.QuotaInfo.Dimensions) + "\n") } diff --git a/mmv1/third_party/terraform/services/compute/compute_operation_test.go.erb b/mmv1/third_party/terraform/services/compute/compute_operation_test.go.erb index 14a9eb76fe13..752653bad184 100644 --- a/mmv1/third_party/terraform/services/compute/compute_operation_test.go.erb +++ b/mmv1/third_party/terraform/services/compute/compute_operation_test.go.erb @@ -60,7 +60,7 @@ func buildOperationError(numLocalizedMsg int, numHelpWithLinks []int) compute.Op } -func buildOperationErrorQuotaExceeded(withDetails bool, withDimensions bool) compute.OperationError { +func buildOperationErrorQuotaExceeded(withDetails bool, withDimensions bool, withFutureLimit bool) compute.OperationError { opError := &compute.OperationErrorErrors{Message: quotaExceededMsg, Code: quotaExceededCode} opErrorErrors := []*compute.OperationErrorErrors{opError} if withDetails { @@ -69,6 +69,9 @@ func buildOperationErrorQuotaExceeded(withDetails bool, withDimensions bool) com LimitName: quotaLimitName, Limit: 1100, } + if withFutureLimit { + quotaInfo.FutureLimit = 2200 + } if withDimensions { quotaInfo.Dimensions = map[string]string{"region": "us-central1"} } @@ -210,21 +213,23 @@ func TestComputeOperationError_Error(t *testing.T) { }, { name: "QuotaMessageOnly", - input: buildOperationErrorQuotaExceeded(false, false), + input: buildOperationErrorQuotaExceeded(false, false, false), expectContains: []string{ "Quota DISKS_TOTAL_GB exceeded. Limit: 1100.0 in region us-central1.", }, expectOmits: append(omitAlways(0, []int{}), []string{ "metric name = compute.googleapis.com/disks_total_storage", + "limit = 1100", }...), }, { name: "QuotaMessageWithDetailsNoDimensions", - input: buildOperationErrorQuotaExceeded(true, false), + input: buildOperationErrorQuotaExceeded(true, false, false), expectContains: []string{ "Quota DISKS_TOTAL_GB exceeded. Limit: 1100.0 in region us-central1.", "metric name = compute.googleapis.com/disks_total_storage", "limit name = DISKS-TOTAL-GB-per-project-region", + "limit = 1100", }, expectOmits: append(omitAlways(0, []int{}), []string{ "dimensions = map[region:us-central1]", @@ -232,11 +237,47 @@ func TestComputeOperationError_Error(t *testing.T) { }, { name: "QuotaMessageWithDetailsWithDimensions", - input: buildOperationErrorQuotaExceeded(true, true), + input: buildOperationErrorQuotaExceeded(true, true, false), + expectContains: []string{ + "Quota DISKS_TOTAL_GB exceeded. Limit: 1100.0 in region us-central1.", + "metric name = compute.googleapis.com/disks_total_storage", + "limit name = DISKS-TOTAL-GB-per-project-region", + "limit = 1100", + "dimensions = map[region:us-central1]", + }, + expectOmits: append(omitAlways(0, []int{}), []string{ + "LocalizedMessage1", + "Help1Link1 Description", + "https://help1.com/link1", + }...), + }, + { + name: "QuotaMessageWithDetailsWithFutureLimit", + input: buildOperationErrorQuotaExceeded(true, false, true), + expectContains: []string{ + "Quota DISKS_TOTAL_GB exceeded. Limit: 1100.0 in region us-central1.", + "metric name = compute.googleapis.com/disks_total_storage", + "limit name = DISKS-TOTAL-GB-per-project-region", + "limit = 1100", + "future limit = 2200", + "rollout status = in progress", + }, + expectOmits: append(omitAlways(0, []int{}), []string{ + "LocalizedMessage1", + "Help1Link1 Description", + "https://help1.com/link1", + }...), + }, + { + name: "QuotaMessageWithDetailsWithDimensionsWithFutureLimit", + input: buildOperationErrorQuotaExceeded(true, true, true), expectContains: []string{ "Quota DISKS_TOTAL_GB exceeded. Limit: 1100.0 in region us-central1.", "metric name = compute.googleapis.com/disks_total_storage", "limit name = DISKS-TOTAL-GB-per-project-region", + "limit = 1100", + "future limit = 2200", + "rollout status = in progress", "dimensions = map[region:us-central1]", }, expectOmits: append(omitAlways(0, []int{}), []string{ 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 775ab9e42d71..59dcba8c061c 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 @@ -60,7 +60,7 @@ var ( "scheduling.0.max_run_duration", "scheduling.0.maintenance_interval", <% end -%> - + "scheduling.0.local_ssd_recovery_timeout", } shieldedInstanceConfigKeys = []string{ @@ -412,14 +412,26 @@ func ResourceComputeInstance() *schema.Resource { Description: `The domain name to be used when creating DNSv6 records for the external IPv6 ranges.`, }, "external_ipv6": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + DiffSuppressFunc: ipv6RepresentationDiffSuppress, + Description: `The first IPv6 address of the external IPv6 range associated with this instance, prefix length is stored in externalIpv6PrefixLength in ipv6AccessConfig. To use a static external IP address, it must be unused and in the same region as the instance's zone. If not specified, Google Cloud will automatically assign an external IPv6 address from the instance's subnetwork.`, + }, + "external_ipv6_prefix_length": { Type: schema.TypeString, + Optional: true, Computed: true, - Description: `The first IPv6 address of the external IPv6 range associated with this instance, prefix length is stored in externalIpv6PrefixLength in ipv6AccessConfig. The field is output only, an IPv6 address from a subnetwork associated with the instance will be allocated dynamically.`, + ForceNew: true, + Description: `The prefix length of the external IPv6 range.`, }, - "external_ipv6_prefix_length": { - Type: schema.TypeString, - Computed: true, - Description: `The prefix length of the external IPv6 range.`, + "name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + Description: `The name of this access configuration. In ipv6AccessConfigs, the recommended name is External IPv6.`, }, }, }, @@ -721,7 +733,36 @@ be from 0 to 999,999,999 inclusive.`, Description: `Specifies the frequency of planned maintenance events. The accepted values are: PERIODIC`, }, <% end -%> - + "local_ssd_recovery_timeout" : { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the maximum amount of time a Local Ssd Vm should wait while + recovery of the Local Ssd state is attempted. Its value should be in + between 0 and 168 hours with hour granularity and the default value being 1 + hour.`, + MaxItems: 1, + ForceNew: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "seconds": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: `Span of time at a resolution of a second. +Must be from 0 to 315,576,000,000 inclusive.`, + }, + "nanos": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `Span of time that's a fraction of a second at nanosecond +resolution. Durations less than one second are represented +with a 0 seconds field and a positive nanos field. Must +be from 0 to 999,999,999 inclusive.`, + }, + }, + }, + }, }, }, }, 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 28c1a0eb6b4f..ca89eddea57c 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 @@ -286,7 +286,6 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { }, }, - <% unless version == "ga" -%> "instance_lifecycle_policy": { Computed: true, Type: schema.TypeList, @@ -305,7 +304,6 @@ func ResourceComputeInstanceGroupManager() *schema.Resource { }, }, }, - <% end -%> <% unless version == "ga" -%> "all_instances_config": { @@ -581,9 +579,7 @@ func resourceComputeInstanceGroupManagerCreate(d *schema.ResourceData, meta inte AutoHealingPolicies: expandAutoHealingPolicies(d.Get("auto_healing_policies").([]interface{})), Versions: expandVersions(d.Get("version").([]interface{})), UpdatePolicy: expandUpdatePolicy(d.Get("update_policy").([]interface{})), - <% unless version == "ga" -%> InstanceLifecyclePolicy: expandInstanceLifecyclePolicy(d.Get("instance_lifecycle_policy").([]interface{})), - <% end -%> <% unless version == "ga" -%> AllInstancesConfig: expandAllInstancesConfig(nil, d.Get("all_instances_config").([]interface{})), <% end -%> @@ -806,11 +802,9 @@ func resourceComputeInstanceGroupManagerRead(d *schema.ResourceData, meta interf if err = d.Set("update_policy", flattenUpdatePolicy(manager.UpdatePolicy)); err != nil { return fmt.Errorf("Error setting update_policy in state: %s", err.Error()) } - <% unless version == "ga" -%> 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()) } - <% end -%> <% unless version == "ga" -%> if manager.AllInstancesConfig != nil { if err = d.Set("all_instances_config", flattenAllInstancesConfig(manager.AllInstancesConfig)); err != nil { @@ -883,12 +877,10 @@ func resourceComputeInstanceGroupManagerUpdate(d *schema.ResourceData, meta inte change = true } - <% unless version == "ga" -%> if d.HasChange("instance_lifecycle_policy") { updatedManager.InstanceLifecyclePolicy = expandInstanceLifecyclePolicy(d.Get("instance_lifecycle_policy").([]interface{})) change = true } - <% end -%> <% unless version == "ga" -%> if d.HasChange("all_instances_config") { @@ -1225,7 +1217,6 @@ func expandFixedOrPercent(configured []interface{}) *compute.FixedOrPercent { return fixedOrPercent } -<% unless version == "ga" -%> func expandInstanceLifecyclePolicy(configured []interface{}) *compute.InstanceGroupManagerInstanceLifecyclePolicy { instanceLifecyclePolicy := &compute.InstanceGroupManagerInstanceLifecyclePolicy{} @@ -1235,7 +1226,6 @@ func expandInstanceLifecyclePolicy(configured []interface{}) *compute.InstanceGr } return instanceLifecyclePolicy } -<% end -%> func expandUpdatePolicy(configured []interface{}) *compute.InstanceGroupManagerUpdatePolicy { updatePolicy := &compute.InstanceGroupManagerUpdatePolicy{} @@ -1381,7 +1371,6 @@ func flattenUpdatePolicy(updatePolicy *compute.InstanceGroupManagerUpdatePolicy) return results } -<% unless version == "ga" -%> func flattenInstanceLifecyclePolicy(instanceLifecyclePolicy *compute.InstanceGroupManagerInstanceLifecyclePolicy) []map[string]interface{} { results := []map[string]interface{}{} if instanceLifecyclePolicy != nil { @@ -1391,7 +1380,6 @@ func flattenInstanceLifecyclePolicy(instanceLifecyclePolicy *compute.InstanceGro } return results } -<% end -%> <% unless version == "ga" -%> func expandAllInstancesConfig(old []interface{}, new []interface{}) *compute.InstanceGroupManagerAllInstancesConfig { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb index 6b01a2147217..ee619a6e4f36 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_instance_template.go.erb @@ -39,6 +39,7 @@ var ( "scheduling.0.max_run_duration", "scheduling.0.maintenance_interval", <% end -%> + "scheduling.0.local_ssd_recovery_timeout", } shieldedInstanceTemplateConfigKeys = []string{ @@ -544,6 +545,11 @@ Google Cloud KMS.`, Computed: true, Description: `The prefix length of the external IPv6 range.`, }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of this access configuration.`, + }, }, }, }, @@ -673,6 +679,35 @@ be from 0 to 999,999,999 inclusive.`, Description: `Specifies the frequency of planned maintenance events. The accepted values are: PERIODIC`, }, <% end -%> + "local_ssd_recovery_timeout" : { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the maximum amount of time a Local Ssd Vm should wait while + recovery of the Local Ssd state is attempted. Its value should be in + between 0 and 168 hours with hour granularity and the default value being 1 + hour.`, + + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "seconds": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: `Span of time at a resolution of a second. +Must be from 0 to 315,576,000,000 inclusive.`, + }, + "nanos": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `Span of time that's a fraction of a second at nanosecond +resolution. Durations less than one second are represented +with a 0 seconds field and a positive nanos field. Must +be from 0 to 999,999,999 inclusive.`, + }, + }, + }, + }, }, }, }, 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 89f5b93082ef..c88d69cda94c 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 @@ -250,7 +250,6 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { Description: `The shape to which the group converges either proactively or on resize events (depending on the value set in updatePolicy.instanceRedistributionType).`, }, - <% unless version == "ga" -%> "instance_lifecycle_policy": { Computed: true, Type: schema.TypeList, @@ -269,7 +268,6 @@ func ResourceComputeRegionInstanceGroupManager() *schema.Resource { }, }, }, - <% end -%> "update_policy": { Type: schema.TypeList, @@ -555,9 +553,7 @@ func resourceComputeRegionInstanceGroupManagerCreate(d *schema.ResourceData, met AutoHealingPolicies: expandAutoHealingPolicies(d.Get("auto_healing_policies").([]interface{})), Versions: expandVersions(d.Get("version").([]interface{})), UpdatePolicy: expandRegionUpdatePolicy(d.Get("update_policy").([]interface{})), - <% unless version == "ga" -%> InstanceLifecyclePolicy: expandInstanceLifecyclePolicy(d.Get("instance_lifecycle_policy").([]interface{})), - <% end -%> <% unless version == "ga" -%> AllInstancesConfig: expandAllInstancesConfig(nil, d.Get("all_instances_config").([]interface{})), <% end -%> @@ -753,11 +749,9 @@ func resourceComputeRegionInstanceGroupManagerRead(d *schema.ResourceData, meta if err := d.Set("update_policy", flattenRegionUpdatePolicy(manager.UpdatePolicy)); err != nil { return fmt.Errorf("Error setting update_policy in state: %s", err.Error()) } - <% unless version == "ga" -%> 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()) } - <% end -%> <% unless version == "ga" -%> if manager.AllInstancesConfig != nil { if err = d.Set("all_instances_config", flattenAllInstancesConfig(manager.AllInstancesConfig)); err != nil { @@ -834,12 +828,10 @@ func resourceComputeRegionInstanceGroupManagerUpdate(d *schema.ResourceData, met change = true } - <% unless version == "ga" -%> if d.HasChange("instance_lifecycle_policy") { updatedManager.InstanceLifecyclePolicy = expandInstanceLifecyclePolicy(d.Get("instance_lifecycle_policy").([]interface{})) change = true } - <% end -%> <% unless version == "ga" -%> if d.HasChange("stateful_internal_ip") || d.HasChange("stateful_external_ip") || d.HasChange("stateful_disk") { diff --git a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb index be490665958a..c495848b23ab 100644 --- a/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb +++ b/mmv1/third_party/terraform/services/compute/resource_compute_region_instance_template.go.erb @@ -516,6 +516,11 @@ Google Cloud KMS.`, Computed: true, Description: `The prefix length of the external IPv6 range.`, }, + "name": { + Type: schema.TypeString, + Computed: true, + Description: `The name of this access configuration.`, + }, }, }, }, @@ -637,6 +642,35 @@ be from 0 to 999,999,999 inclusive.`, Description: `Specifies the frequency of planned maintenance events. The accepted values are: PERIODIC`, }, <% end -%> + "local_ssd_recovery_timeout" : { + Type: schema.TypeList, + Optional: true, + Description: `Specifies the maximum amount of time a Local Ssd Vm should wait while + recovery of the Local Ssd state is attempted. Its value should be in + between 0 and 168 hours with hour granularity and the default value being 1 + hour.`, + + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "seconds": { + Type: schema.TypeInt, + Required: true, + ForceNew: true, + Description: `Span of time at a resolution of a second. +Must be from 0 to 315,576,000,000 inclusive.`, + }, + "nanos": { + Type: schema.TypeInt, + Optional: true, + ForceNew: true, + Description: `Span of time that's a fraction of a second at nanosecond +resolution. Durations less than one second are represented +with a 0 seconds field and a positive nanos field. Must +be from 0 to 999,999,999 inclusive.`, + }, + }, + }, + }, }, }, }, 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 7c55d6320e8d..38ab42fa33e7 100644 --- a/mmv1/third_party/terraform/services/container/node_config.go.erb +++ b/mmv1/third_party/terraform/services/container/node_config.go.erb @@ -606,6 +606,24 @@ func schemaNodeConfig() *schema.Schema { }, }, }, + "host_maintenance_policy": { + Type: schema.TypeList, + Optional: true, + Description: `The maintenance policy for the hosts on which the GKE VMs run on.`, + ForceNew: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "maintenance_interval": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `.`, + ValidateFunc: validation.StringInSlice([]string{"MAINTENANCE_INTERVAL_UNSPECIFIED", "AS_NEEDED", "PERIODIC"}, false), + }, + }, + }, + }, }, }, } @@ -884,6 +902,11 @@ func expandNodeConfig(v interface{}) *container.NodeConfig { nc.SoleTenantConfig = expandSoleTenantConfig(v) } + <% unless version == "ga" -%> + if v, ok := nodeConfig["host_maintenance_policy"]; ok { + nc.HostMaintenancePolicy = expandHostMaintenancePolicy(v) + } + <% end -%> return nc } @@ -982,6 +1005,25 @@ func expandSoleTenantConfig(v interface{}) *container.SoleTenantConfig { } } +<% unless version == "ga" -%> +func expandHostMaintenancePolicy(v interface{}) *container.HostMaintenancePolicy { + if v == nil { + return nil + } + ls := v.([]interface{}) + if len(ls) == 0 { + return nil + } + cfg := ls[0].(map[string]interface{}) + mPolicy := &container.HostMaintenancePolicy{} + if maintenanceInterval, ok := cfg["maintenance_interval"]; ok { + mPolicy.MaintenanceInterval = maintenanceInterval.(string) + } + + return mPolicy +} +<% end -%> + func flattenNodeConfigDefaults(c *container.NodeConfigDefaults) []map[string]interface{} { result := make([]map[string]interface{}, 0, 1) @@ -1035,6 +1077,7 @@ func flattenNodeConfig(c *container.NodeConfig) []map[string]interface{} { "workload_metadata_config": flattenWorkloadMetadataConfig(c.WorkloadMetadataConfig), <% unless version == 'ga' -%> "sandbox_config": flattenSandboxConfig(c.SandboxConfig), + "host_maintenance_policy": flattenHostMaintenancePolicy(c.HostMaintenancePolicy), <% end -%> "boot_disk_kms_key": c.BootDiskKmsKey, "kubelet_config": flattenKubeletConfig(c.KubeletConfig), @@ -1361,3 +1404,16 @@ func flattenSoleTenantConfig(c *container.SoleTenantConfig) []map[string]interfa "node_affinity": affinities, }) } + +<% unless version == 'ga' -%> +func flattenHostMaintenancePolicy(c *container.HostMaintenancePolicy) []map[string]interface{} { + result := []map[string]interface{}{} + if c != nil { + result = append(result, map[string]interface{}{ + "maintenance_interval": c.MaintenanceInterval, + }) + } + + return result +} +<% end -%> \ No newline at end of file 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 eac97fc62d8c..720c614729e1 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 @@ -192,6 +192,7 @@ func ResourceContainerCluster() *schema.Resource { containerClusterNodeVersionRemoveDefaultCustomizeDiff, containerClusterNetworkPolicyEmptyCustomizeDiff, containerClusterSurgeSettingsCustomizeDiff, + containerClusterEnableK8sBetaApisCustomizeDiff, ), Timeouts: &schema.ResourceTimeout{ @@ -819,6 +820,23 @@ func ResourceContainerCluster() *schema.Resource { Description: `Whether to enable Kubernetes Alpha features for this cluster. Note that when this option is enabled, the cluster cannot be upgraded and will be automatically deleted after 30 days.`, }, + "enable_k8s_beta_apis": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: `Configuration for Kubernetes Beta APIs.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled_apis": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: `Enabled Kubernetes Beta APIs.`, + }, + }, + }, + }, + "enable_tpu": { Type: schema.TypeBool, Optional: true, @@ -1165,6 +1183,29 @@ func ResourceContainerCluster() *schema.Resource { }, }, }, + "advanced_datapath_observability_config": { + Type: schema.TypeList, + Optional: true, + Computed: true, + MaxItems: 2, + Description: `Configuration of Advanced Datapath Observability features.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enable_metrics": { + Type: schema.TypeBool, + Required: true, + Description: `Whether or not the advanced datapath metrics are enabled.`, + }, + "relay_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: `Mode used to make Relay available.`, + ValidateFunc: validation.StringInSlice([]string{"DISABLED", "INTERNAL_VPC_LB", "EXTERNAL_LB"}, false), + }, + }, + }, + }, }, }, }, @@ -1574,7 +1615,7 @@ func ResourceContainerCluster() *schema.Resource { Optional: true, AtLeastOneOf: privateClusterConfigKeys, DiffSuppressFunc: containerClusterPrivateClusterConfigSuppress, - Description: `When true, the cluster's private endpoint is used as the cluster endpoint and access through the public endpoint is disabled. When false, either endpoint can be used. This field only applies to private clusters, when enable_private_nodes is true.`, + Description: `When true, the cluster's private endpoint is used as the cluster endpoint and access through the public endpoint is disabled. When false, either endpoint can be used.`, }, "enable_private_nodes": { Type: schema.TypeBool, @@ -2123,6 +2164,7 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er ProtectConfig: expandProtectConfig(d.Get("protect_config")), <% end -%> CostManagementConfig: expandCostManagementConfig(d.Get("cost_management_config")), + EnableK8sBetaApis: expandEnableK8sBetaApis(d.Get("enable_k8s_beta_apis"), nil), } v:= d.Get("enable_shielded_nodes") @@ -2267,6 +2309,14 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er cluster.SecurityPostureConfig = expandSecurityPostureConfig(v) } + // For now PSC based cluster don't support `enable_private_endpoint` on `create`, but only on `update` API call. + // If cluster is PSC based and enable_private_endpoint is set to true we will ignore it on `create` call and update cluster right after creation. + enablePrivateEndpointPSCCluster := isEnablePrivateEndpointPSCCluster(cluster) + if enablePrivateEndpointPSCCluster { + cluster.PrivateClusterConfig.EnablePrivateEndpoint = false + } + + req := &container.CreateClusterRequest{ Cluster: cluster, } @@ -2354,6 +2404,34 @@ func resourceContainerClusterCreate(d *schema.ResourceData, meta interface{}) er } } + if enablePrivateEndpointPSCCluster { + name := containerClusterFullName(project, location, clusterName) + req := &container.UpdateClusterRequest{ + Update: &container.ClusterUpdate{ + DesiredEnablePrivateEndpoint: true, + ForceSendFields: []string{"DesiredEnablePrivateEndpoint"}, + }, + } + + err = transport_tpg.Retry(transport_tpg.RetryOptions{ + RetryFunc: func() error { + clusterUpdateCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.Update(name, req) + if config.UserProjectOverride { + clusterUpdateCall.Header().Add("X-Goog-User-Project", project) + } + op, err = clusterUpdateCall.Do() + return err + }, + }) + if err != nil { + return errwrap.Wrapf("Error updating enable private endpoint: {{err}}", err) + } + + err = ContainerOperationWait(config, op, project, location, "updating enable private endpoint", userAgent, d.Timeout(schema.TimeoutCreate)) + if err != nil { + return errwrap.Wrapf("Error while waiting to enable private endpoint: {{err}}", err) + } + } if err := resourceContainerClusterRead(d, meta); err != nil { return err @@ -2660,6 +2738,9 @@ func resourceContainerClusterRead(d *schema.ResourceData, meta interface{}) erro if err := d.Set("gateway_api_config", flattenGatewayApiConfig(cluster.NetworkConfig.GatewayApiConfig)); err != nil { return err } + if err := d.Set("enable_k8s_beta_apis", flattenEnableK8sBetaApis(cluster.EnableK8sBetaApis)); err != nil { + return err + } if err := d.Set("logging_config", flattenContainerClusterLoggingConfig(cluster.LoggingConfig)); err != nil { return err } @@ -3023,7 +3104,7 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er // Wait until it's updated err = ContainerOperationWait(config, op, project, location, "updating L4", userAgent, d.Timeout(schema.TimeoutUpdate)) - log.Println("[DEBUG] done updating enable_intranode_visibility") + log.Println("[DEBUG] done updating enable_l4_ilb_subsetting") return err } @@ -3718,6 +3799,44 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er } } + if d.HasChange("enable_k8s_beta_apis") { + log.Print("[INFO] Enable Kubernetes Beta APIs") + if v, ok := d.GetOk("enable_k8s_beta_apis"); ok { + name := containerClusterFullName(project, location, clusterName) + clusterGetCall := config.NewContainerClient(userAgent).Projects.Locations.Clusters.Get(name) + if config.UserProjectOverride { + clusterGetCall.Header().Add("X-Goog-User-Project", project) + } + // Fetch the cluster information to get the already enabled Beta APIs. + cluster, err := clusterGetCall.Do() + if err != nil { + return err + } + + // To avoid an already enabled Beta APIs error, we need to deduplicate the requested APIs + // with those that are already enabled. + var enabledAPIs []string + if cluster.EnableK8sBetaApis != nil && len(cluster.EnableK8sBetaApis.EnabledApis) > 0 { + enabledAPIs = cluster.EnableK8sBetaApis.EnabledApis + } + enableK8sBetaAPIs := expandEnableK8sBetaApis(v, enabledAPIs) + + req := &container.UpdateClusterRequest{ + Update: &container.ClusterUpdate{ + DesiredK8sBetaApis: enableK8sBetaAPIs, + }, + } + + updateF := updateFunc(req, "updating enabled Kubernetes Beta APIs") + // Call update serially. + if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { + return err + } + + log.Printf("[INFO] GKE cluster %s enabled Kubernetes Beta APIs has been updated", d.Id()) + } + } + if d.HasChange("node_pool_defaults") && d.HasChange("node_pool_defaults.0.node_config_defaults.0.logging_variant") { if v, ok := d.GetOk("node_pool_defaults.0.node_config_defaults.0.logging_variant"); ok { loggingVariant := v.(string) @@ -3742,26 +3861,26 @@ func resourceContainerClusterUpdate(d *schema.ResourceData, meta interface{}) er } <% unless version == 'ga' -%> - if d.HasChange("node_pool_defaults") && d.HasChange("node_pool_defaults.0.node_config_defaults.0.gcfs_config") { - if v, ok := d.GetOk("node_pool_defaults.0.node_config_defaults.0.gcfs_config"); ok { - gcfsConfig := v.([]interface{})[0].(map[string]interface{}) - req := &container.UpdateClusterRequest{ - Update: &container.ClusterUpdate{ - DesiredGcfsConfig: &container.GcfsConfig{ - Enabled: gcfsConfig["enabled"].(bool), - }, - }, - } - - updateF := updateFunc(req, "updating GKE cluster desired gcfs config.") - // Call update serially. - if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { - return err - } - - log.Printf("[INFO] GKE cluster %s default gcfs config has been updated", d.Id()) - } - } + if d.HasChange("node_pool_defaults") && d.HasChange("node_pool_defaults.0.node_config_defaults.0.gcfs_config") { + if v, ok := d.GetOk("node_pool_defaults.0.node_config_defaults.0.gcfs_config"); ok { + gcfsConfig := v.([]interface{})[0].(map[string]interface{}) + req := &container.UpdateClusterRequest{ + Update: &container.ClusterUpdate{ + DesiredGcfsConfig: &container.GcfsConfig{ + Enabled: gcfsConfig["enabled"].(bool), + }, + }, + } + + updateF := updateFunc(req, "updating GKE cluster desired gcfs config.") + // Call update serially. + if err := transport_tpg.LockedCall(lockKey, updateF); err != nil { + return err + } + + log.Printf("[INFO] GKE cluster %s default gcfs config has been updated", d.Id()) + } + } <% end -%> if d.HasChange("security_posture_config") { @@ -4576,13 +4695,13 @@ func expandBinaryAuthorization(configured interface{}, legacy_enabled bool) *con if len(l) == 0 || l[0] == nil { return &container.BinaryAuthorization{ Enabled: legacy_enabled, - ForceSendFields: []string{"Enabled"}, + ForceSendFields: []string{"Enabled"}, } } config := l[0].(map[string]interface{}) return &container.BinaryAuthorization{ - Enabled: config["enabled"].(bool), - EvaluationMode: config["evaluation_mode"].(string), + Enabled: config["enabled"].(bool), + EvaluationMode: config["evaluation_mode"].(string), } } @@ -4665,6 +4784,22 @@ func expandNetworkPolicy(configured interface{}) *container.NetworkPolicy { return result } +func isEnablePrivateEndpointPSCCluster(cluster *container.Cluster) bool { + // EnablePrivateEndpoint not provided + if cluster == nil || cluster.PrivateClusterConfig == nil { + return false + } + // Not a PSC cluster + if cluster.PrivateClusterConfig.EnablePrivateNodes || len(cluster.PrivateClusterConfig.MasterIpv4CidrBlock) > 0 { + return false + } + // PSC Cluster with EnablePrivateEndpoint + if cluster.PrivateClusterConfig.EnablePrivateEndpoint { + return true + } + return false +} + func expandPrivateClusterConfig(configured interface{}) *container.PrivateClusterConfig { l := configured.([]interface{}) if len(l) == 0 { @@ -4900,6 +5035,28 @@ func expandGatewayApiConfig(configured interface{}) *container.GatewayAPIConfig } } +func expandEnableK8sBetaApis(configured interface{}, enabledAPIs []string) *container.K8sBetaAPIConfig { + l := configured.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil + } + + config := l[0].(map[string]interface{}) + result := &container.K8sBetaAPIConfig{} + if v, ok := config["enabled_apis"]; ok { + notEnabledAPIsSet := v.(*schema.Set) + for _, enabledAPI := range enabledAPIs { + if notEnabledAPIsSet.Contains(enabledAPI) { + notEnabledAPIsSet.Remove(enabledAPI) + } + } + + result.EnabledApis = tpgresource.ConvertStringSet(notEnabledAPIsSet) + } + + return result +} + func expandContainerClusterLoggingConfig(configured interface{}) *container.LoggingConfig { l := configured.([]interface{}) if len(l) == 0 { @@ -4939,6 +5096,16 @@ func expandMonitoringConfig(configured interface{}) *container.MonitoringConfig Enabled: managed_prometheus["enabled"].(bool), } } + + if v, ok := config["advanced_datapath_observability_config"]; ok && len(v.([]interface{})) > 0 { + advanced_datapath_observability_config := v.([]interface{})[0].(map[string]interface{}) + + mc.AdvancedDatapathObservabilityConfig = &container.AdvancedDatapathObservabilityConfig{ + EnableMetrics: advanced_datapath_observability_config["enable_metrics"].(bool), + RelayMode: advanced_datapath_observability_config["relay_mode"].(string), + } + } + return mc } @@ -4977,16 +5144,16 @@ func expandContainerClusterAuthenticatorGroupsConfig(configured interface{}) *co } func expandNodePoolDefaults(configured interface{}) *container.NodePoolDefaults { - l, ok := configured.([]interface{}) - if !ok || l == nil || len(l) == 0 || l[0] == nil { - return nil - } - nodePoolDefaults := &container.NodePoolDefaults{} - config := l[0].(map[string]interface{}) - if v, ok := config["node_config_defaults"]; ok && len(v.([]interface{})) > 0 { - nodePoolDefaults.NodeConfigDefaults = expandNodeConfigDefaults(v) - } - return nodePoolDefaults + l, ok := configured.([]interface{}) + if !ok || l == nil || len(l) == 0 || l[0] == nil { + return nil + } + nodePoolDefaults := &container.NodePoolDefaults{} + config := l[0].(map[string]interface{}) + if v, ok := config["node_config_defaults"]; ok && len(v.([]interface{})) > 0 { + nodePoolDefaults.NodeConfigDefaults = expandNodeConfigDefaults(v) + } + return nodePoolDefaults } func flattenNodePoolDefaults(c *container.NodePoolDefaults) []map[string]interface{} { @@ -5706,6 +5873,17 @@ func flattenGatewayApiConfig(c *container.GatewayAPIConfig) []map[string]interfa } } +func flattenEnableK8sBetaApis(c *container.K8sBetaAPIConfig) []map[string]interface{} { + if c == nil { + return nil + } + return []map[string]interface{}{ + { + "enabled_apis": c.EnabledApis, + }, + } +} + func flattenContainerClusterLoggingConfig(c *container.LoggingConfig) []map[string]interface{} { if c == nil { return nil @@ -5730,9 +5908,22 @@ func flattenMonitoringConfig(c *container.MonitoringConfig) []map[string]interfa if c.ManagedPrometheusConfig != nil { result["managed_prometheus"] = flattenManagedPrometheusConfig(c.ManagedPrometheusConfig) } + if c.AdvancedDatapathObservabilityConfig != nil { + result["advanced_datapath_observability_config"] = flattenAdvancedDatapathObservabilityConfig(c.AdvancedDatapathObservabilityConfig) + } + return []map[string]interface{}{result} } +func flattenAdvancedDatapathObservabilityConfig(c *container.AdvancedDatapathObservabilityConfig) []map[string]interface{} { + return []map[string]interface{}{ + { + "enable_metrics": c.EnableMetrics, + "relay_mode": c.RelayMode, + }, + } +} + func flattenManagedPrometheusConfig(c *container.ManagedPrometheusConfig) []map[string]interface{} { return []map[string]interface{}{ { @@ -5878,12 +6069,15 @@ func containerClusterPrivateClusterConfigSuppress(k, old, new string, d *schema. // Do not suppress diffs when private_endpoint_subnetwork is configured _, hasSubnet := d.GetOk("private_cluster_config.0.private_endpoint_subnetwork") + // Do not suppress diffs when master_global_access_config is configured + _, hasGlobalAccessConfig := d.GetOk("private_cluster_config.0.master_global_access_config") + if k == "private_cluster_config.0.enable_private_endpoint" { return suppressEndpoint && !hasSubnet } else if k == "private_cluster_config.0.enable_private_nodes" { return suppressNodes && !hasSubnet } else if k == "private_cluster_config.#" { - return suppressEndpoint && suppressNodes && !hasSubnet + return suppressEndpoint && suppressNodes && !hasSubnet && !hasGlobalAccessConfig } return false } @@ -5896,6 +6090,9 @@ func validatePrivateClusterConfig(cluster *container.Cluster) error { return fmt.Errorf("master_ipv4_cidr_block can only be set if enable_private_nodes is true") } if cluster.PrivateClusterConfig.EnablePrivateNodes && len(cluster.PrivateClusterConfig.MasterIpv4CidrBlock) == 0 { + if len(cluster.PrivateClusterConfig.PrivateEndpointSubnetwork) > 0 { + return nil + } if cluster.Autopilot == nil || !cluster.Autopilot.Enabled { return fmt.Errorf("master_ipv4_cidr_block must be set if enable_private_nodes is true") } @@ -5973,7 +6170,7 @@ func containerClusterNetworkPolicyDiffSuppress(k, old, new string, r *schema.Res } func BinaryAuthorizationDiffSuppress(k, old, new string, r *schema.ResourceData) bool { - // An empty config is equivalent to a config with enabled set to false. + // An empty config is equivalent to a config with enabled set to false. if k == "binary_authorization.#" && old == "1" && new == "0" { o, _ := r.GetChange("binary_authorization.0.enabled") if !o.(bool) && !r.HasChange("binary_authorization.0.evaluation_mode") { @@ -6015,3 +6212,31 @@ func containerClusterSurgeSettingsCustomizeDiff(_ context.Context, d *schema.Res return nil } + +func containerClusterEnableK8sBetaApisCustomizeDiff(_ context.Context, d *schema.ResourceDiff, meta interface{}) error { + // separate func to allow unit testing + return containerClusterEnableK8sBetaApisCustomizeDiffFunc(d) +} + +func containerClusterEnableK8sBetaApisCustomizeDiffFunc(d tpgresource.TerraformResourceDiff) error { + // The Kubernetes Beta APIs cannot be disabled once they have been enabled by users. + // The reason why we don't allow disabling is that the controller does not have the + // ability to clean up the Kubernetes objects created by the APIs. If the user + // removes the already enabled Kubernetes Beta API from the list, we need to force + // a new cluster. + if !d.HasChange("enable_k8s_beta_apis.0.enabled_apis") { + return nil + } + old, new := d.GetChange("enable_k8s_beta_apis.0.enabled_apis") + if old != "" && new != "" { + oldAPIsSet := old.(*schema.Set) + newAPIsSet := new.(*schema.Set) + for _, oldAPI := range oldAPIsSet.List() { + if !newAPIsSet.Contains(oldAPI) { + return d.ForceNew("enable_k8s_beta_apis.0.enabled_apis") + } + } + } + + return nil +} diff --git a/mmv1/third_party/terraform/services/container/resource_container_cluster_internal_test.go.erb b/mmv1/third_party/terraform/services/container/resource_container_cluster_internal_test.go.erb index 5d2f180027e0..2856b2c82e77 100644 --- a/mmv1/third_party/terraform/services/container/resource_container_cluster_internal_test.go.erb +++ b/mmv1/third_party/terraform/services/container/resource_container_cluster_internal_test.go.erb @@ -2,9 +2,11 @@ package container import ( -<% unless version == 'ga' -%> "testing" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" +<% unless version == 'ga' -%> container "google.golang.org/api/container/v1beta1" <% end -%> ) @@ -91,3 +93,98 @@ func TestValidateNodePoolAutoConfig(t *testing.T) { } } <% end -%> + + +func TestContainerClusterEnableK8sBetaApisCustomizeDiff(t *testing.T) { + t.Parallel() + + cases := map[string]struct { + before *schema.Set + after *schema.Set + expectedForceNew bool + }{ + "no need to force new from nil to empty apis": { + before: schema.NewSet(schema.HashString, nil), + after: schema.NewSet(schema.HashString, []interface{}{}), + expectedForceNew: false, + }, + "no need to force new from empty apis to nil": { + before: schema.NewSet(schema.HashString, []interface{}{}), + after: schema.NewSet(schema.HashString, nil), + expectedForceNew: false, + }, + "no need to force new from empty apis to empty apis": { + before: schema.NewSet(schema.HashString, []interface{}{}), + after: schema.NewSet(schema.HashString, []interface{}{}), + expectedForceNew: false, + }, + "no need to force new from nil to empty string apis": { + before: schema.NewSet(schema.HashString, nil), + after: schema.NewSet(schema.HashString, []interface{}{""}), + expectedForceNew: false, + }, + "no need to force new from empty string apis to empty string apis": { + before: schema.NewSet(schema.HashString, []interface{}{""}), + after: schema.NewSet(schema.HashString, []interface{}{""}), + expectedForceNew: false, + }, + "no need to force new for enabling new api from empty apis": { + before: schema.NewSet(schema.HashString, []interface{}{}), + after: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo"}), + expectedForceNew: false, + }, + "no need to force new for enabling new api from nil": { + before: schema.NewSet(schema.HashString, nil), + after: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo"}), + expectedForceNew: false, + }, + "no need to force new for passing same apis": { + before: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo"}), + after: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo"}), + expectedForceNew: false, + }, + "no need to force new for passing same apis with inconsistent order": { + before: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo", "dummy.k8s.io/v1beta1/bar"}), + after: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/bar", "dummy.k8s.io/v1beta1/foo"}), + expectedForceNew: false, + }, + "need to force new from empty string apis to nil": { + before: schema.NewSet(schema.HashString, []interface{}{""}), + after: schema.NewSet(schema.HashString, nil), + expectedForceNew: true, + }, + "need to force new for disabling existing api": { + before: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo"}), + after: schema.NewSet(schema.HashString, []interface{}{}), + expectedForceNew: true, + }, + "need to force new for disabling existing api with nil": { + before: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo"}), + after: schema.NewSet(schema.HashString, nil), + expectedForceNew: true, + }, + "need to force new for disabling existing apis": { + before: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo", "dummy.k8s.io/v1beta1/bar", "dummy.k8s.io/v1beta1/baz"}), + after: schema.NewSet(schema.HashString, []interface{}{"dummy.k8s.io/v1beta1/foo"}), + expectedForceNew: true, + }, + } + + for tn, tc := range cases { + d := &tpgresource.ResourceDiffMock{ + Before: map[string]interface{}{ + "enable_k8s_beta_apis.0.enabled_apis": tc.before, + }, + After: map[string]interface{}{ + "enable_k8s_beta_apis.0.enabled_apis": tc.after, + }, + } + err := containerClusterEnableK8sBetaApisCustomizeDiffFunc(d) + if err != nil { + t.Errorf("%s failed, found unexpected error: %s", tn, err) + } + if d.IsForceNew != tc.expectedForceNew { + t.Errorf("%v: expected d.IsForceNew to be %v, but was %v", tn, tc.expectedForceNew, d.IsForceNew) + } + } +} 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 bc5b7fa0115f..9d73c6ccb416 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 @@ -191,6 +191,12 @@ var schemaNodePool = map[string]*schema.Schema{ Required: true, Description: `Type defines the type of placement policy`, }, + "policy_name": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Description: `If set, refers to the name of a custom resource policy supplied by the user. The resource policy must be in the same project and region as the node pool. If not found, InvalidArgument error is returned.`, + }, <% unless version == 'ga' -%> "tpu_topology": { Type: schema.TypeString, @@ -937,6 +943,7 @@ func expandNodePool(d *schema.ResourceData, prefix string) (*container.NodePool, placement_policy := v.([]interface{})[0].(map[string]interface{}) np.PlacementPolicy = &container.PlacementPolicy{ Type: placement_policy["type"].(string), + PolicyName: placement_policy["policy_name"].(string), <% unless version == 'ga' -%> TpuTopology: placement_policy["tpu_topology"].(string), <% end -%> @@ -1131,6 +1138,7 @@ func flattenNodePool(d *schema.ResourceData, config *transport_tpg.Config, np *c nodePool["placement_policy"] = []map[string]interface{}{ { "type": np.PlacementPolicy.Type, + "policy_name": np.PlacementPolicy.PolicyName, <% unless version == 'ga' -%> "tpu_topology": np.PlacementPolicy.TpuTopology, <% end -%> diff --git a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb index e748c1228419..2d173db79d3b 100644 --- a/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb +++ b/mmv1/third_party/terraform/services/sql/resource_sql_database_instance.go.erb @@ -327,7 +327,7 @@ is set to true. Defaults to ZONAL.`, Computed: true, Optional: true, AtLeastOneOf: backupConfigurationKeys, - Description: `The number of days of transaction logs we retain for point in time restore, from 1-7.`, + Description: `The number of days of transaction logs we retain for point in time restore, from 1-7. (For PostgreSQL Enterprise Plus instances, from 1 to 35.)`, }, "backup_retention_settings": { Type: schema.TypeList, diff --git a/mmv1/third_party/terraform/tests/resource_alloydb_backup_test.go b/mmv1/third_party/terraform/tests/resource_alloydb_backup_test.go index 66cbdc95d612..699cc95b86b2 100644 --- a/mmv1/third_party/terraform/tests/resource_alloydb_backup_test.go +++ b/mmv1/third_party/terraform/tests/resource_alloydb_backup_test.go @@ -98,6 +98,7 @@ func TestAccAlloydbBackup_createBackupWithMandatoryFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbbackup-mandatory"), } acctest.VcrTest(t, resource.TestCase{ @@ -124,13 +125,13 @@ resource "google_alloydb_backup" "default" { resource "google_alloydb_cluster" "default" { location = "us-central1" cluster_id = "tf-test-alloydb-cluster%{random_suffix}" - network = google_compute_network.default.id + network = data.google_compute_network.default.id } data "google_project" "project" { } -resource "google_compute_network" "default" { - name = "tf-test-alloydb-cluster%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_alloydb_instance" "default" { @@ -146,7 +147,7 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id lifecycle { ignore_changes = [ address, @@ -160,7 +161,7 @@ resource "google_compute_global_address" "private_ip_alloc" { } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } diff --git a/mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go b/mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go index 6d8b1397cd95..6df317a65185 100644 --- a/mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go +++ b/mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go @@ -737,3 +737,358 @@ resource "google_kms_crypto_key_iam_binding" "crypto_key2" { } `, context) } + +// Validates continuous backups defaults to being enabled with 14d retention, even if not explicitly configured. +func TestAccAlloydbCluster_continuousBackup_enabledByDefault(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: testAccCheckAlloydbClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbCluster_withoutContinuousBackupConfig(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.enabled", "true"), + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.recovery_window_days", "14"), + ), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_alloydbClusterBasicExample(context), + }, + }, + }) +} + +// Continuous backups defaults to being enabled with 14d retention. If the same configuration is set explicitly, terraform plan +// should return no changes. +func TestAccAlloydbCluster_continuousBackup_update_noChangeIfDefaultsSet(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "enabled": true, + "recovery_window_days": 14, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbCluster_withoutContinuousBackupConfig(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.enabled", "true"), + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.recovery_window_days", "14"), + ), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_continuousBackupConfig(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.enabled", "true"), + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.recovery_window_days", "14"), + ), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_alloydbClusterBasicExample(context), + }, + }, + }) +} + +// This test ensures that if you start with a terraform configuration where continuous backups are explicitly set to the default configuration +// and then remove continuous backups and call terraform plan, no changes would be found. +func TestAccAlloydbCluster_continuousBackup_noChangeIfRemoved(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "enabled": true, + "recovery_window_days": 14, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbCluster_continuousBackupConfig(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.enabled", "true"), + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.recovery_window_days", "14"), + ), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_alloydbClusterBasicExample(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.enabled", "true"), + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.recovery_window_days", "14"), + ), + }, + }, + }) +} + +// Ensures changes to the continuous backup config properly applies +func TestAccAlloydbCluster_continuousBackup_update(t *testing.T) { + t.Parallel() + + suffix := acctest.RandString(t, 10) + context := map[string]interface{}{ + "random_suffix": suffix, + "enabled": true, + "recovery_window_days": 15, + } + context2 := map[string]interface{}{ + "random_suffix": suffix, + "enabled": false, + "recovery_window_days": 14, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbCluster_withoutContinuousBackupConfig(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.enabled", "true"), + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.recovery_window_days", "14"), + ), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_continuousBackupConfig(context), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.enabled", "true"), + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.recovery_window_days", "15"), + ), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_continuousBackupConfig(context2), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.enabled", "false"), + resource.TestCheckResourceAttr("google_alloydb_cluster.default", "continuous_backup_config.0.recovery_window_days", "14"), + ), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_alloydbClusterBasicExample(context), + }, + }, + }) +} + +func testAccAlloydbCluster_withoutContinuousBackupConfig(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + lifecycle { + prevent_destroy = true + } +} + +data "google_project" "project" { +} + +resource "google_compute_network" "default" { + name = "tf-test-alloydb-cluster%{random_suffix}" +} +`, context) +} + +func testAccAlloydbCluster_continuousBackupConfig(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + + continuous_backup_config { + enabled = %{enabled} + recovery_window_days = %{recovery_window_days} + } + lifecycle { + prevent_destroy = true + } +} + +data "google_project" "project" { +} + +resource "google_compute_network" "default" { + name = "tf-test-alloydb-cluster%{random_suffix}" +} +`, context) +} + +func TestAccAlloydbCluster_continuousBackup_CMEKIsUpdatable(t *testing.T) { + t.Parallel() + + suffix := acctest.RandString(t, 10) + kms := acctest.BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", "us-central1", "tf-bootstrap-alloydb-key1") + context := map[string]interface{}{ + "random_suffix": suffix, + "key_ring": kms.KeyRing.Name, + "key_name": kms.CryptoKey.Name, + } + + kms2 := acctest.BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", "us-central1", "tf-bootstrap-alloydb-key2") + context2 := map[string]interface{}{ + "random_suffix": suffix, + "key_ring": kms2.KeyRing.Name, + "key_name": kms2.CryptoKey.Name, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbCluster_usingCMEKInClusterAndContinuousBackup(context), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_usingCMEKInClusterAndContinuousBackup(context2), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_continuousBackupUsingCMEKAllowDeletion(context2), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"cluster_id", "location"}, + }, + }, + }) +} + +func testAccAlloydbCluster_usingCMEKInClusterAndContinuousBackup(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + continuous_backup_config { + enabled = true + recovery_window_days = 20 + encryption_config { + kms_key_name = "%{key_name}" + } + } + lifecycle { + prevent_destroy = true + } + depends_on = [google_kms_crypto_key_iam_binding.crypto_key] +} + +resource "google_compute_network" "default" { + name = "tf-test-alloydb-cluster%{random_suffix}" +} + +data "google_project" "project" {} + +resource "google_kms_crypto_key_iam_binding" "crypto_key" { + crypto_key_id = "%{key_name}" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", + ] +} +`, context) +} + +func testAccAlloydbCluster_continuousBackupUsingCMEKAllowDeletion(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + continuous_backup_config { + enabled = true + recovery_window_days = 20 + encryption_config { + kms_key_name = "%{key_name}" + } + } + depends_on = [google_kms_crypto_key_iam_binding.crypto_key] +} + +resource "google_compute_network" "default" { + name = "tf-test-alloydb-cluster%{random_suffix}" +} + +data "google_project" "project" {} + +resource "google_kms_crypto_key_iam_binding" "crypto_key" { + crypto_key_id = "%{key_name}" + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", + ] + } +`, context) +} diff --git a/mmv1/third_party/terraform/tests/resource_alloydb_instance_test.go b/mmv1/third_party/terraform/tests/resource_alloydb_instance_test.go index 09766d64193a..a7ef97850146 100644 --- a/mmv1/third_party/terraform/tests/resource_alloydb_instance_test.go +++ b/mmv1/third_party/terraform/tests/resource_alloydb_instance_test.go @@ -12,6 +12,7 @@ func TestAccAlloydbInstance_update(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-update"), } acctest.VcrTest(t, resource.TestCase{ @@ -62,7 +63,7 @@ resource "google_alloydb_instance" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + network = data.google_compute_network.default.id initial_user { password = "tf-test-alloydb-cluster%{random_suffix}" @@ -72,8 +73,8 @@ resource "google_alloydb_cluster" "default" { data "google_project" "project" { } -resource "google_compute_network" "default" { - name = "tf-test-alloydb-cluster%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_compute_global_address" "private_ip_alloc" { @@ -81,11 +82,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -98,6 +99,7 @@ func TestAccAlloydbInstance_createInstanceWithMandatoryFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-mandatory"), } acctest.VcrTest(t, resource.TestCase{ @@ -125,13 +127,13 @@ resource "google_alloydb_instance" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { - name = "tf-test-alloydb-cluster%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_compute_global_address" "private_ip_alloc" { @@ -139,11 +141,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -156,6 +158,7 @@ func TestAccAlloydbInstance_createInstanceWithMaximumFields(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-maximum"), } acctest.VcrTest(t, resource.TestCase{ @@ -202,13 +205,13 @@ resource "google_alloydb_instance" "default" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { - name = "tf-test-alloydb-cluster%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_compute_global_address" "private_ip_alloc" { @@ -216,11 +219,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -233,6 +236,7 @@ func TestAccAlloydbInstance_createPrimaryAndReadPoolInstance(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-readpool"), } acctest.VcrTest(t, resource.TestCase{ @@ -269,13 +273,13 @@ resource "google_alloydb_instance" "read_pool" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { - name = "tf-test-alloydb-cluster%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_compute_global_address" "private_ip_alloc" { @@ -283,11 +287,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -300,6 +304,7 @@ func TestAccAlloydbInstance_updateDatabaseFlagInPrimaryInstance(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedTestNetwork(t, "alloydbinstance-updatedb"), } acctest.VcrTest(t, resource.TestCase{ @@ -337,13 +342,13 @@ resource "google_alloydb_instance" "primary" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { - name = "tf-test-alloydb-cluster%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_compute_global_address" "private_ip_alloc" { @@ -351,11 +356,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } @@ -377,13 +382,13 @@ resource "google_alloydb_instance" "primary" { resource "google_alloydb_cluster" "default" { cluster_id = "tf-test-alloydb-cluster%{random_suffix}" location = "us-central1" - network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + network = data.google_compute_network.default.id } data "google_project" "project" {} -resource "google_compute_network" "default" { - name = "tf-test-alloydb-cluster%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_compute_global_address" "private_ip_alloc" { @@ -391,11 +396,11 @@ resource "google_compute_global_address" "private_ip_alloc" { address_type = "INTERNAL" purpose = "VPC_PEERING" prefix_length = 16 - network = google_compute_network.default.id + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "vpc_connection" { - network = google_compute_network.default.id + network = data.google_compute_network.default.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.private_ip_alloc.name] } diff --git a/mmv1/third_party/terraform/tests/resource_app_engine_application_test.go b/mmv1/third_party/terraform/tests/resource_app_engine_application_test.go index 1b5e577d1d57..fe5a8a19836a 100644 --- a/mmv1/third_party/terraform/tests/resource_app_engine_application_test.go +++ b/mmv1/third_party/terraform/tests/resource_app_engine_application_test.go @@ -14,12 +14,14 @@ func TestAccAppEngineApplication_basic(t *testing.T) { org := envvar.GetTestOrgFromEnv(t) pid := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + billingAccount := envvar.GetTestBillingAccountFromEnv(t) + acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { - Config: testAccAppEngineApplication_basic(pid, org), + Config: testAccAppEngineApplication_basic(pid, org, billingAccount), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttrSet("google_app_engine_application.acceptance", "url_dispatch_rule.#"), resource.TestCheckResourceAttrSet("google_app_engine_application.acceptance", "name"), @@ -34,7 +36,7 @@ func TestAccAppEngineApplication_basic(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAppEngineApplication_update(pid, org), + Config: testAccAppEngineApplication_update(pid, org, billingAccount), }, { ResourceName: "google_app_engine_application.acceptance", @@ -50,13 +52,14 @@ func TestAccAppEngineApplication_withIAP(t *testing.T) { org := envvar.GetTestOrgFromEnv(t) pid := fmt.Sprintf("tf-test-%d", acctest.RandInt(t)) + billingAccount := envvar.GetTestBillingAccountFromEnv(t) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { - Config: testAccAppEngineApplication_withIAP(pid, org), + Config: testAccAppEngineApplication_withIAP(pid, org, billingAccount), }, { ResourceName: "google_app_engine_application.acceptance", @@ -68,12 +71,13 @@ func TestAccAppEngineApplication_withIAP(t *testing.T) { }) } -func testAccAppEngineApplication_withIAP(pid, org string) string { +func testAccAppEngineApplication_withIAP(pid, org, billingAccount string) string { return fmt.Sprintf(` resource "google_project" "acceptance" { project_id = "%s" name = "%s" org_id = "%s" + billing_account = "%s" } resource "google_app_engine_application" "acceptance" { @@ -88,15 +92,16 @@ resource "google_app_engine_application" "acceptance" { oauth2_client_secret = "test" } } -`, pid, pid, org) +`, pid, pid, org, billingAccount) } -func testAccAppEngineApplication_basic(pid, org string) string { +func testAccAppEngineApplication_basic(pid, org, billingAccount string) string { return fmt.Sprintf(` resource "google_project" "acceptance" { project_id = "%s" name = "%s" org_id = "%s" + billing_account = "%s" } resource "google_app_engine_application" "acceptance" { @@ -106,15 +111,16 @@ resource "google_app_engine_application" "acceptance" { database_type = "CLOUD_DATASTORE_COMPATIBILITY" serving_status = "SERVING" } -`, pid, pid, org) +`, pid, pid, org, billingAccount) } -func testAccAppEngineApplication_update(pid, org string) string { +func testAccAppEngineApplication_update(pid, org, billingAccount string) string { return fmt.Sprintf(` resource "google_project" "acceptance" { project_id = "%s" name = "%s" org_id = "%s" + billing_account = "%s" } resource "google_app_engine_application" "acceptance" { @@ -124,5 +130,5 @@ resource "google_app_engine_application" "acceptance" { database_type = "CLOUD_DATASTORE_COMPATIBILITY" serving_status = "USER_DISABLED" } -`, pid, pid, org) +`, pid, pid, org, billingAccount) } diff --git a/mmv1/third_party/terraform/tests/resource_bigquery_data_transfer_config_test.go b/mmv1/third_party/terraform/tests/resource_bigquery_data_transfer_config_test.go index 1bba14b45317..602650c4c665 100644 --- a/mmv1/third_party/terraform/tests/resource_bigquery_data_transfer_config_test.go +++ b/mmv1/third_party/terraform/tests/resource_bigquery_data_transfer_config_test.go @@ -386,7 +386,6 @@ func testAccCheckBigqueryDataTransferConfigDestroyProducer(t *testing.T) func(s func testAccBigqueryDataTransferConfig_scheduledQuery_update_service_account(t *testing.T) { random_suffix1 := acctest.RandString(t, 10) random_suffix2 := acctest.RandString(t, 10) - transferConfigID := "" acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -395,7 +394,6 @@ func testAccBigqueryDataTransferConfig_scheduledQuery_update_service_account(t * Steps: []resource.TestStep{ { Config: testAccBigqueryDataTransferConfig_scheduledQuery_updateServiceAccount(random_suffix1, random_suffix1), - Check: testAccCheckDataTransferConfigID("google_bigquery_data_transfer_config.query_config", &transferConfigID), }, { ResourceName: "google_bigquery_data_transfer_config.query_config", @@ -405,7 +403,7 @@ func testAccBigqueryDataTransferConfig_scheduledQuery_update_service_account(t * }, { Config: testAccBigqueryDataTransferConfig_scheduledQuery_updateServiceAccount(random_suffix1, random_suffix2), - Check: testAccCheckDataTransferConfigIDChange("google_bigquery_data_transfer_config.query_config", &transferConfigID), + Check: testAccCheckDataTransferServiceAccountNamePrefix("google_bigquery_data_transfer_config.query_config", random_suffix2), }, { ResourceName: "google_bigquery_data_transfer_config.query_config", @@ -417,8 +415,8 @@ func testAccBigqueryDataTransferConfig_scheduledQuery_update_service_account(t * }) } -// Retrieve transfer config ID and stores it in transferConfigID -func testAccCheckDataTransferConfigID(resourceName string, transferConfigID *string) resource.TestCheckFunc { +// Check if transfer config service account name starts with given prefix +func testAccCheckDataTransferServiceAccountNamePrefix(resourceName string, prefix string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -426,31 +424,10 @@ func testAccCheckDataTransferConfigID(resourceName string, transferConfigID *str return fmt.Errorf("Not found: %s", resourceName) } - if rs.Primary.ID == "" { - return fmt.Errorf("Transfer config ID is not set") + if !strings.HasPrefix(rs.Primary.Attributes["service_account_name"], "bqwriter"+prefix) { + return fmt.Errorf("Transfer config service account not updated") } - *transferConfigID = rs.Primary.ID - return nil - } -} - -// Check if transfer config ID matches the one stored in transferConfigID -func testAccCheckDataTransferConfigIDChange(resourceName string, transferConfigID *string) resource.TestCheckFunc { - return func(s *terraform.State) error { - - rs, ok := s.RootModule().Resources[resourceName] - if !ok { - return fmt.Errorf("Not found: %s", resourceName) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("Transfer config ID is not set") - } - - if *transferConfigID != rs.Primary.ID { - return fmt.Errorf("Transfer config was recreated after changing service account") - } return nil } } diff --git a/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go b/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go index e3b2d380b937..37b416067003 100644 --- a/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go +++ b/mmv1/third_party/terraform/tests/resource_bigquery_table_test.go @@ -532,6 +532,75 @@ func TestAccBigQueryExternalDataTable_parquetOptions(t *testing.T) { }) } +func TestAccBigQueryExternalDataTable_iceberg(t *testing.T) { + t.Parallel() + + bucketName := testBucketName(t) + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableFromGCSIceberg(datasetID, tableID, bucketName), + }, + }, + }) +} + +func TestAccBigQueryExternalDataTable_parquetFileSetSpecType(t *testing.T) { + t.Parallel() + + bucketName := testBucketName(t) + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + parquetFileName := "test.parquet" + manifestName := fmt.Sprintf("tf_test_%s.manifest.json", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableFromGCSParquetManifest(datasetID, tableID, bucketName, manifestName, parquetFileName), + }, + }, + }) +} + +func TestAccBigQueryExternalDataTable_queryAcceleration(t *testing.T) { + t.Parallel() + + bucketName := testBucketName(t) + objectName := fmt.Sprintf("tf_test_%s.gz.parquet", acctest.RandString(t, 10)) + + datasetID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + tableID := fmt.Sprintf("tf_test_%s", acctest.RandString(t, 10)) + connectionID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + + metadataCacheMode := "AUTOMATIC" + // including an optional field. Should work without specifiying. + // Has to follow google sql IntervalValue encoding + maxStaleness := "0-0 0 10:0:0" + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBigQueryTableFromGCSParquetWithQueryAcceleration(connectionID, datasetID, tableID, bucketName, objectName, metadataCacheMode, maxStaleness), + }, + }, + }) +} + func TestAccBigQueryExternalDataTable_objectTable(t *testing.T) { t.Parallel() @@ -541,6 +610,9 @@ func TestAccBigQueryExternalDataTable_objectTable(t *testing.T) { datasetID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) tableID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) connectionID := fmt.Sprintf("tf_test_%s", RandString(t, 10)) + // including an optional field. Should work without specifiying. + // Has to follow google sql IntervalValue encoding + maxStaleness := "0-0 0 10:0:0" VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -548,13 +620,13 @@ func TestAccBigQueryExternalDataTable_objectTable(t *testing.T) { CheckDestroy: testAccCheckBigQueryTableDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccBigQueryTableFromGCSObjectTable(connectionID, datasetID, tableID, bucketName, objectName), + Config: testAccBigQueryTableFromGCSObjectTable(connectionID, datasetID, tableID, bucketName, objectName, maxStaleness), }, { - Config: testAccBigQueryTableFromGCSObjectTableMetadata(connectionID, datasetID, tableID, bucketName, objectName), + Config: testAccBigQueryTableFromGCSObjectTableMetadata(connectionID, datasetID, tableID, bucketName, objectName, maxStaleness), }, { - Config: testAccBigQueryTableFromGCSObjectTable(connectionID, datasetID, tableID, bucketName, objectName), + Config: testAccBigQueryTableFromGCSObjectTable(connectionID, datasetID, tableID, bucketName, objectName, maxStaleness), }, }, }) @@ -1598,6 +1670,70 @@ resource "google_bigquery_table" "test" { `, datasetID, bucketName, objectName, content, tableID, format, quoteChar) } +func testAccBigQueryTableFromGCSParquetWithQueryAcceleration(connectionID, datasetID, tableID, bucketName, objectName, metadataCacheMode, maxStaleness string) string { + return fmt.Sprintf(` +resource "google_bigquery_connection" "test" { + connection_id = "%s" + location = "US" + cloud_resource {} +} + +locals { + connection_id_split = split("/", google_bigquery_connection.test.name) + connection_id_reformatted = "${local.connection_id_split[1]}.${local.connection_id_split[3]}.${local.connection_id_split[5]}" + } + + data "google_project" "project" {} + + resource "google_project_iam_member" "test" { + role = "roles/storage.objectViewer" + project = data.google_project.project.id + member = "serviceAccount:${google_bigquery_connection.test.cloud_resource[0].service_account_id}" + } + +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" +} + +resource "google_storage_bucket" "test" { + name = "%s" + location = "US" + force_destroy = true +} + +resource "google_storage_bucket_object" "test" { + name = "%s" + source = "./test-fixtures/bigquerytable/test.parquet.gzip" + bucket = google_storage_bucket.test.name +} + +resource "google_bigquery_table" "test" { + deletion_protection = false + table_id = "%s" + dataset_id = google_bigquery_dataset.test.dataset_id + external_data_configuration { + connection_id = local.connection_id_reformatted + autodetect = false + source_format = "PARQUET" + + source_uris = [ + "gs://${google_storage_bucket.test.name}/*", + ] + metadata_cache_mode = "%s" + hive_partitioning_options { + source_uri_prefix = "gs://${google_storage_bucket.test.name}/" + } + } + + max_staleness = "%s" + + depends_on = [ + google_project_iam_member.test + ] +} +`, connectionID, datasetID, bucketName, objectName, tableID, metadataCacheMode, maxStaleness) +} + func testAccBigQueryTableFromGCSParquet(datasetID, tableID, bucketName, objectName string) string { return fmt.Sprintf(` resource "google_bigquery_dataset" "test" { @@ -1673,7 +1809,105 @@ resource "google_bigquery_table" "test" { `, datasetID, bucketName, objectName, tableID, enum, list) } -func testAccBigQueryTableFromGCSObjectTable(connectionID, datasetID, tableID, bucketName, objectName string) string { +func testAccBigQueryTableFromGCSIceberg(datasetID, tableID, bucketName string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" +} + +resource "google_storage_bucket" "test" { + name = "%s" + location = "US" + force_destroy = true + uniform_bucket_level_access = true +} + +# Setup Empty Iceberg table in Bucket. +// . +// ├── data +// └── metadata +// ├── 00000-1114da6b-bb88-4b5a-94bd-370f286c858a.metadata.json +// Upload Data Files +resource "google_storage_bucket_object" "empty_data_folder" { + name = "data/" + content = " " + bucket = google_storage_bucket.test.name +} +// Upload Metadata File. +resource "google_storage_bucket_object" "metadata" { + name = "simple/metadata/00000-1114da6b-bb88-4b5a-94bd-370f286c858a.metadata.json" + source = "./test-fixtures/bigquerytable/simple/metadata/00000-1114da6b-bb88-4b5a-94bd-370f286c858a.metadata.json" + bucket = google_storage_bucket.test.name +} + +resource "google_bigquery_table" "test" { + deletion_protection = false + table_id = "%s" + dataset_id = google_bigquery_dataset.test.dataset_id + external_data_configuration { + autodetect = false + source_format = "ICEBERG" + # Point to metadata.json. + source_uris = [ + "gs://${google_storage_bucket.test.name}/simple/metadata/00000-1114da6b-bb88-4b5a-94bd-370f286c858a.metadata.json", + ] + } + # Depends on Iceberg Table Files + depends_on = [ + google_storage_bucket_object.empty_data_folder, + google_storage_bucket_object.metadata, + ] +} +`, datasetID, bucketName, tableID) +} + +func testAccBigQueryTableFromGCSParquetManifest(datasetID, tableID, bucketName, manifestName, parquetFileName string) string { + return fmt.Sprintf(` +resource "google_bigquery_dataset" "test" { + dataset_id = "%s" +} + +resource "google_storage_bucket" "test" { + name = "%s" + location = "US" + force_destroy = true + uniform_bucket_level_access = true +} + +# Upload Data File. +resource "google_storage_bucket_object" "datafile" { + name = "%s" + source = "./test-fixtures/bigquerytable/simple/data/00000-0-4e4a11ad-368c-496b-97ae-e3ac28051a4d-00001.parquet" + bucket = google_storage_bucket.test.name +} + +# Upload Metadata file +resource "google_storage_bucket_object" "manifest" { + name = "%s" + content = "gs://${google_storage_bucket.test.name}/${google_storage_bucket_object.datafile.name}" + bucket = google_storage_bucket.test.name +} + + +resource "google_bigquery_table" "test" { + deletion_protection = false + table_id = "%s" + dataset_id = google_bigquery_dataset.test.dataset_id + external_data_configuration { + autodetect = false + source_format = "PARQUET" + # Specify URI is a manifest. + file_set_spec_type = "FILE_SET_SPEC_TYPE_NEW_LINE_DELIMITED_MANIFEST" + # Point to metadata.json. + source_uris = [ + "gs://${google_storage_bucket.test.name}/${google_storage_bucket_object.manifest.name}", + ] + } +} +`, datasetID, bucketName, manifestName, parquetFileName, tableID) +} + +func testAccBigQueryTableFromGCSObjectTable(connectionID, datasetID, tableID, bucketName, objectName, maxStaleness string) string { return fmt.Sprintf(` resource "google_bigquery_connection" "test" { connection_id = "%s" @@ -1718,16 +1952,18 @@ resource "google_bigquery_table" "test" { connection_id = local.connection_id_reformatted autodetect = false object_metadata = "SIMPLE" + metadata_cache_mode = "MANUAL" source_uris = [ "gs://${google_storage_bucket.test.name}/*", ] } + max_staleness = "%s" } -`, connectionID, datasetID, bucketName, objectName, tableID) +`, connectionID, datasetID, bucketName, objectName, tableID, maxStaleness) } -func testAccBigQueryTableFromGCSObjectTableMetadata(connectionID, datasetID, tableID, bucketName, objectName string) string { +func testAccBigQueryTableFromGCSObjectTableMetadata(connectionID, datasetID, tableID, bucketName, objectName, maxStaleness string) string { return fmt.Sprintf(` resource "google_bigquery_connection" "test" { connection_id = "%s" @@ -1778,8 +2014,9 @@ resource "google_bigquery_table" "test" { "gs://${google_storage_bucket.test.name}/*", ] } + max_staleness = "%s" } -`, connectionID, datasetID, bucketName, objectName, tableID) +`, connectionID, datasetID, bucketName, objectName, tableID, maxStaleness) } func testAccBigQueryTableFromGCSWithSchemaWithConnectionId(datasetID, tableID, connectionID, projectID, bucketName, objectName, content, schema string) string { diff --git a/mmv1/third_party/terraform/tests/resource_cloudbuild_worker_pool_test.go.erb b/mmv1/third_party/terraform/tests/resource_cloudbuild_worker_pool_test.go.erb index 53247b581b04..8dc25191686e 100644 --- a/mmv1/third_party/terraform/tests/resource_cloudbuild_worker_pool_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_cloudbuild_worker_pool_test.go.erb @@ -98,6 +98,7 @@ func TestAccCloudbuildWorkerPool_withNetwork(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), "project": envvar.GetTestProjectFromEnv(), + "network_name": acctest.BootstrapSharedTestNetwork(t, "cloudbuild-workerpool"), } acctest.VcrTest(t, resource.TestCase{ @@ -119,15 +120,9 @@ func TestAccCloudbuildWorkerPool_withNetwork(t *testing.T) { func testAccCloudbuildWorkerPool_withNetwork(context map[string]interface{}) string { return acctest.Nprintf(` -resource "google_project_service" "servicenetworking" { - service = "servicenetworking.googleapis.com" - disable_on_destroy = false -} -resource "google_compute_network" "network" { - name = "tf-test-network%{random_suffix}" - auto_create_subnetworks = false - depends_on = [google_project_service.servicenetworking] +data "google_compute_network" "network" { + name = "%{network_name}" } resource "google_compute_global_address" "worker_range" { @@ -135,14 +130,13 @@ resource "google_compute_global_address" "worker_range" { purpose = "VPC_PEERING" address_type = "INTERNAL" prefix_length = 16 - network = google_compute_network.network.id + network = data.google_compute_network.network.id } resource "google_service_networking_connection" "worker_pool_conn" { - network = google_compute_network.network.id + network = data.google_compute_network.network.id service = "servicenetworking.googleapis.com" reserved_peering_ranges = [google_compute_global_address.worker_range.name] - depends_on = [google_project_service.servicenetworking] } resource "google_cloudbuild_worker_pool" "pool" { @@ -154,7 +148,7 @@ resource "google_cloudbuild_worker_pool" "pool" { no_external_ip = false } network_config { - peered_network = google_compute_network.network.id + peered_network = data.google_compute_network.network.id peered_network_ip_range = "/29" } depends_on = [google_service_networking_connection.worker_pool_conn] diff --git a/mmv1/third_party/terraform/tests/resource_cloudids_endpoint_test.go b/mmv1/third_party/terraform/tests/resource_cloudids_endpoint_test.go index 8869dc7149a1..683bc4ce255b 100644 --- a/mmv1/third_party/terraform/tests/resource_cloudids_endpoint_test.go +++ b/mmv1/third_party/terraform/tests/resource_cloudids_endpoint_test.go @@ -18,6 +18,7 @@ func TestAccCloudIdsEndpoint_basic(t *testing.T) { context := map[string]interface{}{ "random_suffix": acctest.RandString(t, 10), + "network_name": acctest.BootstrapSharedTestNetwork(t, "cloud-ids-endpoint"), } acctest.VcrTest(t, resource.TestCase{ @@ -47,58 +48,58 @@ func TestAccCloudIdsEndpoint_basic(t *testing.T) { func testCloudIds_basic(context map[string]interface{}) string { return acctest.Nprintf(` -resource "google_compute_network" "default" { - name = "tf-test-my-network%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_compute_global_address" "service_range" { - name = "tf-test-address%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.default.id + name = "tf-test-address%{random_suffix}" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "private_service_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.service_range.name] + network = data.google_compute_network.default.id + service = "servicenetworking.googleapis.com" + reserved_peering_ranges = [google_compute_global_address.service_range.name] } resource "google_cloud_ids_endpoint" "endpoint" { - name = "cloud-ids-test-%{random_suffix}" - location = "us-central1-f" - network = google_compute_network.default.id - severity = "INFORMATIONAL" - threat_exceptions = ["12", "67"] - depends_on = [google_service_networking_connection.private_service_connection] + name = "cloud-ids-test-%{random_suffix}" + location = "us-central1-f" + network = data.google_compute_network.default.id + severity = "INFORMATIONAL" + threat_exceptions = ["12", "67"] + depends_on = [google_service_networking_connection.private_service_connection] } `, context) } func testCloudIds_basicUpdate(context map[string]interface{}) string { return acctest.Nprintf(` -resource "google_compute_network" "default" { - name = "tf-test-my-network%{random_suffix}" +data "google_compute_network" "default" { + name = "%{network_name}" } resource "google_compute_global_address" "service_range" { - name = "tf-test-address%{random_suffix}" - purpose = "VPC_PEERING" - address_type = "INTERNAL" - prefix_length = 16 - network = google_compute_network.default.id + name = "tf-test-address%{random_suffix}" + purpose = "VPC_PEERING" + address_type = "INTERNAL" + prefix_length = 16 + network = data.google_compute_network.default.id } resource "google_service_networking_connection" "private_service_connection" { - network = google_compute_network.default.id - service = "servicenetworking.googleapis.com" - reserved_peering_ranges = [google_compute_global_address.service_range.name] + network = data.google_compute_network.default.id + service = "servicenetworking.googleapis.com" + reserved_peering_ranges = [google_compute_global_address.service_range.name] } resource "google_cloud_ids_endpoint" "endpoint" { - name = "cloud-ids-test-%{random_suffix}" - location = "us-central1-f" - network = google_compute_network.default.id - severity = "INFORMATIONAL" - threat_exceptions = ["33"] - depends_on = [google_service_networking_connection.private_service_connection] + name = "cloud-ids-test-%{random_suffix}" + location = "us-central1-f" + network = data.google_compute_network.default.id + severity = "INFORMATIONAL" + threat_exceptions = ["33"] + depends_on = [google_service_networking_connection.private_service_connection] } `, context) } diff --git a/mmv1/third_party/terraform/tests/resource_compute_instance_from_machine_image_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_instance_from_machine_image_test.go.erb index 9a66b85d4bd5..af1315a1daa1 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_instance_from_machine_image_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_instance_from_machine_image_test.go.erb @@ -46,6 +46,60 @@ func TestAccComputeInstanceFromMachineImage_basic(t *testing.T) { }) } +func TestAccComputeInstanceFromMachineImage_localSsdRecoveryTimeout(t *testing.T) { + t.Parallel() + + var instance compute.Instance + instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + generatedInstanceName := fmt.Sprintf("tf-test-generated-%s", acctest.RandString(t, 10)) + resourceName := "google_compute_instance_from_machine_image.foobar" + var expectedLocalSsdRecoveryTimeout = compute.Duration{} + expectedLocalSsdRecoveryTimeout.Nanos = 0 + expectedLocalSsdRecoveryTimeout.Seconds = 3600 + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckComputeInstanceFromMachineImageDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceFromMachineImage_localSsdRecoveryTimeout(instanceName, generatedInstanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists(t, resourceName, &instance), + testAccCheckComputeInstanceLocalSsdRecoveryTimeout(&instance, expectedLocalSsdRecoveryTimeout), + ), + }, + }, + }) +} + +func TestAccComputeInstanceFromMachineImageWithOverride_localSsdRecoveryTimeout(t *testing.T) { + t.Parallel() + + var instance compute.Instance + instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + generatedInstanceName := fmt.Sprintf("tf-test-generated-%s", acctest.RandString(t, 10)) + resourceName := "google_compute_instance_from_machine_image.foobar" + var expectedLocalSsdRecoveryTimeout = compute.Duration{} + expectedLocalSsdRecoveryTimeout.Nanos = 0 + expectedLocalSsdRecoveryTimeout.Seconds = 7200 + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckComputeInstanceFromMachineImageDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceFromMachineImageWithOverride_localSsdRecoveryTimeout(instanceName, generatedInstanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists(t, resourceName, &instance), + testAccCheckComputeInstanceLocalSsdRecoveryTimeout(&instance, expectedLocalSsdRecoveryTimeout), + ), + }, + }, + }) +} + func TestAccComputeInstanceFromMachineImage_overrideMetadataDotStartupScript(t *testing.T) { t.Parallel() @@ -176,6 +230,118 @@ resource "google_compute_instance_from_machine_image" "foobar" { `, instance, instance, newInstance) } +func testAccComputeInstanceFromMachineImage_localSsdRecoveryTimeout(instance, newInstance string) string { + return fmt.Sprintf(` +resource "google_compute_instance" "vm" { + provider = google-beta + + boot_disk { + initialize_params { + image = "debian-cloud/debian-10" + } + } + + name = "%s" + machine_type = "n1-standard-1" + + network_interface { + network = "default" + } + + metadata = { + foo = "bar" + } + + scheduling { + automatic_restart = true + local_ssd_recovery_timeout { + nanos = 0 + seconds = 3600 + } + } +} + +resource "google_compute_machine_image" "foobar" { + provider = google-beta + name = "%s" + source_instance = google_compute_instance.vm.self_link +} + +resource "google_compute_instance_from_machine_image" "foobar" { + provider = google-beta + name = "%s" + zone = "us-central1-a" + + source_machine_image = google_compute_machine_image.foobar.self_link + + labels = { + my_key = "my_value" + } + scheduling { + automatic_restart = false + } +} +`, instance, instance, newInstance) +} + +func testAccComputeInstanceFromMachineImageWithOverride_localSsdRecoveryTimeout(instance, newInstance string) string { + return fmt.Sprintf(` +resource "google_compute_instance" "vm" { + provider = google-beta + + boot_disk { + initialize_params { + image = "debian-cloud/debian-10" + } + } + + name = "%s" + machine_type = "n1-standard-1" + + network_interface { + network = "default" + } + + metadata = { + foo = "bar" + } + + scheduling { + automatic_restart = true + local_ssd_recovery_timeout { + nanos = 0 + seconds = 3600 + } + } +} + +resource "google_compute_machine_image" "foobar" { + provider = google-beta + name = "%s" + source_instance = google_compute_instance.vm.self_link +} + +resource "google_compute_instance_from_machine_image" "foobar" { + provider = google-beta + name = "%s" + zone = "us-central1-a" + + source_machine_image = google_compute_machine_image.foobar.self_link + + labels = { + my_key = "my_value" + } + scheduling { + automatic_restart = false + local_ssd_recovery_timeout { + nanos = 0 + seconds = 7200 + } + } +} +`, instance, instance, newInstance) +} + func testAccComputeInstanceFromMachineImage_overrideMetadataDotStartupScript(instanceName, generatedInstanceName string) string { return fmt.Sprintf(` resource "google_compute_instance" "vm" { diff --git a/mmv1/third_party/terraform/tests/resource_compute_instance_from_template_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_instance_from_template_test.go.erb index a03df465315c..bd893fd27587 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_instance_from_template_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_instance_from_template_test.go.erb @@ -73,6 +73,66 @@ func TestAccComputeInstanceFromTemplate_self_link_unique(t *testing.T) { }) } +func TestAccComputeInstanceFromTemplate_localSsdRecoveryTimeout(t *testing.T) { + t.Parallel() + + var instance compute.Instance + instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + templateName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + resourceName := "google_compute_instance_from_template.foobar" + + var expectedLocalSsdRecoveryTimeout = compute.Duration{} + expectedLocalSsdRecoveryTimeout.Nanos = 0 + expectedLocalSsdRecoveryTimeout.Seconds = 3600 + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceFromTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceFromTemplate_localSsdRecoveryTimeout(instanceName, templateName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists(t, resourceName, &instance), + + // Check that fields were set based on the template + testAccCheckComputeInstanceLocalSsdRecoveryTimeout(&instance, expectedLocalSsdRecoveryTimeout), + ), + }, + }, + }) +} + +func TestAccComputeInstanceFromTemplateWithOverride_localSsdRecoveryTimeout(t *testing.T) { + t.Parallel() + + var instance compute.Instance + instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + templateName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + resourceName := "google_compute_instance_from_template.foobar" + + var expectedLocalSsdRecoveryTimeout = compute.Duration{} + expectedLocalSsdRecoveryTimeout.Nanos = 0 + expectedLocalSsdRecoveryTimeout.Seconds = 7200 + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceFromTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceFromTemplateWithOverride_localSsdRecoveryTimeout(instanceName, templateName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists(t, resourceName, &instance), + + // Check that fields were set based on the template + testAccCheckComputeInstanceLocalSsdRecoveryTimeout(&instance, expectedLocalSsdRecoveryTimeout), + ), + }, + }, + }) +} + <% unless version == 'ga' -%> func TestAccComputeInstanceFromRegionTemplate_basic(t *testing.T) { @@ -376,6 +436,166 @@ resource "google_compute_instance_from_template" "foobar" { `, template, template, instance) } +func testAccComputeInstanceFromTemplate_localSsdRecoveryTimeout(instance, template string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_disk" "foobar" { + name = "%s" + image = data.google_compute_image.my_image.self_link + size = 10 + type = "pd-ssd" + zone = "us-central1-a" +} + +resource "google_compute_instance_template" "foobar" { + name = "%s" + machine_type = "n1-standard-1" // can't be e2 because of local-ssd + + disk { + source = google_compute_disk.foobar.name + auto_delete = false + boot = true + } + + disk { + disk_type = "local-ssd" + type = "SCRATCH" + interface = "NVME" + disk_size_gb = 375 + } + + disk { + source_image = data.google_compute_image.my_image.self_link + auto_delete = true + disk_size_gb = 100 + boot = false + disk_type = "pd-ssd" + type = "PERSISTENT" + } + + network_interface { + network = "default" + } + + metadata = { + foo = "bar" + } + + scheduling { + automatic_restart = true + local_ssd_recovery_timeout { + nanos = 0 + seconds = 3600 + } + } + + can_ip_forward = true +} + +resource "google_compute_instance_from_template" "foobar" { + name = "%s" + zone = "us-central1-a" + + source_instance_template = google_compute_instance_template.foobar.self_link + + // Overrides + can_ip_forward = false + labels = { + my_key = "my_value" + } + scheduling { + automatic_restart = false + } +} +`, template, template, instance) +} + +func testAccComputeInstanceFromTemplateWithOverride_localSsdRecoveryTimeout(instance, template string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_disk" "foobar" { + name = "%s" + image = data.google_compute_image.my_image.self_link + size = 10 + type = "pd-ssd" + zone = "us-central1-a" +} + +resource "google_compute_instance_template" "foobar" { + name = "%s" + machine_type = "n1-standard-1" // can't be e2 because of local-ssd + + disk { + source = google_compute_disk.foobar.name + auto_delete = false + boot = true + } + + disk { + disk_type = "local-ssd" + type = "SCRATCH" + interface = "NVME" + disk_size_gb = 375 + } + + disk { + source_image = data.google_compute_image.my_image.self_link + auto_delete = true + disk_size_gb = 100 + boot = false + disk_type = "pd-ssd" + type = "PERSISTENT" + } + + network_interface { + network = "default" + } + + metadata = { + foo = "bar" + } + + scheduling { + automatic_restart = true + local_ssd_recovery_timeout { + nanos = 0 + seconds = 3600 + } + } + + can_ip_forward = true +} + +resource "google_compute_instance_from_template" "foobar" { + name = "%s" + zone = "us-central1-a" + + source_instance_template = google_compute_instance_template.foobar.self_link + + // Overrides + can_ip_forward = false + labels = { + my_key = "my_value" + } + scheduling { + automatic_restart = false + local_ssd_recovery_timeout { + nanos = 0 + seconds = 7200 + } + } +} +`, template, template, instance) +} + <% unless version == 'ga' -%> func testAccComputeInstanceFromRegionTemplate_basic(instance, template string) string { diff --git a/mmv1/third_party/terraform/tests/resource_compute_instance_group_manager_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_instance_group_manager_test.go.erb index 3642b4c57775..87fd43a866c4 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_instance_group_manager_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_instance_group_manager_test.go.erb @@ -671,11 +671,9 @@ resource "google_compute_instance_group_manager" "igm-update" { } <% end -%> -<% unless version == "ga" -%> instance_lifecycle_policy { force_update_on_repair = "YES" } -<% end -%> } `, template, target, description, igm) } @@ -779,11 +777,9 @@ resource "google_compute_instance_group_manager" "igm-update" { } <% end -%> -<% unless version == "ga" -%> instance_lifecycle_policy { force_update_on_repair = "NO" } -<% end -%> } `, template1, target1, target2, template2, description, igm) } @@ -1797,11 +1793,9 @@ resource "google_compute_instance_group_manager" "igm-basic" { } } <% end -%> -<% unless version == "ga" -%> instance_lifecycle_policy { force_update_on_repair = "YES" } -<% end -%> wait_for_instances = true wait_for_instances_status = "UPDATED" } diff --git a/mmv1/third_party/terraform/tests/resource_compute_instance_template_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_instance_template_test.go.erb index a8ff94cb4856..d239fcb6cc31 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_instance_template_test.go.erb @@ -4,9 +4,7 @@ package google import ( "fmt" -<% unless version == "ga" -%> "reflect" -<% end -%> "regexp" "strconv" "strings" @@ -1069,7 +1067,36 @@ func TestAccComputeInstanceTemplate_spot_maxRunDuration(t *testing.T) { } <% end -%> +func TestAccComputeInstanceTemplate_localSsdRecoveryTimeout(t *testing.T) { + t.Parallel() + + var instanceTemplate compute.InstanceTemplate + var expectedLocalSsdRecoveryTimeout = compute.Duration{} + expectedLocalSsdRecoveryTimeout.Nanos = 0 + expectedLocalSsdRecoveryTimeout.Seconds = 3600 + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstanceTemplate_localSsdRecoveryTimeout(RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceTemplateExists( + t, "google_compute_instance_template.foobar", &instanceTemplate), + testAccCheckComputeInstanceTemplateAutomaticRestart(&instanceTemplate, false), + testAccCheckComputeInstanceTemplateLocalSsdRecoveryTimeout(&instanceTemplate, expectedLocalSsdRecoveryTimeout), + ), + }, + { + ResourceName: "google_compute_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} func TestAccComputeInstanceTemplate_sourceSnapshotEncryptionKey(t *testing.T) { t.Parallel() @@ -1386,6 +1413,14 @@ func testAccCheckComputeInstanceTemplateMaxRunDuration(instanceTemplate *compute <% end -%> +func testAccCheckComputeInstanceTemplateLocalSsdRecoveryTimeout(instanceTemplate *compute.InstanceTemplate, instance_local_ssd_recovery_timeout_want compute.Duration) resource.TestCheckFunc { + return func(s *terraform.State) error { + if !reflect.DeepEqual(*instanceTemplate.Properties.Scheduling.LocalSsdRecoveryTimeout, instance_local_ssd_recovery_timeout_want) { + return fmt.Errorf("gExpected LocalSsdRecoveryTimeout: %#v; got %#v", instance_local_ssd_recovery_timeout_want, instanceTemplate.Properties.Scheduling.LocalSsdRecoveryTimeout) + } + return nil + } +} func testAccCheckComputeInstanceTemplateAutomaticRestart(instanceTemplate *compute.InstanceTemplate, automaticRestart bool) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -3197,6 +3232,48 @@ resource "google_compute_instance_template" "foobar" { `, suffix) } +func testAccComputeInstanceTemplate_localSsdRecoveryTimeout(suffix string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_instance_template" "foobar" { + name = "tf-test-instance-template-%s" + machine_type = "e2-medium" + can_ip_forward = false + tags = ["foo", "bar"] + + disk { + source_image = data.google_compute_image.my_image.self_link + auto_delete = true + boot = true + } + + network_interface { + network = "default" + } + + scheduling { + automatic_restart = false + local_ssd_recovery_timeout { + nanos = 0 + seconds = 3600 + } + } + + metadata = { + foo = "bar" + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} +`, suffix) +} + func testAccComputeInstanceTemplate_sourceSnapshotEncryptionKey(context map[string]interface{}) string { return acctest.Nprintf(` data "google_kms_key_ring" "ring" { diff --git a/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb index 3617d08fd662..938d0a17c864 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_instance_test.go.erb @@ -3,9 +3,7 @@ package google import ( "fmt" -<% unless version == 'ga' -%> "reflect" -<% end -%> "regexp" "sort" "strconv" @@ -326,6 +324,29 @@ func TestAccComputeInstance_IPv6(t *testing.T) { }) } +func TestAccComputeInstance_ipv6ExternalReservation(t *testing.T) { + t.Parallel() + + var instance compute.Instance + var instanceName = fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_ipv6ExternalReservation(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + ), + }, + computeInstanceImportStep("us-west2-a", instanceName, []string{}), + }, + }) +} + func TestAccComputeInstance_PTRRecord(t *testing.T) { t.Parallel() @@ -2423,6 +2444,69 @@ func TestAccComputeInstance_spotVM_maxRunDuration_update(t *testing.T) { } <% end -%> +func TestAccComputeInstance_localSsdRecoveryTimeout(t *testing.T) { + t.Parallel() + + var instance compute.Instance + var instanceName = fmt.Sprintf("tf-test-%s", RandString(t, 10)) + var expectedLocalSsdRecoveryTimeout = compute.Duration{} + // Define in testAccComputeInstance_localSsdRecoveryTimeout + expectedLocalSsdRecoveryTimeout.Nanos = 0 + expectedLocalSsdRecoveryTimeout.Seconds = 3600 + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_localSsdRecoveryTimeout(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceLocalSsdRecoveryTimeout(&instance, expectedLocalSsdRecoveryTimeout), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{}), + }, + }) +} + +func TestAccComputeInstance_localSsdRecoveryTimeout_update(t *testing.T) { + t.Parallel() + + var instance compute.Instance + var instanceName = fmt.Sprintf("tf-test-%s", RandString(t, 10)) + // Define in testAccComputeInstance_localSsdRecoveryTimeout + var expectedLocalSsdRecoveryTimeout = compute.Duration{} + expectedLocalSsdRecoveryTimeout.Nanos = 0 + expectedLocalSsdRecoveryTimeout.Seconds = 3600 + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeInstance_scheduling(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{}), + { + Config: testAccComputeInstance_localSsdRecoveryTimeout(instanceName), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeInstanceExists( + t, "google_compute_instance.foobar", &instance), + testAccCheckComputeInstanceLocalSsdRecoveryTimeout(&instance, expectedLocalSsdRecoveryTimeout), + ), + }, + computeInstanceImportStep("us-central1-a", instanceName, []string{}), + }, + }) +} + func TestAccComputeInstance_metadataStartupScript_update(t *testing.T) { t.Parallel() @@ -2660,6 +2744,22 @@ func testAccCheckComputeInstanceMaxRunDuration(instance *compute.Instance, insta } <% end -%> +func testAccCheckComputeInstanceLocalSsdRecoveryTimeout(instance *compute.Instance, instanceLocalSsdRecoveryTiemoutWant compute.Duration) resource.TestCheckFunc { + return func(s *terraform.State) error { + if instance == nil { + return fmt.Errorf("instance is nil") + } + if instance.Scheduling == nil { + return fmt.Errorf("no scheduling") + } + + if !reflect.DeepEqual(*instance.Scheduling.LocalSsdRecoveryTimeout, instanceLocalSsdRecoveryTiemoutWant) { + return fmt.Errorf("got the wrong instance local ssd recovery timeout action: have: %#v; want: %#v",instance.Scheduling.LocalSsdRecoveryTimeout, instanceLocalSsdRecoveryTiemoutWant) + } + + return nil + } +} func testAccCheckComputeInstanceTerminationAction(instance *compute.Instance, instanceTerminationActionWant string) resource.TestCheckFunc { return func(s *terraform.State) error { @@ -3604,6 +3704,65 @@ resource "google_compute_instance" "foobar" { `, instance, instance, ip, instance, record) } +func testAccComputeInstance_ipv6ExternalReservation(instance string) string { + return fmt.Sprintf(` +resource "google_compute_address" "ipv6-address" { + region = "us-west2" + name = "%s-address" + address_type = "EXTERNAL" + ip_version = "IPV6" + network_tier = "PREMIUM" + ipv6_endpoint_type = "VM" + subnetwork = google_compute_subnetwork.subnetwork-ipv6.name +} + +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_subnetwork" "subnetwork-ipv6" { + name = "%s-subnetwork" + + ip_cidr_range = "10.0.0.0/22" + region = "us-west2" + + stack_type = "IPV4_IPV6" + ipv6_access_type = "EXTERNAL" + + network = google_compute_network.custom-test.id +} + +resource "google_compute_network" "custom-test" { + name = "%s-network" + auto_create_subnetworks = false +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "e2-medium" + zone = "us-west2-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + subnetwork = google_compute_subnetwork.subnetwork-ipv6.name + stack_type = "IPV4_IPV6" + ipv6_access_config { + external_ipv6 = google_compute_address.ipv6-address.address + external_ipv6_prefix_length = 96 + name = "external-ipv6-access-config" + network_tier = "PREMIUM" + } + } +} +`, instance, instance, instance, instance) +} + func testAccComputeInstance_PTRRecord(record, instance string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { @@ -6529,6 +6688,39 @@ resource "google_compute_instance" "foobar" { `, instance) } +func testAccComputeInstance_localSsdRecoveryTimeout(instance string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "ubuntu-2004-lts" + project = "ubuntu-os-cloud" +} + +resource "google_compute_instance" "foobar" { + name = "%s" + machine_type = "e2-medium" + zone = "us-central1-a" + + boot_disk { + initialize_params { + image = data.google_compute_image.my_image.self_link + } + } + + network_interface { + network = "default" + } + + scheduling { + local_ssd_recovery_timeout { + nanos = 0 + seconds = 3600 + } + } + +} +`, instance) +} + func testAccComputeInstance_metadataStartupScript(instance, machineType, metadata string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { diff --git a/mmv1/third_party/terraform/tests/resource_compute_region_backend_service_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_region_backend_service_test.go.erb index 56ceb1080a10..aa516f0ff93b 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_region_backend_service_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_region_backend_service_test.go.erb @@ -43,6 +43,29 @@ func TestAccComputeRegionBackendService_basic(t *testing.T) { }) } +func TestAccComputeRegionBackendService_ilbBasic_withUnspecifiedProtocol(t *testing.T) { + t.Parallel() + + serviceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + checkName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeRegionBackendServiceDestroyProducer(t), + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccComputeRegionBackendService_ilbBasic_withUnspecifiedProtocol(serviceName, checkName), + }, + { + ResourceName: "google_compute_region_backend_service.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccComputeRegionBackendService_withBackendInternal(t *testing.T) { t.Parallel() @@ -335,6 +358,25 @@ func TestAccComputeRegionBackendService_subsettingUpdate(t *testing.T) { } <% end -%> +func testAccComputeRegionBackendService_ilbBasic_withUnspecifiedProtocol(serviceName, checkName string) string { + return fmt.Sprintf(` +resource "google_compute_region_backend_service" "foobar" { + name = "%s" + health_checks = [google_compute_health_check.health_check.self_link] + protocol = "UNSPECIFIED" + load_balancing_scheme = "INTERNAL" + region = "us-central1" +} + +resource "google_compute_health_check" "health_check" { + name = "%s" + http_health_check { + port = 80 + } +} +`, serviceName, checkName) +} + func testAccComputeRegionBackendService_ilbBasic(serviceName, checkName string) string { return fmt.Sprintf(` resource "google_compute_region_backend_service" "foobar" { diff --git a/mmv1/third_party/terraform/tests/resource_compute_region_instance_group_manager_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_region_instance_group_manager_test.go.erb index ae6d2404c2f7..b9db83038622 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_region_instance_group_manager_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_region_instance_group_manager_test.go.erb @@ -547,11 +547,9 @@ resource "google_compute_region_instance_group_manager" "igm-update" { } <% end -%> -<% unless version == "ga" -%> instance_lifecycle_policy { force_update_on_repair = "YES" } -<% end -%> } `, template, target, igm) } @@ -655,11 +653,9 @@ resource "google_compute_region_instance_group_manager" "igm-update" { } <% end -%> -<% unless version == "ga" -%> instance_lifecycle_policy { force_update_on_repair = "NO" } -<% end -%> } `, template1, target1, target2, template2, igm) } diff --git a/mmv1/third_party/terraform/tests/resource_compute_region_instance_template_test.go.erb b/mmv1/third_party/terraform/tests/resource_compute_region_instance_template_test.go.erb index 42e238f4172f..f26699600ac8 100644 --- a/mmv1/third_party/terraform/tests/resource_compute_region_instance_template_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_compute_region_instance_template_test.go.erb @@ -1023,6 +1023,37 @@ func TestAccComputeRegionInstanceTemplate_spot_maxRunDuration(t *testing.T) { } <% end -%> +func TestAccComputeRegionInstanceTemplate_localSsdRecoveryTimeout(t *testing.T) { + t.Parallel() + + var instanceTemplate compute.InstanceTemplate + var expectedLocalSsdRecoveryTimeout = compute.Duration{} + // Define in testAccComputeRegionInstanceTemplate_spot + expectedLocalSsdRecoveryTimeout.Nanos = 0 + expectedLocalSsdRecoveryTimeout.Seconds = 3600 + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckComputeRegionInstanceTemplateDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionInstanceTemplate_localSsdRecoveryTimeout(acctest.RandString(t, 10)), + Check: resource.ComposeTestCheckFunc( + testAccCheckComputeRegionInstanceTemplateExists( + t, "google_compute_region_instance_template.foobar", &instanceTemplate), + testAccCheckComputeRegionInstanceTemplateLocalSsdRecoveryTimeout(&instanceTemplate, expectedLocalSsdRecoveryTimeout), + ), + }, + { + ResourceName: "google_compute_region_instance_template.foobar", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccComputeRegionInstanceTemplate_sourceSnapshotEncryptionKey(t *testing.T) { t.Parallel() @@ -1326,6 +1357,16 @@ func testAccCheckComputeRegionInstanceTemplateMaxRunDuration(instanceTemplate *c } <% end -%> +func testAccCheckComputeRegionInstanceTemplateLocalSsdRecoveryTimeout(instanceTemplate *compute.InstanceTemplate, instance_local_ssd_recovery_timeout_want compute.Duration) resource.TestCheckFunc { + return func(s *terraform.State) error { + if !reflect.DeepEqual(*instanceTemplate.Properties.Scheduling.LocalSsdRecoveryTimeout, instance_local_ssd_recovery_timeout_want) { + return fmt.Errorf("gExpected local_ssd_recovery_timeout: %#v; got %#v", instance_local_ssd_recovery_timeout_want, instanceTemplate.Properties.Scheduling.LocalSsdRecoveryTimeout) + } + + return nil + } +} + func testAccCheckComputeRegionInstanceTemplateAutomaticRestart(instanceTemplate *compute.InstanceTemplate, automaticRestart bool) resource.TestCheckFunc { return func(s *terraform.State) error { ar := instanceTemplate.Properties.Scheduling.AutomaticRestart @@ -3079,6 +3120,48 @@ resource "google_compute_region_instance_template" "foobar" { `, suffix) } +func testAccComputeRegionInstanceTemplate_localSsdRecoveryTimeout(suffix string) string { + return fmt.Sprintf(` +data "google_compute_image" "my_image" { + family = "debian-11" + project = "debian-cloud" +} + +resource "google_compute_region_instance_template" "foobar" { + name = "tf-test-instance-template-%s" + region = "us-central1" + machine_type = "e2-medium" + can_ip_forward = false + tags = ["foo", "bar"] + + disk { + source_image = data.google_compute_image.my_image.self_link + auto_delete = true + boot = true + } + + network_interface { + network = "default" + } + + scheduling { + local_ssd_recovery_timeout { + nanos = 0 + seconds = 3600 + } + } + + metadata = { + foo = "bar" + } + + service_account { + scopes = ["userinfo-email", "compute-ro", "storage-ro"] + } +} +`, suffix) +} + func testAccComputeRegionInstanceTemplate_sourceSnapshotEncryptionKey(context map[string]interface{}) string { return acctest.Nprintf(` data "google_kms_key_ring" "ring" { diff --git a/mmv1/third_party/terraform/tests/resource_container_cluster_test.go.erb b/mmv1/third_party/terraform/tests/resource_container_cluster_test.go.erb index aaa7798fa319..8563747232de 100644 --- a/mmv1/third_party/terraform/tests/resource_container_cluster_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_container_cluster_test.go.erb @@ -1004,6 +1004,36 @@ func TestAccContainerCluster_withPrivateClusterConfigMissingCidrBlock_withAutopi }) } +func TestAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(clusterName, true), + }, + { + ResourceName: "google_container_cluster.with_private_cluster", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(clusterName, false), + }, + { + ResourceName: "google_container_cluster.with_private_cluster", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func TestAccContainerCluster_withIntraNodeVisibility(t *testing.T) { t.Parallel() @@ -2703,6 +2733,37 @@ func TestAccContainerCluster_withLoggingConfig(t *testing.T) { }) } +func TestAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityConfig(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityConfigEnabled(clusterName), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version"}, + }, + { + Config: testAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityConfigDisabled(clusterName), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version"}, + }, + }, + }) +} + func TestAccContainerCluster_withMonitoringConfig(t *testing.T) { t.Parallel() @@ -3539,6 +3600,61 @@ func TestAccContainerCluster_withEnableKubernetesAlpha(t *testing.T) { }) } +func TestAccContainerCluster_withEnableKubernetesBetaAPIs(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withEnableKubernetesBetaAPIs(clusterName), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version"}, + }, + }, + }) +} + +func TestAccContainerCluster_withEnableKubernetesBetaAPIsOnExistingCluster(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_withoutEnableKubernetesBetaAPIs(clusterName), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version"}, + }, + { + Config: testAccContainerCluster_withEnableKubernetesBetaAPIs(clusterName), + }, + { + ResourceName: "google_container_cluster.primary", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version"}, + }, + }, + }) +} + func TestAccContainerCluster_withIPv4Error(t *testing.T) { t.Parallel() @@ -4680,10 +4796,13 @@ resource "google_container_cluster" "with_private_endpoint_subnetwork" { `, containerNetName, s1Name, s1Cidr, s2Name, s2Cidr, clusterName) } -func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { +func TestAccContainerCluster_withPrivateClusterConfigPrivateEndpointSubnetwork(t *testing.T) { t.Parallel() + r := acctest.RandString(t, 10) + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + containerNetName := fmt.Sprintf("tf-test-container-net-%s", r) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -4691,14 +4810,78 @@ func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccContainerCluster_withoutEnablePrivateEndpoint(clusterName), + Config: testAccContainerCluster_withPrivateClusterConfigPrivateEndpointSubnetwork(containerNetName, clusterName), }, { - ResourceName: "google_container_cluster.with_enable_private_endpoint", - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"min_master_version"}, + ResourceName: "google_container_cluster.with_private_endpoint_subnetwork", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"min_master_version"}, }, + }, + }) +} + +func testAccContainerCluster_withPrivateClusterConfigPrivateEndpointSubnetwork(containerNetName, clusterName string) string { + return fmt.Sprintf(` +resource "google_compute_network" "container_network" { + name = "%s" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "container_subnetwork" { + name = google_compute_network.container_network.name + network = google_compute_network.container_network.name + ip_cidr_range = "10.0.36.0/24" + region = "us-central1" + private_ip_google_access = true + + secondary_ip_range { + range_name = "pod" + ip_cidr_range = "10.0.0.0/19" + } + + secondary_ip_range { + range_name = "svc" + ip_cidr_range = "10.0.32.0/22" + } +} + +resource "google_container_cluster" "with_private_endpoint_subnetwork" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + networking_mode = "VPC_NATIVE" + + network = google_compute_network.container_network.name + subnetwork = google_compute_subnetwork.container_subnetwork.name + + private_cluster_config { + enable_private_nodes = true + enable_private_endpoint = true + private_endpoint_subnetwork = google_compute_subnetwork.container_subnetwork.name + } + master_authorized_networks_config { + gcp_public_cidrs_access_enabled = false + } + ip_allocation_policy { + cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name + services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name + } +} +`, containerNetName, clusterName) +} + +func TestAccContainerCluster_withEnablePrivateEndpointToggle(t *testing.T) { + t.Parallel() + + clusterName := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerClusterDestroyProducer(t), + Steps: []resource.TestStep{ { Config: testAccContainerCluster_withEnablePrivateEndpoint(clusterName, "true"), }, @@ -4773,26 +4956,6 @@ resource "google_container_cluster" "with_enable_private_endpoint" { `, clusterName, flag) } -func testAccContainerCluster_withoutEnablePrivateEndpoint(clusterName string) string { - - return fmt.Sprintf(` -data "google_container_engine_versions" "uscentral1a" { - location = "us-central1-a" -} - -resource "google_container_cluster" "with_enable_private_endpoint" { - name = "%s" - location = "us-central1-a" - min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] - initial_node_count = 1 - - master_authorized_networks_config { - gcp_public_cidrs_access_enabled = false - } -} -`, clusterName) -} - func testAccContainerCluster_regionalWithNodePool(cluster, nodePool string) string { return fmt.Sprintf(` resource "google_container_cluster" "regional" { @@ -6771,6 +6934,22 @@ resource "google_container_cluster" "with_private_cluster" { `, containerNetName, clusterName, masterGlobalAccessEnabled) } +func testAccContainerCluster_withPrivateClusterConfigGlobalAccessEnabledOnly(clusterName string, masterGlobalAccessEnabled bool) string { + return fmt.Sprintf(` +resource "google_container_cluster" "with_private_cluster" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + private_cluster_config { + enable_private_endpoint = false + master_global_access_config { + enabled = %t + } + } +} +`, clusterName, masterGlobalAccessEnabled) +} + func testAccContainerCluster_withShieldedNodes(clusterName string, enabled bool) string { return fmt.Sprintf(` resource "google_container_cluster" "with_shielded_nodes" { @@ -7294,6 +7473,60 @@ resource "google_container_cluster" "primary" { `, cluster, np) } +func testAccContainerCluster_withoutEnableKubernetesBetaAPIs(clusterName string) string { + return fmt.Sprintf(` +data "google_container_engine_versions" "central1a" { + location = "us-central1-a" +} + +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + min_master_version = data.google_container_engine_versions.central1a.release_channel_latest_version["STABLE"] + initial_node_count = 1 +} +`, clusterName) +} + +func testAccContainerCluster_withEnableKubernetesBetaAPIs(cluster string) string { + return fmt.Sprintf(` +data "google_container_engine_versions" "uscentral1a" { + location = "us-central1-a" +} + +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + min_master_version = data.google_container_engine_versions.uscentral1a.release_channel_latest_version["STABLE"] + initial_node_count = 1 + + # This feature has been available since GKE 1.27, and currently the only + # supported Beta API is authentication.k8s.io/v1beta1/selfsubjectreviews. + # However, in the future, more Beta APIs will be supported, such as the + # resource.k8s.io group. At the same time, some existing Beta APIs will be + # deprecated as the feature will be GAed, and the Beta API will be eventually + # removed. In the case of the SelfSubjectReview API, it is planned to be GAed + # in Kubernetes as of 1.28. And, the Beta API of SelfSubjectReview will be removed + # after at least 3 minor version bumps, so it will be removed as of Kubernetes 1.31 + # or later. + # https://pr.k8s.io/117713 + # https://kubernetes.io/docs/reference/using-api/deprecation-guide/ + # + # The new Beta APIs will be available since GKE 1.28 + # - admissionregistration.k8s.io/v1beta1/validatingadmissionpolicies + # - admissionregistration.k8s.io/v1beta1/validatingadmissionpolicybindings + # https://pr.k8s.io/118644 + # + # Removing the Beta API from Kubernetes will break the test. + # TODO: Replace the Beta API with one available on the version of GKE + # if the test is broken. + enable_k8s_beta_apis { + enabled_apis = ["authentication.k8s.io/v1beta1/selfsubjectreviews"] + } +} +`, cluster) +} + func testAccContainerCluster_withIPv4Error(name string) string { return fmt.Sprintf(` resource "google_container_cluster" "primary" { @@ -7598,6 +7831,104 @@ resource "google_container_cluster" "primary" { `, name) } +func testAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityConfigEnabled(name string) string { + return fmt.Sprintf(` +resource "google_compute_network" "container_network" { + name = "%s-nw" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "container_subnetwork" { + name = google_compute_network.container_network.name + network = google_compute_network.container_network.name + ip_cidr_range = "10.0.36.0/24" + region = "us-central1" + private_ip_google_access = true + + secondary_ip_range { + range_name = "services-range" + ip_cidr_range = "192.168.1.0/24" + } + + secondary_ip_range { + range_name = "pod-ranges" + ip_cidr_range = "192.168.64.0/22" + } +} + +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + datapath_provider = "ADVANCED_DATAPATH" + + network = google_compute_network.container_network.name + subnetwork = google_compute_subnetwork.container_subnetwork.name + ip_allocation_policy { + cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name + services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name + } + + monitoring_config { + enable_components = [] + advanced_datapath_observability_config { + enable_metrics = true + relay_mode = "INTERNAL_VPC_LB" + } + } +} +`, name, name) +} + +func testAccContainerCluster_withMonitoringConfigAdvancedDatapathObservabilityConfigDisabled(name string) string { + return fmt.Sprintf(` +resource "google_compute_network" "container_network" { + name = "%s-nw" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "container_subnetwork" { + name = google_compute_network.container_network.name + network = google_compute_network.container_network.name + ip_cidr_range = "10.0.36.0/24" + region = "us-central1" + private_ip_google_access = true + + secondary_ip_range { + range_name = "services-range" + ip_cidr_range = "192.168.1.0/24" + } + + secondary_ip_range { + range_name = "pod-ranges" + ip_cidr_range = "192.168.64.0/22" + } +} + +resource "google_container_cluster" "primary" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 + datapath_provider = "ADVANCED_DATAPATH" + + network = google_compute_network.container_network.name + subnetwork = google_compute_subnetwork.container_subnetwork.name + ip_allocation_policy { + cluster_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[0].range_name + services_secondary_range_name = google_compute_subnetwork.container_subnetwork.secondary_ip_range[1].range_name + } + + monitoring_config { + enable_components = [] + advanced_datapath_observability_config { + enable_metrics = false + relay_mode = "DISABLED" + } + } +} +`, name, name) +} + func testAccContainerCluster_withSoleTenantGroup(name string) string { return fmt.Sprintf(` resource "google_compute_node_template" "soletenant-tmpl" { @@ -7775,3 +8106,64 @@ resource "google_container_cluster" "primary" { min_master_version = 1.27 }`, name, enabled) } + + +func TestAccContainerCluster_customPlacementPolicy(t *testing.T) { + t.Parallel() + + cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + np := fmt.Sprintf("tf-test-nodepool-%s", acctest.RandString(t, 10)) + policy := fmt.Sprintf("tf-test-policy-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerNodePoolDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerCluster_customPlacementPolicy(cluster, np, policy), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.placement_policy.0.type", "COMPACT"), + resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.placement_policy.0.policy_name", policy), + resource.TestCheckResourceAttr("google_container_cluster.cluster", "node_pool.0.node_config.0.machine_type", "c2-standard-4"), + ), + }, + { + ResourceName: "google_container_cluster.cluster", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccContainerCluster_customPlacementPolicy(cluster, np, policyName string) string { + return fmt.Sprintf(` + +resource "google_compute_resource_policy" "policy" { + name = "%s" + region = "us-central1" + group_placement_policy { + collocation = "COLLOCATED" + } +} + +resource "google_container_cluster" "cluster" { + name = "%s" + location = "us-central1-a" + + node_pool { + name = "%s" + initial_node_count = 2 + + node_config { + machine_type = "c2-standard-4" + } + + placement_policy { + type = "COMPACT" + policy_name = google_compute_resource_policy.policy.name + } + } +}`, policyName, cluster, np) +} diff --git a/mmv1/third_party/terraform/tests/resource_container_node_pool_test.go.erb b/mmv1/third_party/terraform/tests/resource_container_node_pool_test.go.erb index ab9e3769337d..f86dd806d573 100644 --- a/mmv1/third_party/terraform/tests/resource_container_node_pool_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_container_node_pool_test.go.erb @@ -1256,6 +1256,8 @@ func TestAccContainerNodePool_withSoleTenantConfig(t *testing.T) { }) } + + <% unless version == 'ga' -%> func TestAccContainerNodePool_ephemeralStorageConfig(t *testing.T) { t.Parallel() @@ -1556,6 +1558,68 @@ resource "google_container_node_pool" "np" { `, cluster, np, placementType) } +func TestAccContainerNodePool_customPlacementPolicy(t *testing.T) { + t.Parallel() + + cluster := fmt.Sprintf("tf-test-cluster-%s", acctest.RandString(t, 10)) + np := fmt.Sprintf("tf-test-nodepool-%s", acctest.RandString(t, 10)) + policy := fmt.Sprintf("tf-test-policy-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerNodePoolDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerNodePool_customPlacementPolicy(cluster, np, policy), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("google_container_node_pool.np", "node_config.0.machine_type", "c2-standard-4"), + resource.TestCheckResourceAttr("google_container_node_pool.np", "placement_policy.0.policy_name", policy), + resource.TestCheckResourceAttr("google_container_node_pool.np", "placement_policy.0.type", "COMPACT"), + ), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccContainerNodePool_customPlacementPolicy(cluster, np, policyName string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "cluster" { + name = "%s" + location = "us-central1-a" + initial_node_count = 1 +} + +resource "google_compute_resource_policy" "policy" { + name = "%s" + region = "us-central1" + group_placement_policy { + collocation = "COLLOCATED" + } +} + +resource "google_container_node_pool" "np" { + name = "%s" + location = "us-central1-a" + cluster = google_container_cluster.cluster.name + initial_node_count = 2 + + node_config { + machine_type = "c2-standard-4" + } + placement_policy { + type = "COMPACT" + policy_name = google_compute_resource_policy.policy.name + } +} +`, cluster, policyName, np) +} + func TestAccContainerNodePool_threadsPerCore(t *testing.T) { t.Parallel() @@ -3154,16 +3218,16 @@ resource "google_container_node_pool" "np1" { location = "us-central1-a" cluster = google_container_cluster.cluster.name initial_node_count = 2 - version = "1.25.10-gke.1400" + version = "1.27.3-gke.1700" } resource "google_container_node_pool" "np2" { - name = "%s" - location = "us-central1-a" - cluster = google_container_cluster.cluster.name - initial_node_count = 2 - version = "1.25.10-gke.1400" - } + name = "%s" + location = "us-central1-a" + cluster = google_container_cluster.cluster.name + initial_node_count = 2 + version = "1.27.3-gke.1700" +} `, cluster, np1, np2) } @@ -3285,4 +3349,56 @@ resource "google_container_node_pool" "with_tpu_topology" { } `, cluster, np1, np2, tpuTopology) } -<% end -%> \ No newline at end of file + +func TestAccContainerNodePool_withHostMaintenancePolicy(t *testing.T) { + t.Parallel() + + cluster := fmt.Sprintf("tf-test-cluster-%s", RandString(t, 10)) + np := fmt.Sprintf("tf-test-np-%s", RandString(t, 10)) + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckContainerNodePoolDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccContainerNodePool_withHostMaintenancePolicy(cluster, np), + }, + { + ResourceName: "google_container_node_pool.np", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccContainerNodePool_withHostMaintenancePolicy(cluster, np string) string { + return fmt.Sprintf(` +resource "google_container_cluster" "cluster" { + name = "%s" + location = "asia-east1-c" + initial_node_count = 1 + node_config { + host_maintenance_policy { + maintenance_interval = "PERIODIC" + } + machine_type = "n2-standard-2" + } +} + +resource "google_container_node_pool" "np" { + name = "%s" + location = "asia-east1-c" + cluster = google_container_cluster.cluster.name + initial_node_count = 1 + node_config { + host_maintenance_policy { + maintenance_interval = "PERIODIC" + } + machine_type = "n2-standard-2" + } +} +`, cluster, np) +} +<% end -%> diff --git a/mmv1/third_party/terraform/tests/resource_firebase_database_instance_test.go.erb b/mmv1/third_party/terraform/tests/resource_firebase_database_instance_test.go.erb index eac6faab3d49..114e9871779f 100644 --- a/mmv1/third_party/terraform/tests/resource_firebase_database_instance_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_firebase_database_instance_test.go.erb @@ -45,6 +45,9 @@ func TestAccFirebaseDatabaseInstance_firebaseDatabaseInstanceStateChange(t *test ImportState: true, ImportStateVerify: true, ImportStateVerifyIgnore: []string{"region", "instance_id", "desired_state"}, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("google_firebase_database_instance.updated", "database_url"), + ), }, { Config: testAccFirebaseDatabaseInstance_firebaseDatabaseInstanceInState(context, "DISABLED"), diff --git a/mmv1/third_party/terraform/tests/resource_google_billing_project_info_test.go b/mmv1/third_party/terraform/tests/resource_google_billing_project_info_test.go new file mode 100644 index 000000000000..d1fc1fb8ffc8 --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_google_billing_project_info_test.go @@ -0,0 +1,69 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccBillingProjectInfo_update(t *testing.T) { + t.Parallel() + + projectId := "tf-test-" + acctest.RandString(t, 10) + orgId := envvar.GetTestOrgFromEnv(t) + billingAccount := envvar.GetTestBillingAccountFromEnv(t) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCoreBillingProjectInfoDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccBillingProjectInfo_basic(projectId, orgId, billingAccount), + }, + { + ResourceName: "google_billing_project_info.info", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBillingProjectInfo_basic(projectId, orgId, ""), + }, + { + ResourceName: "google_billing_project_info.info", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBillingProjectInfo_basic(projectId, orgId, billingAccount), + }, + { + ResourceName: "google_billing_project_info.info", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccBillingProjectInfo_basic(projectId, orgId, billingAccountId string) string { + return fmt.Sprintf(` +resource "google_project" "project" { + project_id = "%s" + name = "%[1]s" + org_id = "%s" + lifecycle { + ignore_changes = [billing_account] + } +} + +resource "google_billing_project_info" "info" { + project = google_project.project.project_id + billing_account = "%s" +} +`, projectId, orgId, billingAccountId) +} diff --git a/mmv1/third_party/terraform/tests/resource_healthcare_fhir_store_test.go b/mmv1/third_party/terraform/tests/resource_healthcare_fhir_store_test.go.erb similarity index 96% rename from mmv1/third_party/terraform/tests/resource_healthcare_fhir_store_test.go rename to mmv1/third_party/terraform/tests/resource_healthcare_fhir_store_test.go.erb index 8d5205347bf8..c609d68237f3 100644 --- a/mmv1/third_party/terraform/tests/resource_healthcare_fhir_store_test.go +++ b/mmv1/third_party/terraform/tests/resource_healthcare_fhir_store_test.go.erb @@ -1,3 +1,4 @@ +<% autogen_exception -%> package google import ( @@ -152,6 +153,14 @@ resource "google_healthcare_fhir_store" "default" { pubsub_topic = google_pubsub_topic.topic.id } +<% unless version == "ga" -%> + notification_configs { + pubsub_topic = google_pubsub_topic.topic.id + send_full_resource = true + send_previous_resource_on_delete = true + } + +<% end -%> labels = { label1 = "labelvalue1" } diff --git a/mmv1/third_party/terraform/tests/resource_monitoring_alert_policy_test.go b/mmv1/third_party/terraform/tests/resource_monitoring_alert_policy_test.go index 5ce46ba0b173..758bdaefe8b7 100644 --- a/mmv1/third_party/terraform/tests/resource_monitoring_alert_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_monitoring_alert_policy_test.go @@ -430,7 +430,6 @@ resource "google_monitoring_alert_policy" "promql" { condition_prometheus_query_language { query = "vector(1)" duration = "60s" - evaluation_interval = "60s" labels = { "severity" = "page" } diff --git a/mmv1/third_party/terraform/tests/resource_monitoring_uptime_check_config_test.go b/mmv1/third_party/terraform/tests/resource_monitoring_uptime_check_config_test.go index 6ad830b7a9e8..047786059c4e 100644 --- a/mmv1/third_party/terraform/tests/resource_monitoring_uptime_check_config_test.go +++ b/mmv1/third_party/terraform/tests/resource_monitoring_uptime_check_config_test.go @@ -20,7 +20,7 @@ func TestAccMonitoringUptimeCheckConfig_update(t *testing.T) { CheckDestroy: testAccCheckMonitoringUptimeCheckConfigDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "mypath", "password1", project, host), + Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "60s", "mypath", "password1", project, host), }, { ResourceName: "google_monitoring_uptime_check_config.http", @@ -29,7 +29,7 @@ func TestAccMonitoringUptimeCheckConfig_update(t *testing.T) { ImportStateVerifyIgnore: []string{"http_check.0.auth_info.0.password"}, }, { - Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "", "password2", project, host), + Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "60s", "", "password2", project, host), }, { ResourceName: "google_monitoring_uptime_check_config.http", @@ -53,7 +53,7 @@ func TestAccMonitoringUptimeCheckConfig_changeNonUpdatableFields(t *testing.T) { CheckDestroy: testAccCheckMonitoringUptimeCheckConfigDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "mypath", "password1", project, "192.168.1.1"), + Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "60s", "mypath", "password1", project, "192.168.1.1"), }, { ResourceName: "google_monitoring_uptime_check_config.http", @@ -62,7 +62,7 @@ func TestAccMonitoringUptimeCheckConfig_changeNonUpdatableFields(t *testing.T) { ImportStateVerifyIgnore: []string{"http_check.0.auth_info.0.password"}, }, { - Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "mypath", "password1", project, "192.168.1.2"), + Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "300s", "mypath", "password1", project, "192.168.1.2"), }, { ResourceName: "google_monitoring_uptime_check_config.http", @@ -71,7 +71,7 @@ func TestAccMonitoringUptimeCheckConfig_changeNonUpdatableFields(t *testing.T) { ImportStateVerifyIgnore: []string{"http_check.0.auth_info.0.password"}, }, { - Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "mypath", "password2", project, "192.168.1.2"), + Config: testAccMonitoringUptimeCheckConfig_update(acctest.RandString(t, 4), "60s", "mypath", "password2", project, "192.168.1.2"), }, { ResourceName: "google_monitoring_uptime_check_config.http", @@ -114,11 +114,12 @@ func TestAccMonitoringUptimeCheckConfig_jsonPathUpdate(t *testing.T) { }) } -func testAccMonitoringUptimeCheckConfig_update(suffix, path, pwd, project, host string) string { +func testAccMonitoringUptimeCheckConfig_update(suffix, period, path, pwd, project, host string) string { return fmt.Sprintf(` resource "google_monitoring_uptime_check_config" "http" { display_name = "http-uptime-check-%s" timeout = "60s" + period = "%s" http_check { path = "/%s" @@ -143,7 +144,7 @@ resource "google_monitoring_uptime_check_config" "http" { matcher = "CONTAINS_STRING" } } -`, suffix, path, pwd, project, host, +`, suffix, period, path, pwd, project, host, ) } diff --git a/mmv1/third_party/terraform/tests/resource_network_connectivity_service_connection_policies_test.go b/mmv1/third_party/terraform/tests/resource_network_connectivity_service_connection_policies_test.go new file mode 100644 index 000000000000..a1c1590550c1 --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_network_connectivity_service_connection_policies_test.go @@ -0,0 +1,109 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-provider-google/google/acctest" +) + +func TestAccNetworkConnectivityServiceConnectionPolicy_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "networkProducerName": fmt.Sprintf("tf-test-network-%s", RandString(t, 10)), + "subnetworkProducerName1": fmt.Sprintf("tf-test-subnet-producer-%s", RandString(t, 10)), + "subnetworkProducerName2": fmt.Sprintf("tf-test-subnet-producer-%s", RandString(t, 10)), + "serviceConnectionPolicyName": fmt.Sprintf("tf-test-service-connection-policy-%s", RandString(t, 10)), + } + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckNetworkConnectivityServiceConnectionPolicyDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccNetworkConnectivityServiceConnectionPolicy_basic(context), + }, + { + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccNetworkConnectivityServiceConnectionPolicy_update(context), + }, + { + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccNetworkConnectivityServiceConnectionPolicy_basic(context), + }, + { + ResourceName: "google_network_connectivity_service_connection_policy.default", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccNetworkConnectivityServiceConnectionPolicy_basic(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_compute_network" "producer_net" { + name = "%{networkProducerName}" + auto_create_subnetworks = false + } + + resource "google_compute_subnetwork" "producer_subnet" { + name = "%{subnetworkProducerName1}" + ip_cidr_range = "10.0.0.0/16" + region = "us-central1" + network = google_compute_network.producer_net.id + } + + resource "google_network_connectivity_service_connection_policy" "default" { + name = "%{serviceConnectionPolicyName}" + location = "us-central1" + service_class = "gcp-memorystore-redis" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.producer_subnet.id] + limit = 2 + } + } +`, context) +} + +func testAccNetworkConnectivityServiceConnectionPolicy_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_compute_network" "producer_net" { + name = "%{networkProducerName}" + auto_create_subnetworks = false +} + +resource "google_compute_subnetwork" "producer_subnet1" { + name = "%{subnetworkProducerName2}" + ip_cidr_range = "10.1.0.0/16" + region = "us-central1" + network = google_compute_network.producer_net.id +} + +resource "google_network_connectivity_service_connection_policy" "default" { + name = "%{serviceConnectionPolicyName}" + location = "us-central1" + service_class = "gcp-memorystore-redis" + network = google_compute_network.producer_net.id + psc_config { + subnetworks = [google_compute_subnetwork.producer_subnet1.id] + limit = 4 + } + labels = { + foo = "bar" + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/tests/resource_pubsub_subscription_test.go b/mmv1/third_party/terraform/tests/resource_pubsub_subscription_test.go index 15e54e5f9807..ab9ef1b6fdd8 100644 --- a/mmv1/third_party/terraform/tests/resource_pubsub_subscription_test.go +++ b/mmv1/third_party/terraform/tests/resource_pubsub_subscription_test.go @@ -118,6 +118,31 @@ func TestAccPubsubSubscription_push(t *testing.T) { }) } +func TestAccPubsubSubscription_pushNoWrapper(t *testing.T) { + t.Parallel() + + topicFoo := fmt.Sprintf("tf-test-topic-foo-%s", acctest.RandString(t, 10)) + subscription := fmt.Sprintf("tf-test-sub-foo-%s", acctest.RandString(t, 10)) + saAccount := fmt.Sprintf("tf-test-pubsub-%s", acctest.RandString(t, 10)) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckPubsubSubscriptionDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccPubsubSubscription_pushNoWrapper(topicFoo, saAccount, subscription), + }, + { + ResourceName: "google_pubsub_subscription.foo", + ImportStateId: subscription, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + // Context: hashicorp/terraform-provider-google#4993 // This test makes a call to GET an subscription before it is actually created. // The PubSub API negative-caches responses so this tests we are @@ -213,6 +238,45 @@ resource "google_pubsub_subscription" "foo" { `, saAccount, topicFoo, subscription) } +func testAccPubsubSubscription_pushNoWrapper(topicFoo, saAccount, subscription string) string { + return fmt.Sprintf(` +data "google_project" "project" { } + +resource "google_service_account" "pub_sub_service_account" { + account_id = "%s" +} + +data "google_iam_policy" "admin" { + binding { + role = "roles/projects.topics.publish" + + members = [ + "serviceAccount:${google_service_account.pub_sub_service_account.email}", + ] + } +} + +resource "google_pubsub_topic" "foo" { + name = "%s" +} + +resource "google_pubsub_subscription" "foo" { + name = "%s" + topic = google_pubsub_topic.foo.name + ack_deadline_seconds = 10 + push_config { + push_endpoint = "https://${data.google_project.project.project_id}.appspot.com" + oidc_token { + service_account_email = google_service_account.pub_sub_service_account.email + } + no_wrapper { + write_metadata = true + } + } +} +`, saAccount, topicFoo, subscription) +} + func testAccPubsubSubscription_basic(topic, subscription, label string, deadline int, exactlyOnceDelivery bool) string { return fmt.Sprintf(` resource "google_pubsub_topic" "foo" { diff --git a/mmv1/third_party/terraform/tests/resource_secret_manager_secret_test.go.erb b/mmv1/third_party/terraform/tests/resource_secret_manager_secret_test.go.erb index eb6a59b37fc0..a85891875600 100644 --- a/mmv1/third_party/terraform/tests/resource_secret_manager_secret_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_secret_manager_secret_test.go.erb @@ -64,6 +64,49 @@ func TestAccSecretManagerSecret_cmek(t *testing.T) { }) } +func TestAccSecretManagerSecret_annotationsUpdate(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: testAccCheckSecretManagerSecretDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccSecretManagerSecret_annotationsBasic(context), + }, + { + ResourceName: "google_secret_manager_secret.secret-with-annotations", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"ttl"}, + }, + { + Config: testAccSecretManagerSecret_annotationsUpdate(context), + }, + { + ResourceName: "google_secret_manager_secret.secret-with-annotations", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"ttl"}, + }, + { + Config: testAccSecretManagerSecret_annotationsBasic(context), + }, + { + ResourceName: "google_secret_manager_secret.secret-with-annotations", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"ttl"}, + }, + }, + }) +} + func testAccSecretManagerSecret_basic(context map[string]interface{}) string { return acctest.Nprintf(` resource "google_secret_manager_secret" "secret-basic" { @@ -127,3 +170,50 @@ resource "google_secret_manager_secret" "secret-basic" { } `, context) } + +func testAccSecretManagerSecret_annotationsBasic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secret_manager_secret" "secret-with-annotations" { + secret_id = "tf-test-secret-%{random_suffix}" + + labels = { + label = "my-label" + } + + annotations = { + key1 = "someval" + key2 = "someval2" + key3 = "someval3" + key4 = "someval4" + key5 = "someval5" + } + + replication { + automatic = true + } +} +`, context) +} + +func testAccSecretManagerSecret_annotationsUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_secret_manager_secret" "secret-with-annotations" { + secret_id = "tf-test-secret-%{random_suffix}" + + labels = { + label = "my-label" + } + + annotations = { + key1 = "someval" + key2update = "someval2" + key3 = "someval3update" + key4update = "someval4update" + } + + replication { + automatic = true + } +} +`, context) +} diff --git a/mmv1/third_party/terraform/tests/resource_workstations_workstation_cluster_test.go.erb b/mmv1/third_party/terraform/tests/resource_workstations_workstation_cluster_test.go.erb index 8c33b2f3d015..9b1e90aa173d 100644 --- a/mmv1/third_party/terraform/tests/resource_workstations_workstation_cluster_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_workstations_workstation_cluster_test.go.erb @@ -43,14 +43,91 @@ func TestAccWorkstationsWorkstationCluster_update(t *testing.T) { }) } +func TestAccWorkstationsWorkstationCluster_Private_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.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckWorkstationsWorkstationClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccWorkstationsWorkstationCluster_workstationClusterPrivateExample(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + { + Config: testAccWorkstationsWorkstationCluster_private_update(context), + }, + { + ResourceName: "google_workstations_workstation_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"etag"}, + }, + }, + }) +} + func testAccWorkstationsWorkstationCluster_update(context map[string]interface{}) string { return acctest.Nprintf(` +data "google_project" "project" { + provider = google-beta +} + resource "google_workstations_workstation_cluster" "default" { - provider = google-beta + 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" + location = "us-central1" + + labels = { + foo = "bar" + } +} + +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 +} +`, context) +} + +func testAccWorkstationsWorkstationCluster_private_update(context map[string]interface{}) string { + return acctest.Nprintf(` +data "google_project" "project" { + provider = google-beta +} + +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" + + private_cluster_config { + allowed_projects = ["${data.google_project.project.project_id}"] + enable_private_endpoint = true + } labels = { foo = "bar" diff --git a/mmv1/third_party/terraform/utils/test-fixtures/bigquerytable/simple/data/00000-0-4e4a11ad-368c-496b-97ae-e3ac28051a4d-00001.parquet b/mmv1/third_party/terraform/utils/test-fixtures/bigquerytable/simple/data/00000-0-4e4a11ad-368c-496b-97ae-e3ac28051a4d-00001.parquet new file mode 100644 index 000000000000..3d7d5cecd196 Binary files /dev/null and b/mmv1/third_party/terraform/utils/test-fixtures/bigquerytable/simple/data/00000-0-4e4a11ad-368c-496b-97ae-e3ac28051a4d-00001.parquet differ diff --git a/mmv1/third_party/terraform/utils/test-fixtures/bigquerytable/simple/metadata/00000-1114da6b-bb88-4b5a-94bd-370f286c858a.metadata.json b/mmv1/third_party/terraform/utils/test-fixtures/bigquerytable/simple/metadata/00000-1114da6b-bb88-4b5a-94bd-370f286c858a.metadata.json new file mode 100644 index 000000000000..732b1ef7af8b --- /dev/null +++ b/mmv1/third_party/terraform/utils/test-fixtures/bigquerytable/simple/metadata/00000-1114da6b-bb88-4b5a-94bd-370f286c858a.metadata.json @@ -0,0 +1,70 @@ +{ + "format-version": 1, + "table-uuid": "20f6c20d-d535-4c0c-be82-cb25d31e9250", + "location": "/home/iceberg/warehouse/simple", + "last-updated-ms": 1686356696798, + "last-column-id": 2, + "schema": { + "type": "struct", + "schema-id": 0, + "fields": [ + { + "id": 1, + "name": "one", + "required": false, + "type": "string" + }, + { + "id": 2, + "name": "two", + "required": false, + "type": "long" + } + ] + }, + "current-schema-id": 0, + "schemas": [ + { + "type": "struct", + "schema-id": 0, + "fields": [ + { + "id": 1, + "name": "one", + "required": false, + "type": "string" + }, + { + "id": 2, + "name": "two", + "required": false, + "type": "long" + } + ] + } + ], + "partition-spec": [], + "default-spec-id": 0, + "partition-specs": [ + { + "spec-id": 0, + "fields": [] + } + ], + "last-partition-id": 999, + "default-sort-order-id": 0, + "sort-orders": [ + { + "order-id": 0, + "fields": [] + } + ], + "properties": { + "owner": "root" + }, + "current-snapshot-id": -1, + "refs": {}, + "snapshots": [], + "snapshot-log": [], + "metadata-log": [] +} \ No newline at end of file diff --git a/mmv1/third_party/terraform/website/docs/d/cloud_identity_group_membership.html.markdown b/mmv1/third_party/terraform/website/docs/d/cloud_identity_group_membership.html.markdown index 43231df65ca8..0141ad037489 100644 --- a/mmv1/third_party/terraform/website/docs/d/cloud_identity_group_membership.html.markdown +++ b/mmv1/third_party/terraform/website/docs/d/cloud_identity_group_membership.html.markdown @@ -33,6 +33,8 @@ In addition to the arguments listed above, the following attributes are exported * `name` - The resource name of the Membership, of the form groups/{group_id}/memberships/{membership_id}. +* `type` - The type of the membership. + * `roles` - The MembershipRoles that apply to the Membership. Structure is [documented below](#nested_roles). * `member_key` - diff --git a/mmv1/third_party/terraform/website/docs/d/data_source_dataproc_metastore_service.markdown b/mmv1/third_party/terraform/website/docs/d/dataproc_metastore_service.markdown similarity index 100% rename from mmv1/third_party/terraform/website/docs/d/data_source_dataproc_metastore_service.markdown rename to mmv1/third_party/terraform/website/docs/d/dataproc_metastore_service.markdown diff --git a/mmv1/third_party/terraform/website/docs/d/data_source_sourcerepo_repository.html.markdown b/mmv1/third_party/terraform/website/docs/d/sourcerepo_repository.html.markdown similarity index 100% rename from mmv1/third_party/terraform/website/docs/d/data_source_sourcerepo_repository.html.markdown rename to mmv1/third_party/terraform/website/docs/d/sourcerepo_repository.html.markdown 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 cf943e567cb0..2b4fec268537 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 @@ -107,6 +107,8 @@ The following arguments are supported: * `friendly_name` - (Optional) A descriptive name for the table. +* `max_staleness`: (Optional) The maximum staleness of data that could be returned when the table (or stale MV) is queried. Staleness encoded as a string encoding of sql IntervalValue type. + * `encryption_configuration` - (Optional) Specifies how the table should be encrypted. If left blank, the table will be encrypted with a Google-managed key; that process is transparent to the user. Structure is [documented below](#nested_encryption_configuration). @@ -208,6 +210,10 @@ in Terraform state, a `terraform destroy` or `terraform apply` that would delete * `source_uris` - (Required) A list of the fully-qualified URIs that point to your data in Google Cloud. +* `file_set_spec_type` - (Optional) Specifies how source URIs are interpreted for constructing the file set to load. + By default source URIs are expanded against the underlying storage. + Other options include specifying manifest files. Only applicable to object storage systems. [Docs](cloud/bigquery/docs/reference/rest/v2/tables#filesetspectype) + * `reference_file_schema_uri` - (Optional) When creating an external table, the user can provide a reference file with the table schema. This is enabled for the following formats: AVRO, PARQUET, ORC. * `metadata_cache_mode` - (Optional) Metadata Cache Mode for the table. Set this to enable caching of metadata from external data source. Valid values are `AUTOMATIC` and `MANUAL`. diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown index 637df56b7037..aa1c929d2db8 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance.html.markdown @@ -239,7 +239,7 @@ is desired, you will need to modify your state file manually using * `labels` - (Optional) A set of key/value label pairs assigned to the disk. This field is only applicable for persistent disks. -* `resource_manager_tags` - (Optional) A tag is a key-value pair that can be attached to a Google Cloud resource. You can use tags to conditionally allow or deny policies based on whether a resource has a specific tag. +* `resource_manager_tags` - (Optional) A tag is a key-value pair that can be attached to a Google Cloud resource. You can use tags to conditionally allow or deny policies based on whether a resource has a specific tag. This value is not returned by the API. In Terraform, this value cannot be updated and changing it will recreate the resource. The `scratch_disk` block supports: @@ -331,12 +331,22 @@ specified, then this instance will have no external IPv6 Internet access. Struct The `ipv6_access_config` block supports: -* `public_ptr_domain_name` - (Optional) The domain name to be used when creating DNSv6 - records for the external IPv6 ranges.. +* `external_ipv6` - (Optional) The first IPv6 address of the external IPv6 range associated + with this instance, prefix length is stored in externalIpv6PrefixLength in ipv6AccessConfig. + To use a static external IP address, it must be unused and in the same region as the instance's zone. + If not specified, Google Cloud will automatically assign an external IPv6 address from the instance's subnetwork. + +* `external_ipv6_prefix_length` - (Optional) The prefix length of the external IPv6 range. + +* `name` - (Optional) The name of this access configuration. In ipv6AccessConfigs, the recommended name + is "External IPv6". * `network_tier` - (Optional) The service-level to be provided for IPv6 traffic when the subnet has an external subnet. Only PREMIUM or STANDARD tier is valid for IPv6. +* `public_ptr_domain_name` - (Optional) The domain name to be used when creating DNSv6 + records for the external IPv6 ranges.. + The `alias_ip_range` block supports: * `ip_cidr_range` - The IP CIDR range represented by this alias IP range. This IP CIDR range @@ -381,7 +391,7 @@ specified, then this instance will have no external IPv6 Internet access. Struct * `min_node_cpus` - (Optional) The minimum number of virtual CPUs this instance will consume when running on a sole-tenant node. * `provisioning_model` - (Optional) Describe the type of preemptible VM. This field accepts the value `STANDARD` or `SPOT`. If the value is `STANDARD`, there will be no discount. If this is set to `SPOT`, - `preemptible` should be `true` and `auto_restart` should be + `preemptible` should be `true` and `automatic_restart` should be `false`. For more info about `SPOT`, read [here](https://cloud.google.com/compute/docs/instances/spot) @@ -402,6 +412,18 @@ specified, then this instance will have no external IPv6 Internet access. Struct * `maintenance_interval` - (Optional) [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) Specifies the frequency of planned maintenance events. The accepted values are: `PERIODIC`. The `guest_accelerator` block supports: +* `local_ssd_recovery_timeout` - (Optional) (https://terraform.io/docs/providers/google/guides/provider_versions.html) Specifies the maximum amount of time a Local Ssd Vm should wait while recovery of the Local Ssd state is attempted. Its value should be in between 0 and 168 hours with hour granularity and the default value being 1 hour. Structure is [documented below](#nested_local_ssd_recovery_timeout). +The `local_ssd_recovery_timeout` block supports: + +* `nanos` - (Optional) Span of time that's a fraction of a second at nanosecond + resolution. Durations less than one second are represented with a 0 + `seconds` field and a positive `nanos` field. Must be from 0 to + 999,999,999 inclusive. + +* `seconds` - (Required) Span of time at a resolution of a second. Must be from 0 to + 315,576,000,000 inclusive. Note: these bounds are computed from: 60 + sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years. + * `type` (Required) - The accelerator type resource to expose to this instance. E.g. `nvidia-tesla-k80`. * `count` (Required) - The number of the guest accelerator cards exposed to this instance. @@ -417,7 +439,7 @@ specified, then this instance will have no external IPv6 Internet access. Struct The `params` block supports: -* `resource_manager_tags` (Optional) - A tag is a key-value pair that can be attached to a Google Cloud resource. You can use tags to conditionally allow or deny policies based on whether a resource has a specific tag. +* `resource_manager_tags` (Optional) - A tag is a key-value pair that can be attached to a Google Cloud resource. You can use tags to conditionally allow or deny policies based on whether a resource has a specific tag. This value is not returned by the API. In Terraform, this value cannot be updated and changing it will recreate the resource. The `shielded_instance_config` block supports: @@ -483,12 +505,6 @@ This field is always inherited from its subnetwork. * `network_interface.0.access_config.0.nat_ip` - If the instance has an access config, either the given external ip (in the `nat_ip` field) or the ephemeral (generated) ip (if you didn't provide one). -* `network_interface.0.ipv6_access_config.0.external_ipv6` - The first IPv6 address of the external IPv6 range -associated with this instance, prefix length is stored in externalIpv6PrefixLength in ipv6AccessConfig. -The field is output only, an IPv6 address from a subnetwork associated with the instance will be allocated dynamically. - -* `network_interface.0.ipv6_access_config.0.external_ipv6_prefix_length` - The prefix length of the external IPv6 range. - * `attached_disk.0.disk_encryption_key_sha256` - The [RFC 4648 base64](https://tools.ietf.org/html/rfc4648#section-4) encoded SHA-256 hash of the [customer-supplied encryption key] (https://cloud.google.com/compute/docs/disks/customer-supplied-encryption) that protects this resource. 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 8312acd499d5..2b7d656a644f 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 @@ -124,8 +124,9 @@ The following arguments are supported: is not provided, the provider project is used. * `target_size` - (Optional) The target number of running instances for this managed - instance group. This value should always be explicitly set unless this resource is attached to - an autoscaler, in which case it should never be set. Defaults to `0`. + instance group. This value will fight with autoscaler settings when set, and generally shouldn't be set + when using one. If a value is required, such as to specify a creation-time target size for the MIG, + `lifecycle.ignore_changes` can be used to prevent Terraform from modifying the value. Defaults to `0`. * `list_managed_instances_results` - (Optional) Pagination behavior of the `listManagedInstances` API method for this managed instance group. Valid values are: `PAGELESS`, `PAGINATED`. @@ -208,7 +209,7 @@ instance_lifecycle_policy { } ``` -* `force_update_on_repair` - (Optional, [Beta](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, (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. - - - diff --git a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown index 8de0fec19b34..34c4bafdaa77 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_instance_template.html.markdown @@ -537,8 +537,10 @@ specified, then this instance will have no external IPv6 Internet access. Struct The [service accounts documentation](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam) explains that access scopes are the legacy method of specifying permissions for your instance. - If you are following best practices and using IAM roles to grant permissions to service accounts, - then you can define this field as an empty list. + To follow best practices you should create a dedicated service account with the minimum permissions the VM requires. + To use a dedicated service account this field should be configured as a list containing the `cloud-platform` scope. + See [Authenticate workloads using service accounts best practices](https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances#best_practices) + and [Best practices for using service accounts](https://cloud.google.com/iam/docs/best-practices-service-accounts#single-purpose). The `scheduling` block supports: @@ -560,7 +562,7 @@ specified, then this instance will have no external IPv6 Internet access. Struct Structure [documented below](#nested_node_affinities). * `provisioning_model` - (Optional) Describe the type of preemptible VM. This field accepts the value `STANDARD` or `SPOT`. If the value is `STANDARD`, there will be no discount. If this is set to `SPOT`, - `preemptible` should be `true` and `auto_restart` should be + `preemptible` should be `true` and `automatic_restart` should be `false`. For more info about `SPOT`, read [here](https://cloud.google.com/compute/docs/instances/spot) @@ -581,6 +583,18 @@ specified, then this instance will have no external IPv6 Internet access. Struct * `maintenance_interval` - (Optional) [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html) Specifies the frequency of planned maintenance events. The accepted values are: `PERIODIC`. The `guest_accelerator` block supports: +* `local_ssd_recovery_timeout` - (Optional) (https://terraform.io/docs/providers/google/guides/provider_versions.html) Specifies the maximum amount of time a Local Ssd Vm should wait while recovery of the Local Ssd state is attempted. Its value should be in between 0 and 168 hours with hour granularity and the default value being 1 hour. Structure is [documented below](#nested_local_ssd_recovery_timeout). +The `local_ssd_recovery_timeout` block supports: + +* `nanos` - (Optional) Span of time that's a fraction of a second at nanosecond + resolution. Durations less than one second are represented with a 0 + `seconds` field and a positive `nanos` field. Must be from 0 to + 999,999,999 inclusive. + +* `seconds` - (Required) Span of time at a resolution of a second. Must be from 0 to + 315,576,000,000 inclusive. Note: these bounds are computed from: 60 + sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years. + * `type` (Required) - The accelerator type resource to expose to this instance. E.g. `nvidia-tesla-k80`. * `count` (Required) - The number of the guest accelerator cards exposed to this 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 45e90554be0e..383c1c3f4a52 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 @@ -126,8 +126,9 @@ The following arguments are supported: is not provided, the provider project is used. * `target_size` - (Optional) The target number of running instances for this managed - instance group. This value should always be explicitly set unless this resource is attached to - an autoscaler, in which case it should never be set. Defaults to `0`. + instance group. This value will fight with autoscaler settings when set, and generally shouldn't be set + when using one. If a value is required, such as to specify a creation-time target size for the MIG, + `lifecycle.ignore_changes` can be used to prevent Terraform from modifying the value. Defaults to `0`. * `list_managed_instances_results` - (Optional) Pagination behavior of the `listManagedInstances` API method for this managed instance group. Valid values are: `PAGELESS`, `PAGINATED`. @@ -218,7 +219,7 @@ instance_lifecycle_policy { } ``` -* `force_update_on_repair` - (Optional, [Beta](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, (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. - - - The `all_instances_config` block supports: diff --git a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown index 263e37eb3051..bb971e854ff8 100644 --- a/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/compute_region_instance_template.html.markdown @@ -548,8 +548,10 @@ specified, then this instance will have no external IPv6 Internet access. Struct The [service accounts documentation](https://cloud.google.com/compute/docs/access/service-accounts#accesscopesiam) explains that access scopes are the legacy method of specifying permissions for your instance. - If you are following best practices and using IAM roles to grant permissions to service accounts, - then you can define this field as an empty list. + To follow best practices you should create a dedicated service account with the minimum permissions the VM requires. + To use a dedicated service account this field should be configured as a list containing the `cloud-platform` scope. + See [Authenticate workloads using service accounts best practices](https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances#best_practices) + and [Best practices for using service accounts](https://cloud.google.com/iam/docs/best-practices-service-accounts#single-purpose). The `scheduling` block supports: @@ -571,7 +573,7 @@ specified, then this instance will have no external IPv6 Internet access. Struct Structure [documented below](#nested_node_affinities). * `provisioning_model` - (Optional) Describe the type of preemptible VM. This field accepts the value `STANDARD` or `SPOT`. If the value is `STANDARD`, there will be no discount. If this is set to `SPOT`, - `preemptible` should be `true` and `auto_restart` should be + `preemptible` should be `true` and `automatic_restart` should be `false`. For more info about `SPOT`, read [here](https://cloud.google.com/compute/docs/instances/spot) @@ -593,6 +595,18 @@ specified, then this instance will have no external IPv6 Internet access. Struct * `maintenance_interval` - (Optional) Specifies the frequency of planned maintenance events. The accepted values are: `PERIODIC`. The `guest_accelerator` block supports: +* `local_ssd_recovery_timeout` - (Optional) (https://terraform.io/docs/providers/google/guides/provider_versions.html) Specifies the maximum amount of time a Local Ssd Vm should wait while recovery of the Local Ssd state is attempted. Its value should be in between 0 and 168 hours with hour granularity and the default value being 1 hour. Structure is [documented below](#nested_local_ssd_recovery_timeout). +The `local_ssd_recovery_timeout` block supports: + +* `nanos` - (Optional) Span of time that's a fraction of a second at nanosecond + resolution. Durations less than one second are represented with a 0 + `seconds` field and a positive `nanos` field. Must be from 0 to + 999,999,999 inclusive. + +* `seconds` - (Required) Span of time at a resolution of a second. Must be from 0 to + 315,576,000,000 inclusive. Note: these bounds are computed from: 60 + sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years. + * `type` (Required) - The accelerator type resource to expose to this instance. E.g. `nvidia-tesla-k80`. * `count` (Required) - The number of the guest accelerator cards exposed to this instance. 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 6a70569fc165..d7fd8ca8d930 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 @@ -164,6 +164,9 @@ for more information. this cluster. Note that when this option is enabled, the cluster cannot be upgraded and will be automatically deleted after 30 days. +* `enable_k8s_beta_apis` - (Optional) Configuration for Kubernetes Beta APIs. + Structure is [documented below](#nested_enable_k8s_beta_apis). + * `enable_tpu` - (Optional) Whether to enable Cloud TPU resources in this cluster. See the [official documentation](https://cloud.google.com/tpu/docs/kubernetes-engine-setup). @@ -346,7 +349,7 @@ subnetwork in which the cluster's instances are launched. * `enable_l4_ilb_subsetting` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Whether L4ILB Subsetting is enabled for this cluster. -* `enable_multi_networking` - (Optional) [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) +* `enable_multi_networking` - (Optional, [Beta](https://terraform.io/docs/providers/google/guides/provider_versions.html)) Whether multi-networking is enabled for this cluster. * `private_ipv6_google_access` - (Optional) @@ -467,6 +470,10 @@ addons_config { * `key_name` - (Required) the key to use to encrypt/decrypt secrets. See the [DatabaseEncryption definition](https://cloud.google.com/kubernetes-engine/docs/reference/rest/v1beta1/projects.locations.clusters#Cluster.DatabaseEncryption) for more information. +The `enable_k8s_beta_apis` block supports: + +* `enabled_apis` - (Required) Enabled Kubernetes Beta APIs. To list a Beta API resource, use the representation {group}/{version}/{resource}. The version must be a Beta version. Note that you cannot disable beta APIs that are already enabled on a cluster without recreating it. See the [Configure beta APIs](https://cloud.google.com/kubernetes-engine/docs/how-to/use-beta-apis#configure-beta-apis) for more information. + The `cloudrun_config` block supports: * `disabled` - (Optional) The status of the CloudRun addon. It is disabled by default. Set `disabled=false` to enable. @@ -588,10 +595,17 @@ This block also contains several computed attributes, documented below. * `managed_prometheus` - (Optional) Configuration for Managed Service for Prometheus. Structure is [documented below](#nested_managed_prometheus). +* `advanced_datapath_observability_config` - (Optional) Configuration for Advanced Datapath Monitoring. Structure is [documented below](#nested_advanced_datapath_observability_config). + The `managed_prometheus` block supports: * `enabled` - (Required) Whether or not the managed collection is enabled. +The `advanced_datapath_observability_config` block supports: + +* `enabled_metrics` - (Required) Whether or not the advanced datapath metrics are enabled. +* `relay_mode` - (Optional) Mode used to make Relay available. + The `maintenance_policy` block supports: * `daily_maintenance_window` - (Optional) structure documented below. * `recurring_window` - (Optional) structure documented below @@ -705,7 +719,7 @@ to have a range chosen with a specific netmask. Set to a CIDR notation (e.g. 10. from the RFC-1918 private networks (e.g. 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) to pick a specific range to use. -* `stack_type` - (Optional) The IP Stack Type of the cluster. +* `stack_type` - (Optional) The IP Stack Type of the cluster. Default value is `IPV4`. Possible values are `IPV4` and `IPV4_IPV6`. @@ -752,7 +766,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' -* `ephemeral_storage_config` - (Optional, [Beta]) Parameters for the ephemeral storage filesystem. If unspecified, ephemeral storage is backed by the boot disk. Structure is [documented below](#nested_ephemeral_storage_config). +* `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). ```hcl ephemeral_storage_config { 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 8f7d75246505..4a8f19b26cd3 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 @@ -262,6 +262,10 @@ cluster. Specifying COMPACT placement policy type places node pool's nodes in a closer physical proximity in order to reduce network latency between nodes. +* `policy_name` - (Optional) If set, refers to the name of a custom resource policy supplied by the user. + The resource policy must be in the same project and region as the node pool. + If not found, InvalidArgument error is returned. + * `tpu_topology` - (Optional, Beta) The [TPU placement topology](https://cloud.google.com/tpu/docs/types-topologies#tpu_topologies) for pod slice node pool. ## Attributes Reference diff --git a/mmv1/third_party/terraform/website/docs/r/os_config_os_policy_assignment.html.markdown b/mmv1/third_party/terraform/website/docs/r/os_config_os_policy_assignment.html.markdown index 070103344c5f..666b5964ccb5 100644 --- a/mmv1/third_party/terraform/website/docs/r/os_config_os_policy_assignment.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/os_config_os_policy_assignment.html.markdown @@ -1,5 +1,5 @@ +--- subcategory: "OS Config" - description: |- OS policy assignment is an API resource that is used to apply a set of OS policies to a dynamically targeted group of Compute Engine VM instances. --- diff --git a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown index 245e5c0a0a99..717ac3d67256 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_database_instance.html.markdown @@ -325,7 +325,7 @@ The optional `settings.backup_configuration` subblock supports: * `location` - (Optional) The region where the backup will be stored -* `transaction_log_retention_days` - (Optional) The number of days of transaction logs we retain for point in time restore, from 1-7. +* `transaction_log_retention_days` - (Optional) The number of days of transaction logs we retain for point in time restore, from 1-7. For PostgreSQL Enterprise Plus instances, the number of days of retained transaction logs can be set from 1 to 35. * `backup_retention_settings` - (Optional) Backup retention settings. The configuration is detailed below. diff --git a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown index 9f5f93b1f2e4..be4fd5be3fe3 100644 --- a/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown +++ b/mmv1/third_party/terraform/website/docs/r/sql_user.html.markdown @@ -38,7 +38,7 @@ resource "google_sql_user" "users" { } ``` -Example creating a Cloud IAM User. (For MySQL, specify `cloudsql_iam_authentication`) +Example using [Cloud SQL IAM database authentication](https://cloud.google.com/sql/docs/mysql/authentication). ```hcl resource "random_id" "db_name_suffix" { @@ -47,7 +47,7 @@ resource "random_id" "db_name_suffix" { resource "google_sql_database_instance" "main" { name = "main-instance-${random_id.db_name_suffix.hex}" - database_version = "POSTGRES_9_6" + database_version = "POSTGRES_15" settings { tier = "db-f1-micro" @@ -59,11 +59,19 @@ resource "google_sql_database_instance" "main" { } } -resource "google_sql_user" "users" { +resource "google_sql_user" "iam_user" { name = "me@example.com" instance = google_sql_database_instance.main.name type = "CLOUD_IAM_USER" } + +resource "google_sql_user" "iam_service_account_user" { + # Note: for Postgres only, GCP requires omitting the ".gserviceaccount.com" suffix + # from the service account email due to length limits on database usernames. + name = trimsuffix(google_service_account.service_account.email, ".gserviceaccount.com") + instance = google_sql_database_instance.main.name + type = "CLOUD_IAM_SERVICE_ACCOUNT" +} ``` ## Argument Reference diff --git a/mmv1/third_party/validator/bigquery_dataset_iam.go b/mmv1/third_party/tgc/bigquery_dataset_iam.go similarity index 100% rename from mmv1/third_party/validator/bigquery_dataset_iam.go rename to mmv1/third_party/tgc/bigquery_dataset_iam.go diff --git a/mmv1/third_party/validator/bigquery_table.go b/mmv1/third_party/tgc/bigquery_table.go similarity index 100% rename from mmv1/third_party/validator/bigquery_table.go rename to mmv1/third_party/tgc/bigquery_table.go diff --git a/mmv1/third_party/validator/bigtable_cluster.go b/mmv1/third_party/tgc/bigtable_cluster.go similarity index 100% rename from mmv1/third_party/validator/bigtable_cluster.go rename to mmv1/third_party/tgc/bigtable_cluster.go diff --git a/mmv1/third_party/validator/bigtable_instance.go b/mmv1/third_party/tgc/bigtable_instance.go similarity index 100% rename from mmv1/third_party/validator/bigtable_instance.go rename to mmv1/third_party/tgc/bigtable_instance.go diff --git a/mmv1/third_party/validator/cai.go b/mmv1/third_party/tgc/cai.go similarity index 100% rename from mmv1/third_party/validator/cai.go rename to mmv1/third_party/tgc/cai.go diff --git a/mmv1/third_party/validator/cloudfunctions_cloud_function.go b/mmv1/third_party/tgc/cloudfunctions_cloud_function.go similarity index 100% rename from mmv1/third_party/validator/cloudfunctions_cloud_function.go rename to mmv1/third_party/tgc/cloudfunctions_cloud_function.go diff --git a/mmv1/third_party/validator/cloudfunctions_function.go b/mmv1/third_party/tgc/cloudfunctions_function.go similarity index 100% rename from mmv1/third_party/validator/cloudfunctions_function.go rename to mmv1/third_party/tgc/cloudfunctions_function.go diff --git a/mmv1/third_party/validator/compute_instance.go.erb b/mmv1/third_party/tgc/compute_instance.go.erb similarity index 100% rename from mmv1/third_party/validator/compute_instance.go.erb rename to mmv1/third_party/tgc/compute_instance.go.erb diff --git a/mmv1/third_party/validator/compute_security_policy.go b/mmv1/third_party/tgc/compute_security_policy.go similarity index 100% rename from mmv1/third_party/validator/compute_security_policy.go rename to mmv1/third_party/tgc/compute_security_policy.go diff --git a/mmv1/third_party/validator/constants.go b/mmv1/third_party/tgc/constants.go similarity index 100% rename from mmv1/third_party/validator/constants.go rename to mmv1/third_party/tgc/constants.go diff --git a/mmv1/third_party/validator/container.go b/mmv1/third_party/tgc/container.go similarity index 100% rename from mmv1/third_party/validator/container.go rename to mmv1/third_party/tgc/container.go diff --git a/mmv1/third_party/validator/dcl.go b/mmv1/third_party/tgc/dcl.go similarity index 100% rename from mmv1/third_party/validator/dcl.go rename to mmv1/third_party/tgc/dcl.go diff --git a/mmv1/third_party/validator/folder.go b/mmv1/third_party/tgc/folder.go similarity index 100% rename from mmv1/third_party/validator/folder.go rename to mmv1/third_party/tgc/folder.go diff --git a/mmv1/third_party/validator/folder_iam.go b/mmv1/third_party/tgc/folder_iam.go similarity index 100% rename from mmv1/third_party/validator/folder_iam.go rename to mmv1/third_party/tgc/folder_iam.go diff --git a/mmv1/third_party/validator/folder_organization_policy.go b/mmv1/third_party/tgc/folder_organization_policy.go similarity index 100% rename from mmv1/third_party/validator/folder_organization_policy.go rename to mmv1/third_party/tgc/folder_organization_policy.go diff --git a/mmv1/third_party/validator/getconfig.go b/mmv1/third_party/tgc/getconfig.go similarity index 100% rename from mmv1/third_party/validator/getconfig.go rename to mmv1/third_party/tgc/getconfig.go diff --git a/mmv1/third_party/validator/getconfig_test.go b/mmv1/third_party/tgc/getconfig_test.go similarity index 100% rename from mmv1/third_party/validator/getconfig_test.go rename to mmv1/third_party/tgc/getconfig_test.go diff --git a/mmv1/third_party/validator/iam_helpers.go b/mmv1/third_party/tgc/iam_helpers.go similarity index 100% rename from mmv1/third_party/validator/iam_helpers.go rename to mmv1/third_party/tgc/iam_helpers.go diff --git a/mmv1/third_party/validator/iam_storage_bucket.go b/mmv1/third_party/tgc/iam_storage_bucket.go similarity index 100% rename from mmv1/third_party/validator/iam_storage_bucket.go rename to mmv1/third_party/tgc/iam_storage_bucket.go diff --git a/mmv1/third_party/validator/json_map.go b/mmv1/third_party/tgc/json_map.go similarity index 100% rename from mmv1/third_party/validator/json_map.go rename to mmv1/third_party/tgc/json_map.go diff --git a/mmv1/third_party/validator/kms_crypto_key_iam.go b/mmv1/third_party/tgc/kms_crypto_key_iam.go similarity index 100% rename from mmv1/third_party/validator/kms_crypto_key_iam.go rename to mmv1/third_party/tgc/kms_crypto_key_iam.go diff --git a/mmv1/third_party/validator/kms_key_ring_iam.go b/mmv1/third_party/tgc/kms_key_ring_iam.go similarity index 100% rename from mmv1/third_party/validator/kms_key_ring_iam.go rename to mmv1/third_party/tgc/kms_key_ring_iam.go diff --git a/mmv1/third_party/validator/monitoring_slo_helper.go b/mmv1/third_party/tgc/monitoring_slo_helper.go similarity index 100% rename from mmv1/third_party/validator/monitoring_slo_helper.go rename to mmv1/third_party/tgc/monitoring_slo_helper.go diff --git a/mmv1/third_party/validator/org_policy_policy.go b/mmv1/third_party/tgc/org_policy_policy.go similarity index 100% rename from mmv1/third_party/validator/org_policy_policy.go rename to mmv1/third_party/tgc/org_policy_policy.go diff --git a/mmv1/third_party/validator/organization_iam.go b/mmv1/third_party/tgc/organization_iam.go similarity index 100% rename from mmv1/third_party/validator/organization_iam.go rename to mmv1/third_party/tgc/organization_iam.go diff --git a/mmv1/third_party/validator/organization_iam_custom_role.go b/mmv1/third_party/tgc/organization_iam_custom_role.go similarity index 100% rename from mmv1/third_party/validator/organization_iam_custom_role.go rename to mmv1/third_party/tgc/organization_iam_custom_role.go diff --git a/mmv1/third_party/validator/organization_policy.go b/mmv1/third_party/tgc/organization_policy.go similarity index 100% rename from mmv1/third_party/validator/organization_policy.go rename to mmv1/third_party/tgc/organization_policy.go diff --git a/mmv1/third_party/validator/project.go b/mmv1/third_party/tgc/project.go similarity index 100% rename from mmv1/third_party/validator/project.go rename to mmv1/third_party/tgc/project.go diff --git a/mmv1/third_party/validator/project_iam.go b/mmv1/third_party/tgc/project_iam.go similarity index 100% rename from mmv1/third_party/validator/project_iam.go rename to mmv1/third_party/tgc/project_iam.go diff --git a/mmv1/third_party/validator/project_iam_custom_role.go b/mmv1/third_party/tgc/project_iam_custom_role.go similarity index 100% rename from mmv1/third_party/validator/project_iam_custom_role.go rename to mmv1/third_party/tgc/project_iam_custom_role.go diff --git a/mmv1/third_party/validator/project_organization_policy.go b/mmv1/third_party/tgc/project_organization_policy.go similarity index 100% rename from mmv1/third_party/validator/project_organization_policy.go rename to mmv1/third_party/tgc/project_organization_policy.go diff --git a/mmv1/third_party/validator/project_service.go b/mmv1/third_party/tgc/project_service.go similarity index 100% rename from mmv1/third_party/validator/project_service.go rename to mmv1/third_party/tgc/project_service.go diff --git a/mmv1/third_party/validator/project_service_test.go b/mmv1/third_party/tgc/project_service_test.go similarity index 100% rename from mmv1/third_party/validator/project_service_test.go rename to mmv1/third_party/tgc/project_service_test.go diff --git a/mmv1/third_party/validator/pubsub_subscription_iam.go b/mmv1/third_party/tgc/pubsub_subscription_iam.go similarity index 100% rename from mmv1/third_party/validator/pubsub_subscription_iam.go rename to mmv1/third_party/tgc/pubsub_subscription_iam.go diff --git a/mmv1/third_party/validator/service_account.go b/mmv1/third_party/tgc/service_account.go similarity index 100% rename from mmv1/third_party/validator/service_account.go rename to mmv1/third_party/tgc/service_account.go diff --git a/mmv1/third_party/validator/spanner_database_iam.go b/mmv1/third_party/tgc/spanner_database_iam.go similarity index 100% rename from mmv1/third_party/validator/spanner_database_iam.go rename to mmv1/third_party/tgc/spanner_database_iam.go diff --git a/mmv1/third_party/validator/spanner_instance_iam.go b/mmv1/third_party/tgc/spanner_instance_iam.go similarity index 100% rename from mmv1/third_party/validator/spanner_instance_iam.go rename to mmv1/third_party/tgc/spanner_instance_iam.go diff --git a/mmv1/third_party/validator/sql_database_instance.go b/mmv1/third_party/tgc/sql_database_instance.go similarity index 100% rename from mmv1/third_party/validator/sql_database_instance.go rename to mmv1/third_party/tgc/sql_database_instance.go diff --git a/mmv1/third_party/validator/storage_bucket.go b/mmv1/third_party/tgc/storage_bucket.go similarity index 100% rename from mmv1/third_party/validator/storage_bucket.go rename to mmv1/third_party/tgc/storage_bucket.go diff --git a/mmv1/third_party/validator/storage_bucket_iam.go b/mmv1/third_party/tgc/storage_bucket_iam.go similarity index 100% rename from mmv1/third_party/validator/storage_bucket_iam.go rename to mmv1/third_party/tgc/storage_bucket_iam.go diff --git a/mmv1/third_party/validator/test_utils.go b/mmv1/third_party/tgc/test_utils.go similarity index 100% rename from mmv1/third_party/validator/test_utils.go rename to mmv1/third_party/tgc/test_utils.go diff --git a/mmv1/third_party/validator/tests/README.md b/mmv1/third_party/tgc/tests/README.md similarity index 100% rename from mmv1/third_party/validator/tests/README.md rename to mmv1/third_party/tgc/tests/README.md diff --git a/mmv1/third_party/validator/tests/data-ignored/README.md b/mmv1/third_party/tgc/tests/data-ignored/README.md similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/README.md rename to mmv1/third_party/tgc/tests/data-ignored/README.md diff --git a/mmv1/third_party/validator/tests/data-ignored/example_compute_security_policy.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_security_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_compute_security_policy.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_security_policy.json diff --git a/mmv1/third_party/validator/tests/data-ignored/example_compute_security_policy.tf b/mmv1/third_party/tgc/tests/data-ignored/example_compute_security_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_compute_security_policy.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_security_policy.tf diff --git a/mmv1/third_party/validator/tests/data-ignored/example_compute_security_policy.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_compute_security_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_compute_security_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_compute_security_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data-ignored/example_monitoring_alert_policy.json b/mmv1/third_party/tgc/tests/data-ignored/example_monitoring_alert_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_monitoring_alert_policy.json rename to mmv1/third_party/tgc/tests/data-ignored/example_monitoring_alert_policy.json diff --git a/mmv1/third_party/validator/tests/data-ignored/example_monitoring_alert_policy.tf b/mmv1/third_party/tgc/tests/data-ignored/example_monitoring_alert_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_monitoring_alert_policy.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_monitoring_alert_policy.tf diff --git a/mmv1/third_party/validator/tests/data-ignored/example_monitoring_alert_policy.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_monitoring_alert_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_monitoring_alert_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_monitoring_alert_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data-ignored/example_redis_instance.json b/mmv1/third_party/tgc/tests/data-ignored/example_redis_instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_redis_instance.json rename to mmv1/third_party/tgc/tests/data-ignored/example_redis_instance.json diff --git a/mmv1/third_party/validator/tests/data-ignored/example_redis_instance.tf b/mmv1/third_party/tgc/tests/data-ignored/example_redis_instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_redis_instance.tf rename to mmv1/third_party/tgc/tests/data-ignored/example_redis_instance.tf diff --git a/mmv1/third_party/validator/tests/data-ignored/example_redis_instance.tfplan.json b/mmv1/third_party/tgc/tests/data-ignored/example_redis_instance.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data-ignored/example_redis_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data-ignored/example_redis_instance.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/bucket.json b/mmv1/third_party/tgc/tests/data/bucket.json similarity index 100% rename from mmv1/third_party/validator/tests/data/bucket.json rename to mmv1/third_party/tgc/tests/data/bucket.json diff --git a/mmv1/third_party/validator/tests/data/bucket.tf b/mmv1/third_party/tgc/tests/data/bucket.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/bucket.tf rename to mmv1/third_party/tgc/tests/data/bucket.tf diff --git a/mmv1/third_party/validator/tests/data/disk.json b/mmv1/third_party/tgc/tests/data/disk.json similarity index 100% rename from mmv1/third_party/validator/tests/data/disk.json rename to mmv1/third_party/tgc/tests/data/disk.json diff --git a/mmv1/third_party/validator/tests/data/disk.tf b/mmv1/third_party/tgc/tests/data/disk.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/disk.tf rename to mmv1/third_party/tgc/tests/data/disk.tf diff --git a/mmv1/third_party/validator/tests/data/example_access_context_manager_access_policy.json b/mmv1/third_party/tgc/tests/data/example_access_context_manager_access_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_access_context_manager_access_policy.json rename to mmv1/third_party/tgc/tests/data/example_access_context_manager_access_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_access_context_manager_access_policy.tf b/mmv1/third_party/tgc/tests/data/example_access_context_manager_access_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_access_context_manager_access_policy.tf rename to mmv1/third_party/tgc/tests/data/example_access_context_manager_access_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_access_context_manager_access_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_access_context_manager_access_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_access_context_manager_access_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_access_context_manager_access_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_access_context_manager_service_perimeter.json b/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_access_context_manager_service_perimeter.json rename to mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.json diff --git a/mmv1/third_party/validator/tests/data/example_access_context_manager_service_perimeter.tf b/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_access_context_manager_service_perimeter.tf rename to mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tf diff --git a/mmv1/third_party/validator/tests/data/example_access_context_manager_service_perimeter.tfplan.json b/mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_access_context_manager_service_perimeter.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_access_context_manager_service_perimeter.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset.tf rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tf diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_member.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tf rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tf diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_dataset_iam_policy_empty_policy_data.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_table.json b/mmv1/third_party/tgc/tests/data/example_bigquery_table.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_table.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_table.json diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_table.tf b/mmv1/third_party/tgc/tests/data/example_bigquery_table.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_table.tf rename to mmv1/third_party/tgc/tests/data/example_bigquery_table.tf diff --git a/mmv1/third_party/validator/tests/data/example_bigquery_table.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigquery_table.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigquery_table.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_bigquery_table.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_bigtable_instance.json b/mmv1/third_party/tgc/tests/data/example_bigtable_instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigtable_instance.json rename to mmv1/third_party/tgc/tests/data/example_bigtable_instance.json diff --git a/mmv1/third_party/validator/tests/data/example_bigtable_instance.tf b/mmv1/third_party/tgc/tests/data/example_bigtable_instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigtable_instance.tf rename to mmv1/third_party/tgc/tests/data/example_bigtable_instance.tf diff --git a/mmv1/third_party/validator/tests/data/example_bigtable_instance.tfplan.json b/mmv1/third_party/tgc/tests/data/example_bigtable_instance.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_bigtable_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_bigtable_instance.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_mapping.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_mapping.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_mapping.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_mapping.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_mapping.tf b/mmv1/third_party/tgc/tests/data/example_cloud_run_mapping.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_mapping.tf rename to mmv1/third_party/tgc/tests/data/example_cloud_run_mapping.tf diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_mapping.tfplan.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_mapping.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_mapping.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_mapping.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service.tf b/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service.tf rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service.tf diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service.tfplan.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_member.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_cloud_run_service_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_cloud_run_service_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_address.json b/mmv1/third_party/tgc/tests/data/example_compute_address.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_address.json rename to mmv1/third_party/tgc/tests/data/example_compute_address.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_address.tf b/mmv1/third_party/tgc/tests/data/example_compute_address.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_address.tf rename to mmv1/third_party/tgc/tests/data/example_compute_address.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_address.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_address.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_address.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_address.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_disk.json b/mmv1/third_party/tgc/tests/data/example_compute_disk.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_disk.json rename to mmv1/third_party/tgc/tests/data/example_compute_disk.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_disk.tf b/mmv1/third_party/tgc/tests/data/example_compute_disk.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_disk.tf rename to mmv1/third_party/tgc/tests/data/example_compute_disk.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_disk.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_disk.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_disk.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_disk_empty_image.json b/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_disk_empty_image.json rename to mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_disk_empty_image.tf b/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_disk_empty_image.tf rename to mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_disk_empty_image.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_disk_empty_image.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_disk_empty_image.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_firewall.json b/mmv1/third_party/tgc/tests/data/example_compute_firewall.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_firewall.json rename to mmv1/third_party/tgc/tests/data/example_compute_firewall.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_firewall.tf b/mmv1/third_party/tgc/tests/data/example_compute_firewall.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_firewall.tf rename to mmv1/third_party/tgc/tests/data/example_compute_firewall.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_firewall.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_firewall.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_firewall.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_firewall.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_forwarding_rule.json b/mmv1/third_party/tgc/tests/data/example_compute_forwarding_rule.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_forwarding_rule.json rename to mmv1/third_party/tgc/tests/data/example_compute_forwarding_rule.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_forwarding_rule.tf b/mmv1/third_party/tgc/tests/data/example_compute_forwarding_rule.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_forwarding_rule.tf rename to mmv1/third_party/tgc/tests/data/example_compute_forwarding_rule.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_global_address.json b/mmv1/third_party/tgc/tests/data/example_compute_global_address.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_global_address.json rename to mmv1/third_party/tgc/tests/data/example_compute_global_address.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_global_address.tf b/mmv1/third_party/tgc/tests/data/example_compute_global_address.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_global_address.tf rename to mmv1/third_party/tgc/tests/data/example_compute_global_address.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_global_address.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_global_address.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_global_address.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_global_address.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_global_forwarding_rule.json b/mmv1/third_party/tgc/tests/data/example_compute_global_forwarding_rule.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_global_forwarding_rule.json rename to mmv1/third_party/tgc/tests/data/example_compute_global_forwarding_rule.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_global_forwarding_rule.tf b/mmv1/third_party/tgc/tests/data/example_compute_global_forwarding_rule.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_global_forwarding_rule.tf rename to mmv1/third_party/tgc/tests/data/example_compute_global_forwarding_rule.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_global_forwarding_rule.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_global_forwarding_rule.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_global_forwarding_rule.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_global_forwarding_rule.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance.json b/mmv1/third_party/tgc/tests/data/example_compute_instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance.json rename to mmv1/third_party/tgc/tests/data/example_compute_instance.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance.tf b/mmv1/third_party/tgc/tests/data/example_compute_instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance.tf rename to mmv1/third_party/tgc/tests/data/example_compute_instance.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_member.json b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_instance_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_instance_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_instance_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_instance_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_network.json b/mmv1/third_party/tgc/tests/data/example_compute_network.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_network.json rename to mmv1/third_party/tgc/tests/data/example_compute_network.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_network.tf b/mmv1/third_party/tgc/tests/data/example_compute_network.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_network.tf rename to mmv1/third_party/tgc/tests/data/example_compute_network.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_network.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_network.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_network.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_network.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_snapshot.json b/mmv1/third_party/tgc/tests/data/example_compute_snapshot.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_snapshot.json rename to mmv1/third_party/tgc/tests/data/example_compute_snapshot.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_snapshot.tf b/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_snapshot.tf rename to mmv1/third_party/tgc/tests/data/example_compute_snapshot.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_snapshot.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_snapshot.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_snapshot.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_ssl_policy.json b/mmv1/third_party/tgc/tests/data/example_compute_ssl_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_ssl_policy.json rename to mmv1/third_party/tgc/tests/data/example_compute_ssl_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_ssl_policy.tf b/mmv1/third_party/tgc/tests/data/example_compute_ssl_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_ssl_policy.tf rename to mmv1/third_party/tgc/tests/data/example_compute_ssl_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_ssl_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_ssl_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_ssl_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_ssl_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_subnetwork.json b/mmv1/third_party/tgc/tests/data/example_compute_subnetwork.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_subnetwork.json rename to mmv1/third_party/tgc/tests/data/example_compute_subnetwork.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_subnetwork.tf b/mmv1/third_party/tgc/tests/data/example_compute_subnetwork.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_subnetwork.tf rename to mmv1/third_party/tgc/tests/data/example_compute_subnetwork.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_subnetwork.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_subnetwork.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_subnetwork.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_subnetwork.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_target_https_proxy.json b/mmv1/third_party/tgc/tests/data/example_compute_target_https_proxy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_target_https_proxy.json rename to mmv1/third_party/tgc/tests/data/example_compute_target_https_proxy.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_target_https_proxy.tf b/mmv1/third_party/tgc/tests/data/example_compute_target_https_proxy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_target_https_proxy.tf rename to mmv1/third_party/tgc/tests/data/example_compute_target_https_proxy.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_target_https_proxy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_target_https_proxy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_target_https_proxy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_target_https_proxy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_target_ssl_proxy.json b/mmv1/third_party/tgc/tests/data/example_compute_target_ssl_proxy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_target_ssl_proxy.json rename to mmv1/third_party/tgc/tests/data/example_compute_target_ssl_proxy.json diff --git a/mmv1/third_party/validator/tests/data/example_compute_target_ssl_proxy.tf b/mmv1/third_party/tgc/tests/data/example_compute_target_ssl_proxy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_target_ssl_proxy.tf rename to mmv1/third_party/tgc/tests/data/example_compute_target_ssl_proxy.tf diff --git a/mmv1/third_party/validator/tests/data/example_compute_target_ssl_proxy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_compute_target_ssl_proxy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_compute_target_ssl_proxy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_compute_target_ssl_proxy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_container_cluster.json b/mmv1/third_party/tgc/tests/data/example_container_cluster.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_container_cluster.json rename to mmv1/third_party/tgc/tests/data/example_container_cluster.json diff --git a/mmv1/third_party/validator/tests/data/example_container_cluster.tf b/mmv1/third_party/tgc/tests/data/example_container_cluster.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_container_cluster.tf rename to mmv1/third_party/tgc/tests/data/example_container_cluster.tf diff --git a/mmv1/third_party/validator/tests/data/example_container_cluster.tfplan.json b/mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_container_cluster.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_container_cluster.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_dns_managed_zone.json b/mmv1/third_party/tgc/tests/data/example_dns_managed_zone.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_dns_managed_zone.json rename to mmv1/third_party/tgc/tests/data/example_dns_managed_zone.json diff --git a/mmv1/third_party/validator/tests/data/example_dns_managed_zone.tf b/mmv1/third_party/tgc/tests/data/example_dns_managed_zone.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_dns_managed_zone.tf rename to mmv1/third_party/tgc/tests/data/example_dns_managed_zone.tf diff --git a/mmv1/third_party/validator/tests/data/example_dns_managed_zone.tfplan.json b/mmv1/third_party/tgc/tests/data/example_dns_managed_zone.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_dns_managed_zone.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_dns_managed_zone.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_dns_policy.json b/mmv1/third_party/tgc/tests/data/example_dns_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_dns_policy.json rename to mmv1/third_party/tgc/tests/data/example_dns_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_dns_policy.tf b/mmv1/third_party/tgc/tests/data/example_dns_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_dns_policy.tf rename to mmv1/third_party/tgc/tests/data/example_dns_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_dns_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_dns_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_dns_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_dns_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_filestore_instance.json b/mmv1/third_party/tgc/tests/data/example_filestore_instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_filestore_instance.json rename to mmv1/third_party/tgc/tests/data/example_filestore_instance.json diff --git a/mmv1/third_party/validator/tests/data/example_filestore_instance.tf b/mmv1/third_party/tgc/tests/data/example_filestore_instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_filestore_instance.tf rename to mmv1/third_party/tgc/tests/data/example_filestore_instance.tf diff --git a/mmv1/third_party/validator/tests/data/example_filestore_instance.tfplan.json b/mmv1/third_party/tgc/tests/data/example_filestore_instance.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_filestore_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_filestore_instance.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_folder_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_folder_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_folder_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_folder_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_folder_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_folder_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_member.json b/mmv1/third_party/tgc/tests/data/example_folder_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_folder_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_folder_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_folder_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_folder_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_folder_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_member_empty_folder.json b/mmv1/third_party/tgc/tests/data/example_folder_iam_member_empty_folder.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_member_empty_folder.json rename to mmv1/third_party/tgc/tests/data/example_folder_iam_member_empty_folder.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_member_empty_folder.tf b/mmv1/third_party/tgc/tests/data/example_folder_iam_member_empty_folder.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_member_empty_folder.tf rename to mmv1/third_party/tgc/tests/data/example_folder_iam_member_empty_folder.tf diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_member_empty_folder.tfplan.json b/mmv1/third_party/tgc/tests/data/example_folder_iam_member_empty_folder.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_member_empty_folder.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_folder_iam_member_empty_folder.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_folder_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_folder_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_folder_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_folder_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_folder_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_folder_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_folder_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_organization_policy.json b/mmv1/third_party/tgc/tests/data/example_folder_organization_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_organization_policy.json rename to mmv1/third_party/tgc/tests/data/example_folder_organization_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_folder_organization_policy.tf b/mmv1/third_party/tgc/tests/data/example_folder_organization_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_organization_policy.tf rename to mmv1/third_party/tgc/tests/data/example_folder_organization_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_folder_organization_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_folder_organization_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_folder_organization_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_folder_organization_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_google_cloudfunctions_function.json b/mmv1/third_party/tgc/tests/data/example_google_cloudfunctions_function.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_google_cloudfunctions_function.json rename to mmv1/third_party/tgc/tests/data/example_google_cloudfunctions_function.json diff --git a/mmv1/third_party/validator/tests/data/example_google_cloudfunctions_function.tf b/mmv1/third_party/tgc/tests/data/example_google_cloudfunctions_function.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_google_cloudfunctions_function.tf rename to mmv1/third_party/tgc/tests/data/example_google_cloudfunctions_function.tf diff --git a/mmv1/third_party/validator/tests/data/example_google_cloudfunctions_function.tfplan.json b/mmv1/third_party/tgc/tests/data/example_google_cloudfunctions_function.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_google_cloudfunctions_function.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_google_cloudfunctions_function.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_google_sql_database.json b/mmv1/third_party/tgc/tests/data/example_google_sql_database.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_google_sql_database.json rename to mmv1/third_party/tgc/tests/data/example_google_sql_database.json diff --git a/mmv1/third_party/validator/tests/data/example_google_sql_database.tf b/mmv1/third_party/tgc/tests/data/example_google_sql_database.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_google_sql_database.tf rename to mmv1/third_party/tgc/tests/data/example_google_sql_database.tf diff --git a/mmv1/third_party/validator/tests/data/example_google_sql_database.tfplan.json b/mmv1/third_party/tgc/tests/data/example_google_sql_database.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_google_sql_database.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_google_sql_database.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key.json b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key.json rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key.tf b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key.tf rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key.tf diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key.tfplan.json b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_member.json b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_crypto_key_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_kms_crypto_key_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring.json b/mmv1/third_party/tgc/tests/data/example_kms_key_ring.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring.json rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring.tf b/mmv1/third_party/tgc/tests/data/example_kms_key_ring.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring.tf rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring.tf diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring.tfplan.json b/mmv1/third_party/tgc/tests/data/example_kms_key_ring.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_member.json b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_kms_key_ring_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_kms_key_ring_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_logging_metric.json b/mmv1/third_party/tgc/tests/data/example_logging_metric.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_logging_metric.json rename to mmv1/third_party/tgc/tests/data/example_logging_metric.json diff --git a/mmv1/third_party/validator/tests/data/example_logging_metric.tf b/mmv1/third_party/tgc/tests/data/example_logging_metric.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_logging_metric.tf rename to mmv1/third_party/tgc/tests/data/example_logging_metric.tf diff --git a/mmv1/third_party/validator/tests/data/example_logging_metric.tfplan.json b/mmv1/third_party/tgc/tests/data/example_logging_metric.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_logging_metric.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_logging_metric.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_monitoring_notification_channel.json b/mmv1/third_party/tgc/tests/data/example_monitoring_notification_channel.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_monitoring_notification_channel.json rename to mmv1/third_party/tgc/tests/data/example_monitoring_notification_channel.json diff --git a/mmv1/third_party/validator/tests/data/example_monitoring_notification_channel.tf b/mmv1/third_party/tgc/tests/data/example_monitoring_notification_channel.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_monitoring_notification_channel.tf rename to mmv1/third_party/tgc/tests/data/example_monitoring_notification_channel.tf diff --git a/mmv1/third_party/validator/tests/data/example_monitoring_notification_channel.tfplan.json b/mmv1/third_party/tgc/tests/data/example_monitoring_notification_channel.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_monitoring_notification_channel.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_monitoring_notification_channel.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_org_policy_policy.json b/mmv1/third_party/tgc/tests/data/example_org_policy_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_org_policy_policy.json rename to mmv1/third_party/tgc/tests/data/example_org_policy_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_org_policy_policy.tf b/mmv1/third_party/tgc/tests/data/example_org_policy_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_org_policy_policy.tf rename to mmv1/third_party/tgc/tests/data/example_org_policy_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_org_policy_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_org_policy_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_org_policy_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_org_policy_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_organization_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_organization_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_organization_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_organization_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_organization_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_organization_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_custom_role.json b/mmv1/third_party/tgc/tests/data/example_organization_iam_custom_role.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_custom_role.json rename to mmv1/third_party/tgc/tests/data/example_organization_iam_custom_role.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_custom_role.tf b/mmv1/third_party/tgc/tests/data/example_organization_iam_custom_role.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_custom_role.tf rename to mmv1/third_party/tgc/tests/data/example_organization_iam_custom_role.tf diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_custom_role.tfplan.json b/mmv1/third_party/tgc/tests/data/example_organization_iam_custom_role.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_custom_role.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_organization_iam_custom_role.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_member.json b/mmv1/third_party/tgc/tests/data/example_organization_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_organization_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_organization_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_organization_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_organization_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_organization_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_organization_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_organization_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_organization_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_organization_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_organization_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_organization_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_organization_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_policy.json b/mmv1/third_party/tgc/tests/data/example_organization_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_policy.json rename to mmv1/third_party/tgc/tests/data/example_organization_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_organization_policy.tf b/mmv1/third_party/tgc/tests/data/example_organization_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_policy.tf rename to mmv1/third_party/tgc/tests/data/example_organization_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_organization_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_organization_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_organization_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_organization_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_create.json b/mmv1/third_party/tgc/tests/data/example_project_create.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_create.json rename to mmv1/third_party/tgc/tests/data/example_project_create.json diff --git a/mmv1/third_party/validator/tests/data/example_project_create.tf b/mmv1/third_party/tgc/tests/data/example_project_create.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_create.tf rename to mmv1/third_party/tgc/tests/data/example_project_create.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_create.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_create.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_create.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_create.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_create_empty_project_id.json b/mmv1/third_party/tgc/tests/data/example_project_create_empty_project_id.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_create_empty_project_id.json rename to mmv1/third_party/tgc/tests/data/example_project_create_empty_project_id.json diff --git a/mmv1/third_party/validator/tests/data/example_project_create_empty_project_id.tf b/mmv1/third_party/tgc/tests/data/example_project_create_empty_project_id.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_create_empty_project_id.tf rename to mmv1/third_party/tgc/tests/data/example_project_create_empty_project_id.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_create_empty_project_id.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_create_empty_project_id.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_create_empty_project_id.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_create_empty_project_id.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_create_empty_project_id_without_default_project.json b/mmv1/third_party/tgc/tests/data/example_project_create_empty_project_id_without_default_project.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_create_empty_project_id_without_default_project.json rename to mmv1/third_party/tgc/tests/data/example_project_create_empty_project_id_without_default_project.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam.json b/mmv1/third_party/tgc/tests/data/example_project_iam.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam.json rename to mmv1/third_party/tgc/tests/data/example_project_iam.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam.tf b/mmv1/third_party/tgc/tests/data/example_project_iam.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam.tf rename to mmv1/third_party/tgc/tests/data/example_project_iam.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_iam.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_iam.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_iam.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_project_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_project_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_project_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_custom_role.json b/mmv1/third_party/tgc/tests/data/example_project_iam_custom_role.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_custom_role.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_custom_role.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_custom_role.tf b/mmv1/third_party/tgc/tests/data/example_project_iam_custom_role.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_custom_role.tf rename to mmv1/third_party/tgc/tests/data/example_project_iam_custom_role.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_custom_role.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_iam_custom_role.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_custom_role.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_custom_role.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_member.json b/mmv1/third_party/tgc/tests/data/example_project_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_project_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_project_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_member_empty_project.json b/mmv1/third_party/tgc/tests/data/example_project_iam_member_empty_project.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_member_empty_project.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_member_empty_project.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_member_empty_project.tf b/mmv1/third_party/tgc/tests/data/example_project_iam_member_empty_project.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_member_empty_project.tf rename to mmv1/third_party/tgc/tests/data/example_project_iam_member_empty_project.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_member_empty_project.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_iam_member_empty_project.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_member_empty_project.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_member_empty_project.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_member_empty_project_without_default_project.json b/mmv1/third_party/tgc/tests/data/example_project_iam_member_empty_project_without_default_project.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_member_empty_project_without_default_project.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_member_empty_project_without_default_project.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_project_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_project_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_project_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_in_folder.json b/mmv1/third_party/tgc/tests/data/example_project_in_folder.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_in_folder.json rename to mmv1/third_party/tgc/tests/data/example_project_in_folder.json diff --git a/mmv1/third_party/validator/tests/data/example_project_in_folder.tf b/mmv1/third_party/tgc/tests/data/example_project_in_folder.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_in_folder.tf rename to mmv1/third_party/tgc/tests/data/example_project_in_folder.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_in_folder.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_in_folder.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_in_folder.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_in_folder.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_in_org.json b/mmv1/third_party/tgc/tests/data/example_project_in_org.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_in_org.json rename to mmv1/third_party/tgc/tests/data/example_project_in_org.json diff --git a/mmv1/third_party/validator/tests/data/example_project_in_org.tf b/mmv1/third_party/tgc/tests/data/example_project_in_org.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_in_org.tf rename to mmv1/third_party/tgc/tests/data/example_project_in_org.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_in_org.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_in_org.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_in_org.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_in_org.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_organization_policy.json b/mmv1/third_party/tgc/tests/data/example_project_organization_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_organization_policy.json rename to mmv1/third_party/tgc/tests/data/example_project_organization_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_project_organization_policy.tf b/mmv1/third_party/tgc/tests/data/example_project_organization_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_organization_policy.tf rename to mmv1/third_party/tgc/tests/data/example_project_organization_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_organization_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_organization_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_organization_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_organization_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_service.json b/mmv1/third_party/tgc/tests/data/example_project_service.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_service.json rename to mmv1/third_party/tgc/tests/data/example_project_service.json diff --git a/mmv1/third_party/validator/tests/data/example_project_service.tf b/mmv1/third_party/tgc/tests/data/example_project_service.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_service.tf rename to mmv1/third_party/tgc/tests/data/example_project_service.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_service.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_service.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_service.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_service.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_update.json b/mmv1/third_party/tgc/tests/data/example_project_update.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_update.json rename to mmv1/third_party/tgc/tests/data/example_project_update.json diff --git a/mmv1/third_party/validator/tests/data/example_project_update.tf b/mmv1/third_party/tgc/tests/data/example_project_update.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_update.tf rename to mmv1/third_party/tgc/tests/data/example_project_update.tf diff --git a/mmv1/third_party/validator/tests/data/example_project_update.tfplan.json b/mmv1/third_party/tgc/tests/data/example_project_update.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_update.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_project_update.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_project_update.tfstate b/mmv1/third_party/tgc/tests/data/example_project_update.tfstate similarity index 100% rename from mmv1/third_party/validator/tests/data/example_project_update.tfstate rename to mmv1/third_party/tgc/tests/data/example_project_update.tfstate diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_reservation.json b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_reservation.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_reservation.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_reservation.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_reservation.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_reservation.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_reservation.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_reservation.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_reservation.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_reservation.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_reservation.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_reservation.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_subscription.json b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_subscription.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_subscription.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_subscription.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_subscription.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_subscription.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_subscription.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_subscription.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_subscription.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_subscription.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_subscription.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_subscription.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_topic.json b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_topic.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_topic.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_topic.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_topic.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_topic.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_topic.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_topic.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_lite_topic.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_lite_topic.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_lite_topic.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_lite_topic.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_schema.json b/mmv1/third_party/tgc/tests/data/example_pubsub_schema.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_schema.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_schema.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_schema.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_schema.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_schema.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_schema.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_schema.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_schema.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_schema.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_schema.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_member.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_subscription_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_subscription_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_topic.json b/mmv1/third_party/tgc/tests/data/example_pubsub_topic.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_topic.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_topic.json diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_topic.tf b/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_topic.tf rename to mmv1/third_party/tgc/tests/data/example_pubsub_topic.tf diff --git a/mmv1/third_party/validator/tests/data/example_pubsub_topic.tfplan.json b/mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_pubsub_topic.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_pubsub_topic.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_member.json b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_secret_manager_secret_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_secret_manager_secret_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_service_account.json b/mmv1/third_party/tgc/tests/data/example_service_account.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_service_account.json rename to mmv1/third_party/tgc/tests/data/example_service_account.json diff --git a/mmv1/third_party/validator/tests/data/example_service_account.tf b/mmv1/third_party/tgc/tests/data/example_service_account.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_service_account.tf rename to mmv1/third_party/tgc/tests/data/example_service_account.tf diff --git a/mmv1/third_party/validator/tests/data/example_service_account.tfplan.json b/mmv1/third_party/tgc/tests/data/example_service_account.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_service_account.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_service_account.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_service_account_update.json b/mmv1/third_party/tgc/tests/data/example_service_account_update.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_service_account_update.json rename to mmv1/third_party/tgc/tests/data/example_service_account_update.json diff --git a/mmv1/third_party/validator/tests/data/example_service_account_update.tf b/mmv1/third_party/tgc/tests/data/example_service_account_update.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_service_account_update.tf rename to mmv1/third_party/tgc/tests/data/example_service_account_update.tf diff --git a/mmv1/third_party/validator/tests/data/example_service_account_update.tfplan.json b/mmv1/third_party/tgc/tests/data/example_service_account_update.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_service_account_update.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_service_account_update.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_service_account_update.tfstate b/mmv1/third_party/tgc/tests/data/example_service_account_update.tfstate similarity index 100% rename from mmv1/third_party/validator/tests/data/example_service_account_update.tfstate rename to mmv1/third_party/tgc/tests/data/example_service_account_update.tfstate diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database.json b/mmv1/third_party/tgc/tests/data/example_spanner_database.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database.json rename to mmv1/third_party/tgc/tests/data/example_spanner_database.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database.tf b/mmv1/third_party/tgc/tests/data/example_spanner_database.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database.tf rename to mmv1/third_party/tgc/tests/data/example_spanner_database.tf diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database.tfplan.json b/mmv1/third_party/tgc/tests/data/example_spanner_database.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_spanner_database.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_member.json b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_spanner_database_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_spanner_database_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_database_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_spanner_database_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_member.json b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_spanner_instance_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_spanner_instance_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_spanner_instance_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_sql_database_instance.json b/mmv1/third_party/tgc/tests/data/example_sql_database_instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_sql_database_instance.json rename to mmv1/third_party/tgc/tests/data/example_sql_database_instance.json diff --git a/mmv1/third_party/validator/tests/data/example_sql_database_instance.tf b/mmv1/third_party/tgc/tests/data/example_sql_database_instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_sql_database_instance.tf rename to mmv1/third_party/tgc/tests/data/example_sql_database_instance.tf diff --git a/mmv1/third_party/validator/tests/data/example_sql_database_instance.tfplan.json b/mmv1/third_party/tgc/tests/data/example_sql_database_instance.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_sql_database_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_sql_database_instance.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket.tf b/mmv1/third_party/tgc/tests/data/example_storage_bucket.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket.tf rename to mmv1/third_party/tgc/tests/data/example_storage_bucket.tf diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket.tfplan.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_binding.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_binding.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_binding.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_binding.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_binding.tf b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_binding.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_binding.tf rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_binding.tf diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_binding.tfplan.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_binding.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_binding.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_binding.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member.tf b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member.tf rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member.tf diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member.tfplan.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member_random_suffix.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member_random_suffix.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member_random_suffix.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member_random_suffix.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member_random_suffix.tf b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member_random_suffix.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member_random_suffix.tf rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member_random_suffix.tf diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member_random_suffix.tfplan.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member_random_suffix.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_member_random_suffix.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_member_random_suffix.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_policy.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_policy.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_policy.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_policy.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_policy.tf b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_policy.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_policy.tf rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_policy.tf diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_iam_policy.tfplan.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_policy.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_iam_policy.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_iam_policy.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/example_storage_bucket_without_default_project.json b/mmv1/third_party/tgc/tests/data/example_storage_bucket_without_default_project.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_storage_bucket_without_default_project.json rename to mmv1/third_party/tgc/tests/data/example_storage_bucket_without_default_project.json diff --git a/mmv1/third_party/validator/tests/data/example_vpc_access_connector.json b/mmv1/third_party/tgc/tests/data/example_vpc_access_connector.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_vpc_access_connector.json rename to mmv1/third_party/tgc/tests/data/example_vpc_access_connector.json diff --git a/mmv1/third_party/validator/tests/data/example_vpc_access_connector.tf b/mmv1/third_party/tgc/tests/data/example_vpc_access_connector.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/example_vpc_access_connector.tf rename to mmv1/third_party/tgc/tests/data/example_vpc_access_connector.tf diff --git a/mmv1/third_party/validator/tests/data/example_vpc_access_connector.tfplan.json b/mmv1/third_party/tgc/tests/data/example_vpc_access_connector.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/example_vpc_access_connector.tfplan.json rename to mmv1/third_party/tgc/tests/data/example_vpc_access_connector.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/firewall.json b/mmv1/third_party/tgc/tests/data/firewall.json similarity index 100% rename from mmv1/third_party/validator/tests/data/firewall.json rename to mmv1/third_party/tgc/tests/data/firewall.json diff --git a/mmv1/third_party/validator/tests/data/firewall.tf b/mmv1/third_party/tgc/tests/data/firewall.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/firewall.tf rename to mmv1/third_party/tgc/tests/data/firewall.tf diff --git a/mmv1/third_party/validator/tests/data/full_compute_firewall.json b/mmv1/third_party/tgc/tests/data/full_compute_firewall.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_compute_firewall.json rename to mmv1/third_party/tgc/tests/data/full_compute_firewall.json diff --git a/mmv1/third_party/validator/tests/data/full_compute_firewall.tf b/mmv1/third_party/tgc/tests/data/full_compute_firewall.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/full_compute_firewall.tf rename to mmv1/third_party/tgc/tests/data/full_compute_firewall.tf diff --git a/mmv1/third_party/validator/tests/data/full_compute_firewall.tfplan.json b/mmv1/third_party/tgc/tests/data/full_compute_firewall.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_compute_firewall.tfplan.json rename to mmv1/third_party/tgc/tests/data/full_compute_firewall.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/full_compute_instance.json b/mmv1/third_party/tgc/tests/data/full_compute_instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_compute_instance.json rename to mmv1/third_party/tgc/tests/data/full_compute_instance.json diff --git a/mmv1/third_party/validator/tests/data/full_compute_instance.tf b/mmv1/third_party/tgc/tests/data/full_compute_instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/full_compute_instance.tf rename to mmv1/third_party/tgc/tests/data/full_compute_instance.tf diff --git a/mmv1/third_party/validator/tests/data/full_compute_instance.tfplan.json b/mmv1/third_party/tgc/tests/data/full_compute_instance.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_compute_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data/full_compute_instance.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/full_container_cluster.json b/mmv1/third_party/tgc/tests/data/full_container_cluster.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_container_cluster.json rename to mmv1/third_party/tgc/tests/data/full_container_cluster.json diff --git a/mmv1/third_party/validator/tests/data/full_container_cluster.tf b/mmv1/third_party/tgc/tests/data/full_container_cluster.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/full_container_cluster.tf rename to mmv1/third_party/tgc/tests/data/full_container_cluster.tf diff --git a/mmv1/third_party/validator/tests/data/full_container_cluster.tfplan.json b/mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_container_cluster.tfplan.json rename to mmv1/third_party/tgc/tests/data/full_container_cluster.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/full_container_node_pool.json b/mmv1/third_party/tgc/tests/data/full_container_node_pool.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_container_node_pool.json rename to mmv1/third_party/tgc/tests/data/full_container_node_pool.json diff --git a/mmv1/third_party/validator/tests/data/full_container_node_pool.tf b/mmv1/third_party/tgc/tests/data/full_container_node_pool.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/full_container_node_pool.tf rename to mmv1/third_party/tgc/tests/data/full_container_node_pool.tf diff --git a/mmv1/third_party/validator/tests/data/full_container_node_pool.tfplan.json b/mmv1/third_party/tgc/tests/data/full_container_node_pool.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_container_node_pool.tfplan.json rename to mmv1/third_party/tgc/tests/data/full_container_node_pool.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/full_spanner_instance.json b/mmv1/third_party/tgc/tests/data/full_spanner_instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_spanner_instance.json rename to mmv1/third_party/tgc/tests/data/full_spanner_instance.json diff --git a/mmv1/third_party/validator/tests/data/full_spanner_instance.tf b/mmv1/third_party/tgc/tests/data/full_spanner_instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/full_spanner_instance.tf rename to mmv1/third_party/tgc/tests/data/full_spanner_instance.tf diff --git a/mmv1/third_party/validator/tests/data/full_spanner_instance.tfplan.json b/mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_spanner_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data/full_spanner_instance.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/full_sql_database_instance.json b/mmv1/third_party/tgc/tests/data/full_sql_database_instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_sql_database_instance.json rename to mmv1/third_party/tgc/tests/data/full_sql_database_instance.json diff --git a/mmv1/third_party/validator/tests/data/full_sql_database_instance.tf b/mmv1/third_party/tgc/tests/data/full_sql_database_instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/full_sql_database_instance.tf rename to mmv1/third_party/tgc/tests/data/full_sql_database_instance.tf diff --git a/mmv1/third_party/validator/tests/data/full_sql_database_instance.tfplan.json b/mmv1/third_party/tgc/tests/data/full_sql_database_instance.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_sql_database_instance.tfplan.json rename to mmv1/third_party/tgc/tests/data/full_sql_database_instance.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/full_storage_bucket.json b/mmv1/third_party/tgc/tests/data/full_storage_bucket.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_storage_bucket.json rename to mmv1/third_party/tgc/tests/data/full_storage_bucket.json diff --git a/mmv1/third_party/validator/tests/data/full_storage_bucket.tf b/mmv1/third_party/tgc/tests/data/full_storage_bucket.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/full_storage_bucket.tf rename to mmv1/third_party/tgc/tests/data/full_storage_bucket.tf diff --git a/mmv1/third_party/validator/tests/data/full_storage_bucket.tfplan.json b/mmv1/third_party/tgc/tests/data/full_storage_bucket.tfplan.json similarity index 100% rename from mmv1/third_party/validator/tests/data/full_storage_bucket.tfplan.json rename to mmv1/third_party/tgc/tests/data/full_storage_bucket.tfplan.json diff --git a/mmv1/third_party/validator/tests/data/instance.json b/mmv1/third_party/tgc/tests/data/instance.json similarity index 100% rename from mmv1/third_party/validator/tests/data/instance.json rename to mmv1/third_party/tgc/tests/data/instance.json diff --git a/mmv1/third_party/validator/tests/data/instance.tf b/mmv1/third_party/tgc/tests/data/instance.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/instance.tf rename to mmv1/third_party/tgc/tests/data/instance.tf diff --git a/mmv1/third_party/validator/tests/data/sql.json b/mmv1/third_party/tgc/tests/data/sql.json similarity index 100% rename from mmv1/third_party/validator/tests/data/sql.json rename to mmv1/third_party/tgc/tests/data/sql.json diff --git a/mmv1/third_party/validator/tests/data/sql.tf b/mmv1/third_party/tgc/tests/data/sql.tf similarity index 100% rename from mmv1/third_party/validator/tests/data/sql.tf rename to mmv1/third_party/tgc/tests/data/sql.tf diff --git a/mmv1/third_party/validator/tests/source/cli_test.go.erb b/mmv1/third_party/tgc/tests/source/cli_test.go.erb similarity index 100% rename from mmv1/third_party/validator/tests/source/cli_test.go.erb rename to mmv1/third_party/tgc/tests/source/cli_test.go.erb diff --git a/mmv1/third_party/validator/tests/source/environment_test.go b/mmv1/third_party/tgc/tests/source/environment_test.go similarity index 100% rename from mmv1/third_party/validator/tests/source/environment_test.go rename to mmv1/third_party/tgc/tests/source/environment_test.go diff --git a/mmv1/third_party/validator/tests/source/iam_test.go.erb b/mmv1/third_party/tgc/tests/source/iam_test.go.erb similarity index 100% rename from mmv1/third_party/validator/tests/source/iam_test.go.erb rename to mmv1/third_party/tgc/tests/source/iam_test.go.erb diff --git a/mmv1/third_party/validator/tests/source/init_test.go b/mmv1/third_party/tgc/tests/source/init_test.go similarity index 100% rename from mmv1/third_party/validator/tests/source/init_test.go rename to mmv1/third_party/tgc/tests/source/init_test.go diff --git a/mmv1/third_party/validator/tests/source/read_test.go.erb b/mmv1/third_party/tgc/tests/source/read_test.go.erb similarity index 100% rename from mmv1/third_party/validator/tests/source/read_test.go.erb rename to mmv1/third_party/tgc/tests/source/read_test.go.erb diff --git a/mmv1/third_party/validator/tests/source/utils_test.go b/mmv1/third_party/tgc/tests/source/utils_test.go similarity index 100% rename from mmv1/third_party/validator/tests/source/utils_test.go rename to mmv1/third_party/tgc/tests/source/utils_test.go diff --git a/mmv1/third_party/validator/tpgiamresource/iam_helpers.go b/mmv1/third_party/tgc/tpgiamresource/iam_helpers.go similarity index 100% rename from mmv1/third_party/validator/tpgiamresource/iam_helpers.go rename to mmv1/third_party/tgc/tpgiamresource/iam_helpers.go diff --git a/mmv1/third_party/validator/tpgiamresource/iam_helpers_test.go b/mmv1/third_party/tgc/tpgiamresource/iam_helpers_test.go similarity index 100% rename from mmv1/third_party/validator/tpgiamresource/iam_helpers_test.go rename to mmv1/third_party/tgc/tpgiamresource/iam_helpers_test.go diff --git a/mmv1/third_party/validator/tpgresource/cai.go b/mmv1/third_party/tgc/tpgresource/cai.go similarity index 100% rename from mmv1/third_party/validator/tpgresource/cai.go rename to mmv1/third_party/tgc/tpgresource/cai.go diff --git a/mmv1/third_party/validator/tpgresource/cai_test.go b/mmv1/third_party/tgc/tpgresource/cai_test.go similarity index 100% rename from mmv1/third_party/validator/tpgresource/cai_test.go rename to mmv1/third_party/tgc/tpgresource/cai_test.go diff --git a/mmv1/third_party/validator/tpgresource/constants.go b/mmv1/third_party/tgc/tpgresource/constants.go similarity index 100% rename from mmv1/third_party/validator/tpgresource/constants.go rename to mmv1/third_party/tgc/tpgresource/constants.go diff --git a/mmv1/third_party/validator/tpgresource/json_map.go b/mmv1/third_party/tgc/tpgresource/json_map.go similarity index 100% rename from mmv1/third_party/validator/tpgresource/json_map.go rename to mmv1/third_party/tgc/tpgresource/json_map.go diff --git a/tools/issue-labeler/backfill.go b/tools/issue-labeler/backfill.go new file mode 100644 index 000000000000..59cabe9014c0 --- /dev/null +++ b/tools/issue-labeler/backfill.go @@ -0,0 +1,129 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "sort" + + "github.com/golang/glog" +) + +type Issue struct { + HTMLURL string `json:"html_url"` + Number int + Body string + Labels []Label + PullRequest map[string]any `json:"pull_request"` +} + +type Label struct { + Name string +} + +type IssueUpdate struct { + Labels []string `json:"labels"` +} + +func backfill(since string, enrolledTeams map[string][]string, dryRun bool) { + client := &http.Client{} + done := false + page := 1 + var issues []Issue + for !done { + url := fmt.Sprintf("https://api.github.com/repos/hashicorp/terraform-provider-google/issues?since=%s&per_page=100&page=%d", since, page) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + glog.Exitf("Error creating request: %v", err) + } + req.Header.Add("Accept", "application/vnd.github+json") + req.Header.Add("Authorization", "Bearer "+os.Getenv("GITHUB_TOKEN")) + req.Header.Add("X-GitHub-Api-Version", "2022-11-28") + resp, err := client.Do(req) + if err != nil { + glog.Exitf("Error listing issues: %v", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + glog.Exitf("Error reading response body: %v", err) + } + var newIssues []Issue + json.Unmarshal(body, &newIssues) + if len(newIssues) == 0 { + done = true + } else { + issues = append(issues, newIssues...) + page++ + } + } + for _, issue := range issues { + if len(issue.PullRequest) > 0 { + continue + } + + desired := make(map[string]struct{}) + for _, existing := range issue.Labels { + desired[existing.Name] = struct{}{} + } + + _, terraform := desired["service/terraform"] + _, linked := desired["forward/linked"] + _, exempt := desired["forward/exempt"] + if terraform || exempt { + continue + } + + var oldLabels []string + for label := range desired { + oldLabels = append(oldLabels, label) + } + + for _, needed := range serviceLabels(issue.Body, enrolledTeams) { + desired[needed] = struct{}{} + } + + if len(desired) > len(oldLabels) { + var desiredSlice []string + if !linked { + desiredSlice = append(desiredSlice, "forward/review") + } + for label := range desired { + desiredSlice = append(desiredSlice, label) + } + sort.Strings(desiredSlice) + url := fmt.Sprintf("https://api.github.com/repos/hashicorp/terraform-provider-google/issues/%d", issue.Number) + update := IssueUpdate{Labels: desiredSlice} + body, err := json.Marshal(update) + if err != nil { + glog.Errorf("Error marshalling json: %v", err) + continue + } + buf := bytes.NewReader(body) + req, err := http.NewRequest("PATCH", url, buf) + if err != nil { + glog.Errorf("Error creating request: %v", err) + continue + } + fmt.Printf("%s %s (%s)\n", req.Method, req.URL, issue.HTMLURL) + b, err := json.MarshalIndent(update, "", " ") + if err != nil { + glog.Errorf("Error marshalling json: %v", err) + continue + } + fmt.Println(string(b)) + fmt.Printf("Existing labels: %v\n", oldLabels) + fmt.Printf("New labels: %v\n", desiredSlice) + if !dryRun { + _, err = client.Do(req) + if err != nil { + glog.Errorf("Error updating issue: %v", err) + continue + } + } + } + } +} diff --git a/tools/issue-labeler/enrolled_teams.yaml b/tools/issue-labeler/enrolled_teams.yml similarity index 51% rename from tools/issue-labeler/enrolled_teams.yaml rename to tools/issue-labeler/enrolled_teams.yml index acb3e2adcc68..6c56f6a6495d 100755 --- a/tools/issue-labeler/enrolled_teams.yaml +++ b/tools/issue-labeler/enrolled_teams.yml @@ -1,84 +1,97 @@ service/accesscontextmanager: -- google_access_context_manager_ +- google_access_context_manager_.* +service/aiplatform-metadata: +- google_vertex_ai_metadata_store service/alloydb: -- google_alloydb_ +- google_alloydb_.* service/apigateway: -- google_api_gateway_ +- google_api_gateway_.* service/apigee: -- google_apigee_ +- google_apigee_.* service/artifactregistry: -- google_artifact_registry_ +- google_artifact_registry_.* service/beyondcorp: -- google_beyondcorp_ +- google_beyondcorp_.* service/bigquery: -- google_bigquery_ +- google_bigquery_.* service/bigtableadmin: -- google_bigtable_ +- google_bigtable_.* service/billingbudgets: - google_billing_budget service/certificatemanager: -- google_certificate_manager_ +- google_certificate_manager_.* +service/cloudasset: +- google_cloud_asset_.* service/cloudbilling: -- google_billing_account +- google_billing_account.* - google_billing_subaccount service/cloudbuild: -- google_cloudbuild_ -- google_cloudbuildv2_ +- google_cloudbuild_.* +- google_cloudbuildv2_.* +service/clouddeploy: +- google_clouddeploy_.* service/cloudfunctions: -- google_cloudfunctions_ -- google_cloudfunctions2_ +- google_cloudfunctions_.* +- google_cloudfunctions2_.* service/cloudkms: -- google_kms_ +- google_kms_.* service/cloudscheduler: -- google_cloud_scheduler_ +- google_cloud_scheduler_.* service/cloudtasks: -- google_cloud_tasks_ +- google_cloud_tasks_.* service/composer: -- google_composer_ +- google_composer_.* service/compute-nat: - google_compute_router_nat service/compute-regional-l7-load-balancer: - google_compute_region_target_http_proxy - google_compute_region_target_https_proxy +service/compute-security-policy: +- google_compute_security_policy service/container: - google_container_cluster - google_container_engine_versions - google_container_node_pool +service/datacatalog: +- google_data_catalog_.* service/dataproc: - google_dataproc_cluster - google_dataproc_autoscaling_policy - google_dataproc_job - google_dataproc_workflow_template - google_dataproc_batch +service/datastream: +- google_datastream_.* service/dlp: -- google_data_loss_prevention_ +- google_data_loss_prevention_.* service/edgenetwork: -- google_edgenetwork_ +- google_edgenetwork_.* service/eventarc: -- google_eventarc_ +- google_eventarc_.* service/filestore: -- google_filestore_ +- google_filestore_.* service/firebase: -- google_firebase_ -- google_firebaserules_ +- google_firebase_.* +- google_firebaserules_.* service/firestore-controlplane: - google_firestore_database service/firestore-dataplane: +- google_datastore_index - google_firestore_document - google_firestore_index - google_firestore_ttl service/gkebackup: -- google_gke_backup_ +- google_gke_backup_.* service/gkehub: -- google_gke_hub_ +- google_gke_hub_.* service/gkemulticloud: -- google_container_aws_ -- google_container_azure_ -- google_container_attached_ +- google_container_aws_.* +- google_container_azure_.* +- google_container_attached_.* service/gkeonprem: -- google_gkeonprem_ +- google_gkeonprem_.* service/healthcare: -- google_healthcare_ +- google_healthcare_.* service/iam-core: - google_organization_iam_custom_role - google_project_iam_custom_role @@ -87,21 +100,25 @@ service/iam-core: - google_iam_role - google_iam_testable_permissions service/iam-serviceaccount: -- google_service_account +- google_service_account.* service/iam-wlid: - google_iam_access_boundary_policy - google_iam_workload_identity_pool - google_iam_workload_identity_pool_provider service/iam-workforce: -- google_iam_workforce_pool +- google_iam_workforce_pool.* +service/iap: +- google_iap_.* service/identitytoolkit: -- google_identity_platform_ +- google_identity_platform_.* service/ids: -- google_cloud_ids_ +- google_cloud_ids_.* service/logging: -- google_logging_ +- google_logging_.* service/looker-core: - google_looker_instance +service/metastore: +- google_dataproc_metastore_.* service/monitoring-alerting: - google_monitoring_notification_channel - google_monitoring_alert_policy @@ -109,30 +126,48 @@ service/monitoring-services: - google_monitoring_custom_service - google_monitoring_dashboard - google_monitoring_monitored_project -- google_monitoring_service_ - google_monitoring_slo +- google_monitoring_service +- google_monitoring_app_engine_service +- google_monitoring_cluster_istio_service - google_monitoring_istio_canonical_service +- google_monitoring_mesh_istio_service +- google_monitoring_istio_canonical_service +service/monitoring-uptime: +- google_monitoring_uptime_.* +service/notebooks: +- google_notebooks_.* service/orgpolicy: -- google_org_policy_ +- google_org_policy_.* service/privateca: -- google_privateca_ +- google_privateca_.* +service/pubsub: +- google_pubsub_schema +- google_pubsub_subscription.* +- google_pubsub_topic.* service/pubsublite: -- google_pubsub_lite_ +- google_pubsub_lite_.* service/redis-instance: - google_redis_instance service/run: -- google_cloud_run_ -- google_cloud_run_v2_ +- google_cloud_run_.* +- google_cloud_run_v2_.* service/secretmanager: -- google_secret_manager_ +- google_secret_manager_.* service/spanner: -- google_spanner_ +- google_spanner_.* service/sqladmin: -- google_sql_ +- google_sql_.* service/storage: -- google_storage_bucket_ -- google_storage_default_object_ +- google_storage_bucket_.* +- google_storage_default_object_.* - google_storage_hmac_key - google_storage_notification -- google_storage_object_ +- google_storage_object_.* - google_storage_project_service_account +service/vmwareengine: +- google_vmwareengine_network +- google_vmwareengine_private_cloud +- google_vmwareengine_cluster +service/workstations: +- google_workstations_.* diff --git a/tools/issue-labeler/labels.go b/tools/issue-labeler/labels.go index 912a8ffe320e..11ca7e80cda0 100644 --- a/tools/issue-labeler/labels.go +++ b/tools/issue-labeler/labels.go @@ -3,29 +3,26 @@ package main import ( "regexp" "sort" - "strings" "github.com/golang/glog" ) -func labels(issueBody string, enrolledTeams map[string][]string) string { +func serviceLabels(issueBody string, enrolledTeams map[string][]string) []string { sectionRegexp := regexp.MustCompile(`### (New or )?Affected Resource\(s\)[^#]+`) affectedResources := sectionRegexp.FindString(issueBody) - var labels []string + var results []string for label, resources := range enrolledTeams { for _, resource := range resources { - if strings.Contains(affectedResources, resource) { + resourceRegexp := regexp.MustCompile(resource) + if resourceRegexp.MatchString(affectedResources) { glog.Infof("found resource %q, applying label %q", resource, label) - labels = append(labels, "\""+label+"\"") + results = append(results, label) break } } } - if len(labels) > 0 { - labels = append(labels, "\"forward/review\"") - sort.Strings(labels) - return "[" + strings.Join(labels, ", ") + "]" - } - return "" + sort.Strings(results) + + return results } diff --git a/tools/issue-labeler/labels_test.go b/tools/issue-labeler/labels_test.go index 0890fb641169..5738d146d316 100644 --- a/tools/issue-labeler/labels_test.go +++ b/tools/issue-labeler/labels_test.go @@ -2,6 +2,7 @@ package main import ( "os" + "reflect" "testing" "github.com/golang/glog" @@ -9,7 +10,7 @@ import ( ) func TestLabels(t *testing.T) { - file, err := os.ReadFile("enrolled_teams.yaml") + file, err := os.ReadFile("enrolled_teams.yml") if err != nil { glog.Exitf("Error reading enrolled teams yaml: %v", err) } @@ -20,23 +21,22 @@ func TestLabels(t *testing.T) { } for _, tc := range []struct { issueBody string - expectedLabels string + expectedLabels []string }{ { issueBody: `### New or Affected Resource(s): google_gke_hub_feature google_storage_hmac_key #`, - expectedLabels: `["forward/review", "service/gkehub", "service/storage"]`, + expectedLabels: []string{"service/gkehub", "service/storage"}, }, { issueBody: `### New or Affected Resource(s): #`, - expectedLabels: "", }, } { - if actualLabels := labels(tc.issueBody, enrolledTeams); actualLabels != tc.expectedLabels { - t.Errorf("unexpected labels for issue body %s: %s, expected %s", tc.issueBody, actualLabels, tc.expectedLabels) + if actualLabels := serviceLabels(tc.issueBody, enrolledTeams); !reflect.DeepEqual(actualLabels, tc.expectedLabels) { + t.Errorf("unexpected labels for issue body %s: %v, expected %v", tc.issueBody, actualLabels, tc.expectedLabels) } } } diff --git a/tools/issue-labeler/main.go b/tools/issue-labeler/main.go index 3034c2bb33ae..4d668af1ac52 100644 --- a/tools/issue-labeler/main.go +++ b/tools/issue-labeler/main.go @@ -1,23 +1,40 @@ package main import ( + "flag" "fmt" "os" + "sort" + "strings" "github.com/golang/glog" "gopkg.in/yaml.v2" ) +var flagBackfillDate = flag.String("backfill-date", "", "run in backfill mode to apply labels to issues filed after given date") +var flagDryRun = flag.Bool("backfill-dry-run", false, "when combined with backfill-date, perform a dry run of backfill mode") + func main() { - issueBody := os.Getenv("ISSUE_BODY") - file, err := os.ReadFile("enrolled_teams.yaml") + flag.Parse() + + file, err := os.ReadFile("enrolled_teams.yml") if err != nil { glog.Exitf("Error reading enrolled teams yaml: %v", err) } enrolledTeams := make(map[string][]string) - err = yaml.Unmarshal(file, &enrolledTeams) - if err != nil { + if err := yaml.Unmarshal(file, &enrolledTeams); err != nil { glog.Exitf("Error unmarshalling enrolled teams yaml: %v", err) } - fmt.Println(labels(issueBody, enrolledTeams)) + + if *flagBackfillDate == "" { + issueBody := os.Getenv("ISSUE_BODY") + desired := serviceLabels(issueBody, enrolledTeams) + if len(desired) > 0 { + desired = append(desired, "forward/review") + sort.Strings(desired) + fmt.Println(`["` + strings.Join(desired, `", "`) + `"]`) + } + } else { + backfill(*flagBackfillDate, enrolledTeams, *flagDryRun) + } } diff --git a/tools/teamcity-generator/main.go b/tools/teamcity-generator/main.go index 17e10969d12f..3695368019ed 100644 --- a/tools/teamcity-generator/main.go +++ b/tools/teamcity-generator/main.go @@ -102,7 +102,16 @@ func createMap(packageNames []string) (string, error) { caser := cases.Title(language.English) var b strings.Builder + // Add copyright header + b.WriteString("/*\n") + b.WriteString(" * Copyright (c) HashiCorp, Inc.\n") + b.WriteString(" * SPDX-License-Identifier: MPL-2.0\n") + b.WriteString(" */\n\n") + + // Add autogen notice b.WriteString("// this file is auto-generated by magic-modules/tools/teamcity-generator, any changes made here will be overwritten\n\n") + + // Add the map b.WriteString("var services = mapOf(\n") for i, p := range packageNames { diff --git a/tpgtools/overrides/networkconnectivity/tpgtools_product.yaml b/tpgtools/overrides/networkconnectivity/tpgtools_product.yaml new file mode 100644 index 000000000000..21c439217d43 --- /dev/null +++ b/tpgtools/overrides/networkconnectivity/tpgtools_product.yaml @@ -0,0 +1,5 @@ +## product level overrides + +- type: PRODUCT_BASE_PATH + details: + skip: true