From d8c9c7b81f4de39103856a4e5043b968407af48f Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Thu, 19 Dec 2024 13:40:47 -0800 Subject: [PATCH 1/9] Remove cluster creation from workflows --- .github/workflows/build.yml | 135 ++------------------- .github/workflows/prerelease.yml | 134 ++------------------ .github/workflows/release.yml | 134 ++------------------ .github/workflows/run-acceptance-tests.yml | 15 +-- .github/workflows/weekly-pulumi-update.yml | 2 +- 5 files changed, 27 insertions(+), 393 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e43f781ff..8c67e8e7ed 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -61,7 +61,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -134,7 +134,7 @@ jobs: - name: Test Provider Library run: make test_provider - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7 + uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.1 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - if: failure() && github.event_name == 'push' @@ -168,7 +168,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -247,7 +247,6 @@ jobs: - build_sdks - build-test-cluster strategy: - fail-fast: true matrix: language: - nodejs @@ -270,7 +269,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -409,7 +408,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -475,7 +474,7 @@ jobs: repository: pulumi/scripts - run: echo "ci-scripts" >> .git/info/exclude - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -545,7 +544,7 @@ jobs: lfs: true ref: ${{ env.PR_COMMIT_SHA }} - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -561,123 +560,3 @@ jobs: name: lint if: github.event_name == 'repository_dispatch' || github.event.pull_request.head.repo.full_name == github.repository - build-test-cluster: - runs-on: ubuntu-latest - name: build-test-cluster - outputs: - stack-name: ${{ steps.stackname.outputs.stack-name }} - permissions: - contents: read - id-token: write - steps: - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - lfs: true - - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 - with: - go-version: ${{ env.GOVERSION }} - cache-dependency-path: "**/*.sum" - - name: Install Pulumi CLI - uses: pulumi/actions@c7fad9e2f0b79653172b36538b8b34b3c0291952 # v6.0.0 - with: - pulumi-version-file: .pulumi.version - - name: Setup Node - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: ${{ env.NODEVERSION }} - registry-url: https://registry.npmjs.org - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 - with: - workload_identity_provider: projects/${{ env.GOOGLE_PROJECT_NUMBER - }}/locations/global/workloadIdentityPools/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_POOL }}/providers/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ env.GOOGLE_CI_SERVICE_ACCOUNT_EMAIL }} - - name: Setup gcloud auth - uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - with: - install_components: gke-gcloud-auth-plugin - - name: Install Kubectl - run: > - curl -LO - https://storage.googleapis.com/kubernetes-release/release/$(curl -s - https://storage.googleapis.com/kubernetes-release/release/stable-1.28.txt)/bin/linux/amd64/kubectl - - chmod +x ./kubectl - - sudo mv kubectl /usr/local/bin - - name: Login to Google Cloud Registry - run: gcloud --quiet auth configure-docker - - name: Set stack name in output - id: stackname - run: echo 'stack-name=${{ env.PULUMI_TEST_OWNER }}/${{ github.sha }}-${{ - github.run_id }}-${{ github.run_attempt }}' >> "$GITHUB_OUTPUT" - - name: Create test infrastructure - run: ./scripts/ci-cluster-create.sh ${{ steps.stackname.outputs.stack-name }} - - name: Upload Kubernetes Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: config - path: ~/.kube/config - destroy-test-cluster: - runs-on: ubuntu-latest - name: teardown-test-cluster - needs: - - build-test-cluster - - test - if: ${{ always() }} && github.event.pull_request.head.repo.full_name == - github.repository - permissions: - contents: read - id-token: write - steps: - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - lfs: true - - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 - with: - go-version: ${{ env.GOVERSION }} - cache-dependency-path: "**/*.sum" - - name: Install Pulumi CLI - uses: pulumi/actions@c7fad9e2f0b79653172b36538b8b34b3c0291952 # v6.0.0 - with: - pulumi-version-file: .pulumi.version - - name: Setup Node - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: ${{ env.NODEVERSION }} - registry-url: https://registry.npmjs.org - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 - with: - workload_identity_provider: projects/${{ env.GOOGLE_PROJECT_NUMBER - }}/locations/global/workloadIdentityPools/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_POOL }}/providers/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ env.GOOGLE_CI_SERVICE_ACCOUNT_EMAIL }} - - name: Setup gcloud auth - uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - with: - install_components: gke-gcloud-auth-plugin - - name: Install Kubectl - run: > - curl -LO - https://storage.googleapis.com/kubernetes-release/release/$(curl -s - https://storage.googleapis.com/kubernetes-release/release/stable-1.28.txt)/bin/linux/amd64/kubectl - - chmod +x ./kubectl - - sudo mv kubectl /usr/local/bin - - name: Login to Google Cloud Registry - run: gcloud --quiet auth configure-docker - - name: Destroy test infra - run: ./scripts/ci-cluster-destroy.sh ${{ - needs.build-test-cluster.outputs.stack-name }} - - uses: geekyeggo/delete-artifact@f275313e70c08f6120db482d7a6b98377786765b # v5.1.0 - with: - name: config diff --git a/.github/workflows/prerelease.yml b/.github/workflows/prerelease.yml index b493a3e9e2..9bc4993cdf 100644 --- a/.github/workflows/prerelease.yml +++ b/.github/workflows/prerelease.yml @@ -53,7 +53,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -126,7 +126,7 @@ jobs: - name: Test Provider Library run: make test_provider - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7 + uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.1 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - if: failure() && github.event_name == 'push' @@ -160,7 +160,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -261,7 +261,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -400,7 +400,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -466,7 +466,7 @@ jobs: repository: pulumi/scripts - run: echo "ci-scripts" >> .git/info/exclude - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -543,7 +543,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -614,123 +614,3 @@ jobs: go.* go/** !*.tar.gz - build-test-cluster: - runs-on: ubuntu-latest - name: build-test-cluster - outputs: - stack-name: ${{ steps.stackname.outputs.stack-name }} - permissions: - contents: read - id-token: write - steps: - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - lfs: true - - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 - with: - go-version: ${{ env.GOVERSION }} - cache-dependency-path: "**/*.sum" - - name: Install Pulumi CLI - uses: pulumi/actions@c7fad9e2f0b79653172b36538b8b34b3c0291952 # v6.0.0 - with: - pulumi-version-file: .pulumi.version - - name: Setup Node - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: ${{ env.NODEVERSION }} - registry-url: https://registry.npmjs.org - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 - with: - workload_identity_provider: projects/${{ env.GOOGLE_PROJECT_NUMBER - }}/locations/global/workloadIdentityPools/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_POOL }}/providers/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ env.GOOGLE_CI_SERVICE_ACCOUNT_EMAIL }} - - name: Setup gcloud auth - uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - with: - install_components: gke-gcloud-auth-plugin - - name: Install Kubectl - run: > - curl -LO - https://storage.googleapis.com/kubernetes-release/release/$(curl -s - https://storage.googleapis.com/kubernetes-release/release/stable-1.28.txt)/bin/linux/amd64/kubectl - - chmod +x ./kubectl - - sudo mv kubectl /usr/local/bin - - name: Login to Google Cloud Registry - run: gcloud --quiet auth configure-docker - - name: Set stack name in output - id: stackname - run: echo 'stack-name=${{ env.PULUMI_TEST_OWNER }}/${{ github.sha }}-${{ - github.run_id }}-${{ github.run_attempt }}' >> "$GITHUB_OUTPUT" - - name: Create test infrastructure - run: ./scripts/ci-cluster-create.sh ${{ steps.stackname.outputs.stack-name }} - - name: Upload Kubernetes Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: config - path: ~/.kube/config - destroy-test-cluster: - runs-on: ubuntu-latest - name: teardown-test-cluster - needs: - - build-test-cluster - - test - if: ${{ always() }} && github.event.pull_request.head.repo.full_name == - github.repository - permissions: - contents: read - id-token: write - steps: - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - lfs: true - - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 - with: - go-version: ${{ env.GOVERSION }} - cache-dependency-path: "**/*.sum" - - name: Install Pulumi CLI - uses: pulumi/actions@c7fad9e2f0b79653172b36538b8b34b3c0291952 # v6.0.0 - with: - pulumi-version-file: .pulumi.version - - name: Setup Node - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: ${{ env.NODEVERSION }} - registry-url: https://registry.npmjs.org - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 - with: - workload_identity_provider: projects/${{ env.GOOGLE_PROJECT_NUMBER - }}/locations/global/workloadIdentityPools/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_POOL }}/providers/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ env.GOOGLE_CI_SERVICE_ACCOUNT_EMAIL }} - - name: Setup gcloud auth - uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - with: - install_components: gke-gcloud-auth-plugin - - name: Install Kubectl - run: > - curl -LO - https://storage.googleapis.com/kubernetes-release/release/$(curl -s - https://storage.googleapis.com/kubernetes-release/release/stable-1.28.txt)/bin/linux/amd64/kubectl - - chmod +x ./kubectl - - sudo mv kubectl /usr/local/bin - - name: Login to Google Cloud Registry - run: gcloud --quiet auth configure-docker - - name: Destroy test infra - run: ./scripts/ci-cluster-destroy.sh ${{ - needs.build-test-cluster.outputs.stack-name }} - - uses: geekyeggo/delete-artifact@f275313e70c08f6120db482d7a6b98377786765b # v5.1.0 - with: - name: config diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2c311baa1d..4b6de36ae5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -53,7 +53,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -126,7 +126,7 @@ jobs: - name: Test Provider Library run: make test_provider - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7 + uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.1 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - if: failure() && github.event_name == 'push' @@ -160,7 +160,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -261,7 +261,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -400,7 +400,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -466,7 +466,7 @@ jobs: repository: pulumi/scripts - run: echo "ci-scripts" >> .git/info/exclude - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -543,7 +543,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -628,123 +628,3 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.PULUMI_BOT_TOKEN }} name: dispatch_docs_build - build-test-cluster: - runs-on: ubuntu-latest - name: build-test-cluster - outputs: - stack-name: ${{ steps.stackname.outputs.stack-name }} - permissions: - contents: read - id-token: write - steps: - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - lfs: true - - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 - with: - go-version: ${{ env.GOVERSION }} - cache-dependency-path: "**/*.sum" - - name: Install Pulumi CLI - uses: pulumi/actions@c7fad9e2f0b79653172b36538b8b34b3c0291952 # v6.0.0 - with: - pulumi-version-file: .pulumi.version - - name: Setup Node - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: ${{ env.NODEVERSION }} - registry-url: https://registry.npmjs.org - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 - with: - workload_identity_provider: projects/${{ env.GOOGLE_PROJECT_NUMBER - }}/locations/global/workloadIdentityPools/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_POOL }}/providers/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ env.GOOGLE_CI_SERVICE_ACCOUNT_EMAIL }} - - name: Setup gcloud auth - uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - with: - install_components: gke-gcloud-auth-plugin - - name: Install Kubectl - run: > - curl -LO - https://storage.googleapis.com/kubernetes-release/release/$(curl -s - https://storage.googleapis.com/kubernetes-release/release/stable-1.28.txt)/bin/linux/amd64/kubectl - - chmod +x ./kubectl - - sudo mv kubectl /usr/local/bin - - name: Login to Google Cloud Registry - run: gcloud --quiet auth configure-docker - - name: Set stack name in output - id: stackname - run: echo 'stack-name=${{ env.PULUMI_TEST_OWNER }}/${{ github.sha }}-${{ - github.run_id }}-${{ github.run_attempt }}' >> "$GITHUB_OUTPUT" - - name: Create test infrastructure - run: ./scripts/ci-cluster-create.sh ${{ steps.stackname.outputs.stack-name }} - - name: Upload Kubernetes Artifacts - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3 - with: - name: config - path: ~/.kube/config - destroy-test-cluster: - runs-on: ubuntu-latest - name: teardown-test-cluster - needs: - - build-test-cluster - - test - if: ${{ always() }} && github.event.pull_request.head.repo.full_name == - github.repository - permissions: - contents: read - id-token: write - steps: - - name: Checkout Repo - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - with: - lfs: true - - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 - with: - go-version: ${{ env.GOVERSION }} - cache-dependency-path: "**/*.sum" - - name: Install Pulumi CLI - uses: pulumi/actions@c7fad9e2f0b79653172b36538b8b34b3c0291952 # v6.0.0 - with: - pulumi-version-file: .pulumi.version - - name: Setup Node - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: ${{ env.NODEVERSION }} - registry-url: https://registry.npmjs.org - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 - with: - workload_identity_provider: projects/${{ env.GOOGLE_PROJECT_NUMBER - }}/locations/global/workloadIdentityPools/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_POOL }}/providers/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ env.GOOGLE_CI_SERVICE_ACCOUNT_EMAIL }} - - name: Setup gcloud auth - uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - with: - install_components: gke-gcloud-auth-plugin - - name: Install Kubectl - run: > - curl -LO - https://storage.googleapis.com/kubernetes-release/release/$(curl -s - https://storage.googleapis.com/kubernetes-release/release/stable-1.28.txt)/bin/linux/amd64/kubectl - - chmod +x ./kubectl - - sudo mv kubectl /usr/local/bin - - name: Login to Google Cloud Registry - run: gcloud --quiet auth configure-docker - - name: Destroy test infra - run: ./scripts/ci-cluster-destroy.sh ${{ - needs.build-test-cluster.outputs.stack-name }} - - uses: geekyeggo/delete-artifact@f275313e70c08f6120db482d7a6b98377786765b # v5.1.0 - with: - name: config diff --git a/.github/workflows/run-acceptance-tests.yml b/.github/workflows/run-acceptance-tests.yml index f0f24d59a7..523a83a85d 100644 --- a/.github/workflows/run-acceptance-tests.yml +++ b/.github/workflows/run-acceptance-tests.yml @@ -75,7 +75,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -148,7 +148,7 @@ jobs: - name: Test Provider Library run: make test_provider - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5.0.7 + uses: codecov/codecov-action@7f8b4b4bde536c465e797be725718b88c5d95e0e # v5.1.1 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - if: failure() && github.event_name == 'push' @@ -185,7 +185,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -289,7 +289,7 @@ jobs: with: set-env: PROVIDER_VERSION - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" @@ -396,11 +396,6 @@ jobs: with: version: v2.5.0 token: ${{ secrets.GITHUB_TOKEN }} - - name: Setup KinD cluster - uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0 - with: - cluster_name: kind-integration-tests-${{ matrix.language }} - node_image: kindest/node:v1.29.2 - name: Run tests run: cd tests/sdk/${{ matrix.language }} && go test -v -count=1 -cover -timeout 2h -parallel 4 -short ./... @@ -439,7 +434,7 @@ jobs: lfs: true ref: ${{ env.PR_COMMIT_SHA }} - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" diff --git a/.github/workflows/weekly-pulumi-update.yml b/.github/workflows/weekly-pulumi-update.yml index 69796b111d..310dc96137 100644 --- a/.github/workflows/weekly-pulumi-update.yml +++ b/.github/workflows/weekly-pulumi-update.yml @@ -46,7 +46,7 @@ jobs: with: lfs: true - name: Install Go - uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0 + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 with: go-version: ${{ env.GOVERSION }} cache-dependency-path: "**/*.sum" From 1073235fe1bb9d3943eaa11b2949d997c8ff3ca9 Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Thu, 19 Dec 2024 14:31:26 -0800 Subject: [PATCH 2/9] Cherry-pick Ramon's cluster setup --- tests/clusters/cluster.go | 50 ++++++++++++ tests/clusters/create.go | 118 +++++++++++++++++++++++++++ tests/clusters/gke-stack/Pulumi.yaml | 3 + tests/clusters/gke-stack/config.ts | 28 +++++++ tests/clusters/gke-stack/gke.ts | 95 +++++++++++++++++++++ tests/clusters/gke-stack/index.ts | 20 +++++ tests/clusters/gke.go | 35 ++++++++ tests/clusters/kind.go | 108 ++++++++++++++++++++++++ tests/go.mod | 6 +- tests/go.sum | 12 ++- 10 files changed, 472 insertions(+), 3 deletions(-) create mode 100644 tests/clusters/cluster.go create mode 100644 tests/clusters/create.go create mode 100644 tests/clusters/gke-stack/Pulumi.yaml create mode 100644 tests/clusters/gke-stack/config.ts create mode 100644 tests/clusters/gke-stack/gke.ts create mode 100644 tests/clusters/gke-stack/index.ts create mode 100644 tests/clusters/gke.go create mode 100644 tests/clusters/kind.go diff --git a/tests/clusters/cluster.go b/tests/clusters/cluster.go new file mode 100644 index 0000000000..266a0c1662 --- /dev/null +++ b/tests/clusters/cluster.go @@ -0,0 +1,50 @@ +package clusters + +import ( + "crypto/rand" + "encoding/base32" + "strings" +) + +// Cluster is an interface to interact with a Kubernetes cluster in a test. +type Cluster interface { + Name() string + Connect() error + Delete() error + KubeconfigPath() string +} + +// normalizeName returns a normalized name for the cluster that adheres +// to the Kubernetes naming restrictions. +// Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/ +func normalizeName(name string) string { + name = strings.ToLower(name) + name = strings.ReplaceAll(name, " ", "-") + name = strings.ReplaceAll(name, ".", "-") + name = strings.ReplaceAll(name, "_", "-") + + // Trauncate names that are too long. + if len(name) > 63 { + name = name[:63] + } + + // Remove any leading numeric characters. + for i, c := range name { + if c >= '0' && c <= '9' { + continue + } + name = name[i:] + break + } + + return name +} + +// randString returns a random string of length 6. +func randString() string { + c := 10 + b := make([]byte, c) + rand.Read(b) + length := 6 + return strings.ToLower(base32.StdEncoding.EncodeToString(b)[:length]) +} diff --git a/tests/clusters/create.go b/tests/clusters/create.go new file mode 100644 index 0000000000..f37b666ecc --- /dev/null +++ b/tests/clusters/create.go @@ -0,0 +1,118 @@ +package clusters + +import ( + "flag" + "fmt" + "os" + "sync" + "testing" + + "github.com/pulumi/pulumi/pkg/v3/testing/integration" +) + +const ( + KindClusterStr = "kind" + GKECluster = "gke" +) + +var ( + TestClusterList = new(TestClusters) +) + +// RunWithClusterCreation is the entry point for the tests and provides a way to create and delete clusters for the tests. +// It is able to create a pool of clusters to randomly run tests on. +func RunWithClusterCreation(m *testing.M, clusterPrefix string) { + createCluster := flag.Bool("create-cluster", false, "Create a cluster for the tests, default is false and to use an existing cluster") + clusterType := flag.String("cluster-type", KindClusterStr, "The type of cluster to create for the tests, default is kind") + numClusters := flag.Int("num-clusters", 1, "The number of clusters to create for the tests, default is 1") + flag.Parse() + + if *createCluster { + makeCluster(clusterPrefix, TestClusterList, *clusterType, *numClusters) + } + + exitCode := m.Run() + + // Always attempt to tear down all the clusters after the tests have run. + var wg sync.WaitGroup + for _, cluster := range TestClusterList.clusters { + cluster := cluster + wg.Add(1) + go func() { + defer wg.Done() + if err := cluster.Delete(); err != nil { + fmt.Println("Unable to delete cluster: ", err) + exitCode = 1 + } + }() + } + wg.Wait() + + os.Exit(exitCode) +} + +func makeCluster(clusterPrefix string, testClusters *TestClusters, clusterType string, numClusters int) { + // Make the slice with the number of clusters to create so we do not need a mutex to handle write access to the slice. + testClusters.clusters = make([]Cluster, numClusters) + + var wg sync.WaitGroup + for i := 0; i < numClusters; i++ { + wg.Add(1) + i := i + go func() { + defer wg.Done() + + var err error + var cluster Cluster + switch clusterType { + case KindClusterStr: + cluster, err = NewKindCluster(clusterPrefix) + if err != nil { + fmt.Println("Unable to create Kind cluster: ", err) + os.Exit(1) + } + case GKECluster: + fmt.Println("STILL TODO") + os.Exit(1) + default: + fmt.Println("Unrecognized cluster type", clusterType) + os.Exit(1) + } + + testClusters.clusters[i] = cluster + }() + } + wg.Wait() +} + +type TestClusters struct { + clusters []Cluster + picked int +} + +// pickCluster picks a cluster to use in sequence (ie. round robbin) from the list of clusters created in TestMain. +// This ensures that we don't an uneven number of tests to run on each cluster. +func (t *TestClusters) PickCluster() Cluster { + t.picked++ + return t.clusters[t.picked%len(t.clusters)] +} + +// WrapProviderTestOptions is a convenience function that wraps the provider test options with the kubeconfig of the cluster to use. +// The cluster's kubeconfig is also returned for test cases that manually shell out to kubectl for validation purposes. This kubeconfig is +// required for the kubectl command to target the right cluster that the test is running on. +func (t *TestClusters) WrapProviderTestOptions(opts integration.ProgramTestOptions) (integration.ProgramTestOptions, string) { + if t.clusters == nil { + // Check if KUBECONFIG is set, if it is then use that for the tests. + kcfg := os.Getenv("KUBECONFIG") + if kcfg == "" { + kcfg = os.ExpandEnv("$HOME/.kube/config") + } + return opts, kcfg + } + + cluster := t.PickCluster() + + return opts.With(integration.ProgramTestOptions{ + Env: []string{"KUBECONFIG=" + cluster.KubeconfigPath()}, + }), cluster.KubeconfigPath() +} diff --git a/tests/clusters/gke-stack/Pulumi.yaml b/tests/clusters/gke-stack/Pulumi.yaml new file mode 100644 index 0000000000..cb3833bc64 --- /dev/null +++ b/tests/clusters/gke-stack/Pulumi.yaml @@ -0,0 +1,3 @@ +name: k8s-test-cluster +description: GKE cluster for pulumi-kubernetes testing +runtime: nodejs diff --git a/tests/clusters/gke-stack/config.ts b/tests/clusters/gke-stack/config.ts new file mode 100644 index 0000000000..3a300727a5 --- /dev/null +++ b/tests/clusters/gke-stack/config.ts @@ -0,0 +1,28 @@ +// Copyright 2016-2019, Pulumi Corporation. +// +// 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. + +import { Config } from "@pulumi/pulumi"; + +const config = new Config(); + +export const gcpProject = "pulumi-k8s-provider"; +export const gcpZone = "a"; +export const gcpLocation = "us-west1-a"; + +// nodeCount is the number of cluster nodes to provision. Defaults to 3 if unspecified. +export const nodeCount = config.getNumber("nodeCount") || 3; + +// nodeMachineType is the machine type to use for cluster nodes. Defaults to n1-standard-2 if unspecified. +// See https://cloud.google.com/compute/docs/machine-types for more details on available machine types. +export const nodeMachineType = config.get("nodeMachineType") || "n1-standard-2"; diff --git a/tests/clusters/gke-stack/gke.ts b/tests/clusters/gke-stack/gke.ts new file mode 100644 index 0000000000..f68b45494b --- /dev/null +++ b/tests/clusters/gke-stack/gke.ts @@ -0,0 +1,95 @@ +// Copyright 2016-2022, Pulumi Corporation. +// +// 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. + +import * as gcp from "@pulumi/gcp"; +import * as k8s from "@pulumi/kubernetes"; +import * as pulumi from "@pulumi/pulumi"; +import * as config from "./config"; + +export class GkeCluster extends pulumi.ComponentResource { + public cluster: gcp.container.Cluster; + public kubeconfig: pulumi.Output; + public provider: k8s.Provider; + + constructor(name: string, + opts: pulumi.ComponentResourceOptions = {}) { + super("pulumi-kubernetes:ci:GkeCluster", name, {}, opts); + + // Use the latest 1.28.x engine version. + const engineVersion = "1.28"; + + // Create the GKE cluster. + const k8sCluster = new gcp.container.Cluster("ephemeral-ci-cluster", { + initialNodeCount: config.nodeCount, + nodeVersion: engineVersion, + minMasterVersion: engineVersion, + nodeConfig: { + machineType: config.nodeMachineType, + oauthScopes: [ + "https://www.googleapis.com/auth/compute", + "https://www.googleapis.com/auth/devstorage.read_only", + "https://www.googleapis.com/auth/logging.write", + "https://www.googleapis.com/auth/monitoring" + ], + }, + project: config.gcpProject, + location: config.gcpLocation, + // Enable network policy addon to test network policy resources. + addonsConfig: { + networkPolicyConfig: { + disabled: false, + }, + }, + networkPolicy: { + enabled: true, + provider: "CALICO", + }, + }, {parent: this}); + this.cluster = k8sCluster; + + // Manufacture a GKE-style Kubeconfig. Note that this is slightly "different" because of the way GKE requires + // gcloud to be in the picture for cluster authentication (rather than using the client cert/key directly). + this.kubeconfig = pulumi.all([k8sCluster.name, k8sCluster.endpoint, k8sCluster.masterAuth]).apply( + ([name, endpoint, auth]) => { + const context = `${config.gcpProject}_${config.gcpZone}_${name}`; + return `apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: ${auth.clusterCaCertificate} + server: https://${endpoint} + name: ${context} +contexts: +- context: + cluster: ${context} + user: ${context} + name: ${context} +current-context: ${context} +kind: Config +preferences: {} +users: +- name: ${context} + user: + exec: + apiVersion: client.authentication.k8s.io/v1beta1 + command: gke-gcloud-auth-plugin + installHint: Install gke-gcloud-auth-plugin for use with kubectl by following + https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke + provideClusterInfo: true`; + }); + + // Export a Kubernetes provider instance that uses our cluster from above. + this.provider = new k8s.Provider("gke", {kubeconfig: this.kubeconfig}, {parent: this}); + } +} + diff --git a/tests/clusters/gke-stack/index.ts b/tests/clusters/gke-stack/index.ts new file mode 100644 index 0000000000..859ce113d9 --- /dev/null +++ b/tests/clusters/gke-stack/index.ts @@ -0,0 +1,20 @@ +// Copyright 2016-2019, Pulumi Corporation. +// +// 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. + +import * as gke from "./gke"; + +// Create Kubernetes clusters. +const gkeCluster = new gke.GkeCluster("ci-cluster"); +export const k8sProvider = gkeCluster.provider; +export const kubeconfig = gkeCluster.kubeconfig; diff --git a/tests/clusters/gke.go b/tests/clusters/gke.go new file mode 100644 index 0000000000..93a26d6d73 --- /dev/null +++ b/tests/clusters/gke.go @@ -0,0 +1,35 @@ +package clusters + +// import ( +// "context" +// "embed" +// "time" +// ) + +// //go:embed gke-stack/* +// var pulumiProgram embed.FS + +// type GKE struct { +// } + +// func NewGKECluster(stackName string) (Cluster, error) { +// ctx := context.WithTimeout(context.Background(), 15*time.Minute) // It normally takes 7-10 minutes to create a cluster. + +// return GKE{}, nil +// } + +// func (c GKE) Name() string { +// return "gke-cluster" +// } + +// func (c GKE) Connect() error { +// return nil +// } + +// func (c GKE) Delete() error { +// return nil +// } + +// func (c GKE) KubeconfigPath() string { +// return "" +// } diff --git a/tests/clusters/kind.go b/tests/clusters/kind.go new file mode 100644 index 0000000000..e13fa09fdf --- /dev/null +++ b/tests/clusters/kind.go @@ -0,0 +1,108 @@ +package clusters + +import ( + "fmt" + "log" + "os" + "path/filepath" + "time" + + "sigs.k8s.io/kind/pkg/cluster" +) + +// KindVersion is a specific Kind version associated with a Kubernetes minor version. +type KindVersion string + +const ( + // Kind versions and their associated image tags. + Kind1_29 KindVersion = "kindest/node:v1.29.2" + Kind1_28 KindVersion = "kindest/node:v1.28.7" + Kind1_27 KindVersion = "kindest/node:v1.27.11" + + KubeconfigFilename = "KUBECONFIG" + + // maxCreateTries is the maximum number of times to try to create a Kind cluster. + maxCreateTries = 5 +) + +type KindCluster struct { + name string + kubeconfigPath string + teardownFn func() error +} + +func (c KindCluster) Name() string { + return c.name +} + +func (c KindCluster) KubeconfigPath() string { + return c.kubeconfigPath +} + +func (c KindCluster) Connect() error { + return nil +} + +func (c KindCluster) Delete() error { + return c.teardownFn() +} + +// newKindCluster creates a new Kind cluster for use in testing with the specified name. The version +// parameter is variadic and defaults to the latest version of Kind if not provided. +func NewKindCluster(name string, version ...KindVersion) (Cluster, error) { + v := Kind1_29 + if len(version) > 0 { + v = version[0] + } + + // Create a new tmpdir to store the kubeconfig. + log.Printf("Creating new Kind cluster with image %q", v) + tmpDir, err := os.MkdirTemp("", "pulumi-test-kind") + if err != nil { + return nil, err + } + + KubeconfigPath := filepath.Join(tmpDir, KubeconfigFilename) + + p := cluster.NewProvider() + + name = normalizeName(name + "-" + randString()) + log.Printf("Creating Kind cluster %q", name) + teardownFn, err := createKindCluster(p, name, tmpDir, KubeconfigPath, v) + if err != nil { + return nil, err + } + + return &KindCluster{name: name, kubeconfigPath: KubeconfigPath, teardownFn: teardownFn}, nil + +} + +// createKindCluster attempts to create a KinD cluster with retry. +func createKindCluster(p *cluster.Provider, name, tmpDir, kcfgPath string, version KindVersion) (func() error, error) { + var err error + for i := 0; i < maxCreateTries; i++ { + log.Printf("Creating Kind cluster, attempt: %d", i+1) + err = p.Create(name, + cluster.CreateWithKubeconfigPath(kcfgPath), + cluster.CreateWithNodeImage(string(version)), + cluster.CreateWithWaitForReady(20*time.Second), + ) + if err == nil { + return func() error { + if err := deleteKindCluster(p, name, kcfgPath); err != nil { + return fmt.Errorf("unable to delete Kind cluster %q: %v", name, err) + } + + return os.RemoveAll(tmpDir) + }, nil + } + } + + // We failed to create the cluster maxCreateTries times, so return failure error. + return nil, err +} + +// deleteKindCluster deletes a specified kind cluster. +func deleteKindCluster(p *cluster.Provider, name, kcfgPath string) error { + return p.Delete(name, kcfgPath) +} diff --git a/tests/go.mod b/tests/go.mod index 47747369bb..ac7b1b3de4 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -24,6 +24,7 @@ require ( helm.sh/helm/v3 v3.15.4 k8s.io/apimachinery v0.32.0 k8s.io/client-go v0.32.0 + sigs.k8s.io/kind v0.26.0 ) require ( @@ -44,7 +45,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect @@ -54,6 +55,7 @@ require ( github.com/ProtonMail/go-crypto v1.0.0 // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/agext/levenshtein v1.2.3 // indirect + github.com/alessio/shellescape v1.4.2 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect @@ -139,6 +141,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/s2a-go v0.1.7 // indirect + github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/google/wire v0.6.0 // indirect @@ -207,6 +210,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 // indirect github.com/opentracing/basictracer-go v1.1.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pgavlin/fx v0.1.6 // indirect github.com/pgavlin/goldmark v1.1.33-0.20200616210433-b5eb04559386 // indirect diff --git a/tests/go.sum b/tests/go.sum index cabe960689..ebf08b7244 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -36,8 +36,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= @@ -70,6 +70,8 @@ github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7l github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4uEoM0= +github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= @@ -375,6 +377,8 @@ github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgY github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+IrK7d0gGgpjGGvd2kz+FzTHVzdqI= +github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -580,6 +584,8 @@ github.com/opentracing/basictracer-go v1.1.0/go.mod h1:V2HZueSJEp879yv285Aap1BS6 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pgavlin/fx v0.1.6 h1:r9jEg69DhNoCd3Xh0+5mIbdbS3PqWrVWujkY76MFRTU= @@ -1030,6 +1036,8 @@ sigs.k8s.io/controller-runtime v0.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHv sigs.k8s.io/controller-runtime v0.18.4/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/kind v0.26.0 h1:8fS6I0Q5WGlmLprSpH0DarlOSdcsv0txnwc93J2BP7M= +sigs.k8s.io/kind v0.26.0/go.mod h1:t7ueEpzPYJvHA8aeLtI52rtFftNgUYUaCwvxjk7phfw= sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo= sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U= sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E= From 71cfd8cc37b131d7bbcd13e0143e9d9a36415e69 Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Thu, 19 Dec 2024 15:52:22 -0800 Subject: [PATCH 3/9] Simplify setup, just spin up one KinD if no .kube/config is present --- provider/go.mod | 2 +- provider/go.sum | 4 +- tests/clusters/cluster.go | 1 - tests/clusters/create.go | 129 ++++++++-------------------------- tests/clusters/kind.go | 66 ++++++----------- tests/go.mod | 2 +- tests/sdk/dotnet/main_test.go | 38 ++++++++++ tests/sdk/go/main_test.go | 38 ++++++++++ tests/sdk/java/main_test.go | 38 ++++++++++ tests/sdk/nodejs/main_test.go | 38 ++++++++++ tests/sdk/python/main_test.go | 38 ++++++++++ 11 files changed, 244 insertions(+), 150 deletions(-) create mode 100644 tests/sdk/dotnet/main_test.go create mode 100644 tests/sdk/go/main_test.go create mode 100644 tests/sdk/java/main_test.go create mode 100644 tests/sdk/nodejs/main_test.go create mode 100644 tests/sdk/python/main_test.go diff --git a/provider/go.mod b/provider/go.mod index 066af89f51..ade367406f 100644 --- a/provider/go.mod +++ b/provider/go.mod @@ -50,7 +50,7 @@ require ( dario.cat/mergo v1.0.0 // indirect github.com/AdaLogics/go-fuzz-headers v0.0.0-20240716105424-66b64c4bb379 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/BurntSushi/toml v1.3.2 // indirect + github.com/BurntSushi/toml v1.4.0 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect diff --git a/provider/go.sum b/provider/go.sum index de51e908a6..a737664a7a 100644 --- a/provider/go.sum +++ b/provider/go.sum @@ -74,8 +74,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg6 github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= -github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= diff --git a/tests/clusters/cluster.go b/tests/clusters/cluster.go index 266a0c1662..c150d6cec8 100644 --- a/tests/clusters/cluster.go +++ b/tests/clusters/cluster.go @@ -11,7 +11,6 @@ type Cluster interface { Name() string Connect() error Delete() error - KubeconfigPath() string } // normalizeName returns a normalized name for the cluster that adheres diff --git a/tests/clusters/create.go b/tests/clusters/create.go index f37b666ecc..939b588420 100644 --- a/tests/clusters/create.go +++ b/tests/clusters/create.go @@ -1,13 +1,13 @@ package clusters import ( - "flag" - "fmt" + "errors" + "log" "os" "sync" - "testing" - "github.com/pulumi/pulumi/pkg/v3/testing/integration" + "github.com/mitchellh/go-homedir" + "k8s.io/client-go/tools/clientcmd" ) const ( @@ -15,104 +15,35 @@ const ( GKECluster = "gke" ) -var ( - TestClusterList = new(TestClusters) -) - -// RunWithClusterCreation is the entry point for the tests and provides a way to create and delete clusters for the tests. -// It is able to create a pool of clusters to randomly run tests on. -func RunWithClusterCreation(m *testing.M, clusterPrefix string) { - createCluster := flag.Bool("create-cluster", false, "Create a cluster for the tests, default is false and to use an existing cluster") - clusterType := flag.String("cluster-type", KindClusterStr, "The type of cluster to create for the tests, default is kind") - numClusters := flag.Int("num-clusters", 1, "The number of clusters to create for the tests, default is 1") - flag.Parse() - - if *createCluster { - makeCluster(clusterPrefix, TestClusterList, *clusterType, *numClusters) +// Ensure that a cluster is available for testing. +// +// If `~/.kube/config` already exists, as is often the case with local +// development, it will be used as the test cluster config. This can speed up +// local development, but you should still periodically reset your cluster to +// avoid cross-test contamination. The `KUBECONFIG` environment variable is +// also respected and can point at an existing path. +// +// If `~/.kube/config` doesn't exist a new KinD cluster will be created. It +// will not be torn down. +// +// TODO: A GKE cluster will be created in the case where we detect we're +// running in a CI release workflow. +var Ensure = sync.OnceValues(func() (func(), error) { + kubeconfig := "~/.kube/config" + if env := os.Getenv("KUBECONFIG"); env != "" { + kubeconfig = env } - exitCode := m.Run() - - // Always attempt to tear down all the clusters after the tests have run. - var wg sync.WaitGroup - for _, cluster := range TestClusterList.clusters { - cluster := cluster - wg.Add(1) - go func() { - defer wg.Done() - if err := cluster.Delete(); err != nil { - fmt.Println("Unable to delete cluster: ", err) - exitCode = 1 - } - }() + abs, _ := homedir.Expand(kubeconfig) + if cfg, err := clientcmd.LoadFromFile(abs); err == nil && len(cfg.Clusters) > 0 { + log.Printf("Using %q for the test cluster", kubeconfig) + return nil, nil } - wg.Wait() - - os.Exit(exitCode) -} - -func makeCluster(clusterPrefix string, testClusters *TestClusters, clusterType string, numClusters int) { - // Make the slice with the number of clusters to create so we do not need a mutex to handle write access to the slice. - testClusters.clusters = make([]Cluster, numClusters) - - var wg sync.WaitGroup - for i := 0; i < numClusters; i++ { - wg.Add(1) - i := i - go func() { - defer wg.Done() - var err error - var cluster Cluster - switch clusterType { - case KindClusterStr: - cluster, err = NewKindCluster(clusterPrefix) - if err != nil { - fmt.Println("Unable to create Kind cluster: ", err) - os.Exit(1) - } - case GKECluster: - fmt.Println("STILL TODO") - os.Exit(1) - default: - fmt.Println("Unrecognized cluster type", clusterType) - os.Exit(1) - } - - testClusters.clusters[i] = cluster - }() - } - wg.Wait() -} - -type TestClusters struct { - clusters []Cluster - picked int -} - -// pickCluster picks a cluster to use in sequence (ie. round robbin) from the list of clusters created in TestMain. -// This ensures that we don't an uneven number of tests to run on each cluster. -func (t *TestClusters) PickCluster() Cluster { - t.picked++ - return t.clusters[t.picked%len(t.clusters)] -} - -// WrapProviderTestOptions is a convenience function that wraps the provider test options with the kubeconfig of the cluster to use. -// The cluster's kubeconfig is also returned for test cases that manually shell out to kubectl for validation purposes. This kubeconfig is -// required for the kubectl command to target the right cluster that the test is running on. -func (t *TestClusters) WrapProviderTestOptions(opts integration.ProgramTestOptions) (integration.ProgramTestOptions, string) { - if t.clusters == nil { - // Check if KUBECONFIG is set, if it is then use that for the tests. - kcfg := os.Getenv("KUBECONFIG") - if kcfg == "" { - kcfg = os.ExpandEnv("$HOME/.kube/config") - } - return opts, kcfg + if os.Getenv("GITHUB_EVENT_NAME") == "push" { + return nil, errors.New("GKE not implemented yet") } - cluster := t.PickCluster() - - return opts.With(integration.ProgramTestOptions{ - Env: []string{"KUBECONFIG=" + cluster.KubeconfigPath()}, - }), cluster.KubeconfigPath() -} + _, err := NewKindCluster("pulumi-kubernetes") + return nil, err +}) diff --git a/tests/clusters/kind.go b/tests/clusters/kind.go index e13fa09fdf..154dfedad2 100644 --- a/tests/clusters/kind.go +++ b/tests/clusters/kind.go @@ -1,44 +1,37 @@ package clusters import ( - "fmt" "log" - "os" - "path/filepath" "time" "sigs.k8s.io/kind/pkg/cluster" ) -// KindVersion is a specific Kind version associated with a Kubernetes minor version. -type KindVersion string +// kindVersion is a specific Kind version associated with a Kubernetes minor version. +type kindVersion string const ( // Kind versions and their associated image tags. - Kind1_29 KindVersion = "kindest/node:v1.29.2" - Kind1_28 KindVersion = "kindest/node:v1.28.7" - Kind1_27 KindVersion = "kindest/node:v1.27.11" - - KubeconfigFilename = "KUBECONFIG" - - // maxCreateTries is the maximum number of times to try to create a Kind cluster. - maxCreateTries = 5 + _kind1_32 kindVersion = "kindest/node:v1.32.0" + _kind1_31 kindVersion = "kindest/node:v1.31.4" + _kind1_30 kindVersion = "kindest/node:v1.30.8" + _kind1_29 kindVersion = "kindest/node:v1.29.2" + _kind1_28 kindVersion = "kindest/node:v1.28.7" + _kind1_27 kindVersion = "kindest/node:v1.27.11" + + // _maxCreateTries is the maximum number of times to try to create a Kind cluster. + _maxCreateTries = 5 ) type KindCluster struct { - name string - kubeconfigPath string - teardownFn func() error + name string + teardownFn func() error } func (c KindCluster) Name() string { return c.name } -func (c KindCluster) KubeconfigPath() string { - return c.kubeconfigPath -} - func (c KindCluster) Connect() error { return nil } @@ -49,51 +42,37 @@ func (c KindCluster) Delete() error { // newKindCluster creates a new Kind cluster for use in testing with the specified name. The version // parameter is variadic and defaults to the latest version of Kind if not provided. -func NewKindCluster(name string, version ...KindVersion) (Cluster, error) { - v := Kind1_29 +func NewKindCluster(name string, version ...kindVersion) (Cluster, error) { + v := _kind1_32 if len(version) > 0 { v = version[0] } - // Create a new tmpdir to store the kubeconfig. - log.Printf("Creating new Kind cluster with image %q", v) - tmpDir, err := os.MkdirTemp("", "pulumi-test-kind") - if err != nil { - return nil, err - } - - KubeconfigPath := filepath.Join(tmpDir, KubeconfigFilename) - p := cluster.NewProvider() name = normalizeName(name + "-" + randString()) log.Printf("Creating Kind cluster %q", name) - teardownFn, err := createKindCluster(p, name, tmpDir, KubeconfigPath, v) + teardownFn, err := createKindCluster(p, name, v) if err != nil { return nil, err } - return &KindCluster{name: name, kubeconfigPath: KubeconfigPath, teardownFn: teardownFn}, nil + return &KindCluster{name: name, teardownFn: teardownFn}, nil } // createKindCluster attempts to create a KinD cluster with retry. -func createKindCluster(p *cluster.Provider, name, tmpDir, kcfgPath string, version KindVersion) (func() error, error) { +func createKindCluster(p *cluster.Provider, name string, version kindVersion) (func() error, error) { var err error - for i := 0; i < maxCreateTries; i++ { + for i := 0; i < _maxCreateTries; i++ { log.Printf("Creating Kind cluster, attempt: %d", i+1) err = p.Create(name, - cluster.CreateWithKubeconfigPath(kcfgPath), cluster.CreateWithNodeImage(string(version)), cluster.CreateWithWaitForReady(20*time.Second), ) if err == nil { return func() error { - if err := deleteKindCluster(p, name, kcfgPath); err != nil { - return fmt.Errorf("unable to delete Kind cluster %q: %v", name, err) - } - - return os.RemoveAll(tmpDir) + return p.Delete(name, "") }, nil } } @@ -101,8 +80,3 @@ func createKindCluster(p *cluster.Provider, name, tmpDir, kcfgPath string, versi // We failed to create the cluster maxCreateTries times, so return failure error. return nil, err } - -// deleteKindCluster deletes a specified kind cluster. -func deleteKindCluster(p *cluster.Provider, name, kcfgPath string) error { - return p.Delete(name, kcfgPath) -} diff --git a/tests/go.mod b/tests/go.mod index ac7b1b3de4..659e152615 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -10,6 +10,7 @@ replace ( ) require ( + github.com/mitchellh/go-homedir v1.1.0 github.com/onsi/gomega v1.35.1 github.com/pkg/errors v0.9.1 github.com/pulumi/providertest v0.0.12 @@ -187,7 +188,6 @@ require ( github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-ps v1.0.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect diff --git a/tests/sdk/dotnet/main_test.go b/tests/sdk/dotnet/main_test.go new file mode 100644 index 0000000000..ae241dfa5d --- /dev/null +++ b/tests/sdk/dotnet/main_test.go @@ -0,0 +1,38 @@ +// Copyright 2024, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + "log" + "os" + "testing" + + "github.com/pulumi/pulumi-kubernetes/tests/v4/clusters" +) + +func TestMain(m *testing.M) { + teardown, err := clusters.Ensure() + if err != nil { + log.Fatal("ensuring cluster: " + err.Error()) + } + + code := m.Run() + + if teardown != nil { + teardown() + } + + os.Exit(code) +} diff --git a/tests/sdk/go/main_test.go b/tests/sdk/go/main_test.go new file mode 100644 index 0000000000..ae241dfa5d --- /dev/null +++ b/tests/sdk/go/main_test.go @@ -0,0 +1,38 @@ +// Copyright 2024, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + "log" + "os" + "testing" + + "github.com/pulumi/pulumi-kubernetes/tests/v4/clusters" +) + +func TestMain(m *testing.M) { + teardown, err := clusters.Ensure() + if err != nil { + log.Fatal("ensuring cluster: " + err.Error()) + } + + code := m.Run() + + if teardown != nil { + teardown() + } + + os.Exit(code) +} diff --git a/tests/sdk/java/main_test.go b/tests/sdk/java/main_test.go new file mode 100644 index 0000000000..ae241dfa5d --- /dev/null +++ b/tests/sdk/java/main_test.go @@ -0,0 +1,38 @@ +// Copyright 2024, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + "log" + "os" + "testing" + + "github.com/pulumi/pulumi-kubernetes/tests/v4/clusters" +) + +func TestMain(m *testing.M) { + teardown, err := clusters.Ensure() + if err != nil { + log.Fatal("ensuring cluster: " + err.Error()) + } + + code := m.Run() + + if teardown != nil { + teardown() + } + + os.Exit(code) +} diff --git a/tests/sdk/nodejs/main_test.go b/tests/sdk/nodejs/main_test.go new file mode 100644 index 0000000000..ae241dfa5d --- /dev/null +++ b/tests/sdk/nodejs/main_test.go @@ -0,0 +1,38 @@ +// Copyright 2024, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + "log" + "os" + "testing" + + "github.com/pulumi/pulumi-kubernetes/tests/v4/clusters" +) + +func TestMain(m *testing.M) { + teardown, err := clusters.Ensure() + if err != nil { + log.Fatal("ensuring cluster: " + err.Error()) + } + + code := m.Run() + + if teardown != nil { + teardown() + } + + os.Exit(code) +} diff --git a/tests/sdk/python/main_test.go b/tests/sdk/python/main_test.go new file mode 100644 index 0000000000..9115a46736 --- /dev/null +++ b/tests/sdk/python/main_test.go @@ -0,0 +1,38 @@ +// Copyright 2024, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package python + +import ( + "log" + "os" + "testing" + + "github.com/pulumi/pulumi-kubernetes/tests/v4/clusters" +) + +func TestMain(m *testing.M) { + teardown, err := clusters.Ensure() + if err != nil { + log.Fatal("ensuring cluster: " + err.Error()) + } + + code := m.Run() + + if teardown != nil { + teardown() + } + + os.Exit(code) +} From 4717b2b2c91abe63001071c2377c28417435ddc6 Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Thu, 19 Dec 2024 15:55:55 -0800 Subject: [PATCH 4/9] lint --- tests/clusters/cluster.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/clusters/cluster.go b/tests/clusters/cluster.go index c150d6cec8..e6cf255bf2 100644 --- a/tests/clusters/cluster.go +++ b/tests/clusters/cluster.go @@ -41,9 +41,8 @@ func normalizeName(name string) string { // randString returns a random string of length 6. func randString() string { - c := 10 - b := make([]byte, c) - rand.Read(b) + buf := make([]byte, 10) + _, _ = rand.Read(buf) length := 6 - return strings.ToLower(base32.StdEncoding.EncodeToString(b)[:length]) + return strings.ToLower(base32.StdEncoding.EncodeToString(buf)[:length]) } From b9f83a5303f9947f181238ceba32962b21bff7d0 Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Fri, 20 Dec 2024 10:45:41 -0800 Subject: [PATCH 5/9] handle the weird sdk/nodejs/examples/ directory --- tests/sdk/nodejs/examples/main_test.go | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/sdk/nodejs/examples/main_test.go diff --git a/tests/sdk/nodejs/examples/main_test.go b/tests/sdk/nodejs/examples/main_test.go new file mode 100644 index 0000000000..ae241dfa5d --- /dev/null +++ b/tests/sdk/nodejs/examples/main_test.go @@ -0,0 +1,38 @@ +// Copyright 2024, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + "log" + "os" + "testing" + + "github.com/pulumi/pulumi-kubernetes/tests/v4/clusters" +) + +func TestMain(m *testing.M) { + teardown, err := clusters.Ensure() + if err != nil { + log.Fatal("ensuring cluster: " + err.Error()) + } + + code := m.Run() + + if teardown != nil { + teardown() + } + + os.Exit(code) +} From 088092ca37b49e777fcc4a8d22b60f28f147e3ea Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Fri, 20 Dec 2024 12:22:48 -0800 Subject: [PATCH 6/9] fix package name --- tests/sdk/nodejs/examples/main_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sdk/nodejs/examples/main_test.go b/tests/sdk/nodejs/examples/main_test.go index ae241dfa5d..f1bf37d1b2 100644 --- a/tests/sdk/nodejs/examples/main_test.go +++ b/tests/sdk/nodejs/examples/main_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package test +package examples import ( "log" From 2cbc5b8ea27e156d660e16b88390705ae5223d6a Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Fri, 20 Dec 2024 13:43:38 -0800 Subject: [PATCH 7/9] Replace GKE stack with code --- scripts/ci-cluster-create.sh | 14 -- scripts/ci-cluster-destroy.sh | 12 -- scripts/go.sum | 233 --------------------------- tests/ci-cluster/Pulumi.yaml | 3 - tests/ci-cluster/config.ts | 28 ---- tests/ci-cluster/gke.ts | 95 ----------- tests/ci-cluster/index.ts | 20 --- tests/ci-cluster/package.json | 11 -- tests/ci-cluster/tsconfig.json | 26 --- tests/clusters/cluster.go | 1 - tests/clusters/create.go | 33 ++-- tests/clusters/gke-stack/Pulumi.yaml | 3 - tests/clusters/gke-stack/config.ts | 28 ---- tests/clusters/gke-stack/gke.ts | 95 ----------- tests/clusters/gke-stack/index.ts | 20 --- tests/clusters/gke.go | 231 +++++++++++++++++++++++--- tests/clusters/kind.go | 5 - tests/go.mod | 4 +- tests/go.sum | 4 + 19 files changed, 233 insertions(+), 633 deletions(-) delete mode 100755 scripts/ci-cluster-create.sh delete mode 100755 scripts/ci-cluster-destroy.sh delete mode 100644 scripts/go.sum delete mode 100644 tests/ci-cluster/Pulumi.yaml delete mode 100644 tests/ci-cluster/config.ts delete mode 100644 tests/ci-cluster/gke.ts delete mode 100644 tests/ci-cluster/index.ts delete mode 100644 tests/ci-cluster/package.json delete mode 100644 tests/ci-cluster/tsconfig.json delete mode 100644 tests/clusters/gke-stack/Pulumi.yaml delete mode 100644 tests/clusters/gke-stack/config.ts delete mode 100644 tests/clusters/gke-stack/gke.ts delete mode 100644 tests/clusters/gke-stack/index.ts diff --git a/scripts/ci-cluster-create.sh b/scripts/ci-cluster-create.sh deleted file mode 100755 index e9cef42f0b..0000000000 --- a/scripts/ci-cluster-create.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -o nounset -o errexit -o pipefail - -echo Creating ephemeral Kubernetes cluster for CI testing... - -pushd tests/ci-cluster -yarn install -pulumi stack init "${1}" -pulumi up --skip-preview --yes --suppress-outputs - -mkdir -p "$HOME/.kube/" -pulumi stack output --show-secrets kubeconfig >~/.kube/config - -popd diff --git a/scripts/ci-cluster-destroy.sh b/scripts/ci-cluster-destroy.sh deleted file mode 100755 index 242107c94e..0000000000 --- a/scripts/ci-cluster-destroy.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -set -o nounset -o errexit -o pipefail - -echo Deleting ephemeral Kubernetes cluster... - -pushd tests/ci-cluster -yarn install -pulumi stack select "${1}" && \ - pulumi destroy --skip-preview --yes && \ - pulumi stack rm --yes - -popd diff --git a/scripts/go.sum b/scripts/go.sum deleted file mode 100644 index 878f409292..0000000000 --- a/scripts/go.sum +++ /dev/null @@ -1,233 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cheggaaa/pb v1.0.18/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/djherbis/times v1.2.0/go.mod h1:CGMZlo255K5r4Yw0b9RRfFQpM2y7uOmxg4jm9HsaVf8= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/pulumi/pulumi/sdk/v2 v2.0.0 h1:3VMXbEo3bqeaU+YDt8ufVBLD0WhLYE3tG3t/nIZ3Iac= -github.com/pulumi/pulumi/sdk/v2 v2.0.0/go.mod h1:W7k1UDYerc5o97mHnlHHp5iQZKEby+oQrQefWt+2RF4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= -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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/texttheater/golang-levenshtein v0.0.0-20191208221605-eb6844b05fc6/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200317142112-1b76d66859c6/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -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= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/tests/ci-cluster/Pulumi.yaml b/tests/ci-cluster/Pulumi.yaml deleted file mode 100644 index c3d25308a5..0000000000 --- a/tests/ci-cluster/Pulumi.yaml +++ /dev/null @@ -1,3 +0,0 @@ -name: k8s-ci-cluster -description: GKE cluster for pulumi-kubernetes CI -runtime: nodejs diff --git a/tests/ci-cluster/config.ts b/tests/ci-cluster/config.ts deleted file mode 100644 index 3a300727a5..0000000000 --- a/tests/ci-cluster/config.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016-2019, Pulumi Corporation. -// -// 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. - -import { Config } from "@pulumi/pulumi"; - -const config = new Config(); - -export const gcpProject = "pulumi-k8s-provider"; -export const gcpZone = "a"; -export const gcpLocation = "us-west1-a"; - -// nodeCount is the number of cluster nodes to provision. Defaults to 3 if unspecified. -export const nodeCount = config.getNumber("nodeCount") || 3; - -// nodeMachineType is the machine type to use for cluster nodes. Defaults to n1-standard-2 if unspecified. -// See https://cloud.google.com/compute/docs/machine-types for more details on available machine types. -export const nodeMachineType = config.get("nodeMachineType") || "n1-standard-2"; diff --git a/tests/ci-cluster/gke.ts b/tests/ci-cluster/gke.ts deleted file mode 100644 index f68b45494b..0000000000 --- a/tests/ci-cluster/gke.ts +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2016-2022, Pulumi Corporation. -// -// 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. - -import * as gcp from "@pulumi/gcp"; -import * as k8s from "@pulumi/kubernetes"; -import * as pulumi from "@pulumi/pulumi"; -import * as config from "./config"; - -export class GkeCluster extends pulumi.ComponentResource { - public cluster: gcp.container.Cluster; - public kubeconfig: pulumi.Output; - public provider: k8s.Provider; - - constructor(name: string, - opts: pulumi.ComponentResourceOptions = {}) { - super("pulumi-kubernetes:ci:GkeCluster", name, {}, opts); - - // Use the latest 1.28.x engine version. - const engineVersion = "1.28"; - - // Create the GKE cluster. - const k8sCluster = new gcp.container.Cluster("ephemeral-ci-cluster", { - initialNodeCount: config.nodeCount, - nodeVersion: engineVersion, - minMasterVersion: engineVersion, - nodeConfig: { - machineType: config.nodeMachineType, - oauthScopes: [ - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/devstorage.read_only", - "https://www.googleapis.com/auth/logging.write", - "https://www.googleapis.com/auth/monitoring" - ], - }, - project: config.gcpProject, - location: config.gcpLocation, - // Enable network policy addon to test network policy resources. - addonsConfig: { - networkPolicyConfig: { - disabled: false, - }, - }, - networkPolicy: { - enabled: true, - provider: "CALICO", - }, - }, {parent: this}); - this.cluster = k8sCluster; - - // Manufacture a GKE-style Kubeconfig. Note that this is slightly "different" because of the way GKE requires - // gcloud to be in the picture for cluster authentication (rather than using the client cert/key directly). - this.kubeconfig = pulumi.all([k8sCluster.name, k8sCluster.endpoint, k8sCluster.masterAuth]).apply( - ([name, endpoint, auth]) => { - const context = `${config.gcpProject}_${config.gcpZone}_${name}`; - return `apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: ${auth.clusterCaCertificate} - server: https://${endpoint} - name: ${context} -contexts: -- context: - cluster: ${context} - user: ${context} - name: ${context} -current-context: ${context} -kind: Config -preferences: {} -users: -- name: ${context} - user: - exec: - apiVersion: client.authentication.k8s.io/v1beta1 - command: gke-gcloud-auth-plugin - installHint: Install gke-gcloud-auth-plugin for use with kubectl by following - https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke - provideClusterInfo: true`; - }); - - // Export a Kubernetes provider instance that uses our cluster from above. - this.provider = new k8s.Provider("gke", {kubeconfig: this.kubeconfig}, {parent: this}); - } -} - diff --git a/tests/ci-cluster/index.ts b/tests/ci-cluster/index.ts deleted file mode 100644 index 859ce113d9..0000000000 --- a/tests/ci-cluster/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016-2019, Pulumi Corporation. -// -// 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. - -import * as gke from "./gke"; - -// Create Kubernetes clusters. -const gkeCluster = new gke.GkeCluster("ci-cluster"); -export const k8sProvider = gkeCluster.provider; -export const kubeconfig = gkeCluster.kubeconfig; diff --git a/tests/ci-cluster/package.json b/tests/ci-cluster/package.json deleted file mode 100644 index 2741fa204c..0000000000 --- a/tests/ci-cluster/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "kubernetes-ci-cluster", - "devDependencies": { - "@types/node": "latest" - }, - "dependencies": { - "@pulumi/gcp": "^5.4.0", - "@pulumi/kubernetes": "^3.2.0", - "@pulumi/pulumi": "^3.2.1" - } -} diff --git a/tests/ci-cluster/tsconfig.json b/tests/ci-cluster/tsconfig.json deleted file mode 100644 index e9f2c3a1e6..0000000000 --- a/tests/ci-cluster/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "outDir": "bin", - "target": "es6", - "lib": [ - "es6" - ], - "module": "commonjs", - "moduleResolution": "node", - "declaration": true, - "sourceMap": true, - "stripInternal": true, - "experimentalDecorators": true, - "pretty": true, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitReturns": true, - "forceConsistentCasingInFileNames": true, - "strictNullChecks": true - }, - "files": [ - "config.ts", - "index.ts", - "gke.ts" - ] -} diff --git a/tests/clusters/cluster.go b/tests/clusters/cluster.go index e6cf255bf2..efe57ee395 100644 --- a/tests/clusters/cluster.go +++ b/tests/clusters/cluster.go @@ -9,7 +9,6 @@ import ( // Cluster is an interface to interact with a Kubernetes cluster in a test. type Cluster interface { Name() string - Connect() error Delete() error } diff --git a/tests/clusters/create.go b/tests/clusters/create.go index 939b588420..46a0831f2b 100644 --- a/tests/clusters/create.go +++ b/tests/clusters/create.go @@ -1,8 +1,6 @@ package clusters import ( - "errors" - "log" "os" "sync" @@ -11,8 +9,8 @@ import ( ) const ( - KindClusterStr = "kind" - GKECluster = "gke" + _kindClusterStr = "kind" + _gkeCluster = "gke" ) // Ensure that a cluster is available for testing. @@ -35,15 +33,24 @@ var Ensure = sync.OnceValues(func() (func(), error) { } abs, _ := homedir.Expand(kubeconfig) - if cfg, err := clientcmd.LoadFromFile(abs); err == nil && len(cfg.Clusters) > 0 { - log.Printf("Using %q for the test cluster", kubeconfig) - return nil, nil - } + cfg, err := clientcmd.LoadFromFile(abs) - if os.Getenv("GITHUB_EVENT_NAME") == "push" { - return nil, errors.New("GKE not implemented yet") - } + // TODO: Temporarily forcing GKE for testing. + cluster, err := NewGKECluster("pulumi-kubernetes", *cfg) + return func() { _ = cluster.Delete() }, err + + /* + if err == nil && len(cfg.Clusters) > 0 { + log.Printf("Using %q for the test cluster", kubeconfig) + return nil, nil + } + + if os.Getenv("GITHUB_EVENT_NAME") == "push" { + cluster, err := NewGKECluster("pulumi-kubernetes", *cfg) + return func() { _ = cluster.Delete() }, err + } - _, err := NewKindCluster("pulumi-kubernetes") - return nil, err + _, err = NewKindCluster("pulumi-kubernetes") + return nil, err + */ }) diff --git a/tests/clusters/gke-stack/Pulumi.yaml b/tests/clusters/gke-stack/Pulumi.yaml deleted file mode 100644 index cb3833bc64..0000000000 --- a/tests/clusters/gke-stack/Pulumi.yaml +++ /dev/null @@ -1,3 +0,0 @@ -name: k8s-test-cluster -description: GKE cluster for pulumi-kubernetes testing -runtime: nodejs diff --git a/tests/clusters/gke-stack/config.ts b/tests/clusters/gke-stack/config.ts deleted file mode 100644 index 3a300727a5..0000000000 --- a/tests/clusters/gke-stack/config.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016-2019, Pulumi Corporation. -// -// 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. - -import { Config } from "@pulumi/pulumi"; - -const config = new Config(); - -export const gcpProject = "pulumi-k8s-provider"; -export const gcpZone = "a"; -export const gcpLocation = "us-west1-a"; - -// nodeCount is the number of cluster nodes to provision. Defaults to 3 if unspecified. -export const nodeCount = config.getNumber("nodeCount") || 3; - -// nodeMachineType is the machine type to use for cluster nodes. Defaults to n1-standard-2 if unspecified. -// See https://cloud.google.com/compute/docs/machine-types for more details on available machine types. -export const nodeMachineType = config.get("nodeMachineType") || "n1-standard-2"; diff --git a/tests/clusters/gke-stack/gke.ts b/tests/clusters/gke-stack/gke.ts deleted file mode 100644 index f68b45494b..0000000000 --- a/tests/clusters/gke-stack/gke.ts +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2016-2022, Pulumi Corporation. -// -// 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. - -import * as gcp from "@pulumi/gcp"; -import * as k8s from "@pulumi/kubernetes"; -import * as pulumi from "@pulumi/pulumi"; -import * as config from "./config"; - -export class GkeCluster extends pulumi.ComponentResource { - public cluster: gcp.container.Cluster; - public kubeconfig: pulumi.Output; - public provider: k8s.Provider; - - constructor(name: string, - opts: pulumi.ComponentResourceOptions = {}) { - super("pulumi-kubernetes:ci:GkeCluster", name, {}, opts); - - // Use the latest 1.28.x engine version. - const engineVersion = "1.28"; - - // Create the GKE cluster. - const k8sCluster = new gcp.container.Cluster("ephemeral-ci-cluster", { - initialNodeCount: config.nodeCount, - nodeVersion: engineVersion, - minMasterVersion: engineVersion, - nodeConfig: { - machineType: config.nodeMachineType, - oauthScopes: [ - "https://www.googleapis.com/auth/compute", - "https://www.googleapis.com/auth/devstorage.read_only", - "https://www.googleapis.com/auth/logging.write", - "https://www.googleapis.com/auth/monitoring" - ], - }, - project: config.gcpProject, - location: config.gcpLocation, - // Enable network policy addon to test network policy resources. - addonsConfig: { - networkPolicyConfig: { - disabled: false, - }, - }, - networkPolicy: { - enabled: true, - provider: "CALICO", - }, - }, {parent: this}); - this.cluster = k8sCluster; - - // Manufacture a GKE-style Kubeconfig. Note that this is slightly "different" because of the way GKE requires - // gcloud to be in the picture for cluster authentication (rather than using the client cert/key directly). - this.kubeconfig = pulumi.all([k8sCluster.name, k8sCluster.endpoint, k8sCluster.masterAuth]).apply( - ([name, endpoint, auth]) => { - const context = `${config.gcpProject}_${config.gcpZone}_${name}`; - return `apiVersion: v1 -clusters: -- cluster: - certificate-authority-data: ${auth.clusterCaCertificate} - server: https://${endpoint} - name: ${context} -contexts: -- context: - cluster: ${context} - user: ${context} - name: ${context} -current-context: ${context} -kind: Config -preferences: {} -users: -- name: ${context} - user: - exec: - apiVersion: client.authentication.k8s.io/v1beta1 - command: gke-gcloud-auth-plugin - installHint: Install gke-gcloud-auth-plugin for use with kubectl by following - https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke - provideClusterInfo: true`; - }); - - // Export a Kubernetes provider instance that uses our cluster from above. - this.provider = new k8s.Provider("gke", {kubeconfig: this.kubeconfig}, {parent: this}); - } -} - diff --git a/tests/clusters/gke-stack/index.ts b/tests/clusters/gke-stack/index.ts deleted file mode 100644 index 859ce113d9..0000000000 --- a/tests/clusters/gke-stack/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2016-2019, Pulumi Corporation. -// -// 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. - -import * as gke from "./gke"; - -// Create Kubernetes clusters. -const gkeCluster = new gke.GkeCluster("ci-cluster"); -export const k8sProvider = gkeCluster.provider; -export const kubeconfig = gkeCluster.kubeconfig; diff --git a/tests/clusters/gke.go b/tests/clusters/gke.go index 93a26d6d73..76544d652b 100644 --- a/tests/clusters/gke.go +++ b/tests/clusters/gke.go @@ -1,35 +1,216 @@ +// Copyright 2024, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package clusters -// import ( -// "context" -// "embed" -// "time" -// ) +import ( + "context" + "fmt" + "log" + "os" + "time" + + container "cloud.google.com/go/container/apiv1" + "cloud.google.com/go/container/apiv1/containerpb" + "github.com/sethvargo/go-githubactions" + "golang.org/x/oauth2" + "golang.org/x/oauth2/google" + "google.golang.org/api/impersonate" + "google.golang.org/api/option" + + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" +) + +type GKECluster struct { + name string + previousContext string + client *container.ClusterManagerClient + kubeconfig api.Config +} + +var _ Cluster = GKECluster{} + +func NewGKECluster(namePrefix string, kubeconfig api.Config) (Cluster, error) { + // It normally takes 7-10 minutes to create a cluster. + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Minute) + defer cancel() + + // Login to GCP. + + clusterName := namePrefix + randString() + projectID := "pulumi-k8s-provider" + location := "us-west1-a" + + serviceAccount := "pulumi-ci@pulumi-k8s-provider.iam.gserviceaccount.com" + audience := fmt.Sprintf("https://iam.googleapis.com/projects/%s/locations/global/workloadIdentityPools/pulumi-ci/pulumi-ci", 637339343727) // Project number? + + // Default to local credentials. + auth, err := google.DefaultTokenSource(ctx) + if err != nil { + return nil, fmt.Errorf("getting default token source: %w", err) + } + if os.Getenv("ACTIONS_ID_TOKEN_REQUEST_TOKEN") != "" { + // If we're running as a GitHub action, grab an ID token so we can use + // that as our token source. + token, err := githubactions.GetIDToken(ctx, audience) + if err != nil { + return nil, fmt.Errorf("getting ID token: %w", err) + } + auth = oauth2.StaticTokenSource(&oauth2.Token{ + AccessToken: token, + TokenType: "urn:ietf:params:oauth:token-type:jwt", + }) + } + + token, err := auth.Token() + if err != nil { + return nil, fmt.Errorf("getting token: %w", err) + } + + ts, err := impersonate.CredentialsTokenSource(ctx, + impersonate.CredentialsConfig{ + Scopes: []string{"https://www.googleapis.com/auth/cloud-platform"}, + TargetPrincipal: serviceAccount, + Subject: token.AccessToken, + }, + option.WithTokenSource(auth), + option.WithAudiences(audience), + ) + if err != nil { + return nil, fmt.Errorf("getting impersonate source: %w", err) + } + + // Create the GKE client + client, err := container.NewClusterManagerClient(ctx, option.WithTokenSource(ts)) + if err != nil { + log.Fatalf("creating GKE client: %v", err) + } + defer client.Close() + + // Define the cluster + cluster := &containerpb.Cluster{ + Name: clusterName, + InitialNodeCount: 1, + NodeConfig: &containerpb.NodeConfig{ + MachineType: "n1-standard-2", + }, + Location: location, + } + + // Create the cluster + createClusterReq := &containerpb.CreateClusterRequest{ + Parent: fmt.Sprintf("projects/%s/locations/%s", projectID, location), + Cluster: cluster, + } + + fmt.Println("creating GKE cluster...") + _, err = client.CreateCluster(ctx, createClusterReq) + if err != nil { + return nil, fmt.Errorf("creating GKE cluster: %w", err) + } + + fmt.Println("waiting for cluster to become ready..") + + for { + req := &containerpb.GetClusterRequest{ + Name: fmt.Sprintf("projects/%s/locations/%s/clusters/%s", projectID, location, clusterName), + } + + cluster, err = client.GetCluster(ctx, req) + if err != nil { + return nil, fmt.Errorf("failed to get cluster details: %w", err) + } + + fmt.Println("cluster is", cluster.Status.String()) + + if cluster.Status == containerpb.Cluster_RUNNING { + break + } + + select { + case <-time.After(10 * time.Second): + continue + case <-ctx.Done(): + return nil, ctx.Err() + } + } + + // Add the cluster to kubeconfig. + + token, err = ts.Token() + if err != nil { + return nil, fmt.Errorf("getting token for kubeconfig: %w", err) + } + + if kubeconfig.Clusters == nil { + kubeconfig.Clusters = map[string]*api.Cluster{} + } + kubeconfig.Clusters[clusterName] = &api.Cluster{ + Server: fmt.Sprintf("https://%s", cluster.Endpoint), + CertificateAuthorityData: []byte(cluster.MasterAuth.ClusterCaCertificate), + } + if kubeconfig.Contexts == nil { + kubeconfig.Contexts = map[string]*api.Context{} + } + kubeconfig.Contexts[clusterName] = &api.Context{ + Cluster: clusterName, + AuthInfo: clusterName, + } + if kubeconfig.AuthInfos == nil { + kubeconfig.AuthInfos = map[string]*api.AuthInfo{} + } + kubeconfig.AuthInfos[clusterName] = &api.AuthInfo{ + Token: token.AccessToken, // Probably won't work... + /* + Exec: &api.ExecConfig{ + Command: "gke-gcloud-auth-plugin", // Not installed... + }, + */ + } -// //go:embed gke-stack/* -// var pulumiProgram embed.FS + previousContext := kubeconfig.CurrentContext + kubeconfig.CurrentContext = clusterName -// type GKE struct { -// } + if err := clientcmd.WriteToFile(kubeconfig, "~/.kube/config"); err != nil { + return nil, fmt.Errorf("writing kubeconfig: %w", err) + } -// func NewGKECluster(stackName string) (Cluster, error) { -// ctx := context.WithTimeout(context.Background(), 15*time.Minute) // It normally takes 7-10 minutes to create a cluster. + return GKECluster{name: clusterName, previousContext: previousContext, client: client}, nil +} -// return GKE{}, nil -// } +func (c GKECluster) Name() string { + return c.name +} -// func (c GKE) Name() string { -// return "gke-cluster" -// } +func (c GKECluster) Delete() error { + _, err := c.client.DeleteCluster(context.Background(), &containerpb.DeleteClusterRequest{ + Name: c.name, + }) + if err != nil { + return fmt.Errorf("deleting cluster: %w", err) + } -// func (c GKE) Connect() error { -// return nil -// } + // Remove the cluster's information and restore previous context. + c.kubeconfig.CurrentContext = c.previousContext + delete(c.kubeconfig.Clusters, c.name) + delete(c.kubeconfig.AuthInfos, c.name) + delete(c.kubeconfig.Contexts, c.name) -// func (c GKE) Delete() error { -// return nil -// } + if err := clientcmd.WriteToFile(c.kubeconfig, "~/.kube/config"); err != nil { + return fmt.Errorf("writing kubeconfig: %w", err) + } -// func (c GKE) KubeconfigPath() string { -// return "" -// } + return nil +} diff --git a/tests/clusters/kind.go b/tests/clusters/kind.go index 154dfedad2..fa8c7d8181 100644 --- a/tests/clusters/kind.go +++ b/tests/clusters/kind.go @@ -32,10 +32,6 @@ func (c KindCluster) Name() string { return c.name } -func (c KindCluster) Connect() error { - return nil -} - func (c KindCluster) Delete() error { return c.teardownFn() } @@ -58,7 +54,6 @@ func NewKindCluster(name string, version ...kindVersion) (Cluster, error) { } return &KindCluster{name: name, teardownFn: teardownFn}, nil - } // createKindCluster attempts to create a KinD cluster with retry. diff --git a/tests/go.mod b/tests/go.mod index 659e152615..c661d64c16 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -10,6 +10,7 @@ replace ( ) require ( + cloud.google.com/go/container v1.33.0 github.com/mitchellh/go-homedir v1.1.0 github.com/onsi/gomega v1.35.1 github.com/pkg/errors v0.9.1 @@ -21,6 +22,7 @@ require ( github.com/pulumiverse/pulumi-time/sdk v0.0.0-20231010123146-089d7304da13 github.com/stretchr/testify v1.10.0 golang.org/x/exp v0.0.0-20241210194714-1829a127f884 + google.golang.org/api v0.169.0 google.golang.org/protobuf v1.35.2 helm.sh/helm/v3 v3.15.4 k8s.io/apimachinery v0.32.0 @@ -235,6 +237,7 @@ require ( github.com/segmentio/asm v1.1.3 // indirect github.com/segmentio/encoding v0.3.5 // indirect github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/sethvargo/go-githubactions v1.3.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/skeema/knownhosts v1.2.2 // indirect @@ -276,7 +279,6 @@ require ( golang.org/x/time v0.8.0 // indirect golang.org/x/tools v0.28.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/api v0.169.0 // indirect google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 // indirect diff --git a/tests/go.sum b/tests/go.sum index ebf08b7244..810b18e5d5 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -5,6 +5,8 @@ cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/container v1.33.0 h1:GS4W16lmqkGP78w7XQ9VEkqayo8CSIXrZkcqbPINvCU= +cloud.google.com/go/container v1.33.0/go.mod h1:u5QBBv/V9dVNK/NtTppCf6T4P8gzp+dQSwx2DqPnAKc= cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= cloud.google.com/go/kms v1.15.7 h1:7caV9K3yIxvlQPAcaFffhlT7d1qpxjB1wHBtjWa13SM= @@ -663,6 +665,8 @@ github.com/segmentio/encoding v0.3.5 h1:UZEiaZ55nlXGDL92scoVuw00RmiRCazIEmvPSbSv github.com/segmentio/encoding v0.3.5/go.mod h1:n0JeuIqEQrQoPDGsjo8UNd1iA0U8d8+oHAA4E3G3OxM= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/sethvargo/go-githubactions v1.3.0 h1:Kg633LIUV2IrJsqy2MfveiED/Ouo+H2P0itWS0eLh8A= +github.com/sethvargo/go-githubactions v1.3.0/go.mod h1:7/4WeHgYfSz9U5vwuToCK9KPnELVHAhGtRwLREOQV80= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= From f87c825c57eedc9f24728e2c5e7388de58974080 Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Fri, 20 Dec 2024 14:04:31 -0800 Subject: [PATCH 8/9] handle missing config --- .github/workflows/run-acceptance-tests.yml | 12 ---------- tests/clusters/create.go | 26 +++++++++++++++++++--- tests/clusters/gke.go | 9 -------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/.github/workflows/run-acceptance-tests.yml b/.github/workflows/run-acceptance-tests.yml index ce885afe56..19519f997d 100644 --- a/.github/workflows/run-acceptance-tests.yml +++ b/.github/workflows/run-acceptance-tests.yml @@ -363,18 +363,6 @@ jobs: role-duration-seconds: 3600 role-session-name: ${{ env.PROVIDER }}@githubActions role-to-assume: ${{ secrets.AWS_CI_ROLE_ARN }} - - name: Authenticate to Google Cloud - uses: google-github-actions/auth@6fc4af4b145ae7821d527454aa9bd537d1f2dc5f # v2.1.7 - with: - workload_identity_provider: projects/${{ env.GOOGLE_PROJECT_NUMBER - }}/locations/global/workloadIdentityPools/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_POOL }}/providers/${{ - env.GOOGLE_CI_WORKLOAD_IDENTITY_PROVIDER }} - service_account: ${{ env.GOOGLE_CI_SERVICE_ACCOUNT_EMAIL }} - - name: Setup gcloud auth - uses: google-github-actions/setup-gcloud@6189d56e4096ee891640bb02ac264be376592d6a # v2.1.2 - with: - install_components: gke-gcloud-auth-plugin - name: Install Kubectl run: > curl -LO diff --git a/tests/clusters/create.go b/tests/clusters/create.go index 46a0831f2b..11fdc550e6 100644 --- a/tests/clusters/create.go +++ b/tests/clusters/create.go @@ -1,3 +1,17 @@ +// Copyright 2024, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package clusters import ( @@ -6,6 +20,7 @@ import ( "github.com/mitchellh/go-homedir" "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/clientcmd/api" ) const ( @@ -34,22 +49,27 @@ var Ensure = sync.OnceValues(func() (func(), error) { abs, _ := homedir.Expand(kubeconfig) cfg, err := clientcmd.LoadFromFile(abs) + if err != nil { + cfg = api.NewConfig() + } // TODO: Temporarily forcing GKE for testing. cluster, err := NewGKECluster("pulumi-kubernetes", *cfg) - return func() { _ = cluster.Delete() }, err + return func() { + if cluster != nil { + _ = cluster.Delete() + } + }, err /* if err == nil && len(cfg.Clusters) > 0 { log.Printf("Using %q for the test cluster", kubeconfig) return nil, nil } - if os.Getenv("GITHUB_EVENT_NAME") == "push" { cluster, err := NewGKECluster("pulumi-kubernetes", *cfg) return func() { _ = cluster.Delete() }, err } - _, err = NewKindCluster("pulumi-kubernetes") return nil, err */ diff --git a/tests/clusters/gke.go b/tests/clusters/gke.go index 76544d652b..d0dfa070a6 100644 --- a/tests/clusters/gke.go +++ b/tests/clusters/gke.go @@ -154,23 +154,14 @@ func NewGKECluster(namePrefix string, kubeconfig api.Config) (Cluster, error) { return nil, fmt.Errorf("getting token for kubeconfig: %w", err) } - if kubeconfig.Clusters == nil { - kubeconfig.Clusters = map[string]*api.Cluster{} - } kubeconfig.Clusters[clusterName] = &api.Cluster{ Server: fmt.Sprintf("https://%s", cluster.Endpoint), CertificateAuthorityData: []byte(cluster.MasterAuth.ClusterCaCertificate), } - if kubeconfig.Contexts == nil { - kubeconfig.Contexts = map[string]*api.Context{} - } kubeconfig.Contexts[clusterName] = &api.Context{ Cluster: clusterName, AuthInfo: clusterName, } - if kubeconfig.AuthInfos == nil { - kubeconfig.AuthInfos = map[string]*api.AuthInfo{} - } kubeconfig.AuthInfos[clusterName] = &api.AuthInfo{ Token: token.AccessToken, // Probably won't work... /* From e565a4676a4dc324be77a9b1ab56fdf613675586 Mon Sep 17 00:00:00 2001 From: Bryce Lampe Date: Fri, 20 Dec 2024 14:17:55 -0800 Subject: [PATCH 9/9] don't require default token --- tests/clusters/gke.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/clusters/gke.go b/tests/clusters/gke.go index d0dfa070a6..ce348409d2 100644 --- a/tests/clusters/gke.go +++ b/tests/clusters/gke.go @@ -58,10 +58,7 @@ func NewGKECluster(namePrefix string, kubeconfig api.Config) (Cluster, error) { // Default to local credentials. auth, err := google.DefaultTokenSource(ctx) - if err != nil { - return nil, fmt.Errorf("getting default token source: %w", err) - } - if os.Getenv("ACTIONS_ID_TOKEN_REQUEST_TOKEN") != "" { + if err != nil && os.Getenv("ACTIONS_ID_TOKEN_REQUEST_TOKEN") != "" { // If we're running as a GitHub action, grab an ID token so we can use // that as our token source. token, err := githubactions.GetIDToken(ctx, audience)