From cea6204b37c161169bc9675501305b6f2bbb68a8 Mon Sep 17 00:00:00 2001 From: Adrian Stobbe Date: Wed, 8 Nov 2023 19:10:01 +0100 Subject: [PATCH] terraform: Terraform module for AWS (#2503) --- .../upload_terraform_module/action.yml | 24 +++ .github/workflows/e2e-test-tf-module.yml | 185 ++++++++++++++++++ .github/workflows/e2e-test-weekly.yml | 17 +- cli/internal/terraform/BUILD.bazel | 77 +------- cli/internal/terraform/loader.go | 12 +- dev-docs/workflows/release.md | 4 + internal/constants/constants.go | 2 +- terraform/BUILD.bazel | 84 ++++++++ terraform/assets.go | 16 ++ .../aws-constellation/.terraform.lock.hcl | 99 ++++++++++ terraform/aws-constellation/fetch-ami/main.tf | 28 +++ .../aws-constellation/fetch-ami/output.tf | 4 + .../aws-constellation/fetch-ami/variables.tf | 14 ++ terraform/aws-constellation/install-yq.sh | 43 ++++ terraform/aws-constellation/main.tf | 67 +++++++ terraform/aws-constellation/variables.tf | 71 +++++++ .../constellation-cluster/.terraform.lock.hcl | 25 +++ .../install-constellation.sh | 31 +++ terraform/constellation-cluster/main.tf | 109 +++++++++++ terraform/constellation-cluster/variables.tf | 86 ++++++++ .../infrastructure}/aws/.terraform.lock.hcl | 0 .../infrastructure}/aws/main.tf | 1 - .../aws/modules/instance_group/main.tf | 0 .../aws/modules/instance_group/variables.tf | 0 .../aws/modules/jump_host/main.tf | 0 .../aws/modules/jump_host/output.tf | 0 .../aws/modules/jump_host/variables.tf | 0 .../aws/modules/load_balancer_target/main.tf | 0 .../modules/load_balancer_target/output.tf | 0 .../modules/load_balancer_target/variables.tf | 0 .../aws/modules/public_private_subnet/main.tf | 0 .../modules/public_private_subnet/output.tf | 0 .../public_private_subnet/variables.tf | 0 .../infrastructure}/aws/outputs.tf | 0 .../infrastructure}/aws/variables.tf | 0 .../infrastructure}/azure/.terraform.lock.hcl | 0 .../infrastructure}/azure/main.tf | 0 .../azure/modules/jump_host/main.tf | 0 .../azure/modules/jump_host/outputs.tf | 0 .../azure/modules/jump_host/variables.tf | 0 .../modules/load_balancer_backend/main.tf | 0 .../modules/load_balancer_backend/outputs.tf | 0 .../load_balancer_backend/variables.tf | 0 .../azure/modules/scale_set/main.tf | 0 .../azure/modules/scale_set/variables.tf | 0 .../infrastructure}/azure/outputs.tf | 0 .../infrastructure}/azure/variables.tf | 0 .../infrastructure}/gcp/.terraform.lock.hcl | 0 .../infrastructure}/gcp/main.tf | 0 .../gcp/modules/instance_group/main.tf | 0 .../gcp/modules/instance_group/outputs.tf | 0 .../gcp/modules/instance_group/variables.tf | 0 .../modules/internal_load_balancer/main.tf | 0 .../internal_load_balancer/variables.tf | 0 .../gcp/modules/jump_host/main.tf | 0 .../gcp/modules/jump_host/outputs.tf | 0 .../gcp/modules/jump_host/variables.tf | 0 .../gcp/modules/loadbalancer/main.tf | 0 .../gcp/modules/loadbalancer/variables.tf | 0 .../infrastructure}/gcp/outputs.tf | 0 .../infrastructure}/gcp/variables.tf | 0 .../iam/aws/.terraform.lock.hcl | 0 .../infrastructure}/iam/aws/README.md | 0 .../infrastructure}/iam/aws/main.tf | 0 .../infrastructure}/iam/aws/outputs.tf | 0 .../infrastructure}/iam/aws/variables.tf | 0 .../iam/azure/.terraform.lock.hcl | 0 .../infrastructure}/iam/azure/README.md | 0 .../infrastructure}/iam/azure/main.tf | 0 .../infrastructure}/iam/azure/outputs.tf | 0 .../infrastructure}/iam/azure/variables.tf | 0 .../iam/gcp/.terraform.lock.hcl | 0 .../infrastructure}/iam/gcp/README.md | 0 .../infrastructure}/iam/gcp/main.tf | 0 .../infrastructure}/iam/gcp/outputs.tf | 0 .../infrastructure}/iam/gcp/variables.tf | 0 .../openstack/.terraform.lock.hcl | 0 .../infrastructure}/openstack/main.tf | 0 .../openstack/modules/instance_group/main.tf | 0 .../modules/instance_group/outputs.tf | 0 .../modules/instance_group/variables.tf | 0 .../openstack/modules/loadbalancer/main.tf | 0 .../modules/loadbalancer/variables.tf | 0 .../infrastructure}/openstack/outputs.tf | 0 .../infrastructure}/openstack/variables.tf | 0 .../infrastructure}/qemu/.terraform.lock.hcl | 0 .../infrastructure}/qemu/main.tf | 0 .../qemu/modules/instance_group/domain.xsl | 0 .../qemu/modules/instance_group/main.tf | 0 .../qemu/modules/instance_group/outputs.tf | 0 .../modules/instance_group/tdx_domain.xsl | 0 .../qemu/modules/instance_group/variables.tf | 0 .../infrastructure}/qemu/outputs.tf | 0 .../infrastructure}/qemu/variables.tf | 0 94 files changed, 912 insertions(+), 87 deletions(-) create mode 100644 .github/actions/upload_terraform_module/action.yml create mode 100644 .github/workflows/e2e-test-tf-module.yml create mode 100644 terraform/BUILD.bazel create mode 100644 terraform/assets.go create mode 100644 terraform/aws-constellation/.terraform.lock.hcl create mode 100644 terraform/aws-constellation/fetch-ami/main.tf create mode 100644 terraform/aws-constellation/fetch-ami/output.tf create mode 100644 terraform/aws-constellation/fetch-ami/variables.tf create mode 100755 terraform/aws-constellation/install-yq.sh create mode 100644 terraform/aws-constellation/main.tf create mode 100644 terraform/aws-constellation/variables.tf create mode 100644 terraform/constellation-cluster/.terraform.lock.hcl create mode 100755 terraform/constellation-cluster/install-constellation.sh create mode 100644 terraform/constellation-cluster/main.tf create mode 100644 terraform/constellation-cluster/variables.tf rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/.terraform.lock.hcl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/main.tf (99%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/instance_group/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/instance_group/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/jump_host/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/jump_host/output.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/jump_host/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/load_balancer_target/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/load_balancer_target/output.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/load_balancer_target/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/public_private_subnet/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/public_private_subnet/output.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/modules/public_private_subnet/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/aws/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/.terraform.lock.hcl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/modules/jump_host/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/modules/jump_host/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/modules/jump_host/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/modules/load_balancer_backend/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/modules/load_balancer_backend/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/modules/load_balancer_backend/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/modules/scale_set/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/modules/scale_set/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/azure/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/.terraform.lock.hcl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/instance_group/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/instance_group/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/instance_group/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/internal_load_balancer/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/internal_load_balancer/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/jump_host/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/jump_host/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/jump_host/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/loadbalancer/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/modules/loadbalancer/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/gcp/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/aws/.terraform.lock.hcl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/aws/README.md (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/aws/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/aws/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/aws/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/azure/.terraform.lock.hcl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/azure/README.md (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/azure/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/azure/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/azure/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/gcp/.terraform.lock.hcl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/gcp/README.md (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/gcp/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/gcp/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/iam/gcp/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/.terraform.lock.hcl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/modules/instance_group/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/modules/instance_group/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/modules/instance_group/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/modules/loadbalancer/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/modules/loadbalancer/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/openstack/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/.terraform.lock.hcl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/modules/instance_group/domain.xsl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/modules/instance_group/main.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/modules/instance_group/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/modules/instance_group/tdx_domain.xsl (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/modules/instance_group/variables.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/outputs.tf (100%) rename {cli/internal/terraform/terraform => terraform/infrastructure}/qemu/variables.tf (100%) diff --git a/.github/actions/upload_terraform_module/action.yml b/.github/actions/upload_terraform_module/action.yml new file mode 100644 index 000000000..53277f5c8 --- /dev/null +++ b/.github/actions/upload_terraform_module/action.yml @@ -0,0 +1,24 @@ +name: Upload Terraform module +description: "Upload the Terraform module as an artifact." +runs: + using: "composite" + steps: + - name: Copy Terraform module + shell: bash + run: | + cp -r terraform terraform-module + find terraform-module -name "*.go" -type f -delete + find terraform-module -name "*.bazel" -type f -delete + - name: Zip terraform dir + shell: bash + run: | + zip -r terraform-module.zip terraform-module + - name: Upload artifact + uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3 + with: + name: terraform-module + path: terraform-module.zip + - name: Cleanup Terraform module dir + shell: bash + run: | + rm -r terraform-module diff --git a/.github/workflows/e2e-test-tf-module.yml b/.github/workflows/e2e-test-tf-module.yml new file mode 100644 index 000000000..08067e1a0 --- /dev/null +++ b/.github/workflows/e2e-test-tf-module.yml @@ -0,0 +1,185 @@ +name: e2e test Terraform module + +on: + workflow_dispatch: + inputs: + ref: + type: string + description: "Git ref to checkout" + required: false + cloudProvider: + description: "Which cloud provider to use." + type: choice + options: + - "aws" + default: "aws" + required: true + regionZone: + description: "Region or zone to create the cluster in. Leave empty for default region/zone." + type: string + required: false + image: + description: "Node image version of the cluster." + type: string + required: true + cliVersion: + description: "Constellation CLI version to use. Empty value means build from source." + type: string + default: "" + required: false + workflow_call: + inputs: + ref: + type: string + description: "Git ref to checkout" + required: false + cloudProvider: + description: "Which cloud provider to use." + type: string + default: "aws" + regionZone: + description: "Which zone to use." + type: string + image: + description: "Node image reference which is compatible with the current dev release version." + type: string + required: true + cliVersion: + description: "Constellation CLI version to use. Empty value means build from source." + type: string + default: "" + required: false +jobs: + build: + runs-on: ubuntu-22.04 + permissions: + id-token: write + contents: read + packages: write + steps: + - name: Checkout + id: checkout + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + with: + ref: ${{ inputs.ref || github.head_ref }} + + - name: Upload module + uses: ./.github/actions/upload_terraform_module + + - name: Download Terraform module + uses: actions/download-artifact@v3 + with: + name: terraform-module + + - name: Unzip Terraform module + run: unzip terraform-module.zip + + - name: Create resource prefix + id: create-prefix + shell: bash + run: | + run_id=${{ github.run_id }} + last_three="${run_id: -3}" + echo "prefix=e2e-${last_three}-${{ github.run_attempt }}" | tee -a "$GITHUB_OUTPUT" + + - name: Create Terraform variable input file + if: inputs.cloudProvider == 'aws' + working-directory: ./terraform-module/aws-constellation + run: | + cat > terraform.tfvars <> /etc/hosts' + + - name: Login to AWS (IAM + Cluster role) + if: inputs.cloudProvider == 'aws' + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 # v2.2.0 + with: + role-to-assume: arn:aws:iam::795746500882:role/GithubActionsE2ETerraform + aws-region: eu-central-1 + # extend token expiry to 6 hours to ensure constellation can terminate + role-duration-seconds: 21600 + + - name: Apply Terraform Cluster + id: apply_terraform + working-directory: ./terraform-module/${{ inputs.cloudProvider }}-constellation + run: | + cp ../../constellation . + terraform init + terraform apply -var-file=terraform.tfvars -auto-approve + + - name: Destroy Terraform Cluster + # outcome is part of the steps context (https://docs.github.com/en/actions/learn-github-actions/contexts#steps-context) + if: always() && steps.apply_terraform.outcome != 'skipped' + working-directory: ./terraform-module/${{ inputs.cloudProvider }}-constellation + run: | + terraform init + terraform destroy -var-file=terraform.tfvars -auto-approve + + - name: Verify cleanup + working-directory: ./terraform-module/${{ inputs.cloudProvider }}-constellation + run: | + if [ -f constellation-mastersecret.json ] || [ -f constellation-conf.yaml ]; then + echo "Files constellation-mastersecret.json or constellation-conf.yaml still exist" + exit 1 + fi diff --git a/.github/workflows/e2e-test-weekly.yml b/.github/workflows/e2e-test-weekly.yml index 64510df4a..6312da77f 100644 --- a/.github/workflows/e2e-test-weekly.yml +++ b/.github/workflows/e2e-test-weekly.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - refStream: ["ref/main/stream/debug/?", "ref/release/stream/stable/?"] + refStream: ["ref/main/stream/nightly/?","ref/main/stream/debug/?", "ref/release/stream/stable/?"] name: Find latest image runs-on: ubuntu-22.04 permissions: @@ -19,6 +19,7 @@ jobs: outputs: image-main-debug: ${{ steps.relabel-output.outputs.image-main-debug }} image-release-stable: ${{ steps.relabel-output.outputs.image-release-stable }} + image-main-nightly: ${{ steps.relabel-output.outputs.image-main-nightly }} steps: - name: Checkout uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 @@ -367,3 +368,17 @@ jobs: uses: ./.github/workflows/e2e-windows.yml with: scheduled: ${{ github.event_name == 'schedule' }} + + e2e-tf-module: + name: Test Terraform Module + permissions: + id-token: write + contents: read + packages: write + needs: [find-latest-image] + secrets: inherit + uses: ./.github/workflows/e2e-test-tf-module.yml + with: + cloudProvider: "aws" + regionZone: "eu-west-1b" + image: ${{ needs.find-latest-image.outputs.image-main-nightly }} diff --git a/cli/internal/terraform/BUILD.bazel b/cli/internal/terraform/BUILD.bazel index f1d394cdc..3c277b9ad 100644 --- a/cli/internal/terraform/BUILD.bazel +++ b/cli/internal/terraform/BUILD.bazel @@ -9,82 +9,6 @@ go_library( "terraform.go", "variables.go", ], - embedsrcs = [ - "terraform/aws/.terraform.lock.hcl", - "terraform/aws/main.tf", - "terraform/aws/modules/instance_group/main.tf", - "terraform/aws/modules/instance_group/variables.tf", - "terraform/aws/modules/load_balancer_target/main.tf", - "terraform/aws/modules/load_balancer_target/output.tf", - "terraform/aws/modules/load_balancer_target/variables.tf", - "terraform/aws/modules/public_private_subnet/main.tf", - "terraform/aws/modules/public_private_subnet/output.tf", - "terraform/aws/modules/public_private_subnet/variables.tf", - "terraform/aws/outputs.tf", - "terraform/aws/variables.tf", - "terraform/azure/.terraform.lock.hcl", - "terraform/azure/main.tf", - "terraform/azure/modules/load_balancer_backend/main.tf", - "terraform/azure/modules/load_balancer_backend/outputs.tf", - "terraform/azure/modules/load_balancer_backend/variables.tf", - "terraform/azure/modules/scale_set/main.tf", - "terraform/azure/modules/scale_set/variables.tf", - "terraform/azure/outputs.tf", - "terraform/azure/variables.tf", - "terraform/gcp/.terraform.lock.hcl", - "terraform/gcp/main.tf", - "terraform/gcp/modules/instance_group/main.tf", - "terraform/gcp/modules/instance_group/outputs.tf", - "terraform/gcp/modules/instance_group/variables.tf", - "terraform/gcp/modules/loadbalancer/main.tf", - "terraform/gcp/modules/loadbalancer/variables.tf", - "terraform/gcp/outputs.tf", - "terraform/gcp/variables.tf", - "terraform/iam/aws/README.md", - "terraform/iam/aws/main.tf", - "terraform/iam/aws/outputs.tf", - "terraform/iam/aws/variables.tf", - "terraform/iam/azure/README.md", - "terraform/iam/azure/main.tf", - "terraform/iam/azure/outputs.tf", - "terraform/iam/azure/variables.tf", - "terraform/iam/gcp/README.md", - "terraform/iam/gcp/main.tf", - "terraform/iam/gcp/outputs.tf", - "terraform/iam/gcp/variables.tf", - "terraform/qemu/.terraform.lock.hcl", - "terraform/qemu/main.tf", - "terraform/qemu/modules/instance_group/domain.xsl", - "terraform/qemu/modules/instance_group/main.tf", - "terraform/qemu/modules/instance_group/outputs.tf", - "terraform/qemu/modules/instance_group/variables.tf", - "terraform/qemu/outputs.tf", - "terraform/qemu/variables.tf", - "terraform/openstack/.terraform.lock.hcl", - "terraform/openstack/main.tf", - "terraform/openstack/modules/instance_group/main.tf", - "terraform/openstack/modules/instance_group/outputs.tf", - "terraform/openstack/modules/instance_group/variables.tf", - "terraform/openstack/modules/loadbalancer/main.tf", - "terraform/openstack/modules/loadbalancer/variables.tf", - "terraform/openstack/outputs.tf", - "terraform/openstack/variables.tf", - "terraform/qemu/modules/instance_group/tdx_domain.xsl", - "terraform/iam/aws/.terraform.lock.hcl", - "terraform/iam/azure/.terraform.lock.hcl", - "terraform/iam/gcp/.terraform.lock.hcl", - "terraform/gcp/modules/internal_load_balancer/main.tf", - "terraform/gcp/modules/internal_load_balancer/variables.tf", - "terraform/gcp/modules/jump_host/main.tf", - "terraform/gcp/modules/jump_host/outputs.tf", - "terraform/gcp/modules/jump_host/variables.tf", - "terraform/aws/modules/jump_host/main.tf", - "terraform/aws/modules/jump_host/output.tf", - "terraform/aws/modules/jump_host/variables.tf", - "terraform/azure/modules/jump_host/main.tf", - "terraform/azure/modules/jump_host/variables.tf", - "terraform/azure/modules/jump_host/outputs.tf", - ], importpath = "github.com/edgelesssys/constellation/v2/cli/internal/terraform", visibility = ["//cli:__subpackages__"], deps = [ @@ -92,6 +16,7 @@ go_library( "//internal/cloud/cloudprovider", "//internal/constants", "//internal/file", + "//terraform", "@com_github_hashicorp_go_version//:go-version", "@com_github_hashicorp_hc_install//:hc-install", "@com_github_hashicorp_hc_install//fs", diff --git a/cli/internal/terraform/loader.go b/cli/internal/terraform/loader.go index 7ab5436f3..d6e448ce9 100644 --- a/cli/internal/terraform/loader.go +++ b/cli/internal/terraform/loader.go @@ -7,22 +7,18 @@ SPDX-License-Identifier: AGPL-3.0-only package terraform import ( - "embed" "errors" "io/fs" slashpath "path" "path/filepath" "strings" + "github.com/edgelesssys/constellation/v2/terraform" + "github.com/edgelesssys/constellation/v2/internal/file" "github.com/spf13/afero" ) -//go:embed terraform/* -//go:embed terraform/*/.terraform.lock.hcl -//go:embed terraform/iam/*/.terraform.lock.hcl -var terraformFS embed.FS - // prepareWorkspace loads the embedded Terraform files, // and writes them into the workspace. func prepareWorkspace(rootDir string, fileHandler file.Handler, workingDir string) error { @@ -32,7 +28,7 @@ func prepareWorkspace(rootDir string, fileHandler file.Handler, workingDir strin // terraformCopier copies the embedded Terraform files into the workspace. func terraformCopier(fileHandler file.Handler, rootDir, workingDir string) error { goEmbedRootDir := filepath.ToSlash(rootDir) - return fs.WalkDir(terraformFS, goEmbedRootDir, func(path string, d fs.DirEntry, err error) error { + return fs.WalkDir(terraform.Assets, goEmbedRootDir, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } @@ -41,7 +37,7 @@ func terraformCopier(fileHandler file.Handler, rootDir, workingDir string) error } goEmbedPath := filepath.ToSlash(path) - content, err := terraformFS.ReadFile(goEmbedPath) + content, err := terraform.Assets.ReadFile(goEmbedPath) if err != nil { return err } diff --git a/dev-docs/workflows/release.md b/dev-docs/workflows/release.md index 9eca1b9fc..28efa0af0 100644 --- a/dev-docs/workflows/release.md +++ b/dev-docs/workflows/release.md @@ -30,6 +30,10 @@ Releases should be performed using [the automated release pipeline](https://gith git push origin ${working_branch} ``` +### Update CLI version for Terraform module + +Update the `version` inside `terraform/constellation-cluster/install-constellation.sh` to the new release. + ### Patch release 1. `cherry-pick` (only) the required commits from `main` diff --git a/internal/constants/constants.go b/internal/constants/constants.go index f3a14e650..3e68392b4 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -172,7 +172,7 @@ const ( // TerraformIAMUpgradeBackupDir is the directory name being used to backup the pre-upgrade state of iam in an upgrade. TerraformIAMUpgradeBackupDir = "terraform-iam-backup" // TerraformEmbeddedDir is the name of the base directory embedded in the CLI binary containing the Terraform files. - TerraformEmbeddedDir = "terraform" + TerraformEmbeddedDir = "infrastructure" // UpgradeDir is the name of the directory being used for cluster upgrades. UpgradeDir = "constellation-upgrade" // ControlPlaneDefault is the name of the default control plane worker group. diff --git a/terraform/BUILD.bazel b/terraform/BUILD.bazel new file mode 100644 index 000000000..ef22922f1 --- /dev/null +++ b/terraform/BUILD.bazel @@ -0,0 +1,84 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "terraform", + srcs = ["assets.go"], + embedsrcs = [ + "infrastructure/aws/.terraform.lock.hcl", + "infrastructure/aws/main.tf", + "infrastructure/aws/modules/instance_group/main.tf", + "infrastructure/aws/modules/instance_group/variables.tf", + "infrastructure/aws/modules/jump_host/main.tf", + "infrastructure/aws/modules/jump_host/output.tf", + "infrastructure/aws/modules/jump_host/variables.tf", + "infrastructure/aws/modules/load_balancer_target/main.tf", + "infrastructure/aws/modules/load_balancer_target/output.tf", + "infrastructure/aws/modules/load_balancer_target/variables.tf", + "infrastructure/aws/modules/public_private_subnet/main.tf", + "infrastructure/aws/modules/public_private_subnet/output.tf", + "infrastructure/aws/modules/public_private_subnet/variables.tf", + "infrastructure/aws/outputs.tf", + "infrastructure/aws/variables.tf", + "infrastructure/azure/.terraform.lock.hcl", + "infrastructure/azure/main.tf", + "infrastructure/azure/modules/jump_host/main.tf", + "infrastructure/azure/modules/jump_host/outputs.tf", + "infrastructure/azure/modules/jump_host/variables.tf", + "infrastructure/azure/modules/load_balancer_backend/main.tf", + "infrastructure/azure/modules/load_balancer_backend/outputs.tf", + "infrastructure/azure/modules/load_balancer_backend/variables.tf", + "infrastructure/azure/modules/scale_set/main.tf", + "infrastructure/azure/modules/scale_set/variables.tf", + "infrastructure/azure/outputs.tf", + "infrastructure/azure/variables.tf", + "infrastructure/gcp/.terraform.lock.hcl", + "infrastructure/gcp/main.tf", + "infrastructure/gcp/modules/instance_group/main.tf", + "infrastructure/gcp/modules/instance_group/outputs.tf", + "infrastructure/gcp/modules/instance_group/variables.tf", + "infrastructure/gcp/modules/internal_load_balancer/main.tf", + "infrastructure/gcp/modules/internal_load_balancer/variables.tf", + "infrastructure/gcp/modules/jump_host/main.tf", + "infrastructure/gcp/modules/jump_host/outputs.tf", + "infrastructure/gcp/modules/jump_host/variables.tf", + "infrastructure/gcp/modules/loadbalancer/main.tf", + "infrastructure/gcp/modules/loadbalancer/variables.tf", + "infrastructure/gcp/outputs.tf", + "infrastructure/gcp/variables.tf", + "infrastructure/iam/aws/.terraform.lock.hcl", + "infrastructure/iam/aws/README.md", + "infrastructure/iam/aws/main.tf", + "infrastructure/iam/aws/outputs.tf", + "infrastructure/iam/aws/variables.tf", + "infrastructure/iam/azure/.terraform.lock.hcl", + "infrastructure/iam/azure/README.md", + "infrastructure/iam/azure/main.tf", + "infrastructure/iam/azure/outputs.tf", + "infrastructure/iam/azure/variables.tf", + "infrastructure/iam/gcp/.terraform.lock.hcl", + "infrastructure/iam/gcp/README.md", + "infrastructure/iam/gcp/main.tf", + "infrastructure/iam/gcp/outputs.tf", + "infrastructure/iam/gcp/variables.tf", + "infrastructure/openstack/.terraform.lock.hcl", + "infrastructure/openstack/main.tf", + "infrastructure/openstack/modules/instance_group/main.tf", + "infrastructure/openstack/modules/instance_group/outputs.tf", + "infrastructure/openstack/modules/instance_group/variables.tf", + "infrastructure/openstack/modules/loadbalancer/main.tf", + "infrastructure/openstack/modules/loadbalancer/variables.tf", + "infrastructure/openstack/outputs.tf", + "infrastructure/openstack/variables.tf", + "infrastructure/qemu/.terraform.lock.hcl", + "infrastructure/qemu/main.tf", + "infrastructure/qemu/modules/instance_group/domain.xsl", + "infrastructure/qemu/modules/instance_group/main.tf", + "infrastructure/qemu/modules/instance_group/outputs.tf", + "infrastructure/qemu/modules/instance_group/tdx_domain.xsl", + "infrastructure/qemu/modules/instance_group/variables.tf", + "infrastructure/qemu/outputs.tf", + "infrastructure/qemu/variables.tf", + ], + importpath = "github.com/edgelesssys/constellation/v2/terraform", + visibility = ["//visibility:public"], +) diff --git a/terraform/assets.go b/terraform/assets.go new file mode 100644 index 000000000..9e0d71842 --- /dev/null +++ b/terraform/assets.go @@ -0,0 +1,16 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package terraform + +import "embed" + +// Assets are the exported Terraform template files. +// +//go:embed infrastructure/* +//go:embed infrastructure/*/.terraform.lock.hcl +//go:embed infrastructure/iam/*/.terraform.lock.hcl +var Assets embed.FS diff --git a/terraform/aws-constellation/.terraform.lock.hcl b/terraform/aws-constellation/.terraform.lock.hcl new file mode 100644 index 000000000..21499c2e4 --- /dev/null +++ b/terraform/aws-constellation/.terraform.lock.hcl @@ -0,0 +1,99 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.17.0" + constraints = "5.17.0" + hashes = [ + "h1:+riTtJ8Tqjd6js1SGim+926BtDuxy8Jn4F+xV8LXvvg=", + "h1:OJMhYliR4PFDrTtOPocwq4NfuYZVGmmxwInPmcIC1x0=", + "h1:U+EDfeUqefebA1h7KyBMD1xH0h311LMi7wijPDPkC/0=", + "h1:fKgoYBRyK55vJSChUHPptDUQuXqjfDjVKVJ11+scq64=", + "h1:rplvK7UGP2FuzM44t2eRX+QYYPC0aUIoKdi5XayRI8M=", + "zh:0087b9dd2c9c638fd63e527e5b9b70988008e263d480a199f180efe5a4f070f0", + "zh:0fd532a4fd03ddef11f0502ff9fe4343443e1ae805cb088825a71d6d48906ec7", + "zh:16411e731100cd15f7e165f53c23be784b2c86c2fcfd34781e0642d17090d342", + "zh:251d520927e77f091e2ec6302e921d839a2430ac541c6a461aed7c08fb5eae12", + "zh:4919e69682dc2a8c32d44f6ebc038a52c9f40af9c61cb574b64e322800d6a794", + "zh:5334c60759d5f76bdc51355d1a3ebcc451d4d20f632f5c73b6e55c52b5dc9e52", + "zh:7341a2b7247572eba0d0486094a870b872967702ec0ac7af728c2df2c30af4e5", + "zh:81d1b1cb2cac6b3922a05adab69543b678f344a01debd54500263700dad7a288", + "zh:882bc8e15ef6d4020a07321ec4c056977c5c1d96934118032922561d29504d43", + "zh:8cd4871ef2b03fd916de1a6dc7eb8a81a354c421177d4334a2e3308e50215e41", + "zh:97e12fe6529b21298adf1046c5e20ac35d0569c836a6f385ff041e257e00cfd2", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9f5baf5d59b9f3cf5504d1fa975f10f27da3791896a9e18ece47c258bac17634", + "zh:dffafba6731ac1db1c540bdbd6a8c878486b71de9d0ca1d23c5c00a6c3c14d80", + "zh:fa7440c3c15a42fc5731444d324ced75407d417bfe3184661ae47d40a9718dce", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.4.0" + hashes = [ + "h1:7RnIbO3CFakblTJs7o0mUiY44dc9xGYsLhSNFSNS1Ds=", + "h1:Bs7LAkV/iQTLv72j+cTMrvx2U3KyXrcVHaGbdns1NcE=", + "h1:OMqURhlP2IgLEgUCzSlaKXyb/IbnKForgDSjZF/NY4Y=", + "h1:R97FTYETo88sT2VHfMgkPU3lzCsZLunPftjSI5vfKe8=", + "h1:ZUEYUmm2t4vxwzxy1BvN1wL6SDWrDxfH7pxtzX8c6d0=", + "zh:53604cd29cb92538668fe09565c739358dc53ca56f9f11312b9d7de81e48fab9", + "zh:66a46e9c508716a1c98efbf793092f03d50049fa4a83cd6b2251e9a06aca2acf", + "zh:70a6f6a852dd83768d0778ce9817d81d4b3f073fab8fa570bff92dcb0824f732", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:82a803f2f484c8b766e2e9c32343e9c89b91997b9f8d2697f9f3837f62926b35", + "zh:9708a4e40d6cc4b8afd1352e5186e6e1502f6ae599867c120967aebe9d90ed04", + "zh:973f65ce0d67c585f4ec250c1e634c9b22d9c4288b484ee2a871d7fa1e317406", + "zh:c8fa0f98f9316e4cfef082aa9b785ba16e36ff754d6aba8b456dab9500e671c6", + "zh:cfa5342a5f5188b20db246c73ac823918c189468e1382cb3c48a9c0c08fc5bf7", + "zh:e0e2b477c7e899c63b06b38cd8684a893d834d6d0b5e9b033cedc06dd7ffe9e2", + "zh:f62d7d05ea1ee566f732505200ab38d94315a4add27947a60afa29860822d3fc", + "zh:fa7ce69dde358e172bd719014ad637634bbdabc49363104f4fca759b4b73f2ce", + ] +} + +provider "registry.terraform.io/hashicorp/null" { + version = "3.2.1" + hashes = [ + "h1:FbGfc+muBsC17Ohy5g806iuI1hQc4SIexpYCrQHQd8w=", + "h1:tSj1mL6OQ8ILGqR2mDu7OYYYWf+hoir0pf9KAQ8IzO8=", + "h1:vUW21lLLsKlxtBf0QF7LKJreKxs0CM7YXGzqW1N/ODY=", + "h1:wqgRvlyVIbkCeCQs+5jj6zVuQL0KDxZZtNofGqqlSdI=", + "h1:ydA0/SNRVB1o95btfshvYsmxA+jZFRZcvKzZSB+4S1M=", + "zh:58ed64389620cc7b82f01332e27723856422820cfd302e304b5f6c3436fb9840", + "zh:62a5cc82c3b2ddef7ef3a6f2fedb7b9b3deff4ab7b414938b08e51d6e8be87cb", + "zh:63cff4de03af983175a7e37e52d4bd89d990be256b16b5c7f919aff5ad485aa5", + "zh:74cb22c6700e48486b7cabefa10b33b801dfcab56f1a6ac9b6624531f3d36ea3", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:79e553aff77f1cfa9012a2218b8238dd672ea5e1b2924775ac9ac24d2a75c238", + "zh:a1e06ddda0b5ac48f7e7c7d59e1ab5a4073bbcf876c73c0299e4610ed53859dc", + "zh:c37a97090f1a82222925d45d84483b2aa702ef7ab66532af6cbcfb567818b970", + "zh:e4453fbebf90c53ca3323a92e7ca0f9961427d2f0ce0d2b65523cc04d5d999c2", + "zh:e80a746921946d8b6761e77305b752ad188da60688cfd2059322875d363be5f5", + "zh:fbdb892d9822ed0e4cb60f2fedbdbb556e4da0d88d3b942ae963ed6ff091e48f", + "zh:fca01a623d90d0cad0843102f9b8b9fe0d3ff8244593bd817f126582b52dd694", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.5.1" + constraints = "3.5.1" + hashes = [ + "h1:3hjTP5tQBspPcFAJlfafnWrNrKnr7J4Cp0qB9jbqf30=", + "h1:6FVyQ/aG6tawPam6B+oFjgdidKd83uG9n7dOSQ66HBA=", + "h1:IL9mSatmwov+e0+++YX2V6uel+dV6bn+fC/cnGDK3Ck=", + "h1:VSnd9ZIPyfKHOObuQCaKfnjIHRtR7qTw19Rz8tJxm+k=", + "h1:sZ7MTSD4FLekNN2wSNFGpM+5slfvpm5A/NLVZiB7CO0=", + "zh:04e3fbd610cb52c1017d282531364b9c53ef72b6bc533acb2a90671957324a64", + "zh:119197103301ebaf7efb91df8f0b6e0dd31e6ff943d231af35ee1831c599188d", + "zh:4d2b219d09abf3b1bb4df93d399ed156cadd61f44ad3baf5cf2954df2fba0831", + "zh:6130bdde527587bbe2dcaa7150363e96dbc5250ea20154176d82bc69df5d4ce3", + "zh:6cc326cd4000f724d3086ee05587e7710f032f94fc9af35e96a386a1c6f2214f", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:b6d88e1d28cf2dfa24e9fdcc3efc77adcdc1c3c3b5c7ce503a423efbdd6de57b", + "zh:ba74c592622ecbcef9dc2a4d81ed321c4e44cddf7da799faa324da9bf52a22b2", + "zh:c7c5cde98fe4ef1143bd1b3ec5dc04baf0d4cc3ca2c5c7d40d17c0e9b2076865", + "zh:dac4bad52c940cd0dfc27893507c1e92393846b024c5a9db159a93c534a3da03", + "zh:de8febe2a2acd9ac454b844a4106ed295ae9520ef54dc8ed2faf29f12716b602", + "zh:eab0d0495e7e711cca367f7d4df6e322e6c562fc52151ec931176115b83ed014", + ] +} diff --git a/terraform/aws-constellation/fetch-ami/main.tf b/terraform/aws-constellation/fetch-ami/main.tf new file mode 100644 index 000000000..5c94699cc --- /dev/null +++ b/terraform/aws-constellation/fetch-ami/main.tf @@ -0,0 +1,28 @@ +locals { + + image_ref = startswith(var.image, "v") ? "ref/-/stream/stable/${var.image}" : var.image + fetch_ami_command = < "${path.module}/ami.txt" + echo -n "AMI: " + cat "${path.module}/ami.txt" + EOT +} + +resource "null_resource" "fetch_ami" { + provisioner "local-exec" { + command = local.fetch_ami_command + + environment = { + attestation_variant = var.attestation_variant + } + } + triggers = { + always_run = "${timestamp()}" + } +} + +data "local_file" "ami" { + filename = "${path.module}/ami.txt" + depends_on = [null_resource.fetch_ami] +} diff --git a/terraform/aws-constellation/fetch-ami/output.tf b/terraform/aws-constellation/fetch-ami/output.tf new file mode 100644 index 000000000..af2c61504 --- /dev/null +++ b/terraform/aws-constellation/fetch-ami/output.tf @@ -0,0 +1,4 @@ +output "ami" { + description = "The fetched AMI." + value = data.local_file.ami.content +} diff --git a/terraform/aws-constellation/fetch-ami/variables.tf b/terraform/aws-constellation/fetch-ami/variables.tf new file mode 100644 index 000000000..35d855c1a --- /dev/null +++ b/terraform/aws-constellation/fetch-ami/variables.tf @@ -0,0 +1,14 @@ +variable "attestation_variant" { + description = "The attestation variant to fetch AMI data for." + type = string +} + +variable "region" { + description = "The AWS region to fetch AMI data for." + type = string +} + +variable "image" { + description = "The image reference or semantical release version to fetch AMI data for." + type = string +} diff --git a/terraform/aws-constellation/install-yq.sh b/terraform/aws-constellation/install-yq.sh new file mode 100755 index 000000000..12b62c1c4 --- /dev/null +++ b/terraform/aws-constellation/install-yq.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +VERSION="v4.35.2" +if [[ -f ./yq ]] && ./yq --version | grep -q "${VERSION}"; then + echo "yq is already available and up to date." + exit 0 +fi +if [[ -f ./yq ]]; then + echo "yq is already available but not at the required version. Replacing with ${VERSION}." + rm -f yq +fi + +echo "Fetching yq ${VERSION}" +OS=$(uname -s) +ARCH=$(uname -m) +URL="" + +if [[ ${OS} == "Darwin" ]]; then + if [[ ${ARCH} == "arm64" ]]; then + URL="https://github.com/mikefarah/yq/releases/download/${VERSION}/yq_darwin_arm64" + elif [[ ${ARCH} == "x86_64" ]]; then + URL="https://github.com/mikefarah/yq/releases/download/${VERSION}/yq_darwin_amd64" + fi +elif [[ ${OS} == "Linux" ]]; then + if [[ ${ARCH} == "x86_64" ]]; then + URL="https://github.com/mikefarah/yq/releases/download/${VERSION}/yq_linux_amd64" + elif [[ ${ARCH} == "arm64" ]]; then + URL="https://github.com/mikefarah/yq/releases/download/${VERSION}/yq_linux_arm64" + fi +fi + +if [[ -z ${URL} ]]; then + echo "OS \"${OS}\" and/or architecture \"${ARCH}\" is not supported." + exit 1 +else + echo "Downloading yq from ${URL}" + curl -o yq -L "${URL}" + chmod +x ./yq + ./yq --version + if ! ./yq --version | grep -q "${VERSION}"; then # check that yq was installed correctly + echo "Version is incorrect" + exit 1 + fi +fi diff --git a/terraform/aws-constellation/main.tf b/terraform/aws-constellation/main.tf new file mode 100644 index 000000000..7ec4e7028 --- /dev/null +++ b/terraform/aws-constellation/main.tf @@ -0,0 +1,67 @@ +locals { + region = substr(var.zone, 0, length(var.zone) - 1) +} + +module "aws_iam" { + source = "../infrastructure/iam/aws" + name_prefix = var.name_prefix + region = local.region +} + + +resource "null_resource" "ensure_yq" { + provisioner "local-exec" { + command = <