From 5279ad58fe295f5968d32dff0c6d5e490860369a Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Mon, 24 Aug 2026 12:28:15 +0200 Subject: [PATCH 01/13] test(terraform): apply modules against MiniStack --- .github/workflows/ministack.yml | 77 ++++++++++++++++ .gitignore | 1 + tests/ministack/.terraform.lock.hcl | 74 +++++++++++++++ tests/ministack/README.md | 39 ++++++++ tests/ministack/main.tf | 138 ++++++++++++++++++++++++++++ 5 files changed, 329 insertions(+) create mode 100644 .github/workflows/ministack.yml create mode 100644 tests/ministack/.terraform.lock.hcl create mode 100644 tests/ministack/README.md create mode 100644 tests/ministack/main.tf diff --git a/.github/workflows/ministack.yml b/.github/workflows/ministack.yml new file mode 100644 index 0000000000..03d0ad3dfd --- /dev/null +++ b/.github/workflows/ministack.yml @@ -0,0 +1,77 @@ +name: "MiniStack Terraform apply" + +on: + push: + branches: + - main + paths: + - ".github/workflows/ministack.yml" + - "modules/lambda/**" + - "modules/setup-iam-permissions/**" + - "modules/ssm/**" + - "tests/ministack/**" + pull_request: + paths: + - ".github/workflows/ministack.yml" + - "modules/lambda/**" + - "modules/setup-iam-permissions/**" + - "modules/ssm/**" + - "tests/ministack/**" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +env: + AWS_DEFAULT_REGION: eu-west-1 + AWS_EC2_METADATA_DISABLED: "true" + AWS_ENDPOINT_URL: http://ministack:4566 + AWS_REGION: eu-west-1 + TF_IN_AUTOMATION: "true" + TF_INPUT: "false" + TF_VAR_ministack_endpoint: http://ministack:4566 + +jobs: + terraform_apply: + name: Apply modules against MiniStack + runs-on: ubuntu-latest + timeout-minutes: 15 + container: + image: hashicorp/terraform@sha256:1d10ec4073f4ddbdf34a28540a3b9250852ab500cb1c53f68c8bd17d82f474d8 # 1.14 + services: + ministack: + image: ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 + env: + MINISTACK_ACCOUNT_ID: "000000000000" + MINISTACK_REGION: eu-west-1 + defaults: + run: + working-directory: tests/ministack + steps: + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Terraform init + run: terraform init -backend=false -input=false + + - name: Terraform validate + run: terraform validate + + - name: Terraform apply + id: apply + run: terraform apply -auto-approve -input=false + + - name: Terraform destroy + if: ${{ always() && steps.apply.outcome != 'skipped' }} + run: terraform destroy -auto-approve -input=false diff --git a/.gitignore b/.gitignore index 276fe10733..7fab34ca3a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # lock files **/.terraform.lock.hcl !examples/**/.terraform.lock.hcl +!tests/ministack/.terraform.lock.hcl # keys diff --git a/tests/ministack/.terraform.lock.hcl b/tests/ministack/.terraform.lock.hcl new file mode 100644 index 0000000000..700ec43e25 --- /dev/null +++ b/tests/ministack/.terraform.lock.hcl @@ -0,0 +1,74 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/archive" { + version = "2.8.0" + constraints = "~> 2.7" + hashes = [ + "h1:WB6H5ksIZiyq1lQlD/PWeh+tn4FLsbSjVnRW3+4xe2Y=", + "h1:cMBtvdHEgvTmglbioVehZCaOIPocumu9+vlGw5Dsaro=", + "h1:jdmKm+xl6ZcQrijxapnZ94RVuz/G4vk7hsIa1N0VT5Q=", + "zh:0d14713fdc259fb377d0b899ad3c650a34194bd52194c863303ef22a65a580e2", + "zh:369b56040c7a8085d04e7e8ffac1e2b321a3170e502f788819bc34b868ec016f", + "zh:4d1a3b983ed6af5a52bfe12794674ae55cbadfa6021b37106ade68b433ad216a", + "zh:5c547549e26e083573c78a966ca68ce6d7df6bb8f3948f66a575f07da46b74ea", + "zh:6de093e62a975eb19a5e3017ce38e6e3cb639c17b79648d2000e0a8348f0e997", + "zh:7267936c2cdbc448efeb594d73e6b56a53d6a7ae14fe88cdd2a4133adc3302f0", + "zh:7482f023050ed426b4b45116e1761643bc33b1fd4ce4a6fab207ae2571f35940", + "zh:76bbd93b234e5a2927d98b511d86565700f549b570871a194c35f944b96cefb7", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:c6afc4bc1f002bac9c173007dd4da05fde788cd14c2916089f958c33fedb0dfa", + "zh:d3ba40bd806a3a08e9237dece679193c99afb2085de6b45d7f5d1f673cfcd368", + "zh:e1ad7ded53ecd6f0e5b473a3b44eae2b2e885653a56050ab583d387332be02e4", + "zh:e93e78575ce82be6084cc153c24ba8f385dc8d6880888ee66e918460c870953d", + ] +} + +provider "registry.terraform.io/hashicorp/aws" { + version = "6.61.0" + constraints = ">= 6.21.0, >= 6.33.0" + hashes = [ + "h1:Kl91YvWRdorx6POwgdFf6ZBsHHa86GhazsqOwPvunyo=", + "h1:luPmlKygfw2SMKJkMQ++/J8rRR0ZgR0uJPupp8wy3pw=", + "h1:xgqNausjCmDbyoc3aY+flDVsUKgefbTjgKA9cQun4Ks=", + "zh:216566f0fbc506e107d3a961c87d88aed052ec2b4ced13388394d3cff30425ac", + "zh:4700ad141d0ad96465ac35a3900f2ff7c91a1e5528428ac687c8b5825c0be718", + "zh:6b79d2fa6550fc51e2fac04f1066c5cc96e957e7634ad86d2250240e637db205", + "zh:76f6227bf2bcd7422cf29d9868d8b517c8220ec3edd4e7c8434b867a71c03334", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:a7be5814cf94a8e3869ec9fa7f5182223a11373a4510ce68b9bab431f9b83746", + "zh:b65392e24506fe99f8df7bd2b5d3940d7a234b64b79a890f1aabe2be91a827e5", + "zh:b68a5092203cf5a9d1a5f01f9f2e96fded3eb7cacfd49ae851c50b87bc610fe9", + "zh:b8fedfa62bac16592519e1bae0c82dd7cd1544b0637543d72e3597e46ad7db32", + "zh:bba8a35212c07e68b6c881aa011c4b26a284e42b971059579aca9ffb63a8faef", + "zh:bbd0391e3e2f21c8930872829df7cf7f4e35f84c4d6d7b7619a94f8078fe6f3d", + "zh:c9c921e8e466281c04cada8d336ec1ce978128ee153e9df7b451847fbea49d18", + "zh:c9cb0be3097f4392b977fa254d28efd0909d008f572e74a41ead6c0d84c0daaa", + "zh:cc7aeb23fa3775816e391d4668a9865f787993f9f8d6f5b7a9f7e4effdffb3cb", + "zh:e59e487220cec8999bbd120ba8f97b5e04b010fb9149e47d4c9032961614d7c7", + "zh:fa19a7571a99397120f2f2bdcf33bbcc2f39091b9b0c879cd7e5f9ebb1966c40", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.9.0" + constraints = "~> 3.7" + hashes = [ + "h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=", + "h1:UlBuNVuCGJ39tTv2c5gz2NRZnQbXfbIWbTzWcth5o74=", + "h1:lVDv+0AjDjrLfpmaJbWqUmIw/k3/AHXLc3N4m55SNdo=", + "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", + "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", + "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", + "zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0", + "zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61", + "zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc", + "zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e", + "zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef", + "zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b", + "zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257", + "zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04", + ] +} diff --git a/tests/ministack/README.md b/tests/ministack/README.md new file mode 100644 index 0000000000..0958545f56 --- /dev/null +++ b/tests/ministack/README.md @@ -0,0 +1,39 @@ +# MiniStack apply test + +This fixture applies the `ssm`, `setup-iam-permissions`, and `lambda` modules +against [MiniStack](https://github.com/ministackorg/ministack). It exercises +real AWS provider create, read, and delete calls without an AWS account. + +The fixture configures synthetic credentials in the AWS provider, and the +GitHub Actions workflow routes every AWS service to the `ministack` service +container. For a local run, start MiniStack on port 4566 and set the global AWS +endpoint before running Terraform: + +```shell +docker run --detach --rm --name terraform-aws-github-runner-ministack \ + --publish 127.0.0.1:4566:4566 \ + --env MINISTACK_ACCOUNT_ID=000000000000 \ + --env MINISTACK_REGION=eu-west-1 \ + ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 + +curl --fail --retry 10 --retry-connrefused --retry-delay 1 \ + http://127.0.0.1:4566/_ministack/health + +export AWS_ENDPOINT_URL=http://127.0.0.1:4566 +export AWS_REGION=eu-west-1 +export AWS_EC2_METADATA_DISABLED=true + +terraform init -backend=false -input=false +terraform apply -auto-approve -input=false +terraform destroy -auto-approve -input=false +docker stop terraform-aws-github-runner-ministack +``` + +Run the Terraform commands from this directory. The endpoint input only accepts +the loopback addresses used locally and the service hostname used in CI. The +provider also ignores ambient AWS credentials, and `AWS_ENDPOINT_URL` catches +any AWS service added to the fixture in the future. + +This test covers AWS provider and module API compatibility. MiniStack runs with +authorization disabled, so it does not validate IAM policy enforcement, real +KMS encryption, Lambda execution, or AWS service limits. diff --git a/tests/ministack/main.tf b/tests/ministack/main.tf new file mode 100644 index 0000000000..0cbf2bcbfb --- /dev/null +++ b/tests/ministack/main.tf @@ -0,0 +1,138 @@ +terraform { + required_version = ">= 1.10.0" + + required_providers { + archive = { + source = "hashicorp/archive" + version = "~> 2.7" + } + aws = { + source = "hashicorp/aws" + version = ">= 6.33" + } + random = { + source = "hashicorp/random" + version = "~> 3.7" + } + } +} + +variable "ministack_endpoint" { + description = "HTTP endpoint for the local MiniStack instance." + type = string + default = "http://127.0.0.1:4566" + + validation { + condition = contains([ + "http://127.0.0.1:4566", + "http://localhost:4566", + "http://ministack:4566", + ], var.ministack_endpoint) + error_message = "The MiniStack endpoint must use port 4566 on the local host or the CI service hostname." + } +} + +provider "aws" { + access_key = "000000000000" + region = "eu-west-1" + secret_key = sha256("ministack:${var.ministack_endpoint}") + skip_credentials_validation = true + skip_metadata_api_check = true + skip_requesting_account_id = true + + endpoints { + iam = var.ministack_endpoint + lambda = var.ministack_endpoint + logs = var.ministack_endpoint + ssm = var.ministack_endpoint + sts = var.ministack_endpoint + } +} + +data "aws_caller_identity" "ministack" {} + +data "archive_file" "lambda" { + type = "zip" + output_path = "${path.root}/.terraform/ministack-lambda.zip" + + source { + content = "exports.handler = async () => ({ statusCode: 200, body: 'ok' });" + filename = "index.js" + } +} + +resource "random_password" "github_app_key" { + length = 64 + special = false +} + +resource "random_password" "github_webhook_secret" { + length = 32 + special = false +} + +resource "random_password" "additional_github_app_key" { + length = 64 + special = false +} + +module "ssm" { + source = "../../modules/ssm" + + path_prefix = "/ministack/terraform-aws-github-runner" + github_app = { + id = "ministack-primary-app" + key_base64 = base64encode(random_password.github_app_key.result) + webhook_secret = random_password.github_webhook_secret.result + } + additional_github_apps = [{ + id = "ministack-additional-app" + key_base64 = base64encode(random_password.additional_github_app_key.result) + installation_id = "ministack-installation" + }] + tags = { + Test = "ministack" + } +} + +module "setup_iam_permissions" { + source = "../../modules/setup-iam-permissions" + + prefix = "ministack-test" + account_id = data.aws_caller_identity.ministack.account_id + namespaces = { + boundary_namespace = "ministack-boundaries" + instance_profile_namespace = "ministack-instance-profiles" + policy_namespace = "ministack-policies" + role_namespace = "ministack-roles" + } +} + +module "lambda" { + source = "../../modules/lambda" + + lambda = { + architecture = "x86_64" + handler = "index.handler" + logging_retention_in_days = 1 + name = "api-compatibility" + prefix = "ministack-test" + runtime = "nodejs22.x" + tags = { + Test = "ministack" + } + zip = data.archive_file.lambda.output_path + } +} + +output "applied_resources" { + description = "Representative resources created through the MiniStack AWS API." + value = { + caller_account_id = data.aws_caller_identity.ministack.account_id + deployment_boundary = module.setup_iam_permissions.boundary + deployment_role = module.setup_iam_permissions.role + lambda_arn = module.lambda.lambda.function.arn + lambda_log_group = module.lambda.lambda.log_group.arn + ssm_parameters = module.ssm.parameters + } +} From 4f8f3e299c080386b1ec720eca543b7eb18c25d1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 10:29:38 +0000 Subject: [PATCH 02/13] docs: auto update terraform docs --- tests/ministack/README.md | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/ministack/README.md b/tests/ministack/README.md index 0958545f56..6d9e35784e 100644 --- a/tests/ministack/README.md +++ b/tests/ministack/README.md @@ -37,3 +37,52 @@ any AWS service added to the fixture in the future. This test covers AWS provider and module API compatibility. MiniStack runs with authorization disabled, so it does not validate IAM policy enforcement, real KMS encryption, Lambda execution, or AWS service limits. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.10.0 | +| [archive](#requirement\_archive) | ~> 2.7 | +| [aws](#requirement\_aws) | >= 6.33 | +| [random](#requirement\_random) | ~> 3.7 | + +## Providers + +| Name | Version | +|------|---------| +| [archive](#provider\_archive) | 2.8.0 | +| [aws](#provider\_aws) | 6.61.0 | +| [random](#provider\_random) | 3.9.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [lambda](#module\_lambda) | ../../modules/lambda | n/a | +| [setup\_iam\_permissions](#module\_setup\_iam\_permissions) | ../../modules/setup-iam-permissions | n/a | +| [ssm](#module\_ssm) | ../../modules/ssm | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_password.additional_github_app_key](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [random_password.github_app_key](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [random_password.github_webhook_secret](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [archive_file.lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | +| [aws_caller_identity.ministack](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [ministack\_endpoint](#input\_ministack\_endpoint) | HTTP endpoint for the local MiniStack instance. | `string` | `"http://127.0.0.1:4566"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [applied\_resources](#output\_applied\_resources) | Representative resources created through the MiniStack AWS API. | + \ No newline at end of file From 155aad7be5e3a34d3e89f13fea93b14ae7574a42 Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Mon, 24 Aug 2026 13:46:09 +0200 Subject: [PATCH 03/13] test(terraform): apply default example against MiniStack --- .github/workflows/ministack.yml | 41 +++--- .gitignore | 1 - examples/default/.terraform.lock.hcl | 21 +++ examples/default/README.md | 25 ++++ examples/default/main.tf | 7 +- examples/default/tests/ministack.tftest.hcl | 67 ++++++++++ examples/default/tests/setup/main.tf | 52 ++++++++ examples/default/variables.tf | 13 ++ tests/ministack/.terraform.lock.hcl | 74 ----------- tests/ministack/README.md | 88 ------------- tests/ministack/main.tf | 138 -------------------- 11 files changed, 208 insertions(+), 319 deletions(-) create mode 100644 examples/default/tests/ministack.tftest.hcl create mode 100644 examples/default/tests/setup/main.tf delete mode 100644 tests/ministack/.terraform.lock.hcl delete mode 100644 tests/ministack/README.md delete mode 100644 tests/ministack/main.tf diff --git a/.github/workflows/ministack.yml b/.github/workflows/ministack.yml index 03d0ad3dfd..76517dc8a0 100644 --- a/.github/workflows/ministack.yml +++ b/.github/workflows/ministack.yml @@ -6,17 +6,31 @@ on: - main paths: - ".github/workflows/ministack.yml" + - "*.tf" + - "policies/**" + - "examples/base/**" + - "examples/default/**" + - "modules/ami-housekeeper/**" - "modules/lambda/**" - - "modules/setup-iam-permissions/**" + - "modules/runner-binaries-syncer/**" + - "modules/runners/**" - "modules/ssm/**" - - "tests/ministack/**" + - "modules/termination-watcher/**" + - "modules/webhook/**" pull_request: paths: - ".github/workflows/ministack.yml" + - "*.tf" + - "policies/**" + - "examples/base/**" + - "examples/default/**" + - "modules/ami-housekeeper/**" - "modules/lambda/**" - - "modules/setup-iam-permissions/**" + - "modules/runner-binaries-syncer/**" + - "modules/runners/**" - "modules/ssm/**" - - "tests/ministack/**" + - "modules/termination-watcher/**" + - "modules/webhook/**" workflow_dispatch: concurrency: @@ -27,17 +41,18 @@ permissions: contents: read env: + AWS_ACCESS_KEY_ID: "000000000000" AWS_DEFAULT_REGION: eu-west-1 AWS_EC2_METADATA_DISABLED: "true" AWS_ENDPOINT_URL: http://ministack:4566 AWS_REGION: eu-west-1 + AWS_SECRET_ACCESS_KEY: test-only TF_IN_AUTOMATION: "true" TF_INPUT: "false" - TF_VAR_ministack_endpoint: http://ministack:4566 jobs: terraform_apply: - name: Apply modules against MiniStack + name: Apply default example against MiniStack runs-on: ubuntu-latest timeout-minutes: 15 container: @@ -50,7 +65,7 @@ jobs: MINISTACK_REGION: eu-west-1 defaults: run: - working-directory: tests/ministack + working-directory: examples/default steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 @@ -65,13 +80,5 @@ jobs: - name: Terraform init run: terraform init -backend=false -input=false - - name: Terraform validate - run: terraform validate - - - name: Terraform apply - id: apply - run: terraform apply -auto-approve -input=false - - - name: Terraform destroy - if: ${{ always() && steps.apply.outcome != 'skipped' }} - run: terraform destroy -auto-approve -input=false + - name: Terraform apply test + run: terraform test -filter=tests/ministack.tftest.hcl diff --git a/.gitignore b/.gitignore index 7fab34ca3a..276fe10733 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,6 @@ # lock files **/.terraform.lock.hcl !examples/**/.terraform.lock.hcl -!tests/ministack/.terraform.lock.hcl # keys diff --git a/examples/default/.terraform.lock.hcl b/examples/default/.terraform.lock.hcl index 136f5367b1..c9bdeb915e 100644 --- a/examples/default/.terraform.lock.hcl +++ b/examples/default/.terraform.lock.hcl @@ -1,6 +1,27 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. +provider "registry.terraform.io/hashicorp/archive" { + version = "2.8.0" + constraints = "~> 2.7" + hashes = [ + "h1:WB6H5ksIZiyq1lQlD/PWeh+tn4FLsbSjVnRW3+4xe2Y=", + "zh:0d14713fdc259fb377d0b899ad3c650a34194bd52194c863303ef22a65a580e2", + "zh:369b56040c7a8085d04e7e8ffac1e2b321a3170e502f788819bc34b868ec016f", + "zh:4d1a3b983ed6af5a52bfe12794674ae55cbadfa6021b37106ade68b433ad216a", + "zh:5c547549e26e083573c78a966ca68ce6d7df6bb8f3948f66a575f07da46b74ea", + "zh:6de093e62a975eb19a5e3017ce38e6e3cb639c17b79648d2000e0a8348f0e997", + "zh:7267936c2cdbc448efeb594d73e6b56a53d6a7ae14fe88cdd2a4133adc3302f0", + "zh:7482f023050ed426b4b45116e1761643bc33b1fd4ce4a6fab207ae2571f35940", + "zh:76bbd93b234e5a2927d98b511d86565700f549b570871a194c35f944b96cefb7", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:c6afc4bc1f002bac9c173007dd4da05fde788cd14c2916089f958c33fedb0dfa", + "zh:d3ba40bd806a3a08e9237dece679193c99afb2085de6b45d7f5d1f673cfcd368", + "zh:e1ad7ded53ecd6f0e5b473a3b44eae2b2e885653a56050ab583d387332be02e4", + "zh:e93e78575ce82be6084cc153c24ba8f385dc8d6880888ee66e918460c870953d", + ] +} + provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" diff --git a/examples/default/README.md b/examples/default/README.md index c75e37831f..91756dd8c7 100644 --- a/examples/default/README.md +++ b/examples/default/README.md @@ -28,6 +28,30 @@ The example will try to update the webhook of your GitHub. In case the update fa terraform output -raw webhook_secret ``` +## MiniStack apply test + +The MiniStack test applies this example with synthetic GitHub App values and +inert Lambda archives. It overrides the GitHub App webhook updater and AMI +lookup, while all AWS resources are created through the local MiniStack API. +Terraform test destroys the resources and keeps the generated inert archive +isolated in the ignored `.terraform/ministack/` cache. + +With Terraform 1.10 or newer, start MiniStack locally, route the AWS provider +to it, and run the focused test: + +```bash +docker run --detach --rm --name terraform-aws-github-runner-ministack \ + --publish 127.0.0.1:4566:4566 \ + --env MINISTACK_ACCOUNT_ID=000000000000 \ + --env MINISTACK_REGION=eu-west-1 \ + ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 + +export AWS_ENDPOINT_URL=http://127.0.0.1:4566 +terraform init -backend=false -input=false +terraform test -filter=tests/ministack.tftest.hcl +docker stop terraform-aws-github-runner-ministack +``` + ## Requirements @@ -65,6 +89,7 @@ terraform output -raw webhook_secret | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [lambda\_zip\_overrides](#input\_lambda\_zip\_overrides) | Optional local Lambda archive paths passed to the runner module. |
object({
ami_housekeeper = optional(string)
runner_binaries_syncer = optional(string)
runners = optional(string)
termination_watcher = optional(string)
webhook = optional(string)
})
| `{}` | no | ## Outputs diff --git a/examples/default/main.tf b/examples/default/main.tf index 71c69612c3..caa69abbef 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -49,6 +49,9 @@ module "runners" { # webhook_lambda_zip = "../lambdas-download/webhook.zip" # runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" # runners_lambda_zip = "../lambdas-download/runners.zip" + webhook_lambda_zip = var.lambda_zip_overrides.webhook + runner_binaries_syncer_lambda_zip = var.lambda_zip_overrides.runner_binaries_syncer + runners_lambda_zip = var.lambda_zip_overrides.runners enable_organization_runners = true # Note: labels starting with `ghr-` are ignored during webhook label matching @@ -108,7 +111,8 @@ module "runners" { # capture_http_requests = true # } - enable_ami_housekeeper = true + enable_ami_housekeeper = true + ami_housekeeper_lambda_zip = var.lambda_zip_overrides.ami_housekeeper ami_housekeeper_cleanup_config = { ssmParameterNames = ["*/ami-id"] minimumDaysOld = 10 @@ -122,6 +126,7 @@ module "runners" { instance_termination_watcher = { enable = true + zip = var.lambda_zip_overrides.termination_watcher } # enable metric creation (experimental) diff --git a/examples/default/tests/ministack.tftest.hcl b/examples/default/tests/ministack.tftest.hcl new file mode 100644 index 0000000000..7b564028d7 --- /dev/null +++ b/examples/default/tests/ministack.tftest.hcl @@ -0,0 +1,67 @@ +provider "aws" { + region = "eu-west-1" + + access_key = "000000000000" + secret_key = "test-only" + + skip_credentials_validation = true + skip_metadata_api_check = true + skip_requesting_account_id = true + s3_use_path_style = true +} + +run "setup_lambda_archive" { + command = apply + + module { + source = "./tests/setup" + } + + assert { + condition = endswith(output.lambda_archive, ".terraform/ministack/lambda.zip") + error_message = "The test setup should create its inert Lambda archive in the Terraform cache." + } +} + +run "apply_default_example" { + command = apply + + override_module { + target = module.webhook_github_app + } + + override_data { + target = module.runners.module.runners.data.aws_ami.runner + values = { + id = "ami-00000000000000000" + name = "al2023-ami-ministack-test" + creation_date = "2026-08-24T00:00:00.000Z" + deprecation_time = "" + } + } + + variables { + environment = "ministack" + github_app = { + id = "0" + key_base64 = "bWluaXN0YWNrLWludmFsaWQtZ2l0aHViLWFwcC1rZXk=" + } + lambda_zip_overrides = { + ami_housekeeper = run.setup_lambda_archive.lambda_archive + runner_binaries_syncer = run.setup_lambda_archive.lambda_archive + runners = run.setup_lambda_archive.lambda_archive + termination_watcher = run.setup_lambda_archive.lambda_archive + webhook = run.setup_lambda_archive.lambda_archive + } + } + + assert { + condition = output.webhook_endpoint != "" + error_message = "The default example should create a webhook endpoint through MiniStack." + } + + assert { + condition = output.runners.lambda_syncer_name != "" + error_message = "The default example should create the runner binaries sync Lambda through MiniStack." + } +} diff --git a/examples/default/tests/setup/main.tf b/examples/default/tests/setup/main.tf new file mode 100644 index 0000000000..a4c49a87e4 --- /dev/null +++ b/examples/default/tests/setup/main.tf @@ -0,0 +1,52 @@ +terraform { + required_version = ">= 1.10.0" + + required_providers { + archive = { + source = "hashicorp/archive" + version = "~> 2.7" + } + local = { + source = "hashicorp/local" + version = "~> 2.0" + } + } +} + +locals { + lambda_source = <<-EOT + const response = async () => ({ statusCode: 200, body: "ministack" }); + + export { + response as adjustPool, + response as deregisterRetry, + response as directWebhook, + response as dispatchToRunners, + response as eventBridgeWebhook, + response as handler, + response as interruptionWarning, + response as jobRetryCheck, + response as scaleDownHandler, + response as scaleUpHandler, + response as ssmHousekeeper, + response as termination, + }; + EOT +} + +resource "local_file" "lambda_source" { + content = local.lambda_source + filename = "${path.module}/../../.terraform/ministack/index.mjs" + file_permission = "0644" +} + +data "archive_file" "lambda" { + type = "zip" + source_file = local_file.lambda_source.filename + output_path = "${path.module}/../../.terraform/ministack/lambda.zip" +} + +output "lambda_archive" { + description = "Path to the inert Lambda archive used by the MiniStack apply test." + value = data.archive_file.lambda.output_path +} diff --git a/examples/default/variables.tf b/examples/default/variables.tf index 8a3bce0854..baa49e0205 100644 --- a/examples/default/variables.tf +++ b/examples/default/variables.tf @@ -20,3 +20,16 @@ variable "aws_region" { type = string default = "eu-west-1" } + +variable "lambda_zip_overrides" { + description = "Optional local Lambda archive paths passed to the runner module." + + type = object({ + ami_housekeeper = optional(string) + runner_binaries_syncer = optional(string) + runners = optional(string) + termination_watcher = optional(string) + webhook = optional(string) + }) + default = {} +} diff --git a/tests/ministack/.terraform.lock.hcl b/tests/ministack/.terraform.lock.hcl deleted file mode 100644 index 700ec43e25..0000000000 --- a/tests/ministack/.terraform.lock.hcl +++ /dev/null @@ -1,74 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/archive" { - version = "2.8.0" - constraints = "~> 2.7" - hashes = [ - "h1:WB6H5ksIZiyq1lQlD/PWeh+tn4FLsbSjVnRW3+4xe2Y=", - "h1:cMBtvdHEgvTmglbioVehZCaOIPocumu9+vlGw5Dsaro=", - "h1:jdmKm+xl6ZcQrijxapnZ94RVuz/G4vk7hsIa1N0VT5Q=", - "zh:0d14713fdc259fb377d0b899ad3c650a34194bd52194c863303ef22a65a580e2", - "zh:369b56040c7a8085d04e7e8ffac1e2b321a3170e502f788819bc34b868ec016f", - "zh:4d1a3b983ed6af5a52bfe12794674ae55cbadfa6021b37106ade68b433ad216a", - "zh:5c547549e26e083573c78a966ca68ce6d7df6bb8f3948f66a575f07da46b74ea", - "zh:6de093e62a975eb19a5e3017ce38e6e3cb639c17b79648d2000e0a8348f0e997", - "zh:7267936c2cdbc448efeb594d73e6b56a53d6a7ae14fe88cdd2a4133adc3302f0", - "zh:7482f023050ed426b4b45116e1761643bc33b1fd4ce4a6fab207ae2571f35940", - "zh:76bbd93b234e5a2927d98b511d86565700f549b570871a194c35f944b96cefb7", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:c6afc4bc1f002bac9c173007dd4da05fde788cd14c2916089f958c33fedb0dfa", - "zh:d3ba40bd806a3a08e9237dece679193c99afb2085de6b45d7f5d1f673cfcd368", - "zh:e1ad7ded53ecd6f0e5b473a3b44eae2b2e885653a56050ab583d387332be02e4", - "zh:e93e78575ce82be6084cc153c24ba8f385dc8d6880888ee66e918460c870953d", - ] -} - -provider "registry.terraform.io/hashicorp/aws" { - version = "6.61.0" - constraints = ">= 6.21.0, >= 6.33.0" - hashes = [ - "h1:Kl91YvWRdorx6POwgdFf6ZBsHHa86GhazsqOwPvunyo=", - "h1:luPmlKygfw2SMKJkMQ++/J8rRR0ZgR0uJPupp8wy3pw=", - "h1:xgqNausjCmDbyoc3aY+flDVsUKgefbTjgKA9cQun4Ks=", - "zh:216566f0fbc506e107d3a961c87d88aed052ec2b4ced13388394d3cff30425ac", - "zh:4700ad141d0ad96465ac35a3900f2ff7c91a1e5528428ac687c8b5825c0be718", - "zh:6b79d2fa6550fc51e2fac04f1066c5cc96e957e7634ad86d2250240e637db205", - "zh:76f6227bf2bcd7422cf29d9868d8b517c8220ec3edd4e7c8434b867a71c03334", - "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:a7be5814cf94a8e3869ec9fa7f5182223a11373a4510ce68b9bab431f9b83746", - "zh:b65392e24506fe99f8df7bd2b5d3940d7a234b64b79a890f1aabe2be91a827e5", - "zh:b68a5092203cf5a9d1a5f01f9f2e96fded3eb7cacfd49ae851c50b87bc610fe9", - "zh:b8fedfa62bac16592519e1bae0c82dd7cd1544b0637543d72e3597e46ad7db32", - "zh:bba8a35212c07e68b6c881aa011c4b26a284e42b971059579aca9ffb63a8faef", - "zh:bbd0391e3e2f21c8930872829df7cf7f4e35f84c4d6d7b7619a94f8078fe6f3d", - "zh:c9c921e8e466281c04cada8d336ec1ce978128ee153e9df7b451847fbea49d18", - "zh:c9cb0be3097f4392b977fa254d28efd0909d008f572e74a41ead6c0d84c0daaa", - "zh:cc7aeb23fa3775816e391d4668a9865f787993f9f8d6f5b7a9f7e4effdffb3cb", - "zh:e59e487220cec8999bbd120ba8f97b5e04b010fb9149e47d4c9032961614d7c7", - "zh:fa19a7571a99397120f2f2bdcf33bbcc2f39091b9b0c879cd7e5f9ebb1966c40", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.9.0" - constraints = "~> 3.7" - hashes = [ - "h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=", - "h1:UlBuNVuCGJ39tTv2c5gz2NRZnQbXfbIWbTzWcth5o74=", - "h1:lVDv+0AjDjrLfpmaJbWqUmIw/k3/AHXLc3N4m55SNdo=", - "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", - "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", - "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", - "zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0", - "zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61", - "zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc", - "zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e", - "zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef", - "zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b", - "zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257", - "zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04", - ] -} diff --git a/tests/ministack/README.md b/tests/ministack/README.md deleted file mode 100644 index 6d9e35784e..0000000000 --- a/tests/ministack/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# MiniStack apply test - -This fixture applies the `ssm`, `setup-iam-permissions`, and `lambda` modules -against [MiniStack](https://github.com/ministackorg/ministack). It exercises -real AWS provider create, read, and delete calls without an AWS account. - -The fixture configures synthetic credentials in the AWS provider, and the -GitHub Actions workflow routes every AWS service to the `ministack` service -container. For a local run, start MiniStack on port 4566 and set the global AWS -endpoint before running Terraform: - -```shell -docker run --detach --rm --name terraform-aws-github-runner-ministack \ - --publish 127.0.0.1:4566:4566 \ - --env MINISTACK_ACCOUNT_ID=000000000000 \ - --env MINISTACK_REGION=eu-west-1 \ - ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 - -curl --fail --retry 10 --retry-connrefused --retry-delay 1 \ - http://127.0.0.1:4566/_ministack/health - -export AWS_ENDPOINT_URL=http://127.0.0.1:4566 -export AWS_REGION=eu-west-1 -export AWS_EC2_METADATA_DISABLED=true - -terraform init -backend=false -input=false -terraform apply -auto-approve -input=false -terraform destroy -auto-approve -input=false -docker stop terraform-aws-github-runner-ministack -``` - -Run the Terraform commands from this directory. The endpoint input only accepts -the loopback addresses used locally and the service hostname used in CI. The -provider also ignores ambient AWS credentials, and `AWS_ENDPOINT_URL` catches -any AWS service added to the fixture in the future. - -This test covers AWS provider and module API compatibility. MiniStack runs with -authorization disabled, so it does not validate IAM policy enforcement, real -KMS encryption, Lambda execution, or AWS service limits. - - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.10.0 | -| [archive](#requirement\_archive) | ~> 2.7 | -| [aws](#requirement\_aws) | >= 6.33 | -| [random](#requirement\_random) | ~> 3.7 | - -## Providers - -| Name | Version | -|------|---------| -| [archive](#provider\_archive) | 2.8.0 | -| [aws](#provider\_aws) | 6.61.0 | -| [random](#provider\_random) | 3.9.0 | - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| [lambda](#module\_lambda) | ../../modules/lambda | n/a | -| [setup\_iam\_permissions](#module\_setup\_iam\_permissions) | ../../modules/setup-iam-permissions | n/a | -| [ssm](#module\_ssm) | ../../modules/ssm | n/a | - -## Resources - -| Name | Type | -|------|------| -| [random_password.additional_github_app_key](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | -| [random_password.github_app_key](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | -| [random_password.github_webhook_secret](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | -| [archive_file.lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | -| [aws_caller_identity.ministack](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [ministack\_endpoint](#input\_ministack\_endpoint) | HTTP endpoint for the local MiniStack instance. | `string` | `"http://127.0.0.1:4566"` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| [applied\_resources](#output\_applied\_resources) | Representative resources created through the MiniStack AWS API. | - \ No newline at end of file diff --git a/tests/ministack/main.tf b/tests/ministack/main.tf deleted file mode 100644 index 0cbf2bcbfb..0000000000 --- a/tests/ministack/main.tf +++ /dev/null @@ -1,138 +0,0 @@ -terraform { - required_version = ">= 1.10.0" - - required_providers { - archive = { - source = "hashicorp/archive" - version = "~> 2.7" - } - aws = { - source = "hashicorp/aws" - version = ">= 6.33" - } - random = { - source = "hashicorp/random" - version = "~> 3.7" - } - } -} - -variable "ministack_endpoint" { - description = "HTTP endpoint for the local MiniStack instance." - type = string - default = "http://127.0.0.1:4566" - - validation { - condition = contains([ - "http://127.0.0.1:4566", - "http://localhost:4566", - "http://ministack:4566", - ], var.ministack_endpoint) - error_message = "The MiniStack endpoint must use port 4566 on the local host or the CI service hostname." - } -} - -provider "aws" { - access_key = "000000000000" - region = "eu-west-1" - secret_key = sha256("ministack:${var.ministack_endpoint}") - skip_credentials_validation = true - skip_metadata_api_check = true - skip_requesting_account_id = true - - endpoints { - iam = var.ministack_endpoint - lambda = var.ministack_endpoint - logs = var.ministack_endpoint - ssm = var.ministack_endpoint - sts = var.ministack_endpoint - } -} - -data "aws_caller_identity" "ministack" {} - -data "archive_file" "lambda" { - type = "zip" - output_path = "${path.root}/.terraform/ministack-lambda.zip" - - source { - content = "exports.handler = async () => ({ statusCode: 200, body: 'ok' });" - filename = "index.js" - } -} - -resource "random_password" "github_app_key" { - length = 64 - special = false -} - -resource "random_password" "github_webhook_secret" { - length = 32 - special = false -} - -resource "random_password" "additional_github_app_key" { - length = 64 - special = false -} - -module "ssm" { - source = "../../modules/ssm" - - path_prefix = "/ministack/terraform-aws-github-runner" - github_app = { - id = "ministack-primary-app" - key_base64 = base64encode(random_password.github_app_key.result) - webhook_secret = random_password.github_webhook_secret.result - } - additional_github_apps = [{ - id = "ministack-additional-app" - key_base64 = base64encode(random_password.additional_github_app_key.result) - installation_id = "ministack-installation" - }] - tags = { - Test = "ministack" - } -} - -module "setup_iam_permissions" { - source = "../../modules/setup-iam-permissions" - - prefix = "ministack-test" - account_id = data.aws_caller_identity.ministack.account_id - namespaces = { - boundary_namespace = "ministack-boundaries" - instance_profile_namespace = "ministack-instance-profiles" - policy_namespace = "ministack-policies" - role_namespace = "ministack-roles" - } -} - -module "lambda" { - source = "../../modules/lambda" - - lambda = { - architecture = "x86_64" - handler = "index.handler" - logging_retention_in_days = 1 - name = "api-compatibility" - prefix = "ministack-test" - runtime = "nodejs22.x" - tags = { - Test = "ministack" - } - zip = data.archive_file.lambda.output_path - } -} - -output "applied_resources" { - description = "Representative resources created through the MiniStack AWS API." - value = { - caller_account_id = data.aws_caller_identity.ministack.account_id - deployment_boundary = module.setup_iam_permissions.boundary - deployment_role = module.setup_iam_permissions.role - lambda_arn = module.lambda.lambda.function.arn - lambda_log_group = module.lambda.lambda.log_group.arn - ssm_parameters = module.ssm.parameters - } -} From 72e15bf387665cf5dbefd471552acc8987944130 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 11:47:31 +0000 Subject: [PATCH 04/13] docs: auto update terraform docs --- examples/default/tests/setup/README.md | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 examples/default/tests/setup/README.md diff --git a/examples/default/tests/setup/README.md b/examples/default/tests/setup/README.md new file mode 100644 index 0000000000..74d8d69662 --- /dev/null +++ b/examples/default/tests/setup/README.md @@ -0,0 +1,37 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.10.0 | +| [archive](#requirement\_archive) | ~> 2.7 | +| [local](#requirement\_local) | ~> 2.0 | + +## Providers + +| Name | Version | +|------|---------| +| [archive](#provider\_archive) | ~> 2.7 | +| [local](#provider\_local) | ~> 2.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [local_file.lambda_source](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | +| [archive_file.lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [lambda\_archive](#output\_lambda\_archive) | Path to the inert Lambda archive used by the MiniStack apply test. | + \ No newline at end of file From 687bd1c4ea7dfd1eec9a558400185aeab916ef34 Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Mon, 24 Aug 2026 16:43:27 +0200 Subject: [PATCH 05/13] test(terraform): apply examples against MiniStack --- .github/workflows/ministack.yml | 99 ++++++++++----- .gitignore | 1 + examples/base/.terraform.lock.hcl | 34 +++--- examples/default/.terraform.lock.hcl | 21 ---- examples/default/README.md | 25 ---- examples/default/main.tf | 7 +- examples/default/tests/ministack.tftest.hcl | 67 ---------- examples/default/tests/setup/README.md | 37 ------ examples/default/tests/setup/main.tf | 52 -------- examples/default/variables.tf | 13 -- .../permissions-boundary/.terraform.lock.hcl | 115 +++++++++--------- .../setup/.terraform.lock.hcl | 76 +++++++++--- .../termination-watcher/.terraform.lock.hcl | 34 +++--- tests/ministack/README.md | 30 +++++ tests/ministack/overrides/base_override.tf | 7 ++ tests/ministack/overrides/common.tf | 19 +++ tests/ministack/overrides/default_override.tf | 29 +++++ .../ministack/overrides/ephemeral_override.tf | 23 ++++ .../external-managed-ssm-secrets_override.tf | 27 ++++ .../overrides/multi-runner_override.tf | 36 ++++++ .../permissions-boundary-provider_override.tf | 14 +++ .../permissions-boundary_override.tf | 13 ++ .../ministack/overrides/prebuilt_override.tf | 26 ++++ tests/ministack/overrides/provider.tf | 13 ++ .../overrides/termination-watcher_override.tf | 15 +++ .../ministack/overrides/versions_override.tf | 8 ++ tests/ministack/run-example.sh | 103 ++++++++++++++++ tests/ministack/setup/.terraform.lock.hcl | 46 +++++++ tests/ministack/setup/index.mjs | 16 +++ tests/ministack/setup/main.tf | 69 +++++++++++ 30 files changed, 718 insertions(+), 357 deletions(-) delete mode 100644 examples/default/tests/ministack.tftest.hcl delete mode 100644 examples/default/tests/setup/README.md delete mode 100644 examples/default/tests/setup/main.tf create mode 100644 tests/ministack/README.md create mode 100644 tests/ministack/overrides/base_override.tf create mode 100644 tests/ministack/overrides/common.tf create mode 100644 tests/ministack/overrides/default_override.tf create mode 100644 tests/ministack/overrides/ephemeral_override.tf create mode 100644 tests/ministack/overrides/external-managed-ssm-secrets_override.tf create mode 100644 tests/ministack/overrides/multi-runner_override.tf create mode 100644 tests/ministack/overrides/permissions-boundary-provider_override.tf create mode 100644 tests/ministack/overrides/permissions-boundary_override.tf create mode 100644 tests/ministack/overrides/prebuilt_override.tf create mode 100644 tests/ministack/overrides/provider.tf create mode 100644 tests/ministack/overrides/termination-watcher_override.tf create mode 100644 tests/ministack/overrides/versions_override.tf create mode 100755 tests/ministack/run-example.sh create mode 100644 tests/ministack/setup/.terraform.lock.hcl create mode 100644 tests/ministack/setup/index.mjs create mode 100644 tests/ministack/setup/main.tf diff --git a/.github/workflows/ministack.yml b/.github/workflows/ministack.yml index 76517dc8a0..092ed30173 100644 --- a/.github/workflows/ministack.yml +++ b/.github/workflows/ministack.yml @@ -1,4 +1,4 @@ -name: "MiniStack Terraform apply" +name: "MiniStack Terraform lifecycle" on: push: @@ -6,31 +6,19 @@ on: - main paths: - ".github/workflows/ministack.yml" + - "tests/ministack/**" - "*.tf" - "policies/**" - - "examples/base/**" - - "examples/default/**" - - "modules/ami-housekeeper/**" - - "modules/lambda/**" - - "modules/runner-binaries-syncer/**" - - "modules/runners/**" - - "modules/ssm/**" - - "modules/termination-watcher/**" - - "modules/webhook/**" + - "examples/**" + - "modules/**" pull_request: paths: - ".github/workflows/ministack.yml" + - "tests/ministack/**" - "*.tf" - "policies/**" - - "examples/base/**" - - "examples/default/**" - - "modules/ami-housekeeper/**" - - "modules/lambda/**" - - "modules/runner-binaries-syncer/**" - - "modules/runners/**" - - "modules/ssm/**" - - "modules/termination-watcher/**" - - "modules/webhook/**" + - "examples/**" + - "modules/**" workflow_dispatch: concurrency: @@ -51,10 +39,23 @@ env: TF_INPUT: "false" jobs: - terraform_apply: - name: Apply default example against MiniStack + terraform_lifecycle: + name: Apply/destroy ${{ matrix.example }} against MiniStack runs-on: ubuntu-latest - timeout-minutes: 15 + timeout-minutes: 30 + strategy: + fail-fast: false + max-parallel: 4 + matrix: + example: + - base + - default + - ephemeral + - external-managed-ssm-secrets + - multi-runner + - permissions-boundary + - prebuilt + - termination-watcher container: image: hashicorp/terraform@sha256:1d10ec4073f4ddbdf34a28540a3b9250852ab500cb1c53f68c8bd17d82f474d8 # 1.14 services: @@ -63,9 +64,6 @@ jobs: env: MINISTACK_ACCOUNT_ID: "000000000000" MINISTACK_REGION: eu-west-1 - defaults: - run: - working-directory: examples/default steps: - name: Harden the runner (Audit all outbound calls) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 @@ -77,8 +75,51 @@ jobs: with: persist-credentials: false - - name: Terraform init - run: terraform init -backend=false -input=false + - id: prepare + name: Prepare isolated fixture + env: + EXAMPLE: ${{ matrix.example }} + run: tests/ministack/run-example.sh prepare "$EXAMPLE" + + - id: fixture + name: Apply shared fixture + env: + EXAMPLE: ${{ matrix.example }} + run: tests/ministack/run-example.sh fixture-apply "$EXAMPLE" + + - id: setup + name: Apply permissions-boundary prerequisite + if: matrix.example == 'permissions-boundary' + env: + EXAMPLE: ${{ matrix.example }} + run: tests/ministack/run-example.sh setup-apply "$EXAMPLE" + + - id: init + name: Terraform init + env: + EXAMPLE: ${{ matrix.example }} + run: tests/ministack/run-example.sh init "$EXAMPLE" - - name: Terraform apply test - run: terraform test -filter=tests/ministack.tftest.hcl + - id: apply + name: Terraform apply + env: + EXAMPLE: ${{ matrix.example }} + run: tests/ministack/run-example.sh apply "$EXAMPLE" + + - name: Terraform destroy + if: always() && steps.init.outcome == 'success' + env: + EXAMPLE: ${{ matrix.example }} + run: tests/ministack/run-example.sh destroy "$EXAMPLE" + + - name: Destroy permissions-boundary prerequisite + if: always() && matrix.example == 'permissions-boundary' && steps.setup.outcome != 'skipped' + env: + EXAMPLE: ${{ matrix.example }} + run: tests/ministack/run-example.sh setup-destroy "$EXAMPLE" + + - name: Destroy shared fixture + if: always() && steps.prepare.outcome == 'success' && steps.fixture.outcome != 'skipped' + env: + EXAMPLE: ${{ matrix.example }} + run: tests/ministack/run-example.sh fixture-destroy "$EXAMPLE" diff --git a/.gitignore b/.gitignore index 276fe10733..9bb0ac7d7e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ # lock files **/.terraform.lock.hcl !examples/**/.terraform.lock.hcl +!tests/ministack/setup/.terraform.lock.hcl # keys diff --git a/examples/base/.terraform.lock.hcl b/examples/base/.terraform.lock.hcl index c160b58a9e..5b187aa735 100644 --- a/examples/base/.terraform.lock.hcl +++ b/examples/base/.terraform.lock.hcl @@ -2,24 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "6.0.0" - constraints = ">= 5.0.0, >= 6.0.0" + version = "6.35.1" + constraints = ">= 5.0.0, 6.35.1" hashes = [ - "h1:dbRRZ1NzH1QV/+83xT/X3MLYaZobMXt8DNwbqnJojpo=", - "zh:16b1bb786719b7ebcddba3ab751b976ebf4006f7144afeebcb83f0c5f41f8eb9", - "zh:1fbc08b817b9eaf45a2b72ccba59f4ea19e7fcf017be29f5a9552b623eccc5bc", - "zh:304f58f3333dbe846cfbdfc2227e6ed77041ceea33b6183972f3f8ab51bd065f", - "zh:4cd447b5c24f14553bd6e1a0e4fea3c7d7b218cbb2316a3d93f1c5cb562c181b", - "zh:589472b56be8277558616075fc5480fcd812ba6dc70e8979375fc6d8750f83ef", - "zh:5d78484ba43c26f1ef6067c4150550b06fd39c5d4bfb790f92c4a6f7d9d0201b", - "zh:5f470ce664bffb22ace736643d2abe7ad45858022b652143bcd02d71d38d4e42", - "zh:7a9cbb947aaab8c885096bce5da22838ca482196cf7d04ffb8bdf7fd28003e47", - "zh:854df3e4c50675e727705a0eaa4f8d42ccd7df6a5efa2456f0205a9901ace019", - "zh:87162c0f47b1260f5969679dccb246cb528f27f01229d02fd30a8e2f9869ba2c", - "zh:9a145404d506b52078cd7060e6cbb83f8fc7953f3f63a5e7137d41f69d6317a3", + "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", + "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", + "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", + "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", + "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", + "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", + "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", + "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", + "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", + "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:a4eab2649f5afe06cc406ce2aaf9fd44dcf311123f48d344c255e93454c08921", - "zh:bea09141c6186a3e133413ae3a2e3d1aaf4f43466a6a468827287527edf21710", - "zh:d7ea2a35ff55ddfe639ab3b04331556b772a8698eca01f5d74151615d9f336db", + "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", + "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", + "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", + "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", + "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", ] } diff --git a/examples/default/.terraform.lock.hcl b/examples/default/.terraform.lock.hcl index c9bdeb915e..136f5367b1 100644 --- a/examples/default/.terraform.lock.hcl +++ b/examples/default/.terraform.lock.hcl @@ -1,27 +1,6 @@ # This file is maintained automatically by "terraform init". # Manual edits may be lost in future updates. -provider "registry.terraform.io/hashicorp/archive" { - version = "2.8.0" - constraints = "~> 2.7" - hashes = [ - "h1:WB6H5ksIZiyq1lQlD/PWeh+tn4FLsbSjVnRW3+4xe2Y=", - "zh:0d14713fdc259fb377d0b899ad3c650a34194bd52194c863303ef22a65a580e2", - "zh:369b56040c7a8085d04e7e8ffac1e2b321a3170e502f788819bc34b868ec016f", - "zh:4d1a3b983ed6af5a52bfe12794674ae55cbadfa6021b37106ade68b433ad216a", - "zh:5c547549e26e083573c78a966ca68ce6d7df6bb8f3948f66a575f07da46b74ea", - "zh:6de093e62a975eb19a5e3017ce38e6e3cb639c17b79648d2000e0a8348f0e997", - "zh:7267936c2cdbc448efeb594d73e6b56a53d6a7ae14fe88cdd2a4133adc3302f0", - "zh:7482f023050ed426b4b45116e1761643bc33b1fd4ce4a6fab207ae2571f35940", - "zh:76bbd93b234e5a2927d98b511d86565700f549b570871a194c35f944b96cefb7", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:c6afc4bc1f002bac9c173007dd4da05fde788cd14c2916089f958c33fedb0dfa", - "zh:d3ba40bd806a3a08e9237dece679193c99afb2085de6b45d7f5d1f673cfcd368", - "zh:e1ad7ded53ecd6f0e5b473a3b44eae2b2e885653a56050ab583d387332be02e4", - "zh:e93e78575ce82be6084cc153c24ba8f385dc8d6880888ee66e918460c870953d", - ] -} - provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" diff --git a/examples/default/README.md b/examples/default/README.md index 91756dd8c7..c75e37831f 100644 --- a/examples/default/README.md +++ b/examples/default/README.md @@ -28,30 +28,6 @@ The example will try to update the webhook of your GitHub. In case the update fa terraform output -raw webhook_secret ``` -## MiniStack apply test - -The MiniStack test applies this example with synthetic GitHub App values and -inert Lambda archives. It overrides the GitHub App webhook updater and AMI -lookup, while all AWS resources are created through the local MiniStack API. -Terraform test destroys the resources and keeps the generated inert archive -isolated in the ignored `.terraform/ministack/` cache. - -With Terraform 1.10 or newer, start MiniStack locally, route the AWS provider -to it, and run the focused test: - -```bash -docker run --detach --rm --name terraform-aws-github-runner-ministack \ - --publish 127.0.0.1:4566:4566 \ - --env MINISTACK_ACCOUNT_ID=000000000000 \ - --env MINISTACK_REGION=eu-west-1 \ - ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 - -export AWS_ENDPOINT_URL=http://127.0.0.1:4566 -terraform init -backend=false -input=false -terraform test -filter=tests/ministack.tftest.hcl -docker stop terraform-aws-github-runner-ministack -``` - ## Requirements @@ -89,7 +65,6 @@ docker stop terraform-aws-github-runner-ministack | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [lambda\_zip\_overrides](#input\_lambda\_zip\_overrides) | Optional local Lambda archive paths passed to the runner module. |
object({
ami_housekeeper = optional(string)
runner_binaries_syncer = optional(string)
runners = optional(string)
termination_watcher = optional(string)
webhook = optional(string)
})
| `{}` | no | ## Outputs diff --git a/examples/default/main.tf b/examples/default/main.tf index caa69abbef..71c69612c3 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -49,9 +49,6 @@ module "runners" { # webhook_lambda_zip = "../lambdas-download/webhook.zip" # runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" # runners_lambda_zip = "../lambdas-download/runners.zip" - webhook_lambda_zip = var.lambda_zip_overrides.webhook - runner_binaries_syncer_lambda_zip = var.lambda_zip_overrides.runner_binaries_syncer - runners_lambda_zip = var.lambda_zip_overrides.runners enable_organization_runners = true # Note: labels starting with `ghr-` are ignored during webhook label matching @@ -111,8 +108,7 @@ module "runners" { # capture_http_requests = true # } - enable_ami_housekeeper = true - ami_housekeeper_lambda_zip = var.lambda_zip_overrides.ami_housekeeper + enable_ami_housekeeper = true ami_housekeeper_cleanup_config = { ssmParameterNames = ["*/ami-id"] minimumDaysOld = 10 @@ -126,7 +122,6 @@ module "runners" { instance_termination_watcher = { enable = true - zip = var.lambda_zip_overrides.termination_watcher } # enable metric creation (experimental) diff --git a/examples/default/tests/ministack.tftest.hcl b/examples/default/tests/ministack.tftest.hcl deleted file mode 100644 index 7b564028d7..0000000000 --- a/examples/default/tests/ministack.tftest.hcl +++ /dev/null @@ -1,67 +0,0 @@ -provider "aws" { - region = "eu-west-1" - - access_key = "000000000000" - secret_key = "test-only" - - skip_credentials_validation = true - skip_metadata_api_check = true - skip_requesting_account_id = true - s3_use_path_style = true -} - -run "setup_lambda_archive" { - command = apply - - module { - source = "./tests/setup" - } - - assert { - condition = endswith(output.lambda_archive, ".terraform/ministack/lambda.zip") - error_message = "The test setup should create its inert Lambda archive in the Terraform cache." - } -} - -run "apply_default_example" { - command = apply - - override_module { - target = module.webhook_github_app - } - - override_data { - target = module.runners.module.runners.data.aws_ami.runner - values = { - id = "ami-00000000000000000" - name = "al2023-ami-ministack-test" - creation_date = "2026-08-24T00:00:00.000Z" - deprecation_time = "" - } - } - - variables { - environment = "ministack" - github_app = { - id = "0" - key_base64 = "bWluaXN0YWNrLWludmFsaWQtZ2l0aHViLWFwcC1rZXk=" - } - lambda_zip_overrides = { - ami_housekeeper = run.setup_lambda_archive.lambda_archive - runner_binaries_syncer = run.setup_lambda_archive.lambda_archive - runners = run.setup_lambda_archive.lambda_archive - termination_watcher = run.setup_lambda_archive.lambda_archive - webhook = run.setup_lambda_archive.lambda_archive - } - } - - assert { - condition = output.webhook_endpoint != "" - error_message = "The default example should create a webhook endpoint through MiniStack." - } - - assert { - condition = output.runners.lambda_syncer_name != "" - error_message = "The default example should create the runner binaries sync Lambda through MiniStack." - } -} diff --git a/examples/default/tests/setup/README.md b/examples/default/tests/setup/README.md deleted file mode 100644 index 74d8d69662..0000000000 --- a/examples/default/tests/setup/README.md +++ /dev/null @@ -1,37 +0,0 @@ - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.10.0 | -| [archive](#requirement\_archive) | ~> 2.7 | -| [local](#requirement\_local) | ~> 2.0 | - -## Providers - -| Name | Version | -|------|---------| -| [archive](#provider\_archive) | ~> 2.7 | -| [local](#provider\_local) | ~> 2.0 | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [local_file.lambda_source](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | -| [archive_file.lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | - -## Inputs - -No inputs. - -## Outputs - -| Name | Description | -|------|-------------| -| [lambda\_archive](#output\_lambda\_archive) | Path to the inert Lambda archive used by the MiniStack apply test. | - \ No newline at end of file diff --git a/examples/default/tests/setup/main.tf b/examples/default/tests/setup/main.tf deleted file mode 100644 index a4c49a87e4..0000000000 --- a/examples/default/tests/setup/main.tf +++ /dev/null @@ -1,52 +0,0 @@ -terraform { - required_version = ">= 1.10.0" - - required_providers { - archive = { - source = "hashicorp/archive" - version = "~> 2.7" - } - local = { - source = "hashicorp/local" - version = "~> 2.0" - } - } -} - -locals { - lambda_source = <<-EOT - const response = async () => ({ statusCode: 200, body: "ministack" }); - - export { - response as adjustPool, - response as deregisterRetry, - response as directWebhook, - response as dispatchToRunners, - response as eventBridgeWebhook, - response as handler, - response as interruptionWarning, - response as jobRetryCheck, - response as scaleDownHandler, - response as scaleUpHandler, - response as ssmHousekeeper, - response as termination, - }; - EOT -} - -resource "local_file" "lambda_source" { - content = local.lambda_source - filename = "${path.module}/../../.terraform/ministack/index.mjs" - file_permission = "0644" -} - -data "archive_file" "lambda" { - type = "zip" - source_file = local_file.lambda_source.filename - output_path = "${path.module}/../../.terraform/ministack/lambda.zip" -} - -output "lambda_archive" { - description = "Path to the inert Lambda archive used by the MiniStack apply test." - value = data.archive_file.lambda.output_path -} diff --git a/examples/default/variables.tf b/examples/default/variables.tf index baa49e0205..8a3bce0854 100644 --- a/examples/default/variables.tf +++ b/examples/default/variables.tf @@ -20,16 +20,3 @@ variable "aws_region" { type = string default = "eu-west-1" } - -variable "lambda_zip_overrides" { - description = "Optional local Lambda archive paths passed to the runner module." - - type = object({ - ami_housekeeper = optional(string) - runner_binaries_syncer = optional(string) - runners = optional(string) - termination_watcher = optional(string) - webhook = optional(string) - }) - default = {} -} diff --git a/examples/permissions-boundary/.terraform.lock.hcl b/examples/permissions-boundary/.terraform.lock.hcl index be40c689d7..54f9bc8743 100644 --- a/examples/permissions-boundary/.terraform.lock.hcl +++ b/examples/permissions-boundary/.terraform.lock.hcl @@ -2,84 +2,87 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "6.22.1" - constraints = ">= 5.0.0, >= 6.21.0" + version = "6.35.1" + constraints = ">= 5.0.0, >= 6.21.0, >= 6.33.0, 6.35.1" hashes = [ - "h1:PTgxp+nMDBd6EFHAIH6ceFfvwa2blqkCwXglZn6Dqa8=", - "zh:3995ca97e6c2c1ed9e231c453287585d3dc1ca2a304683ac0b269b3448fda7c0", - "zh:4f69f70d2edeb0dde9c693b7cd7e8e21c781b2fac7062bed5300092dbadb71e1", - "zh:5c76042fdf3df56a1f581bc477e5d6fc3e099d4d6544fe725b3747e9990726bd", - "zh:6ff8221340955f4b3ba9230918bb026c4414a5aebe9d0967845c43e8e8908aec", - "zh:73cdd8638cb52bbe25887cd5b7946cc3fcb891867de11bcb0fde9b35c4f70a41", - "zh:7af5aec2fd01fa5e5f600f1db1bcf200aaadc05a2c8ffcbb4b6b61cd2bd3e33b", - "zh:7e055cfa7f40b667f5f7af564db9544f46aa189cdbe5530ad812e027647132f5", + "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", + "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", + "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", + "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", + "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", + "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", + "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", + "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", + "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", + "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:aba898190c668ade4471da65c96db414679367174ac5b73e8ce7551056c77e3e", - "zh:aedaa8d7d71e6d58cdc09a7e3bcb8031b3ea496a7ac142376eb679d1756057f3", - "zh:cb9739952d467b3f6d72d57722943956e80ab235b58a0e34758538381dcc386c", - "zh:e12a2681028a70cb08eaf4c3364ddab386416502f966067bf99e79ba6be0d7b6", - "zh:e32a922a7d6fd5df69b3cc92932fc2689dc195b0f8b493dcd686abdd892b06cd", - "zh:f2dea7dead6f34b51e8b6aae177a8b333834a41d25529baa634a087d99ea32f6", - "zh:f6eee6df0366e8452d912cfd498792579aede88de3b67c15d36b8949e37479b1", + "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", + "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", + "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", + "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", + "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.6.1" + version = "2.9.0" constraints = "~> 2.0" hashes = [ - "h1:DbiR/D2CPigzCGweYIyJH0N0x04oyI5xiZ9wSW/s3kQ=", - "zh:10050d08f416de42a857e4b6f76809aae63ea4ec6f5c852a126a915dede814b4", - "zh:2df2a3ebe9830d4759c59b51702e209fe053f47453cb4688f43c063bac8746b7", - "zh:2e759568bcc38c86ca0e43701d34cf29945736fdc8e429c5b287ddc2703c7b18", - "zh:6a62a34e48500ab4aea778e355e162ebde03260b7a9eb9edc7e534c84fbca4c6", - "zh:74373728ba32a1d5450a3a88ac45624579e32755b086cd4e51e88d9aca240ef6", + "h1:m24fjcInWvTVZ1XSo2MaNuKPe+X/gfG8SIi09rA7a7M=", + "zh:0baa4566cf77f1ff52f4293d1c8536202dd23edc197c3196413a28343c3ac3a0", + "zh:16b5559c3c07088ddad11a9bb9e9c0799999363c2958e9a5be2bcbbf2cd9ca64", + "zh:197c79015a10d1cce904a8ea722cbc750c42aeae2da53f44a6a0751d9fd1aa90", + "zh:29d0b03e5343a80677ebfeb2e2c31cbe4b1f65e736e53417454a4277fec2544c", + "zh:4896bfa6cf1d2fd562b47ef2e87f47862ae92a04f8ad5d764380f0c6653473b8", + "zh:531f8529cbca49f681883e57761a05a8398afaef6d1ab0d205d26bf12f4428e8", + "zh:6aaf5011d83161c86d2bfb80c0923ec934e578288758da2f37acb7aec129004b", + "zh:7430275253d3d3c40aa6179e0ec0d63212874dbbc06c5a51b9d07ec590f9756c", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:8dddae588971a996f622e7589cd8b9da7834c744ac12bfb59c97fa77ded95255", - "zh:946f82f66353bb97aefa8d95c4ca86db227f9b7c50b82415289ac47e4e74d08d", - "zh:e9a5c09e6f35e510acf15b666fd0b34a30164cecdcd81ce7cda0f4b2dade8d91", - "zh:eafe5b873ef42b32feb2f969c38ff8652507e695620cbaf03b9db714bee52249", - "zh:ec146289fa27650c9d433bb5c7847379180c0b7a323b1b94e6e7ad5d2a7dbe71", - "zh:fc882c35ce05631d76c0973b35adde26980778fc81d9da81a2fade2b9d73423b", + "zh:be17dc611e95e26cdf6cad79dfccf1064f0e32032a2efeb939a9bbe7fb1cbfe9", + "zh:f0e3b0aa644202e1d79d2000dca91f6019425da71e9800fa23f27e51c034f195", + "zh:f62bae4519e4ead49182ddc8afe8cf61e2a4c3ba3973b0fbba967736a2696aa3", + "zh:fcafa360a5b0b96244f26f4e3a6d642b716a376557142c2442ff2fb12d11da18", ] } provider "registry.terraform.io/hashicorp/null" { - version = "3.2.4" + version = "3.3.1" constraints = "~> 3.0, ~> 3.2" hashes = [ - "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", - "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", + "h1:m5FqidbIgh+E9OigiZh8/xbkvpUQFSj3hZo/jqNLCLQ=", + "zh:08c59776542ea16e5a8545752787b17ff412922182b4cfabe16139197be8ac44", + "zh:123109cc7e5ed6d515787fbc212f2a3fd5e75647bb24ab7c801ccd4d4ed42451", + "zh:14b3fa4372754b54844b41d5dbd4671a292d8d6828b90169061feb4d7b15dd05", + "zh:56a4daaa3212f57b764bf3d1f333141c6610c5f21abb240e0111221f7c7fa4d4", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", - "zh:7b9c7b16f118fbc2b05a983817b8ce2f86df125857966ad356353baf4bff5c0a", - "zh:85e33ab43e0e1726e5f97a874b8e24820b6565ff8076523cc2922ba671492991", - "zh:9d32ac3619cfc93eb3c4f423492a8e0f79db05fec58e449dee9b2d5873d5f69f", - "zh:9e15c3c9dd8e0d1e3731841d44c34571b6c97f5b95e8296a45318b94e5287a6e", - "zh:b4c2ab35d1b7696c30b64bf2c0f3a62329107bd1a9121ce70683dec58af19615", - "zh:c43723e8cc65bcdf5e0c92581dcbbdcbdcf18b8d2037406a5f2033b1e22de442", - "zh:ceb5495d9c31bfb299d246ab333f08c7fb0d67a4f82681fbf47f2a21c3e11ab5", - "zh:e171026b3659305c558d9804062762d168f50ba02b88b231d20ec99578a6233f", - "zh:ed0fe2acdb61330b01841fa790be00ec6beaac91d41f311fb8254f74eb6a711f", + "zh:7e888a026dbacd2474a42264227ae35f639780f0f0c613529d10a95cd61988b3", + "zh:85a53646267e87d600df7124e4767ffde9bba3b6356d45d961618bdd68131cc7", + "zh:8ffa0e9c7c39b2ab0905b472465d6e35ef0b776b3f6273bb34c150340b61bff1", + "zh:9846510a1841530d4403f4818e233f91e3b3bade7441047599fbf800742f65be", + "zh:afa98d44860875f037c6def0a7e6ff208e042712ba771f620482b143cd336891", + "zh:bdca130d9ef27488ae0b13bc8fd8019e8bbdd4f2ceff29da066bd333165d68c5", + "zh:cb3b94cbca88210dd0d1f11e2b8a89333f48c3857faf8f70f589072ce7c28610", + "zh:f0c0ba87925fe32f84b80f7513b1efb1b0866f51f899ba825e95ad59ff09b018", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.7.2" + version = "3.9.0" constraints = "~> 3.0" hashes = [ - "h1:KG4NuIBl1mRWU0KD/BGfCi1YN/j3F7H4YgeeM7iSdNs=", - "zh:14829603a32e4bc4d05062f059e545a91e27ff033756b48afbae6b3c835f508f", - "zh:1527fb07d9fea400d70e9e6eb4a2b918d5060d604749b6f1c361518e7da546dc", - "zh:1e86bcd7ebec85ba336b423ba1db046aeaa3c0e5f921039b3f1a6fc2f978feab", - "zh:24536dec8bde66753f4b4030b8f3ef43c196d69cccbea1c382d01b222478c7a3", - "zh:29f1786486759fad9b0ce4fdfbbfece9343ad47cd50119045075e05afe49d212", - "zh:4d701e978c2dd8604ba1ce962b047607701e65c078cb22e97171513e9e57491f", + "h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=", + "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", + "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", + "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", + "zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0", + "zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61", + "zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc", + "zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:7b8434212eef0f8c83f5a90c6d76feaf850f6502b61b53c329e85b3b281cba34", - "zh:ac8a23c212258b7976e1621275e3af7099e7e4a3d4478cf8d5d2a27f3bc3e967", - "zh:b516ca74431f3df4c6cf90ddcdb4042c626e026317a33c53f0b445a3d93b720d", - "zh:dc76e4326aec2490c1600d6871a95e78f9050f9ce427c71707ea412a2f2f1a62", - "zh:eac7b63e86c749c7d48f527671c7aee5b4e26c10be6ad7232d6860167f99dbb0", + "zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e", + "zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef", + "zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b", + "zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257", + "zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04", ] } diff --git a/examples/permissions-boundary/setup/.terraform.lock.hcl b/examples/permissions-boundary/setup/.terraform.lock.hcl index 9ccf7ef886..91bf7dac01 100644 --- a/examples/permissions-boundary/setup/.terraform.lock.hcl +++ b/examples/permissions-boundary/setup/.terraform.lock.hcl @@ -2,24 +2,66 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "5.31.0" - constraints = "~> 5.2" + version = "6.35.1" + constraints = ">= 6.21.0, 6.35.1" hashes = [ - "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", - "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", - "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", - "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", - "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", - "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", - "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", - "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", - "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", - "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", + "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", + "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", + "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", + "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", + "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", + "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", + "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", + "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", + "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", + "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", - "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", - "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", - "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", - "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", + "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", + "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", + "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", + "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", + "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", + ] +} + +provider "registry.terraform.io/hashicorp/local" { + version = "2.9.0" + constraints = "~> 2.0" + hashes = [ + "h1:m24fjcInWvTVZ1XSo2MaNuKPe+X/gfG8SIi09rA7a7M=", + "zh:0baa4566cf77f1ff52f4293d1c8536202dd23edc197c3196413a28343c3ac3a0", + "zh:16b5559c3c07088ddad11a9bb9e9c0799999363c2958e9a5be2bcbbf2cd9ca64", + "zh:197c79015a10d1cce904a8ea722cbc750c42aeae2da53f44a6a0751d9fd1aa90", + "zh:29d0b03e5343a80677ebfeb2e2c31cbe4b1f65e736e53417454a4277fec2544c", + "zh:4896bfa6cf1d2fd562b47ef2e87f47862ae92a04f8ad5d764380f0c6653473b8", + "zh:531f8529cbca49f681883e57761a05a8398afaef6d1ab0d205d26bf12f4428e8", + "zh:6aaf5011d83161c86d2bfb80c0923ec934e578288758da2f37acb7aec129004b", + "zh:7430275253d3d3c40aa6179e0ec0d63212874dbbc06c5a51b9d07ec590f9756c", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:be17dc611e95e26cdf6cad79dfccf1064f0e32032a2efeb939a9bbe7fb1cbfe9", + "zh:f0e3b0aa644202e1d79d2000dca91f6019425da71e9800fa23f27e51c034f195", + "zh:f62bae4519e4ead49182ddc8afe8cf61e2a4c3ba3973b0fbba967736a2696aa3", + "zh:fcafa360a5b0b96244f26f4e3a6d642b716a376557142c2442ff2fb12d11da18", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.9.0" + constraints = "~> 3.0" + hashes = [ + "h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=", + "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", + "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", + "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", + "zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0", + "zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61", + "zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc", + "zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e", + "zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef", + "zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b", + "zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257", + "zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04", ] } diff --git a/examples/termination-watcher/.terraform.lock.hcl b/examples/termination-watcher/.terraform.lock.hcl index 4f33187500..5840ca1343 100644 --- a/examples/termination-watcher/.terraform.lock.hcl +++ b/examples/termination-watcher/.terraform.lock.hcl @@ -2,24 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "6.22.1" - constraints = ">= 6.21.0" + version = "6.35.1" + constraints = ">= 6.21.0, 6.35.1" hashes = [ - "h1:PTgxp+nMDBd6EFHAIH6ceFfvwa2blqkCwXglZn6Dqa8=", - "zh:3995ca97e6c2c1ed9e231c453287585d3dc1ca2a304683ac0b269b3448fda7c0", - "zh:4f69f70d2edeb0dde9c693b7cd7e8e21c781b2fac7062bed5300092dbadb71e1", - "zh:5c76042fdf3df56a1f581bc477e5d6fc3e099d4d6544fe725b3747e9990726bd", - "zh:6ff8221340955f4b3ba9230918bb026c4414a5aebe9d0967845c43e8e8908aec", - "zh:73cdd8638cb52bbe25887cd5b7946cc3fcb891867de11bcb0fde9b35c4f70a41", - "zh:7af5aec2fd01fa5e5f600f1db1bcf200aaadc05a2c8ffcbb4b6b61cd2bd3e33b", - "zh:7e055cfa7f40b667f5f7af564db9544f46aa189cdbe5530ad812e027647132f5", + "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", + "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", + "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", + "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", + "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", + "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", + "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", + "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", + "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", + "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:aba898190c668ade4471da65c96db414679367174ac5b73e8ce7551056c77e3e", - "zh:aedaa8d7d71e6d58cdc09a7e3bcb8031b3ea496a7ac142376eb679d1756057f3", - "zh:cb9739952d467b3f6d72d57722943956e80ab235b58a0e34758538381dcc386c", - "zh:e12a2681028a70cb08eaf4c3364ddab386416502f966067bf99e79ba6be0d7b6", - "zh:e32a922a7d6fd5df69b3cc92932fc2689dc195b0f8b493dcd686abdd892b06cd", - "zh:f2dea7dead6f34b51e8b6aae177a8b333834a41d25529baa634a087d99ea32f6", - "zh:f6eee6df0366e8452d912cfd498792579aede88de3b67c15d36b8949e37479b1", + "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", + "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", + "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", + "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", + "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", ] } diff --git a/tests/ministack/README.md b/tests/ministack/README.md new file mode 100644 index 0000000000..1b9042a575 --- /dev/null +++ b/tests/ministack/README.md @@ -0,0 +1,30 @@ +# MiniStack example lifecycle tests + +The MiniStack workflow runs explicit `terraform apply` and `terraform destroy` +commands against the repository's runnable AWS examples. Every matrix entry gets +an isolated source tree, Terraform state, and MiniStack service. + +The fixture creates synthetic SSM values through MiniStack and an inert Lambda +archive under its ignored `.terraform/` directory. Test-only Terraform override +files route each example to that archive and a MiniStack AMI. They also disable +the `webhook-github-app` local-exec module, which would otherwise update a real +GitHub App. The production example configurations are not changed. + +| Example | Lifecycle coverage | +| --- | --- | +| `base` | VPC and Resource Groups | +| `default` | Full default runner stack | +| `ephemeral` | Ephemeral runner and job-retry stack | +| `external-managed-ssm-secrets` | Runner stack with fixture-owned external SSM parameters | +| `multi-runner` | All runner lanes: public/private SSM wiring for Linux x64/ARM64 and module-managed AMI parameters for three lanes | +| `permissions-boundary` | IAM setup, assumed-role runner stack, and reverse-order teardown | +| `prebuilt` | Prebuilt-runner stack using a MiniStack AMI | +| `termination-watcher` | Standalone termination watcher | + +Two examples are intentionally outside the matrix: + +- `dedicated-mac-hosts` requires the EC2 Dedicated Hosts and License Manager + APIs, which MiniStack v1.5.0 does not implement. +- `lambdas-download` has no AWS resources. Its apply operation downloads release + archives from GitHub, so it is not a MiniStack lifecycle test. The underlying + `download-lambda` module remains in the existing module validation matrix. diff --git a/tests/ministack/overrides/base_override.tf b/tests/ministack/overrides/base_override.tf new file mode 100644 index 0000000000..7450840076 --- /dev/null +++ b/tests/ministack/overrides/base_override.tf @@ -0,0 +1,7 @@ +variable "prefix" { + default = "ministack-base" +} + +variable "aws_region" { + default = "eu-west-1" +} diff --git a/tests/ministack/overrides/common.tf b/tests/ministack/overrides/common.tf new file mode 100644 index 0000000000..8cec884357 --- /dev/null +++ b/tests/ministack/overrides/common.tf @@ -0,0 +1,19 @@ +variable "ministack_lambda_archive" { + description = "Absolute path to the inert Lambda archive created by the MiniStack fixture." + type = string + + validation { + condition = endswith(var.ministack_lambda_archive, "/tests/ministack/setup/.terraform/ministack/lambda.zip") + error_message = "The MiniStack Lambda archive must come from the isolated test fixture." + } +} + +locals { + ministack_ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] + } +} diff --git a/tests/ministack/overrides/default_override.tf b/tests/ministack/overrides/default_override.tf new file mode 100644 index 0000000000..654aa37161 --- /dev/null +++ b/tests/ministack/overrides/default_override.tf @@ -0,0 +1,29 @@ +variable "environment" { + default = "ministack-default" +} + +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +module "runners" { + ami = local.ministack_ami + ami_housekeeper_lambda_zip = var.ministack_lambda_archive + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive + + instance_termination_watcher = { + enable = true + zip = var.ministack_lambda_archive + } +} + +# The production example updates GitHub through a local-exec provisioner. +# A zero count structurally prevents any external GitHub API call in this test. +module "webhook_github_app" { + count = 0 +} diff --git a/tests/ministack/overrides/ephemeral_override.tf b/tests/ministack/overrides/ephemeral_override.tf new file mode 100644 index 0000000000..ab85df74b1 --- /dev/null +++ b/tests/ministack/overrides/ephemeral_override.tf @@ -0,0 +1,23 @@ +variable "environment" { + default = "ministack-ephemeral" +} + +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +module "runners" { + ami = local.ministack_ami + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} + +# The production example updates GitHub through a local-exec provisioner. +# A zero count structurally prevents any external GitHub API call in this test. +module "webhook_github_app" { + count = 0 +} diff --git a/tests/ministack/overrides/external-managed-ssm-secrets_override.tf b/tests/ministack/overrides/external-managed-ssm-secrets_override.tf new file mode 100644 index 0000000000..701b8b61b8 --- /dev/null +++ b/tests/ministack/overrides/external-managed-ssm-secrets_override.tf @@ -0,0 +1,27 @@ +variable "environment" { + default = "ministack-external-ssm" +} + +variable "github_app_ssm_parameters" { + default = { + id = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id" + name = "/ministack/terraform-aws-github-runner/github-app/id" + } + key_base64 = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64" + name = "/ministack/terraform-aws-github-runner/github-app/key-base64" + } + webhook_secret = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret" + name = "/ministack/terraform-aws-github-runner/github-app/webhook-secret" + } + } +} + +module "runners" { + ami = local.ministack_ami + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} diff --git a/tests/ministack/overrides/multi-runner_override.tf b/tests/ministack/overrides/multi-runner_override.tf new file mode 100644 index 0000000000..4db65a2597 --- /dev/null +++ b/tests/ministack/overrides/multi-runner_override.tf @@ -0,0 +1,36 @@ +variable "environment" { + default = "ministack" +} + +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +locals { + multi_runner_config = { + for name, config in local.multi_runner_config_files : name => merge(config, { + runner_config = merge(config.runner_config, { + ami = contains(keys(config.runner_config), "ami") ? merge(local.ministack_ami, { + id_ssm_parameter_arn = lookup(local.ssm_ami_arns, name, null) + }) : null + subnet_ids = lookup(config.runner_config, "subnet_ids", null) != null ? [module.base.vpc.private_subnets[0]] : null + vpc_id = lookup(config.runner_config, "vpc_id", null) != null ? module.base.vpc.vpc_id : null + }) + }) + } +} + +module "runners" { + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} + +# The production example updates GitHub through a local-exec provisioner. +# A zero count structurally prevents any external GitHub API call in this test. +module "webhook_github_app" { + count = 0 +} diff --git a/tests/ministack/overrides/permissions-boundary-provider_override.tf b/tests/ministack/overrides/permissions-boundary-provider_override.tf new file mode 100644 index 0000000000..1c1a2ea07d --- /dev/null +++ b/tests/ministack/overrides/permissions-boundary-provider_override.tf @@ -0,0 +1,14 @@ +provider "aws" { + alias = "terraform_role" + region = "eu-west-1" + + # These values are MiniStack test identifiers and cannot authenticate to AWS. + access_key = "000000000000" + secret_key = "ministack-test-only" + + skip_credentials_validation = true + skip_metadata_api_check = true + skip_region_validation = true + skip_requesting_account_id = true + s3_use_path_style = true +} diff --git a/tests/ministack/overrides/permissions-boundary_override.tf b/tests/ministack/overrides/permissions-boundary_override.tf new file mode 100644 index 0000000000..b45b581f6b --- /dev/null +++ b/tests/ministack/overrides/permissions-boundary_override.tf @@ -0,0 +1,13 @@ +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +module "runners" { + ami = local.ministack_ami + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} diff --git a/tests/ministack/overrides/prebuilt_override.tf b/tests/ministack/overrides/prebuilt_override.tf new file mode 100644 index 0000000000..32c35b7f4d --- /dev/null +++ b/tests/ministack/overrides/prebuilt_override.tf @@ -0,0 +1,26 @@ +variable "environment" { + default = "ministack-prebuilt" +} + +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +variable "ami_name_filter" { + default = "amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2" +} + +module "runners" { + ami_housekeeper_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} + +# The production example updates GitHub through a local-exec provisioner. +# A zero count structurally prevents any external GitHub API call in this test. +module "webhook_github_app" { + count = 0 +} diff --git a/tests/ministack/overrides/provider.tf b/tests/ministack/overrides/provider.tf new file mode 100644 index 0000000000..d8718ca141 --- /dev/null +++ b/tests/ministack/overrides/provider.tf @@ -0,0 +1,13 @@ +provider "aws" { + region = "eu-west-1" + + # These values are MiniStack test identifiers and cannot authenticate to AWS. + access_key = "000000000000" + secret_key = "ministack-test-only" + + skip_credentials_validation = true + skip_metadata_api_check = true + skip_region_validation = true + skip_requesting_account_id = true + s3_use_path_style = true +} diff --git a/tests/ministack/overrides/termination-watcher_override.tf b/tests/ministack/overrides/termination-watcher_override.tf new file mode 100644 index 0000000000..b4f4a6833c --- /dev/null +++ b/tests/ministack/overrides/termination-watcher_override.tf @@ -0,0 +1,15 @@ +module "spot_termination_watchter" { + config = { + metrics = { + enable = true + metric = { + enable_spot_termination_warning = true + } + } + prefix = "global" + tag_filters = { + "ghr:Application" = "github-action-runner" + } + zip = var.ministack_lambda_archive + } +} diff --git a/tests/ministack/overrides/versions_override.tf b/tests/ministack/overrides/versions_override.tf new file mode 100644 index 0000000000..8c18ed1e34 --- /dev/null +++ b/tests/ministack/overrides/versions_override.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "= 6.35.1" + } + } +} diff --git a/tests/ministack/run-example.sh b/tests/ministack/run-example.sh new file mode 100755 index 0000000000..4d30670867 --- /dev/null +++ b/tests/ministack/run-example.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +set -eu + +action="${1:-}" +example="${2:-}" + +case "$example" in + base | default | ephemeral | external-managed-ssm-secrets | multi-runner | permissions-boundary | prebuilt | termination-watcher) ;; + *) + echo "Unsupported MiniStack example: $example" >&2 + exit 64 + ;; +esac + +case "$action" in + prepare | fixture-apply | setup-apply | init | apply | destroy | setup-destroy | fixture-destroy) ;; + *) + echo "Usage: $0 {prepare|fixture-apply|setup-apply|init|apply|destroy|setup-destroy|fixture-destroy} EXAMPLE" >&2 + exit 64 + ;; +esac + +script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) +source_root="${GITHUB_WORKSPACE:-$(CDPATH='' cd -- "$script_dir/../.." && pwd)}" +temporary_root="${RUNNER_TEMP:-${TMPDIR:-/tmp}}" +worktree="$temporary_root/terraform-aws-github-runner-ministack-$example" +example_root="$worktree/examples/$example" +fixture_root="$worktree/tests/ministack/setup" +lambda_archive="$fixture_root/.terraform/ministack/lambda.zip" + +terraform_example() { + terraform -chdir="$example_root" "$@" -var="ministack_lambda_archive=$lambda_archive" +} + +case "$action" in + prepare) + if [ -e "$worktree" ]; then + echo "Refusing to overwrite existing MiniStack worktree: $worktree" >&2 + exit 73 + fi + + mkdir -p "$worktree" + git -C "$source_root" archive --format=tar "${MINISTACK_SOURCE_REF:-${GITHUB_SHA:-HEAD}}" | tar -xf - -C "$worktree" + + if [ ! -f "$example_root/main.tf" ]; then + echo "The isolated worktree does not contain examples/$example/main.tf" >&2 + exit 66 + fi + + cp "$worktree/tests/ministack/overrides/common.tf" "$example_root/ministack_common.tf" + cp "$worktree/tests/ministack/overrides/${example}_override.tf" "$example_root/ministack_example_override.tf" + cp "$worktree/tests/ministack/overrides/versions_override.tf" "$example_root/ministack_versions_override.tf" + + case "$example" in + base | termination-watcher) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" + ;; + permissions-boundary) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" + cp "$worktree/tests/ministack/overrides/permissions-boundary-provider_override.tf" "$example_root/ministack_permissions_provider_override.tf" + ;; + *) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider_override.tf" + ;; + esac + + ;; + fixture-apply) + terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$fixture_root" apply -auto-approve -input=false + ;; + setup-apply) + if [ "$example" != "permissions-boundary" ]; then + exit 0 + fi + + terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$example_root/setup" apply -auto-approve -input=false + ;; + init) + terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + ;; + apply) + terraform_example apply -auto-approve -input=false + ;; + destroy) + terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + terraform_example destroy -auto-approve -input=false + ;; + setup-destroy) + if [ "$example" != "permissions-boundary" ]; then + exit 0 + fi + + terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$example_root/setup" destroy -auto-approve -input=false + ;; + fixture-destroy) + terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$fixture_root" destroy -auto-approve -input=false + ;; +esac diff --git a/tests/ministack/setup/.terraform.lock.hcl b/tests/ministack/setup/.terraform.lock.hcl new file mode 100644 index 0000000000..162bcd106b --- /dev/null +++ b/tests/ministack/setup/.terraform.lock.hcl @@ -0,0 +1,46 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/archive" { + version = "2.8.0" + constraints = "~> 2.7" + hashes = [ + "h1:WB6H5ksIZiyq1lQlD/PWeh+tn4FLsbSjVnRW3+4xe2Y=", + "zh:0d14713fdc259fb377d0b899ad3c650a34194bd52194c863303ef22a65a580e2", + "zh:369b56040c7a8085d04e7e8ffac1e2b321a3170e502f788819bc34b868ec016f", + "zh:4d1a3b983ed6af5a52bfe12794674ae55cbadfa6021b37106ade68b433ad216a", + "zh:5c547549e26e083573c78a966ca68ce6d7df6bb8f3948f66a575f07da46b74ea", + "zh:6de093e62a975eb19a5e3017ce38e6e3cb639c17b79648d2000e0a8348f0e997", + "zh:7267936c2cdbc448efeb594d73e6b56a53d6a7ae14fe88cdd2a4133adc3302f0", + "zh:7482f023050ed426b4b45116e1761643bc33b1fd4ce4a6fab207ae2571f35940", + "zh:76bbd93b234e5a2927d98b511d86565700f549b570871a194c35f944b96cefb7", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:c6afc4bc1f002bac9c173007dd4da05fde788cd14c2916089f958c33fedb0dfa", + "zh:d3ba40bd806a3a08e9237dece679193c99afb2085de6b45d7f5d1f673cfcd368", + "zh:e1ad7ded53ecd6f0e5b473a3b44eae2b2e885653a56050ab583d387332be02e4", + "zh:e93e78575ce82be6084cc153c24ba8f385dc8d6880888ee66e918460c870953d", + ] +} + +provider "registry.terraform.io/hashicorp/aws" { + version = "6.35.1" + constraints = "6.35.1" + hashes = [ + "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", + "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", + "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", + "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", + "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", + "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", + "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", + "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", + "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", + "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", + "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", + "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", + "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", + "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", + ] +} diff --git a/tests/ministack/setup/index.mjs b/tests/ministack/setup/index.mjs new file mode 100644 index 0000000000..57b6fbdf51 --- /dev/null +++ b/tests/ministack/setup/index.mjs @@ -0,0 +1,16 @@ +const response = async () => ({ statusCode: 200, body: "ministack" }); + +export { + response as adjustPool, + response as deregisterRetry, + response as directWebhook, + response as dispatchToRunners, + response as eventBridgeWebhook, + response as handler, + response as interruptionWarning, + response as jobRetryCheck, + response as scaleDownHandler, + response as scaleUpHandler, + response as ssmHousekeeper, + response as termination, +}; diff --git a/tests/ministack/setup/main.tf b/tests/ministack/setup/main.tf new file mode 100644 index 0000000000..208e29c66d --- /dev/null +++ b/tests/ministack/setup/main.tf @@ -0,0 +1,69 @@ +terraform { + required_version = ">= 1.10.0" + + required_providers { + archive = { + source = "hashicorp/archive" + version = "~> 2.7" + } + aws = { + source = "hashicorp/aws" + version = "= 6.35.1" + } + } +} + +provider "aws" { + region = "eu-west-1" + + # These values are MiniStack test identifiers and cannot authenticate to AWS. + access_key = "000000000000" + secret_key = "ministack-test-only" + + skip_credentials_validation = true + skip_metadata_api_check = true + skip_region_validation = true + skip_requesting_account_id = true + s3_use_path_style = true +} + +data "archive_file" "lambda" { + type = "zip" + source_file = "${path.module}/index.mjs" + output_path = "${path.module}/.terraform/ministack/lambda.zip" +} + +resource "aws_ssm_parameter" "al2023_x64" { + name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64" + type = "String" + value = "ami-0a1b2c3d4e5f67890" +} + +resource "aws_ssm_parameter" "al2023_arm64" { + name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64" + type = "String" + value = "ami-0a1b2c3d4e5f67890" +} + +resource "aws_ssm_parameter" "github_app_id" { + name = "/ministack/terraform-aws-github-runner/github-app/id" + type = "String" + value = "0" +} + +resource "aws_ssm_parameter" "github_app_key" { + name = "/ministack/terraform-aws-github-runner/github-app/key-base64" + type = "SecureString" + value = "ministack-invalid-github-app-key" +} + +resource "aws_ssm_parameter" "github_app_webhook_secret" { + name = "/ministack/terraform-aws-github-runner/github-app/webhook-secret" + type = "SecureString" + value = "ministack-test-only" +} + +output "lambda_archive" { + description = "Absolute path to the inert Lambda archive used by the example tests." + value = abspath(data.archive_file.lambda.output_path) +} From e0e175f2f1d61dec13dab4d3c0fb750890ea751a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:49:53 +0000 Subject: [PATCH 06/13] docs: auto update terraform docs --- examples/base/README.md | 2 +- examples/permissions-boundary/README.md | 4 +- examples/permissions-boundary/setup/README.md | 2 +- tests/ministack/overrides/README.md | 39 ++++++++++++++++++ tests/ministack/setup/README.md | 41 +++++++++++++++++++ 5 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 tests/ministack/overrides/README.md create mode 100644 tests/ministack/setup/README.md diff --git a/examples/base/README.md b/examples/base/README.md index 95b6fcee52..e866dea9bf 100644 --- a/examples/base/README.md +++ b/examples/base/README.md @@ -10,7 +10,7 @@ | Name | Version | |------|---------| -| [aws](#provider\_aws) | 6.0.0 | +| [aws](#provider\_aws) | 6.35.1 | ## Modules diff --git a/examples/permissions-boundary/README.md b/examples/permissions-boundary/README.md index 523e10edda..16ed574ed4 100644 --- a/examples/permissions-boundary/README.md +++ b/examples/permissions-boundary/README.md @@ -43,8 +43,8 @@ terraform apply | Name | Version | |------|---------| -| [aws](#provider\_aws) | 6.22.1 | -| [random](#provider\_random) | 3.7.2 | +| [aws](#provider\_aws) | 6.35.1 | +| [random](#provider\_random) | 3.9.0 | | [terraform](#provider\_terraform) | n/a | ## Modules diff --git a/examples/permissions-boundary/setup/README.md b/examples/permissions-boundary/setup/README.md index defdfa8873..4b1778c8f8 100644 --- a/examples/permissions-boundary/setup/README.md +++ b/examples/permissions-boundary/setup/README.md @@ -12,7 +12,7 @@ | Name | Version | |------|---------| -| [aws](#provider\_aws) | 5.31.0 | +| [aws](#provider\_aws) | 6.35.1 | ## Modules diff --git a/tests/ministack/overrides/README.md b/tests/ministack/overrides/README.md new file mode 100644 index 0000000000..16f52b5086 --- /dev/null +++ b/tests/ministack/overrides/README.md @@ -0,0 +1,39 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [aws](#requirement\_aws) | = 6.35.1 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [runners](#module\_runners) | | n/a | +| [spot\_termination\_watchter](#module\_spot\_termination\_watchter) | | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | | n/a | + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [ami\_name\_filter](#input\_ami\_name\_filter) | n/a | `string` | `"amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"` | no | +| [aws\_region](#input\_aws\_region) | n/a | `string` | `"eu-west-1"` | no | +| [environment](#input\_environment) | n/a | `string` | `"ministack-prebuilt"` | no | +| [github\_app](#input\_github\_app) | n/a | `map` |
{
"id": "0",
"key_base64": "ministack-invalid-key"
}
| no | +| [github\_app\_ssm\_parameters](#input\_github\_app\_ssm\_parameters) | n/a | `map` |
{
"id": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id",
"name": "/ministack/terraform-aws-github-runner/github-app/id"
},
"key_base64": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64",
"name": "/ministack/terraform-aws-github-runner/github-app/key-base64"
},
"webhook_secret": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret",
"name": "/ministack/terraform-aws-github-runner/github-app/webhook-secret"
}
}
| no | +| [ministack\_lambda\_archive](#input\_ministack\_lambda\_archive) | Absolute path to the inert Lambda archive created by the MiniStack fixture. | `string` | n/a | yes | +| [prefix](#input\_prefix) | n/a | `string` | `"ministack-base"` | no | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/tests/ministack/setup/README.md b/tests/ministack/setup/README.md new file mode 100644 index 0000000000..4c39a7450a --- /dev/null +++ b/tests/ministack/setup/README.md @@ -0,0 +1,41 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.10.0 | +| [archive](#requirement\_archive) | ~> 2.7 | +| [aws](#requirement\_aws) | = 6.35.1 | + +## Providers + +| Name | Version | +|------|---------| +| [archive](#provider\_archive) | 2.8.0 | +| [aws](#provider\_aws) | 6.35.1 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_ssm_parameter.al2023_arm64](https://registry.terraform.io/providers/hashicorp/aws/6.35.1/docs/resources/ssm_parameter) | resource | +| [aws_ssm_parameter.al2023_x64](https://registry.terraform.io/providers/hashicorp/aws/6.35.1/docs/resources/ssm_parameter) | resource | +| [aws_ssm_parameter.github_app_id](https://registry.terraform.io/providers/hashicorp/aws/6.35.1/docs/resources/ssm_parameter) | resource | +| [aws_ssm_parameter.github_app_key](https://registry.terraform.io/providers/hashicorp/aws/6.35.1/docs/resources/ssm_parameter) | resource | +| [aws_ssm_parameter.github_app_webhook_secret](https://registry.terraform.io/providers/hashicorp/aws/6.35.1/docs/resources/ssm_parameter) | resource | +| [archive_file.lambda](https://registry.terraform.io/providers/hashicorp/archive/latest/docs/data-sources/file) | data source | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [lambda\_archive](#output\_lambda\_archive) | Absolute path to the inert Lambda archive used by the example tests. | + \ No newline at end of file From ded17db872eaba43c874a350503fd72ed1320c68 Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Mon, 24 Aug 2026 17:08:14 +0200 Subject: [PATCH 07/13] fix(ci): trust GitHub Actions checkout --- .github/workflows/ministack.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ministack.yml b/.github/workflows/ministack.yml index 092ed30173..3f5df29de3 100644 --- a/.github/workflows/ministack.yml +++ b/.github/workflows/ministack.yml @@ -75,6 +75,10 @@ jobs: with: persist-credentials: false + - name: Mark repository as safe + shell: sh + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - id: prepare name: Prepare isolated fixture env: From 69f8c7994830380f86226c8d62bc67d5356d9bc5 Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Mon, 24 Aug 2026 17:28:15 +0200 Subject: [PATCH 08/13] fix(ci): add Linux provider checksums --- examples/base/.terraform.lock.hcl | 1 + examples/default/.terraform.lock.hcl | 4 ++++ examples/ephemeral/.terraform.lock.hcl | 4 ++++ examples/external-managed-ssm-secrets/.terraform.lock.hcl | 4 ++++ examples/multi-runner/.terraform.lock.hcl | 4 ++++ examples/permissions-boundary/.terraform.lock.hcl | 4 ++++ examples/permissions-boundary/setup/.terraform.lock.hcl | 3 +++ examples/prebuilt/.terraform.lock.hcl | 4 ++++ examples/termination-watcher/.terraform.lock.hcl | 1 + tests/ministack/setup/.terraform.lock.hcl | 2 ++ 10 files changed, 31 insertions(+) diff --git a/examples/base/.terraform.lock.hcl b/examples/base/.terraform.lock.hcl index 5b187aa735..5fc3fb1c53 100644 --- a/examples/base/.terraform.lock.hcl +++ b/examples/base/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, 6.35.1" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", diff --git a/examples/default/.terraform.lock.hcl b/examples/default/.terraform.lock.hcl index 136f5367b1..17012dcab0 100644 --- a/examples/default/.terraform.lock.hcl +++ b/examples/default/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -28,6 +29,7 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ + "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -49,6 +51,7 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", + "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -68,6 +71,7 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ + "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/ephemeral/.terraform.lock.hcl b/examples/ephemeral/.terraform.lock.hcl index 136f5367b1..17012dcab0 100644 --- a/examples/ephemeral/.terraform.lock.hcl +++ b/examples/ephemeral/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -28,6 +29,7 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ + "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -49,6 +51,7 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", + "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -68,6 +71,7 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ + "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/external-managed-ssm-secrets/.terraform.lock.hcl b/examples/external-managed-ssm-secrets/.terraform.lock.hcl index 136f5367b1..17012dcab0 100644 --- a/examples/external-managed-ssm-secrets/.terraform.lock.hcl +++ b/examples/external-managed-ssm-secrets/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -28,6 +29,7 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ + "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -49,6 +51,7 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", + "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -68,6 +71,7 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ + "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/multi-runner/.terraform.lock.hcl b/examples/multi-runner/.terraform.lock.hcl index 136f5367b1..17012dcab0 100644 --- a/examples/multi-runner/.terraform.lock.hcl +++ b/examples/multi-runner/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -28,6 +29,7 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ + "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -49,6 +51,7 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", + "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -68,6 +71,7 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ + "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/permissions-boundary/.terraform.lock.hcl b/examples/permissions-boundary/.terraform.lock.hcl index 54f9bc8743..de4b9eeb40 100644 --- a/examples/permissions-boundary/.terraform.lock.hcl +++ b/examples/permissions-boundary/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0, >= 6.33.0, 6.35.1" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -28,6 +29,7 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.9.0" constraints = "~> 2.0" hashes = [ + "h1:9rBZCMNpxKwMlRbWH2QpwD3kqUCAejdOZQ/aiiDObXQ=", "h1:m24fjcInWvTVZ1XSo2MaNuKPe+X/gfG8SIi09rA7a7M=", "zh:0baa4566cf77f1ff52f4293d1c8536202dd23edc197c3196413a28343c3ac3a0", "zh:16b5559c3c07088ddad11a9bb9e9c0799999363c2958e9a5be2bcbbf2cd9ca64", @@ -49,6 +51,7 @@ provider "registry.terraform.io/hashicorp/null" { version = "3.3.1" constraints = "~> 3.0, ~> 3.2" hashes = [ + "h1:TuxJq10DVnRP7c5HBZPyyvQGcckNVfijyU1eXEu5e4M=", "h1:m5FqidbIgh+E9OigiZh8/xbkvpUQFSj3hZo/jqNLCLQ=", "zh:08c59776542ea16e5a8545752787b17ff412922182b4cfabe16139197be8ac44", "zh:123109cc7e5ed6d515787fbc212f2a3fd5e75647bb24ab7c801ccd4d4ed42451", @@ -71,6 +74,7 @@ provider "registry.terraform.io/hashicorp/random" { constraints = "~> 3.0" hashes = [ "h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=", + "h1:UlBuNVuCGJ39tTv2c5gz2NRZnQbXfbIWbTzWcth5o74=", "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", diff --git a/examples/permissions-boundary/setup/.terraform.lock.hcl b/examples/permissions-boundary/setup/.terraform.lock.hcl index 91bf7dac01..82fd8e4c2a 100644 --- a/examples/permissions-boundary/setup/.terraform.lock.hcl +++ b/examples/permissions-boundary/setup/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 6.21.0, 6.35.1" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -28,6 +29,7 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.9.0" constraints = "~> 2.0" hashes = [ + "h1:9rBZCMNpxKwMlRbWH2QpwD3kqUCAejdOZQ/aiiDObXQ=", "h1:m24fjcInWvTVZ1XSo2MaNuKPe+X/gfG8SIi09rA7a7M=", "zh:0baa4566cf77f1ff52f4293d1c8536202dd23edc197c3196413a28343c3ac3a0", "zh:16b5559c3c07088ddad11a9bb9e9c0799999363c2958e9a5be2bcbbf2cd9ca64", @@ -50,6 +52,7 @@ provider "registry.terraform.io/hashicorp/random" { constraints = "~> 3.0" hashes = [ "h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=", + "h1:UlBuNVuCGJ39tTv2c5gz2NRZnQbXfbIWbTzWcth5o74=", "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", diff --git a/examples/prebuilt/.terraform.lock.hcl b/examples/prebuilt/.terraform.lock.hcl index 136f5367b1..17012dcab0 100644 --- a/examples/prebuilt/.terraform.lock.hcl +++ b/examples/prebuilt/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -28,6 +29,7 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ + "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -49,6 +51,7 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", + "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -68,6 +71,7 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ + "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/termination-watcher/.terraform.lock.hcl b/examples/termination-watcher/.terraform.lock.hcl index 5840ca1343..26f5f13ef8 100644 --- a/examples/termination-watcher/.terraform.lock.hcl +++ b/examples/termination-watcher/.terraform.lock.hcl @@ -5,6 +5,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 6.21.0, 6.35.1" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", diff --git a/tests/ministack/setup/.terraform.lock.hcl b/tests/ministack/setup/.terraform.lock.hcl index 162bcd106b..8917cfa897 100644 --- a/tests/ministack/setup/.terraform.lock.hcl +++ b/tests/ministack/setup/.terraform.lock.hcl @@ -6,6 +6,7 @@ provider "registry.terraform.io/hashicorp/archive" { constraints = "~> 2.7" hashes = [ "h1:WB6H5ksIZiyq1lQlD/PWeh+tn4FLsbSjVnRW3+4xe2Y=", + "h1:jdmKm+xl6ZcQrijxapnZ94RVuz/G4vk7hsIa1N0VT5Q=", "zh:0d14713fdc259fb377d0b899ad3c650a34194bd52194c863303ef22a65a580e2", "zh:369b56040c7a8085d04e7e8ffac1e2b321a3170e502f788819bc34b868ec016f", "zh:4d1a3b983ed6af5a52bfe12794674ae55cbadfa6021b37106ade68b433ad216a", @@ -26,6 +27,7 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = "6.35.1" hashes = [ + "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", From 5afd3edbb501c0c832d969a7eadc85f8a6234e0d Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Tue, 25 Aug 2026 19:59:09 +0200 Subject: [PATCH 09/13] refactor(ci): apply MiniStack tests to examples directly --- .github/workflows/ministack.yml | 3 +- examples/default/README.md | 8 + examples/default/main.tf | 8 + examples/default/providers.tf | 3 +- examples/default/variables.tf | 53 ++++++ examples/ephemeral/README.md | 6 + examples/ephemeral/main.tf | 6 + examples/ephemeral/providers.tf | 3 +- examples/ephemeral/variables.tf | 41 +++++ .../external-managed-ssm-secrets/README.md | 5 + examples/external-managed-ssm-secrets/main.tf | 5 + .../external-managed-ssm-secrets/providers.tf | 3 +- .../external-managed-ssm-secrets/variables.tf | 35 ++++ examples/multi-runner/README.md | 6 + examples/multi-runner/main.tf | 7 +- examples/multi-runner/providers.tf | 3 +- examples/multi-runner/variables.tf | 43 ++++- examples/permissions-boundary/README.md | 6 + examples/permissions-boundary/main.tf | 9 +- examples/permissions-boundary/providers.tf | 5 +- examples/permissions-boundary/variables.tf | 41 +++++ examples/prebuilt/README.md | 5 + examples/prebuilt/main.tf | 5 + examples/prebuilt/providers.tf | 3 +- examples/prebuilt/variables.tf | 30 ++++ examples/termination-watcher/README.md | 4 +- examples/termination-watcher/main.tf | 1 + examples/termination-watcher/variables.tf | 5 + modules/webhook-github-app/README.md | 1 + modules/webhook-github-app/main.tf | 7 + modules/webhook-github-app/variables.tf | 6 + tests/ministack/README.md | 22 ++- tests/ministack/inputs/base.tfvars | 2 + tests/ministack/inputs/default.tfvars | 14 ++ tests/ministack/inputs/ephemeral.tfvars | 14 ++ .../external-managed-ssm-secrets.tfvars | 23 +++ tests/ministack/inputs/multi-runner.tfvars | 14 ++ .../inputs/permissions-boundary.tfvars | 12 ++ tests/ministack/inputs/prebuilt.tfvars | 8 + tests/ministack/overrides/README.md | 39 ---- tests/ministack/overrides/base_override.tf | 7 - tests/ministack/overrides/common.tf | 19 -- tests/ministack/overrides/default_override.tf | 29 --- .../ministack/overrides/ephemeral_override.tf | 23 --- .../external-managed-ssm-secrets_override.tf | 27 --- .../overrides/multi-runner_override.tf | 36 ---- .../permissions-boundary-provider_override.tf | 14 -- .../permissions-boundary_override.tf | 13 -- .../ministack/overrides/prebuilt_override.tf | 26 --- tests/ministack/overrides/provider.tf | 13 -- .../overrides/termination-watcher_override.tf | 15 -- .../ministack/overrides/versions_override.tf | 8 - tests/ministack/run-example.sh | 167 ++++++++++++++---- tests/ministack/setup/README.md | 4 +- tests/ministack/setup/main.tf | 16 +- 55 files changed, 598 insertions(+), 333 deletions(-) create mode 100644 examples/termination-watcher/variables.tf create mode 100644 tests/ministack/inputs/base.tfvars create mode 100644 tests/ministack/inputs/default.tfvars create mode 100644 tests/ministack/inputs/ephemeral.tfvars create mode 100644 tests/ministack/inputs/external-managed-ssm-secrets.tfvars create mode 100644 tests/ministack/inputs/multi-runner.tfvars create mode 100644 tests/ministack/inputs/permissions-boundary.tfvars create mode 100644 tests/ministack/inputs/prebuilt.tfvars delete mode 100644 tests/ministack/overrides/README.md delete mode 100644 tests/ministack/overrides/base_override.tf delete mode 100644 tests/ministack/overrides/common.tf delete mode 100644 tests/ministack/overrides/default_override.tf delete mode 100644 tests/ministack/overrides/ephemeral_override.tf delete mode 100644 tests/ministack/overrides/external-managed-ssm-secrets_override.tf delete mode 100644 tests/ministack/overrides/multi-runner_override.tf delete mode 100644 tests/ministack/overrides/permissions-boundary-provider_override.tf delete mode 100644 tests/ministack/overrides/permissions-boundary_override.tf delete mode 100644 tests/ministack/overrides/prebuilt_override.tf delete mode 100644 tests/ministack/overrides/provider.tf delete mode 100644 tests/ministack/overrides/termination-watcher_override.tf delete mode 100644 tests/ministack/overrides/versions_override.tf diff --git a/.github/workflows/ministack.yml b/.github/workflows/ministack.yml index 3f5df29de3..a3ecfb1dfc 100644 --- a/.github/workflows/ministack.yml +++ b/.github/workflows/ministack.yml @@ -61,6 +61,7 @@ jobs: services: ministack: image: ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 + options: --network-alias 000000000000.ministack env: MINISTACK_ACCOUNT_ID: "000000000000" MINISTACK_REGION: eu-west-1 @@ -80,7 +81,7 @@ jobs: run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - id: prepare - name: Prepare isolated fixture + name: Prepare test runtime env: EXAMPLE: ${{ matrix.example }} run: tests/ministack/run-example.sh prepare "$EXAMPLE" diff --git a/examples/default/README.md b/examples/default/README.md index c75e37831f..97b2c69083 100644 --- a/examples/default/README.md +++ b/examples/default/README.md @@ -62,9 +62,17 @@ terraform output -raw webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | +| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | Path to the AMI housekeeper Lambda archive. Uses the module default when unset. | `string` | `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | +| [configure\_github\_app](#input\_configure\_github\_app) | Whether to update the GitHub App webhook after deploying the runners. | `bool` | `true` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [termination\_watcher\_lambda\_zip](#input\_termination\_watcher\_lambda\_zip) | Path to the termination watcher Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/default/main.tf b/examples/default/main.tf index 71c69612c3..b9e288f738 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -20,6 +20,7 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets + ami = var.ami prefix = local.environment tags = { @@ -32,6 +33,11 @@ module "runners" { webhook_secret = random_id.random.hex } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + ami_housekeeper_lambda_zip = var.ami_housekeeper_lambda_zip + # configure the block device mappings, default for Amazon Linux2 # block_device_mappings = [{ # device_name = "/dev/xvda" @@ -122,6 +128,7 @@ module "runners" { instance_termination_watcher = { enable = true + zip = var.termination_watcher_lambda_zip } # enable metric creation (experimental) @@ -149,6 +156,7 @@ module "runners" { module "webhook_github_app" { source = "../../modules/webhook-github-app" depends_on = [module.runners] + enabled = var.configure_github_app github_app = { key_base64 = var.github_app.key_base64 diff --git a/examples/default/providers.tf b/examples/default/providers.tf index eca2fe96a7..c0584efe1d 100644 --- a/examples/default/providers.tf +++ b/examples/default/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { diff --git a/examples/default/variables.tf b/examples/default/variables.tf index 8a3bce0854..71704e7570 100644 --- a/examples/default/variables.tf +++ b/examples/default/variables.tf @@ -20,3 +20,56 @@ variable "aws_region" { type = string default = "eu-west-1" } + +variable "ami" { + description = "AMI configuration for the action runner instances. Uses the module default when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "configure_github_app" { + description = "Whether to update the GitHub App webhook after deploying the runners." + type = bool + default = true +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "ami_housekeeper_lambda_zip" { + description = "Path to the AMI housekeeper Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "termination_watcher_lambda_zip" { + description = "Path to the termination watcher Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/ephemeral/README.md b/examples/ephemeral/README.md index e6bf4961b4..c36a8fe0ca 100644 --- a/examples/ephemeral/README.md +++ b/examples/ephemeral/README.md @@ -61,9 +61,15 @@ terraform output webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | +| [configure\_github\_app](#input\_configure\_github\_app) | Whether to update the GitHub App webhook after deploying the runners. | `bool` | `true` | no | | [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/ephemeral/main.tf b/examples/ephemeral/main.tf index 2b9403ca4d..a5107d3a60 100644 --- a/examples/ephemeral/main.tf +++ b/examples/ephemeral/main.tf @@ -20,6 +20,7 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets + ami = var.ami prefix = local.environment tags = { @@ -32,6 +33,10 @@ module "runners" { webhook_secret = random_id.random.hex } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + # When not explicitly set lambda zip files are grapped from the module requiring lambda build. # Alternatively you can set the path to the lambda zip files here. # @@ -112,6 +117,7 @@ module "runners" { module "webhook_github_app" { source = "../../modules/webhook-github-app" depends_on = [module.runners] + enabled = var.configure_github_app github_app = { key_base64 = var.github_app.key_base64 diff --git a/examples/ephemeral/providers.tf b/examples/ephemeral/providers.tf index ccdd0b1622..55f6616e44 100644 --- a/examples/ephemeral/providers.tf +++ b/examples/ephemeral/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { Example = local.environment diff --git a/examples/ephemeral/variables.tf b/examples/ephemeral/variables.tf index f78b2c6ae2..1d0a243e6a 100644 --- a/examples/ephemeral/variables.tf +++ b/examples/ephemeral/variables.tf @@ -21,3 +21,44 @@ variable "aws_region" { type = string default = "eu-west-1" } + +variable "ami" { + description = "AMI configuration for the action runner instances. Uses the module default when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "configure_github_app" { + description = "Whether to update the GitHub App webhook after deploying the runners." + type = bool + default = true +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/external-managed-ssm-secrets/README.md b/examples/external-managed-ssm-secrets/README.md index af9c95a38c..5792eff17d 100644 --- a/examples/external-managed-ssm-secrets/README.md +++ b/examples/external-managed-ssm-secrets/README.md @@ -103,9 +103,14 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app\_ssm\_parameters](#input\_github\_app\_ssm\_parameters) | SSM parameters details for the GitHub App, that you've created manually on AWS. |
object({
key_base64 = optional(object({
arn = string
name = string
}))
id = optional(object({
arn = string
name = string
}))
webhook_secret = optional(object({
arn = string
name = string
}))
})
| `{}` | no | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/external-managed-ssm-secrets/main.tf b/examples/external-managed-ssm-secrets/main.tf index e390a56792..73a77fbfa1 100644 --- a/examples/external-managed-ssm-secrets/main.tf +++ b/examples/external-managed-ssm-secrets/main.tf @@ -16,6 +16,7 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets + ami = var.ami prefix = local.environment tags = { @@ -28,6 +29,10 @@ module "runners" { webhook_secret_ssm = var.github_app_ssm_parameters.webhook_secret } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + enable_organization_runners = true runner_extra_labels = ["default", "example"] diff --git a/examples/external-managed-ssm-secrets/providers.tf b/examples/external-managed-ssm-secrets/providers.tf index eca2fe96a7..c0584efe1d 100644 --- a/examples/external-managed-ssm-secrets/providers.tf +++ b/examples/external-managed-ssm-secrets/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { diff --git a/examples/external-managed-ssm-secrets/variables.tf b/examples/external-managed-ssm-secrets/variables.tf index 047f404400..4e32ed2e51 100644 --- a/examples/external-managed-ssm-secrets/variables.tf +++ b/examples/external-managed-ssm-secrets/variables.tf @@ -30,3 +30,38 @@ variable "aws_region" { type = string default = "eu-west-1" } + +variable "ami" { + description = "AMI configuration for the action runner instances. Uses the module default when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/multi-runner/README.md b/examples/multi-runner/README.md index a899015568..39f1190875 100644 --- a/examples/multi-runner/README.md +++ b/examples/multi-runner/README.md @@ -90,9 +90,15 @@ terraform output -raw webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration applied to each runner configuration. Uses each configuration's AMI when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region to deploy to | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | +| [configure\_github\_app](#input\_configure\_github\_app) | Whether to update the GitHub App webhook after deploying the runners. | `bool` | `true` | no | | [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/multi-runner/main.tf b/examples/multi-runner/main.tf index 1921656074..1f3559a5fa 100644 --- a/examples/multi-runner/main.tf +++ b/examples/multi-runner/main.tf @@ -54,7 +54,7 @@ locals { subnet_ids = lookup(v.runner_config, "subnet_ids", null) != null ? [module.base.vpc.private_subnets[0]] : null vpc_id = lookup(v.runner_config, "vpc_id", null) != null ? module.base.vpc.vpc_id : null ami = contains(keys(v.runner_config), "ami") ? merge( - v.runner_config.ami, + merge(concat([v.runner_config.ami], var.ami[*])...), { id_ssm_parameter_arn = lookup(local.ssm_ami_arns, k, null) != null ? local.ssm_ami_arns[k] : null } @@ -117,6 +117,10 @@ module "runners" { webhook_secret = random_id.random.hex } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + # Uncomment to distribute GitHub API rate limit usage across multiple GitHub Apps. # Each additional app must be installed on the same repos/orgs as the primary app. # The control-plane lambdas will randomly select an app for each API call. @@ -176,6 +180,7 @@ module "runners" { module "webhook_github_app" { source = "../../modules/webhook-github-app" depends_on = [module.runners] + enabled = var.configure_github_app github_app = { key_base64 = var.github_app.key_base64 diff --git a/examples/multi-runner/providers.tf b/examples/multi-runner/providers.tf index eca2fe96a7..c0584efe1d 100644 --- a/examples/multi-runner/providers.tf +++ b/examples/multi-runner/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { diff --git a/examples/multi-runner/variables.tf b/examples/multi-runner/variables.tf index bc490ae273..2388c280de 100644 --- a/examples/multi-runner/variables.tf +++ b/examples/multi-runner/variables.tf @@ -19,4 +19,45 @@ variable "aws_region" { type = string default = "eu-west-1" -} \ No newline at end of file +} + +variable "ami" { + description = "AMI configuration applied to each runner configuration. Uses each configuration's AMI when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "configure_github_app" { + description = "Whether to update the GitHub App webhook after deploying the runners." + type = bool + default = true +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/permissions-boundary/README.md b/examples/permissions-boundary/README.md index 16ed574ed4..ea688df474 100644 --- a/examples/permissions-boundary/README.md +++ b/examples/permissions-boundary/README.md @@ -67,7 +67,13 @@ terraform apply | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [iam\_state\_path](#input\_iam\_state\_path) | Path to the state produced by the permissions-boundary setup. Uses the example setup state when unset. | `string` | `null` | no | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. | `string` | `"../lambdas-download/runner-binaries-syncer.zip"` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. | `string` | `"../lambdas-download/runners.zip"` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. | `string` | `"../lambdas-download/webhook.zip"` | no | ## Outputs diff --git a/examples/permissions-boundary/main.tf b/examples/permissions-boundary/main.tf index 3b7348ae8c..dac02d5410 100644 --- a/examples/permissions-boundary/main.tf +++ b/examples/permissions-boundary/main.tf @@ -11,7 +11,7 @@ data "terraform_remote_state" "iam" { backend = "local" config = { - path = "${path.module}/setup/terraform.tfstate" + path = var.iam_state_path != null ? var.iam_state_path : "${path.module}/setup/terraform.tfstate" } } @@ -40,6 +40,7 @@ module "runners" { vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets kms_key_arn = aws_kms_key.github.key_id + ami = var.ami prefix = local.environment tags = { @@ -52,9 +53,9 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = "../lambdas-download/webhook.zip" - runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" - runners_lambda_zip = "../lambdas-download/runners.zip" + webhook_lambda_zip = var.webhook_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + runners_lambda_zip = var.runners_lambda_zip enable_organization_runners = false runner_extra_labels = ["default", "example"] diff --git a/examples/permissions-boundary/providers.tf b/examples/permissions-boundary/providers.tf index c9a9238804..2fcdcb4561 100644 --- a/examples/permissions-boundary/providers.tf +++ b/examples/permissions-boundary/providers.tf @@ -1,6 +1,7 @@ provider "aws" { - alias = "terraform_role" - region = local.aws_region + alias = "terraform_role" + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style assume_role { role_arn = data.terraform_remote_state.iam.outputs.role } diff --git a/examples/permissions-boundary/variables.tf b/examples/permissions-boundary/variables.tf index d8b5356484..3d0d26e23e 100644 --- a/examples/permissions-boundary/variables.tf +++ b/examples/permissions-boundary/variables.tf @@ -6,3 +6,44 @@ variable "github_app" { key_base64 = string }) } + +variable "ami" { + description = "AMI configuration for the action runner instances. Uses the module default when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive." + type = string + default = "../lambdas-download/webhook.zip" +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive." + type = string + default = "../lambdas-download/runners.zip" +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive." + type = string + default = "../lambdas-download/runner-binaries-syncer.zip" +} + +variable "iam_state_path" { + description = "Path to the state produced by the permissions-boundary setup. Uses the example setup state when unset." + type = string + default = null +} diff --git a/examples/prebuilt/README.md b/examples/prebuilt/README.md index f90a47261e..23e39476da 100644 --- a/examples/prebuilt/README.md +++ b/examples/prebuilt/README.md @@ -108,11 +108,16 @@ terraform output webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | Path to the AMI housekeeper Lambda archive. Uses the module default when unset. | `string` | `null` | no | | [ami\_name\_filter](#input\_ami\_name\_filter) | AMI name filter for the action runner AMI. By default amazon linux 2 is used. | `string` | `"github-runner-al2023-x86_64-*"` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | +| [configure\_github\_app](#input\_configure\_github\_app) | Whether to update the GitHub App webhook after deploying the runners. | `bool` | `true` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | | [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux, osx, windows). | `string` | `"linux"` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/prebuilt/main.tf b/examples/prebuilt/main.tf index 62434f3f61..ea70b52bb9 100644 --- a/examples/prebuilt/main.tf +++ b/examples/prebuilt/main.tf @@ -32,6 +32,10 @@ module "runners" { webhook_secret = random_id.random.hex } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + ami_housekeeper_lambda_zip = var.ami_housekeeper_lambda_zip + # link to downloaded lambda zip files. # When not explicitly set lambda zip files are grabbed from the module requiring lambda build. # @@ -104,6 +108,7 @@ module "runners" { module "webhook_github_app" { source = "../../modules/webhook-github-app" depends_on = [module.runners] + enabled = var.configure_github_app github_app = { key_base64 = var.github_app.key_base64 diff --git a/examples/prebuilt/providers.tf b/examples/prebuilt/providers.tf index ccdd0b1622..55f6616e44 100644 --- a/examples/prebuilt/providers.tf +++ b/examples/prebuilt/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { Example = local.environment diff --git a/examples/prebuilt/variables.tf b/examples/prebuilt/variables.tf index 11670a5d2e..2af18bd7e3 100644 --- a/examples/prebuilt/variables.tf +++ b/examples/prebuilt/variables.tf @@ -34,3 +34,33 @@ variable "ami_name_filter" { type = string default = "github-runner-al2023-x86_64-*" } + +variable "configure_github_app" { + description = "Whether to update the GitHub App webhook after deploying the runners." + type = bool + default = true +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "ami_housekeeper_lambda_zip" { + description = "Path to the AMI housekeeper Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/termination-watcher/README.md b/examples/termination-watcher/README.md index 98f2c8783b..6c1a8be75a 100644 --- a/examples/termination-watcher/README.md +++ b/examples/termination-watcher/README.md @@ -45,7 +45,9 @@ No resources. ## Inputs -No inputs. +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [termination\_watcher\_lambda\_zip](#input\_termination\_watcher\_lambda\_zip) | Path to the termination watcher Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/termination-watcher/main.tf b/examples/termination-watcher/main.tf index 7877d04bc1..264deb1a35 100644 --- a/examples/termination-watcher/main.tf +++ b/examples/termination-watcher/main.tf @@ -12,5 +12,6 @@ module "spot_termination_watchter" { tag_filters = { "ghr:Application" = "github-action-runner" } + zip = var.termination_watcher_lambda_zip } } diff --git a/examples/termination-watcher/variables.tf b/examples/termination-watcher/variables.tf new file mode 100644 index 0000000000..562d63e8ad --- /dev/null +++ b/examples/termination-watcher/variables.tf @@ -0,0 +1,5 @@ +variable "termination_watcher_lambda_zip" { + description = "Path to the termination watcher Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/modules/webhook-github-app/README.md b/modules/webhook-github-app/README.md index 6de85ee30d..85d65e9f34 100644 --- a/modules/webhook-github-app/README.md +++ b/modules/webhook-github-app/README.md @@ -34,6 +34,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [enabled](#input\_enabled) | Whether to update the GitHub App webhook. | `bool` | `true` | no | | [github\_app](#input\_github\_app) | GitHub app parameters, see your GitHub app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`). |
object({
key_base64 = string
id = string
webhook_secret = string
})
| n/a | yes | | [webhook\_endpoint](#input\_webhook\_endpoint) | The endpoint to use for the webhook, defaults to the endpoint of the runners module. | `string` | n/a | yes | diff --git a/modules/webhook-github-app/main.tf b/modules/webhook-github-app/main.tf index 609eb85279..b5bdccca6e 100644 --- a/modules/webhook-github-app/main.tf +++ b/modules/webhook-github-app/main.tf @@ -1,4 +1,6 @@ resource "null_resource" "update_app" { + count = var.enabled ? 1 : 0 + triggers = { webhook_endpoint = var.webhook_endpoint webhook_secret = var.github_app.webhook_secret @@ -10,3 +12,8 @@ resource "null_resource" "update_app" { on_failure = continue } } + +moved { + from = null_resource.update_app + to = null_resource.update_app[0] +} diff --git a/modules/webhook-github-app/variables.tf b/modules/webhook-github-app/variables.tf index a9bd738509..0044439b18 100644 --- a/modules/webhook-github-app/variables.tf +++ b/modules/webhook-github-app/variables.tf @@ -12,3 +12,9 @@ variable "webhook_endpoint" { description = "The endpoint to use for the webhook, defaults to the endpoint of the runners module." type = string } + +variable "enabled" { + description = "Whether to update the GitHub App webhook." + type = bool + default = true +} diff --git a/tests/ministack/README.md b/tests/ministack/README.md index 1b9042a575..574a520b80 100644 --- a/tests/ministack/README.md +++ b/tests/ministack/README.md @@ -1,14 +1,22 @@ # MiniStack example lifecycle tests The MiniStack workflow runs explicit `terraform apply` and `terraform destroy` -commands against the repository's runnable AWS examples. Every matrix entry gets -an isolated source tree, Terraform state, and MiniStack service. +commands from each checked-in `examples/` root. MiniStack-specific values +are supplied through ordinary example inputs in `tests/ministack/inputs`; no +Terraform configuration is copied into or layered over an example. -The fixture creates synthetic SSM values through MiniStack and an inert Lambda -archive under its ignored `.terraform/` directory. Test-only Terraform override -files route each example to that archive and a MiniStack AMI. They also disable -the `webhook-github-app` local-exec module, which would otherwise update a real -GitHub App. The production example configurations are not changed. +Terraform data, state, and the inert Lambda archive live under the runner's +temporary directory. The small `tests/ministack/setup` root is a prerequisite, +not the code under test: it creates the inert archive and seeds the external SSM +parameters consumed by the external-secrets and multi-runner examples. The +archive prevents scheduled or S3-triggered Lambda functions from making GitHub +calls. The GitHub App updater is disabled through its normal `enabled` input. + +The runner accepts only `http://127.0.0.1:4566`, `http://localhost:4566`, or +`http://ministack:4566` as the AWS endpoint and always replaces ambient AWS +credentials with synthetic MiniStack identifiers. It also rejects +service-specific endpoint variables and ignores ambient AWS profile files so +they cannot bypass the validated global endpoint. | Example | Lifecycle coverage | | --- | --- | diff --git a/tests/ministack/inputs/base.tfvars b/tests/ministack/inputs/base.tfvars new file mode 100644 index 0000000000..8205d159f7 --- /dev/null +++ b/tests/ministack/inputs/base.tfvars @@ -0,0 +1,2 @@ +prefix = "ministack-base" +aws_region = "eu-west-1" diff --git a/tests/ministack/inputs/default.tfvars b/tests/ministack/inputs/default.tfvars new file mode 100644 index 0000000000..6f3bab3bf4 --- /dev/null +++ b/tests/ministack/inputs/default.tfvars @@ -0,0 +1,14 @@ +environment = "ministack-default" +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +configure_github_app = false +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/ephemeral.tfvars b/tests/ministack/inputs/ephemeral.tfvars new file mode 100644 index 0000000000..b40451097b --- /dev/null +++ b/tests/ministack/inputs/ephemeral.tfvars @@ -0,0 +1,14 @@ +environment = "ministack-ephemeral" +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +configure_github_app = false +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/external-managed-ssm-secrets.tfvars b/tests/ministack/inputs/external-managed-ssm-secrets.tfvars new file mode 100644 index 0000000000..83b91acf4a --- /dev/null +++ b/tests/ministack/inputs/external-managed-ssm-secrets.tfvars @@ -0,0 +1,23 @@ +environment = "ministack-external-ssm" +github_app_ssm_parameters = { + id = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id" + name = "/ministack/terraform-aws-github-runner/github-app/id" + } + key_base64 = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64" + name = "/ministack/terraform-aws-github-runner/github-app/key-base64" + } + webhook_secret = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret" + name = "/ministack/terraform-aws-github-runner/github-app/webhook-secret" + } +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/multi-runner.tfvars b/tests/ministack/inputs/multi-runner.tfvars new file mode 100644 index 0000000000..e2d8d28ffa --- /dev/null +++ b/tests/ministack/inputs/multi-runner.tfvars @@ -0,0 +1,14 @@ +environment = "ministack" +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +configure_github_app = false +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/permissions-boundary.tfvars b/tests/ministack/inputs/permissions-boundary.tfvars new file mode 100644 index 0000000000..d8b20423a7 --- /dev/null +++ b/tests/ministack/inputs/permissions-boundary.tfvars @@ -0,0 +1,12 @@ +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/prebuilt.tfvars b/tests/ministack/inputs/prebuilt.tfvars new file mode 100644 index 0000000000..493d6b97a6 --- /dev/null +++ b/tests/ministack/inputs/prebuilt.tfvars @@ -0,0 +1,8 @@ +environment = "ministack-prebuilt" +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami_name_filter = "amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2" +configure_github_app = false +aws_s3_use_path_style = true diff --git a/tests/ministack/overrides/README.md b/tests/ministack/overrides/README.md deleted file mode 100644 index 16f52b5086..0000000000 --- a/tests/ministack/overrides/README.md +++ /dev/null @@ -1,39 +0,0 @@ - -## Requirements - -| Name | Version | -|------|---------| -| [aws](#requirement\_aws) | = 6.35.1 | - -## Providers - -No providers. - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| [runners](#module\_runners) | | n/a | -| [spot\_termination\_watchter](#module\_spot\_termination\_watchter) | | n/a | -| [webhook\_github\_app](#module\_webhook\_github\_app) | | n/a | - -## Resources - -No resources. - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [ami\_name\_filter](#input\_ami\_name\_filter) | n/a | `string` | `"amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"` | no | -| [aws\_region](#input\_aws\_region) | n/a | `string` | `"eu-west-1"` | no | -| [environment](#input\_environment) | n/a | `string` | `"ministack-prebuilt"` | no | -| [github\_app](#input\_github\_app) | n/a | `map` |
{
"id": "0",
"key_base64": "ministack-invalid-key"
}
| no | -| [github\_app\_ssm\_parameters](#input\_github\_app\_ssm\_parameters) | n/a | `map` |
{
"id": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id",
"name": "/ministack/terraform-aws-github-runner/github-app/id"
},
"key_base64": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64",
"name": "/ministack/terraform-aws-github-runner/github-app/key-base64"
},
"webhook_secret": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret",
"name": "/ministack/terraform-aws-github-runner/github-app/webhook-secret"
}
}
| no | -| [ministack\_lambda\_archive](#input\_ministack\_lambda\_archive) | Absolute path to the inert Lambda archive created by the MiniStack fixture. | `string` | n/a | yes | -| [prefix](#input\_prefix) | n/a | `string` | `"ministack-base"` | no | - -## Outputs - -No outputs. - \ No newline at end of file diff --git a/tests/ministack/overrides/base_override.tf b/tests/ministack/overrides/base_override.tf deleted file mode 100644 index 7450840076..0000000000 --- a/tests/ministack/overrides/base_override.tf +++ /dev/null @@ -1,7 +0,0 @@ -variable "prefix" { - default = "ministack-base" -} - -variable "aws_region" { - default = "eu-west-1" -} diff --git a/tests/ministack/overrides/common.tf b/tests/ministack/overrides/common.tf deleted file mode 100644 index 8cec884357..0000000000 --- a/tests/ministack/overrides/common.tf +++ /dev/null @@ -1,19 +0,0 @@ -variable "ministack_lambda_archive" { - description = "Absolute path to the inert Lambda archive created by the MiniStack fixture." - type = string - - validation { - condition = endswith(var.ministack_lambda_archive, "/tests/ministack/setup/.terraform/ministack/lambda.zip") - error_message = "The MiniStack Lambda archive must come from the isolated test fixture." - } -} - -locals { - ministack_ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] - } -} diff --git a/tests/ministack/overrides/default_override.tf b/tests/ministack/overrides/default_override.tf deleted file mode 100644 index 654aa37161..0000000000 --- a/tests/ministack/overrides/default_override.tf +++ /dev/null @@ -1,29 +0,0 @@ -variable "environment" { - default = "ministack-default" -} - -variable "github_app" { - default = { - id = "0" - key_base64 = "ministack-invalid-key" - } -} - -module "runners" { - ami = local.ministack_ami - ami_housekeeper_lambda_zip = var.ministack_lambda_archive - runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive - runners_lambda_zip = var.ministack_lambda_archive - webhook_lambda_zip = var.ministack_lambda_archive - - instance_termination_watcher = { - enable = true - zip = var.ministack_lambda_archive - } -} - -# The production example updates GitHub through a local-exec provisioner. -# A zero count structurally prevents any external GitHub API call in this test. -module "webhook_github_app" { - count = 0 -} diff --git a/tests/ministack/overrides/ephemeral_override.tf b/tests/ministack/overrides/ephemeral_override.tf deleted file mode 100644 index ab85df74b1..0000000000 --- a/tests/ministack/overrides/ephemeral_override.tf +++ /dev/null @@ -1,23 +0,0 @@ -variable "environment" { - default = "ministack-ephemeral" -} - -variable "github_app" { - default = { - id = "0" - key_base64 = "ministack-invalid-key" - } -} - -module "runners" { - ami = local.ministack_ami - runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive - runners_lambda_zip = var.ministack_lambda_archive - webhook_lambda_zip = var.ministack_lambda_archive -} - -# The production example updates GitHub through a local-exec provisioner. -# A zero count structurally prevents any external GitHub API call in this test. -module "webhook_github_app" { - count = 0 -} diff --git a/tests/ministack/overrides/external-managed-ssm-secrets_override.tf b/tests/ministack/overrides/external-managed-ssm-secrets_override.tf deleted file mode 100644 index 701b8b61b8..0000000000 --- a/tests/ministack/overrides/external-managed-ssm-secrets_override.tf +++ /dev/null @@ -1,27 +0,0 @@ -variable "environment" { - default = "ministack-external-ssm" -} - -variable "github_app_ssm_parameters" { - default = { - id = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id" - name = "/ministack/terraform-aws-github-runner/github-app/id" - } - key_base64 = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64" - name = "/ministack/terraform-aws-github-runner/github-app/key-base64" - } - webhook_secret = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret" - name = "/ministack/terraform-aws-github-runner/github-app/webhook-secret" - } - } -} - -module "runners" { - ami = local.ministack_ami - runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive - runners_lambda_zip = var.ministack_lambda_archive - webhook_lambda_zip = var.ministack_lambda_archive -} diff --git a/tests/ministack/overrides/multi-runner_override.tf b/tests/ministack/overrides/multi-runner_override.tf deleted file mode 100644 index 4db65a2597..0000000000 --- a/tests/ministack/overrides/multi-runner_override.tf +++ /dev/null @@ -1,36 +0,0 @@ -variable "environment" { - default = "ministack" -} - -variable "github_app" { - default = { - id = "0" - key_base64 = "ministack-invalid-key" - } -} - -locals { - multi_runner_config = { - for name, config in local.multi_runner_config_files : name => merge(config, { - runner_config = merge(config.runner_config, { - ami = contains(keys(config.runner_config), "ami") ? merge(local.ministack_ami, { - id_ssm_parameter_arn = lookup(local.ssm_ami_arns, name, null) - }) : null - subnet_ids = lookup(config.runner_config, "subnet_ids", null) != null ? [module.base.vpc.private_subnets[0]] : null - vpc_id = lookup(config.runner_config, "vpc_id", null) != null ? module.base.vpc.vpc_id : null - }) - }) - } -} - -module "runners" { - runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive - runners_lambda_zip = var.ministack_lambda_archive - webhook_lambda_zip = var.ministack_lambda_archive -} - -# The production example updates GitHub through a local-exec provisioner. -# A zero count structurally prevents any external GitHub API call in this test. -module "webhook_github_app" { - count = 0 -} diff --git a/tests/ministack/overrides/permissions-boundary-provider_override.tf b/tests/ministack/overrides/permissions-boundary-provider_override.tf deleted file mode 100644 index 1c1a2ea07d..0000000000 --- a/tests/ministack/overrides/permissions-boundary-provider_override.tf +++ /dev/null @@ -1,14 +0,0 @@ -provider "aws" { - alias = "terraform_role" - region = "eu-west-1" - - # These values are MiniStack test identifiers and cannot authenticate to AWS. - access_key = "000000000000" - secret_key = "ministack-test-only" - - skip_credentials_validation = true - skip_metadata_api_check = true - skip_region_validation = true - skip_requesting_account_id = true - s3_use_path_style = true -} diff --git a/tests/ministack/overrides/permissions-boundary_override.tf b/tests/ministack/overrides/permissions-boundary_override.tf deleted file mode 100644 index b45b581f6b..0000000000 --- a/tests/ministack/overrides/permissions-boundary_override.tf +++ /dev/null @@ -1,13 +0,0 @@ -variable "github_app" { - default = { - id = "0" - key_base64 = "ministack-invalid-key" - } -} - -module "runners" { - ami = local.ministack_ami - runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive - runners_lambda_zip = var.ministack_lambda_archive - webhook_lambda_zip = var.ministack_lambda_archive -} diff --git a/tests/ministack/overrides/prebuilt_override.tf b/tests/ministack/overrides/prebuilt_override.tf deleted file mode 100644 index 32c35b7f4d..0000000000 --- a/tests/ministack/overrides/prebuilt_override.tf +++ /dev/null @@ -1,26 +0,0 @@ -variable "environment" { - default = "ministack-prebuilt" -} - -variable "github_app" { - default = { - id = "0" - key_base64 = "ministack-invalid-key" - } -} - -variable "ami_name_filter" { - default = "amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2" -} - -module "runners" { - ami_housekeeper_lambda_zip = var.ministack_lambda_archive - runners_lambda_zip = var.ministack_lambda_archive - webhook_lambda_zip = var.ministack_lambda_archive -} - -# The production example updates GitHub through a local-exec provisioner. -# A zero count structurally prevents any external GitHub API call in this test. -module "webhook_github_app" { - count = 0 -} diff --git a/tests/ministack/overrides/provider.tf b/tests/ministack/overrides/provider.tf deleted file mode 100644 index d8718ca141..0000000000 --- a/tests/ministack/overrides/provider.tf +++ /dev/null @@ -1,13 +0,0 @@ -provider "aws" { - region = "eu-west-1" - - # These values are MiniStack test identifiers and cannot authenticate to AWS. - access_key = "000000000000" - secret_key = "ministack-test-only" - - skip_credentials_validation = true - skip_metadata_api_check = true - skip_region_validation = true - skip_requesting_account_id = true - s3_use_path_style = true -} diff --git a/tests/ministack/overrides/termination-watcher_override.tf b/tests/ministack/overrides/termination-watcher_override.tf deleted file mode 100644 index b4f4a6833c..0000000000 --- a/tests/ministack/overrides/termination-watcher_override.tf +++ /dev/null @@ -1,15 +0,0 @@ -module "spot_termination_watchter" { - config = { - metrics = { - enable = true - metric = { - enable_spot_termination_warning = true - } - } - prefix = "global" - tag_filters = { - "ghr:Application" = "github-action-runner" - } - zip = var.ministack_lambda_archive - } -} diff --git a/tests/ministack/overrides/versions_override.tf b/tests/ministack/overrides/versions_override.tf deleted file mode 100644 index 8c18ed1e34..0000000000 --- a/tests/ministack/overrides/versions_override.tf +++ /dev/null @@ -1,8 +0,0 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = "= 6.35.1" - } - } -} diff --git a/tests/ministack/run-example.sh b/tests/ministack/run-example.sh index 4d30670867..17c04ba664 100755 --- a/tests/ministack/run-example.sh +++ b/tests/ministack/run-example.sh @@ -21,71 +21,162 @@ case "$action" in ;; esac +ministack_endpoint="${AWS_ENDPOINT_URL:-http://127.0.0.1:4566}" +case "$ministack_endpoint" in + http://127.0.0.1:4566) + # S3 Control prefixes the account ID to the endpoint hostname. The + # account-prefixed localhost name resolves locally, while 127.0.0.1 does not. + ministack_endpoint="http://localhost:4566" + ;; + http://localhost:4566 | http://ministack:4566) ;; + *) + echo "Refusing to run against non-MiniStack endpoint: $ministack_endpoint" >&2 + exit 65 + ;; +esac + +service_endpoint_variables=$( + env | awk -F= ' + $1 ~ /^AWS_ENDPOINT_URL_/ || $1 ~ /^AWS_[A-Z0-9_]+_ENDPOINT$/ { print $1 } + ' +) +if [ -n "$service_endpoint_variables" ]; then + echo "Refusing to run with service-specific AWS endpoint variables:" >&2 + printf '%s\n' "$service_endpoint_variables" >&2 + exit 65 +fi + +# Always use synthetic credentials and route every AWS client to MiniStack. +export AWS_ACCESS_KEY_ID="000000000000" +export AWS_CONFIG_FILE="/dev/null" +export AWS_DEFAULT_REGION="eu-west-1" +export AWS_EC2_METADATA_DISABLED="true" +export AWS_ENDPOINT_URL="$ministack_endpoint" +export AWS_IGNORE_CONFIGURED_ENDPOINT_URLS="false" +export AWS_REGION="eu-west-1" +export AWS_SECRET_ACCESS_KEY="ministack-test-only" +export AWS_SHARED_CREDENTIALS_FILE="/dev/null" +unset AWS_ACCESS_KEY AWS_DEFAULT_PROFILE AWS_PROFILE AWS_SECRET_KEY AWS_SECURITY_TOKEN AWS_SESSION_TOKEN + +ministack_no_proxy="localhost,127.0.0.1,ministack,.ministack,000000000000.ministack" +export NO_PROXY="${NO_PROXY:+$NO_PROXY,}$ministack_no_proxy" +export no_proxy="${no_proxy:+$no_proxy,}$ministack_no_proxy" + script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) source_root="${GITHUB_WORKSPACE:-$(CDPATH='' cd -- "$script_dir/../.." && pwd)}" temporary_root="${RUNNER_TEMP:-${TMPDIR:-/tmp}}" -worktree="$temporary_root/terraform-aws-github-runner-ministack-$example" -example_root="$worktree/examples/$example" -fixture_root="$worktree/tests/ministack/setup" -lambda_archive="$fixture_root/.terraform/ministack/lambda.zip" +runtime_root="$temporary_root/terraform-aws-github-runner-ministack-$example" +example_root="$source_root/examples/$example" +fixture_root="$source_root/tests/ministack/setup" +input_file="$source_root/tests/ministack/inputs/$example.tfvars" + +fixture_data_dir="$runtime_root/fixture-data" +fixture_state="$runtime_root/fixture.tfstate" +lambda_archive="$runtime_root/lambda.zip" +example_data_dir="$runtime_root/example-data" +example_state="$runtime_root/example.tfstate" +permissions_data_dir="$runtime_root/permissions-data" +permissions_state="$runtime_root/permissions.tfstate" + +terraform_fixture() { + subcommand="$1" + shift + TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" "$subcommand" "$@" \ + -state="$fixture_state" \ + -var="lambda_archive_path=$lambda_archive" +} + +terraform_permissions() { + subcommand="$1" + shift + TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" "$subcommand" "$@" \ + -state="$permissions_state" +} terraform_example() { - terraform -chdir="$example_root" "$@" -var="ministack_lambda_archive=$lambda_archive" + subcommand="$1" + shift + set -- "$subcommand" "$@" "-state=$example_state" + + if [ -f "$input_file" ]; then + set -- "$@" "-var-file=$input_file" + fi + + case "$example" in + default) + set -- "$@" \ + "-var=webhook_lambda_zip=$lambda_archive" \ + "-var=runners_lambda_zip=$lambda_archive" \ + "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" \ + "-var=ami_housekeeper_lambda_zip=$lambda_archive" \ + "-var=termination_watcher_lambda_zip=$lambda_archive" + ;; + ephemeral | external-managed-ssm-secrets | multi-runner) + set -- "$@" \ + "-var=webhook_lambda_zip=$lambda_archive" \ + "-var=runners_lambda_zip=$lambda_archive" \ + "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" + ;; + permissions-boundary) + set -- "$@" \ + "-var=webhook_lambda_zip=$lambda_archive" \ + "-var=runners_lambda_zip=$lambda_archive" \ + "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" \ + "-var=iam_state_path=$permissions_state" + ;; + prebuilt) + set -- "$@" \ + "-var=webhook_lambda_zip=$lambda_archive" \ + "-var=runners_lambda_zip=$lambda_archive" \ + "-var=ami_housekeeper_lambda_zip=$lambda_archive" + ;; + termination-watcher) + set -- "$@" "-var=termination_watcher_lambda_zip=$lambda_archive" + ;; + esac + + TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" "$@" } case "$action" in prepare) - if [ -e "$worktree" ]; then - echo "Refusing to overwrite existing MiniStack worktree: $worktree" >&2 + if [ -e "$runtime_root" ]; then + echo "Refusing to overwrite existing MiniStack runtime: $runtime_root" >&2 exit 73 fi - mkdir -p "$worktree" - git -C "$source_root" archive --format=tar "${MINISTACK_SOURCE_REF:-${GITHUB_SHA:-HEAD}}" | tar -xf - -C "$worktree" - if [ ! -f "$example_root/main.tf" ]; then - echo "The isolated worktree does not contain examples/$example/main.tf" >&2 + echo "The repository does not contain examples/$example/main.tf" >&2 exit 66 fi - cp "$worktree/tests/ministack/overrides/common.tf" "$example_root/ministack_common.tf" - cp "$worktree/tests/ministack/overrides/${example}_override.tf" "$example_root/ministack_example_override.tf" - cp "$worktree/tests/ministack/overrides/versions_override.tf" "$example_root/ministack_versions_override.tf" - - case "$example" in - base | termination-watcher) - cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" - ;; - permissions-boundary) - cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" - cp "$worktree/tests/ministack/overrides/permissions-boundary-provider_override.tf" "$example_root/ministack_permissions_provider_override.tf" - ;; - *) - cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider_override.tf" - ;; - esac - + mkdir -p "$runtime_root" ;; fixture-apply) - terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly - terraform -chdir="$fixture_root" apply -auto-approve -input=false + TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform_fixture apply -auto-approve -input=false + + if [ ! -f "$lambda_archive" ]; then + echo "The shared fixture did not create the inert Lambda archive." >&2 + exit 74 + fi ;; setup-apply) if [ "$example" != "permissions-boundary" ]; then exit 0 fi - terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly - terraform -chdir="$example_root/setup" apply -auto-approve -input=false + TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly + terraform_permissions apply -auto-approve -input=false ;; init) - terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly ;; apply) terraform_example apply -auto-approve -input=false ;; destroy) - terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly terraform_example destroy -auto-approve -input=false ;; setup-destroy) @@ -93,11 +184,11 @@ case "$action" in exit 0 fi - terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly - terraform -chdir="$example_root/setup" destroy -auto-approve -input=false + TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly + terraform_permissions destroy -auto-approve -input=false ;; fixture-destroy) - terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly - terraform -chdir="$fixture_root" destroy -auto-approve -input=false + TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform_fixture destroy -auto-approve -input=false ;; esac diff --git a/tests/ministack/setup/README.md b/tests/ministack/setup/README.md index 4c39a7450a..aa1a833a37 100644 --- a/tests/ministack/setup/README.md +++ b/tests/ministack/setup/README.md @@ -31,7 +31,9 @@ No modules. ## Inputs -No inputs. +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [lambda\_archive\_path](#input\_lambda\_archive\_path) | Path where the inert Lambda archive is created. | `string` | `null` | no | ## Outputs diff --git a/tests/ministack/setup/main.tf b/tests/ministack/setup/main.tf index 208e29c66d..bbdaab3bd4 100644 --- a/tests/ministack/setup/main.tf +++ b/tests/ministack/setup/main.tf @@ -27,22 +27,32 @@ provider "aws" { s3_use_path_style = true } +variable "lambda_archive_path" { + description = "Path where the inert Lambda archive is created." + type = string + default = null +} + +locals { + lambda_archive_path = var.lambda_archive_path != null ? var.lambda_archive_path : "${path.module}/.terraform/ministack/lambda.zip" +} + data "archive_file" "lambda" { type = "zip" source_file = "${path.module}/index.mjs" - output_path = "${path.module}/.terraform/ministack/lambda.zip" + output_path = local.lambda_archive_path } resource "aws_ssm_parameter" "al2023_x64" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64" type = "String" - value = "ami-0a1b2c3d4e5f67890" + value = "ami-0abcdef1234567890" } resource "aws_ssm_parameter" "al2023_arm64" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64" type = "String" - value = "ami-0a1b2c3d4e5f67890" + value = "ami-0abcdef1234567890" } resource "aws_ssm_parameter" "github_app_id" { From 265e64d223b8d1ff66d5a8fce01b7776b6848f23 Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Wed, 26 Aug 2026 12:35:40 +0200 Subject: [PATCH 10/13] fix: undo changes --- .github/workflows/ministack.yml | 3 +- examples/default/README.md | 8 - examples/default/main.tf | 8 - examples/default/providers.tf | 3 +- examples/default/variables.tf | 53 ------ examples/ephemeral/README.md | 6 - examples/ephemeral/main.tf | 6 - examples/ephemeral/providers.tf | 3 +- examples/ephemeral/variables.tf | 41 ----- .../external-managed-ssm-secrets/README.md | 5 - examples/external-managed-ssm-secrets/main.tf | 5 - .../external-managed-ssm-secrets/providers.tf | 3 +- .../external-managed-ssm-secrets/variables.tf | 35 ---- examples/multi-runner/README.md | 6 - examples/multi-runner/main.tf | 7 +- examples/multi-runner/providers.tf | 3 +- examples/multi-runner/variables.tf | 43 +---- examples/permissions-boundary/README.md | 6 - examples/permissions-boundary/main.tf | 9 +- examples/permissions-boundary/providers.tf | 5 +- examples/permissions-boundary/variables.tf | 41 ----- examples/prebuilt/README.md | 5 - examples/prebuilt/main.tf | 5 - examples/prebuilt/providers.tf | 3 +- examples/prebuilt/variables.tf | 30 ---- examples/termination-watcher/README.md | 4 +- examples/termination-watcher/main.tf | 1 - examples/termination-watcher/variables.tf | 5 - modules/webhook-github-app/README.md | 1 - modules/webhook-github-app/main.tf | 7 - modules/webhook-github-app/variables.tf | 6 - tests/ministack/README.md | 22 +-- tests/ministack/inputs/base.tfvars | 2 - tests/ministack/inputs/default.tfvars | 14 -- tests/ministack/inputs/ephemeral.tfvars | 14 -- .../external-managed-ssm-secrets.tfvars | 23 --- tests/ministack/inputs/multi-runner.tfvars | 14 -- .../inputs/permissions-boundary.tfvars | 12 -- tests/ministack/inputs/prebuilt.tfvars | 8 - tests/ministack/run-example.sh | 167 ++++-------------- tests/ministack/setup/README.md | 4 +- tests/ministack/setup/main.tf | 16 +- 42 files changed, 64 insertions(+), 598 deletions(-) delete mode 100644 examples/termination-watcher/variables.tf delete mode 100644 tests/ministack/inputs/base.tfvars delete mode 100644 tests/ministack/inputs/default.tfvars delete mode 100644 tests/ministack/inputs/ephemeral.tfvars delete mode 100644 tests/ministack/inputs/external-managed-ssm-secrets.tfvars delete mode 100644 tests/ministack/inputs/multi-runner.tfvars delete mode 100644 tests/ministack/inputs/permissions-boundary.tfvars delete mode 100644 tests/ministack/inputs/prebuilt.tfvars diff --git a/.github/workflows/ministack.yml b/.github/workflows/ministack.yml index a3ecfb1dfc..3f5df29de3 100644 --- a/.github/workflows/ministack.yml +++ b/.github/workflows/ministack.yml @@ -61,7 +61,6 @@ jobs: services: ministack: image: ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 - options: --network-alias 000000000000.ministack env: MINISTACK_ACCOUNT_ID: "000000000000" MINISTACK_REGION: eu-west-1 @@ -81,7 +80,7 @@ jobs: run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - id: prepare - name: Prepare test runtime + name: Prepare isolated fixture env: EXAMPLE: ${{ matrix.example }} run: tests/ministack/run-example.sh prepare "$EXAMPLE" diff --git a/examples/default/README.md b/examples/default/README.md index 97b2c69083..c75e37831f 100644 --- a/examples/default/README.md +++ b/examples/default/README.md @@ -62,17 +62,9 @@ terraform output -raw webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | -| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | Path to the AMI housekeeper Lambda archive. Uses the module default when unset. | `string` | `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | -| [configure\_github\_app](#input\_configure\_github\_app) | Whether to update the GitHub App webhook after deploying the runners. | `bool` | `true` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [termination\_watcher\_lambda\_zip](#input\_termination\_watcher\_lambda\_zip) | Path to the termination watcher Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/default/main.tf b/examples/default/main.tf index b9e288f738..71c69612c3 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -20,7 +20,6 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets - ami = var.ami prefix = local.environment tags = { @@ -33,11 +32,6 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - ami_housekeeper_lambda_zip = var.ami_housekeeper_lambda_zip - # configure the block device mappings, default for Amazon Linux2 # block_device_mappings = [{ # device_name = "/dev/xvda" @@ -128,7 +122,6 @@ module "runners" { instance_termination_watcher = { enable = true - zip = var.termination_watcher_lambda_zip } # enable metric creation (experimental) @@ -156,7 +149,6 @@ module "runners" { module "webhook_github_app" { source = "../../modules/webhook-github-app" depends_on = [module.runners] - enabled = var.configure_github_app github_app = { key_base64 = var.github_app.key_base64 diff --git a/examples/default/providers.tf b/examples/default/providers.tf index c0584efe1d..eca2fe96a7 100644 --- a/examples/default/providers.tf +++ b/examples/default/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { diff --git a/examples/default/variables.tf b/examples/default/variables.tf index 71704e7570..8a3bce0854 100644 --- a/examples/default/variables.tf +++ b/examples/default/variables.tf @@ -20,56 +20,3 @@ variable "aws_region" { type = string default = "eu-west-1" } - -variable "ami" { - description = "AMI configuration for the action runner instances. Uses the module default when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "configure_github_app" { - description = "Whether to update the GitHub App webhook after deploying the runners." - type = bool - default = true -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "ami_housekeeper_lambda_zip" { - description = "Path to the AMI housekeeper Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "termination_watcher_lambda_zip" { - description = "Path to the termination watcher Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/examples/ephemeral/README.md b/examples/ephemeral/README.md index c36a8fe0ca..e6bf4961b4 100644 --- a/examples/ephemeral/README.md +++ b/examples/ephemeral/README.md @@ -61,15 +61,9 @@ terraform output webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | -| [configure\_github\_app](#input\_configure\_github\_app) | Whether to update the GitHub App webhook after deploying the runners. | `bool` | `true` | no | | [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/ephemeral/main.tf b/examples/ephemeral/main.tf index a5107d3a60..2b9403ca4d 100644 --- a/examples/ephemeral/main.tf +++ b/examples/ephemeral/main.tf @@ -20,7 +20,6 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets - ami = var.ami prefix = local.environment tags = { @@ -33,10 +32,6 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - # When not explicitly set lambda zip files are grapped from the module requiring lambda build. # Alternatively you can set the path to the lambda zip files here. # @@ -117,7 +112,6 @@ module "runners" { module "webhook_github_app" { source = "../../modules/webhook-github-app" depends_on = [module.runners] - enabled = var.configure_github_app github_app = { key_base64 = var.github_app.key_base64 diff --git a/examples/ephemeral/providers.tf b/examples/ephemeral/providers.tf index 55f6616e44..ccdd0b1622 100644 --- a/examples/ephemeral/providers.tf +++ b/examples/ephemeral/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { Example = local.environment diff --git a/examples/ephemeral/variables.tf b/examples/ephemeral/variables.tf index 1d0a243e6a..f78b2c6ae2 100644 --- a/examples/ephemeral/variables.tf +++ b/examples/ephemeral/variables.tf @@ -21,44 +21,3 @@ variable "aws_region" { type = string default = "eu-west-1" } - -variable "ami" { - description = "AMI configuration for the action runner instances. Uses the module default when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "configure_github_app" { - description = "Whether to update the GitHub App webhook after deploying the runners." - type = bool - default = true -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/examples/external-managed-ssm-secrets/README.md b/examples/external-managed-ssm-secrets/README.md index 5792eff17d..af9c95a38c 100644 --- a/examples/external-managed-ssm-secrets/README.md +++ b/examples/external-managed-ssm-secrets/README.md @@ -103,14 +103,9 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app\_ssm\_parameters](#input\_github\_app\_ssm\_parameters) | SSM parameters details for the GitHub App, that you've created manually on AWS. |
object({
key_base64 = optional(object({
arn = string
name = string
}))
id = optional(object({
arn = string
name = string
}))
webhook_secret = optional(object({
arn = string
name = string
}))
})
| `{}` | no | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/external-managed-ssm-secrets/main.tf b/examples/external-managed-ssm-secrets/main.tf index 73a77fbfa1..e390a56792 100644 --- a/examples/external-managed-ssm-secrets/main.tf +++ b/examples/external-managed-ssm-secrets/main.tf @@ -16,7 +16,6 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets - ami = var.ami prefix = local.environment tags = { @@ -29,10 +28,6 @@ module "runners" { webhook_secret_ssm = var.github_app_ssm_parameters.webhook_secret } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - enable_organization_runners = true runner_extra_labels = ["default", "example"] diff --git a/examples/external-managed-ssm-secrets/providers.tf b/examples/external-managed-ssm-secrets/providers.tf index c0584efe1d..eca2fe96a7 100644 --- a/examples/external-managed-ssm-secrets/providers.tf +++ b/examples/external-managed-ssm-secrets/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { diff --git a/examples/external-managed-ssm-secrets/variables.tf b/examples/external-managed-ssm-secrets/variables.tf index 4e32ed2e51..047f404400 100644 --- a/examples/external-managed-ssm-secrets/variables.tf +++ b/examples/external-managed-ssm-secrets/variables.tf @@ -30,38 +30,3 @@ variable "aws_region" { type = string default = "eu-west-1" } - -variable "ami" { - description = "AMI configuration for the action runner instances. Uses the module default when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/examples/multi-runner/README.md b/examples/multi-runner/README.md index 39f1190875..a899015568 100644 --- a/examples/multi-runner/README.md +++ b/examples/multi-runner/README.md @@ -90,15 +90,9 @@ terraform output -raw webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration applied to each runner configuration. Uses each configuration's AMI when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region to deploy to | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | -| [configure\_github\_app](#input\_configure\_github\_app) | Whether to update the GitHub App webhook after deploying the runners. | `bool` | `true` | no | | [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/multi-runner/main.tf b/examples/multi-runner/main.tf index 1f3559a5fa..1921656074 100644 --- a/examples/multi-runner/main.tf +++ b/examples/multi-runner/main.tf @@ -54,7 +54,7 @@ locals { subnet_ids = lookup(v.runner_config, "subnet_ids", null) != null ? [module.base.vpc.private_subnets[0]] : null vpc_id = lookup(v.runner_config, "vpc_id", null) != null ? module.base.vpc.vpc_id : null ami = contains(keys(v.runner_config), "ami") ? merge( - merge(concat([v.runner_config.ami], var.ami[*])...), + v.runner_config.ami, { id_ssm_parameter_arn = lookup(local.ssm_ami_arns, k, null) != null ? local.ssm_ami_arns[k] : null } @@ -117,10 +117,6 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - # Uncomment to distribute GitHub API rate limit usage across multiple GitHub Apps. # Each additional app must be installed on the same repos/orgs as the primary app. # The control-plane lambdas will randomly select an app for each API call. @@ -180,7 +176,6 @@ module "runners" { module "webhook_github_app" { source = "../../modules/webhook-github-app" depends_on = [module.runners] - enabled = var.configure_github_app github_app = { key_base64 = var.github_app.key_base64 diff --git a/examples/multi-runner/providers.tf b/examples/multi-runner/providers.tf index c0584efe1d..eca2fe96a7 100644 --- a/examples/multi-runner/providers.tf +++ b/examples/multi-runner/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { diff --git a/examples/multi-runner/variables.tf b/examples/multi-runner/variables.tf index 2388c280de..bc490ae273 100644 --- a/examples/multi-runner/variables.tf +++ b/examples/multi-runner/variables.tf @@ -19,45 +19,4 @@ variable "aws_region" { type = string default = "eu-west-1" -} - -variable "ami" { - description = "AMI configuration applied to each runner configuration. Uses each configuration's AMI when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "configure_github_app" { - description = "Whether to update the GitHub App webhook after deploying the runners." - type = bool - default = true -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." - type = string - default = null -} +} \ No newline at end of file diff --git a/examples/permissions-boundary/README.md b/examples/permissions-boundary/README.md index ea688df474..16ed574ed4 100644 --- a/examples/permissions-boundary/README.md +++ b/examples/permissions-boundary/README.md @@ -67,13 +67,7 @@ terraform apply | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [iam\_state\_path](#input\_iam\_state\_path) | Path to the state produced by the permissions-boundary setup. Uses the example setup state when unset. | `string` | `null` | no | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. | `string` | `"../lambdas-download/runner-binaries-syncer.zip"` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. | `string` | `"../lambdas-download/runners.zip"` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. | `string` | `"../lambdas-download/webhook.zip"` | no | ## Outputs diff --git a/examples/permissions-boundary/main.tf b/examples/permissions-boundary/main.tf index dac02d5410..3b7348ae8c 100644 --- a/examples/permissions-boundary/main.tf +++ b/examples/permissions-boundary/main.tf @@ -11,7 +11,7 @@ data "terraform_remote_state" "iam" { backend = "local" config = { - path = var.iam_state_path != null ? var.iam_state_path : "${path.module}/setup/terraform.tfstate" + path = "${path.module}/setup/terraform.tfstate" } } @@ -40,7 +40,6 @@ module "runners" { vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets kms_key_arn = aws_kms_key.github.key_id - ami = var.ami prefix = local.environment tags = { @@ -53,9 +52,9 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - runners_lambda_zip = var.runners_lambda_zip + webhook_lambda_zip = "../lambdas-download/webhook.zip" + runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" + runners_lambda_zip = "../lambdas-download/runners.zip" enable_organization_runners = false runner_extra_labels = ["default", "example"] diff --git a/examples/permissions-boundary/providers.tf b/examples/permissions-boundary/providers.tf index 2fcdcb4561..c9a9238804 100644 --- a/examples/permissions-boundary/providers.tf +++ b/examples/permissions-boundary/providers.tf @@ -1,7 +1,6 @@ provider "aws" { - alias = "terraform_role" - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + alias = "terraform_role" + region = local.aws_region assume_role { role_arn = data.terraform_remote_state.iam.outputs.role } diff --git a/examples/permissions-boundary/variables.tf b/examples/permissions-boundary/variables.tf index 3d0d26e23e..d8b5356484 100644 --- a/examples/permissions-boundary/variables.tf +++ b/examples/permissions-boundary/variables.tf @@ -6,44 +6,3 @@ variable "github_app" { key_base64 = string }) } - -variable "ami" { - description = "AMI configuration for the action runner instances. Uses the module default when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive." - type = string - default = "../lambdas-download/webhook.zip" -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive." - type = string - default = "../lambdas-download/runners.zip" -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive." - type = string - default = "../lambdas-download/runner-binaries-syncer.zip" -} - -variable "iam_state_path" { - description = "Path to the state produced by the permissions-boundary setup. Uses the example setup state when unset." - type = string - default = null -} diff --git a/examples/prebuilt/README.md b/examples/prebuilt/README.md index 23e39476da..f90a47261e 100644 --- a/examples/prebuilt/README.md +++ b/examples/prebuilt/README.md @@ -108,16 +108,11 @@ terraform output webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | Path to the AMI housekeeper Lambda archive. Uses the module default when unset. | `string` | `null` | no | | [ami\_name\_filter](#input\_ami\_name\_filter) | AMI name filter for the action runner AMI. By default amazon linux 2 is used. | `string` | `"github-runner-al2023-x86_64-*"` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | -| [configure\_github\_app](#input\_configure\_github\_app) | Whether to update the GitHub App webhook after deploying the runners. | `bool` | `true` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | | [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux, osx, windows). | `string` | `"linux"` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/prebuilt/main.tf b/examples/prebuilt/main.tf index ea70b52bb9..62434f3f61 100644 --- a/examples/prebuilt/main.tf +++ b/examples/prebuilt/main.tf @@ -32,10 +32,6 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - ami_housekeeper_lambda_zip = var.ami_housekeeper_lambda_zip - # link to downloaded lambda zip files. # When not explicitly set lambda zip files are grabbed from the module requiring lambda build. # @@ -108,7 +104,6 @@ module "runners" { module "webhook_github_app" { source = "../../modules/webhook-github-app" depends_on = [module.runners] - enabled = var.configure_github_app github_app = { key_base64 = var.github_app.key_base64 diff --git a/examples/prebuilt/providers.tf b/examples/prebuilt/providers.tf index 55f6616e44..ccdd0b1622 100644 --- a/examples/prebuilt/providers.tf +++ b/examples/prebuilt/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { Example = local.environment diff --git a/examples/prebuilt/variables.tf b/examples/prebuilt/variables.tf index 2af18bd7e3..11670a5d2e 100644 --- a/examples/prebuilt/variables.tf +++ b/examples/prebuilt/variables.tf @@ -34,33 +34,3 @@ variable "ami_name_filter" { type = string default = "github-runner-al2023-x86_64-*" } - -variable "configure_github_app" { - description = "Whether to update the GitHub App webhook after deploying the runners." - type = bool - default = true -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "ami_housekeeper_lambda_zip" { - description = "Path to the AMI housekeeper Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/examples/termination-watcher/README.md b/examples/termination-watcher/README.md index 6c1a8be75a..98f2c8783b 100644 --- a/examples/termination-watcher/README.md +++ b/examples/termination-watcher/README.md @@ -45,9 +45,7 @@ No resources. ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [termination\_watcher\_lambda\_zip](#input\_termination\_watcher\_lambda\_zip) | Path to the termination watcher Lambda archive. Uses the module default when unset. | `string` | `null` | no | +No inputs. ## Outputs diff --git a/examples/termination-watcher/main.tf b/examples/termination-watcher/main.tf index 264deb1a35..7877d04bc1 100644 --- a/examples/termination-watcher/main.tf +++ b/examples/termination-watcher/main.tf @@ -12,6 +12,5 @@ module "spot_termination_watchter" { tag_filters = { "ghr:Application" = "github-action-runner" } - zip = var.termination_watcher_lambda_zip } } diff --git a/examples/termination-watcher/variables.tf b/examples/termination-watcher/variables.tf deleted file mode 100644 index 562d63e8ad..0000000000 --- a/examples/termination-watcher/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "termination_watcher_lambda_zip" { - description = "Path to the termination watcher Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/modules/webhook-github-app/README.md b/modules/webhook-github-app/README.md index 85d65e9f34..6de85ee30d 100644 --- a/modules/webhook-github-app/README.md +++ b/modules/webhook-github-app/README.md @@ -34,7 +34,6 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [enabled](#input\_enabled) | Whether to update the GitHub App webhook. | `bool` | `true` | no | | [github\_app](#input\_github\_app) | GitHub app parameters, see your GitHub app. Ensure the key is the base64-encoded `.pem` file (the output of `base64 app.private-key.pem`, not the content of `private-key.pem`). |
object({
key_base64 = string
id = string
webhook_secret = string
})
| n/a | yes | | [webhook\_endpoint](#input\_webhook\_endpoint) | The endpoint to use for the webhook, defaults to the endpoint of the runners module. | `string` | n/a | yes | diff --git a/modules/webhook-github-app/main.tf b/modules/webhook-github-app/main.tf index b5bdccca6e..609eb85279 100644 --- a/modules/webhook-github-app/main.tf +++ b/modules/webhook-github-app/main.tf @@ -1,6 +1,4 @@ resource "null_resource" "update_app" { - count = var.enabled ? 1 : 0 - triggers = { webhook_endpoint = var.webhook_endpoint webhook_secret = var.github_app.webhook_secret @@ -12,8 +10,3 @@ resource "null_resource" "update_app" { on_failure = continue } } - -moved { - from = null_resource.update_app - to = null_resource.update_app[0] -} diff --git a/modules/webhook-github-app/variables.tf b/modules/webhook-github-app/variables.tf index 0044439b18..a9bd738509 100644 --- a/modules/webhook-github-app/variables.tf +++ b/modules/webhook-github-app/variables.tf @@ -12,9 +12,3 @@ variable "webhook_endpoint" { description = "The endpoint to use for the webhook, defaults to the endpoint of the runners module." type = string } - -variable "enabled" { - description = "Whether to update the GitHub App webhook." - type = bool - default = true -} diff --git a/tests/ministack/README.md b/tests/ministack/README.md index 574a520b80..1b9042a575 100644 --- a/tests/ministack/README.md +++ b/tests/ministack/README.md @@ -1,22 +1,14 @@ # MiniStack example lifecycle tests The MiniStack workflow runs explicit `terraform apply` and `terraform destroy` -commands from each checked-in `examples/` root. MiniStack-specific values -are supplied through ordinary example inputs in `tests/ministack/inputs`; no -Terraform configuration is copied into or layered over an example. +commands against the repository's runnable AWS examples. Every matrix entry gets +an isolated source tree, Terraform state, and MiniStack service. -Terraform data, state, and the inert Lambda archive live under the runner's -temporary directory. The small `tests/ministack/setup` root is a prerequisite, -not the code under test: it creates the inert archive and seeds the external SSM -parameters consumed by the external-secrets and multi-runner examples. The -archive prevents scheduled or S3-triggered Lambda functions from making GitHub -calls. The GitHub App updater is disabled through its normal `enabled` input. - -The runner accepts only `http://127.0.0.1:4566`, `http://localhost:4566`, or -`http://ministack:4566` as the AWS endpoint and always replaces ambient AWS -credentials with synthetic MiniStack identifiers. It also rejects -service-specific endpoint variables and ignores ambient AWS profile files so -they cannot bypass the validated global endpoint. +The fixture creates synthetic SSM values through MiniStack and an inert Lambda +archive under its ignored `.terraform/` directory. Test-only Terraform override +files route each example to that archive and a MiniStack AMI. They also disable +the `webhook-github-app` local-exec module, which would otherwise update a real +GitHub App. The production example configurations are not changed. | Example | Lifecycle coverage | | --- | --- | diff --git a/tests/ministack/inputs/base.tfvars b/tests/ministack/inputs/base.tfvars deleted file mode 100644 index 8205d159f7..0000000000 --- a/tests/ministack/inputs/base.tfvars +++ /dev/null @@ -1,2 +0,0 @@ -prefix = "ministack-base" -aws_region = "eu-west-1" diff --git a/tests/ministack/inputs/default.tfvars b/tests/ministack/inputs/default.tfvars deleted file mode 100644 index 6f3bab3bf4..0000000000 --- a/tests/ministack/inputs/default.tfvars +++ /dev/null @@ -1,14 +0,0 @@ -environment = "ministack-default" -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -configure_github_app = false -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/ephemeral.tfvars b/tests/ministack/inputs/ephemeral.tfvars deleted file mode 100644 index b40451097b..0000000000 --- a/tests/ministack/inputs/ephemeral.tfvars +++ /dev/null @@ -1,14 +0,0 @@ -environment = "ministack-ephemeral" -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -configure_github_app = false -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/external-managed-ssm-secrets.tfvars b/tests/ministack/inputs/external-managed-ssm-secrets.tfvars deleted file mode 100644 index 83b91acf4a..0000000000 --- a/tests/ministack/inputs/external-managed-ssm-secrets.tfvars +++ /dev/null @@ -1,23 +0,0 @@ -environment = "ministack-external-ssm" -github_app_ssm_parameters = { - id = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id" - name = "/ministack/terraform-aws-github-runner/github-app/id" - } - key_base64 = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64" - name = "/ministack/terraform-aws-github-runner/github-app/key-base64" - } - webhook_secret = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret" - name = "/ministack/terraform-aws-github-runner/github-app/webhook-secret" - } -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/multi-runner.tfvars b/tests/ministack/inputs/multi-runner.tfvars deleted file mode 100644 index e2d8d28ffa..0000000000 --- a/tests/ministack/inputs/multi-runner.tfvars +++ /dev/null @@ -1,14 +0,0 @@ -environment = "ministack" -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -configure_github_app = false -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/permissions-boundary.tfvars b/tests/ministack/inputs/permissions-boundary.tfvars deleted file mode 100644 index d8b20423a7..0000000000 --- a/tests/ministack/inputs/permissions-boundary.tfvars +++ /dev/null @@ -1,12 +0,0 @@ -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/prebuilt.tfvars b/tests/ministack/inputs/prebuilt.tfvars deleted file mode 100644 index 493d6b97a6..0000000000 --- a/tests/ministack/inputs/prebuilt.tfvars +++ /dev/null @@ -1,8 +0,0 @@ -environment = "ministack-prebuilt" -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami_name_filter = "amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2" -configure_github_app = false -aws_s3_use_path_style = true diff --git a/tests/ministack/run-example.sh b/tests/ministack/run-example.sh index 17c04ba664..4d30670867 100755 --- a/tests/ministack/run-example.sh +++ b/tests/ministack/run-example.sh @@ -21,162 +21,71 @@ case "$action" in ;; esac -ministack_endpoint="${AWS_ENDPOINT_URL:-http://127.0.0.1:4566}" -case "$ministack_endpoint" in - http://127.0.0.1:4566) - # S3 Control prefixes the account ID to the endpoint hostname. The - # account-prefixed localhost name resolves locally, while 127.0.0.1 does not. - ministack_endpoint="http://localhost:4566" - ;; - http://localhost:4566 | http://ministack:4566) ;; - *) - echo "Refusing to run against non-MiniStack endpoint: $ministack_endpoint" >&2 - exit 65 - ;; -esac - -service_endpoint_variables=$( - env | awk -F= ' - $1 ~ /^AWS_ENDPOINT_URL_/ || $1 ~ /^AWS_[A-Z0-9_]+_ENDPOINT$/ { print $1 } - ' -) -if [ -n "$service_endpoint_variables" ]; then - echo "Refusing to run with service-specific AWS endpoint variables:" >&2 - printf '%s\n' "$service_endpoint_variables" >&2 - exit 65 -fi - -# Always use synthetic credentials and route every AWS client to MiniStack. -export AWS_ACCESS_KEY_ID="000000000000" -export AWS_CONFIG_FILE="/dev/null" -export AWS_DEFAULT_REGION="eu-west-1" -export AWS_EC2_METADATA_DISABLED="true" -export AWS_ENDPOINT_URL="$ministack_endpoint" -export AWS_IGNORE_CONFIGURED_ENDPOINT_URLS="false" -export AWS_REGION="eu-west-1" -export AWS_SECRET_ACCESS_KEY="ministack-test-only" -export AWS_SHARED_CREDENTIALS_FILE="/dev/null" -unset AWS_ACCESS_KEY AWS_DEFAULT_PROFILE AWS_PROFILE AWS_SECRET_KEY AWS_SECURITY_TOKEN AWS_SESSION_TOKEN - -ministack_no_proxy="localhost,127.0.0.1,ministack,.ministack,000000000000.ministack" -export NO_PROXY="${NO_PROXY:+$NO_PROXY,}$ministack_no_proxy" -export no_proxy="${no_proxy:+$no_proxy,}$ministack_no_proxy" - script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) source_root="${GITHUB_WORKSPACE:-$(CDPATH='' cd -- "$script_dir/../.." && pwd)}" temporary_root="${RUNNER_TEMP:-${TMPDIR:-/tmp}}" -runtime_root="$temporary_root/terraform-aws-github-runner-ministack-$example" -example_root="$source_root/examples/$example" -fixture_root="$source_root/tests/ministack/setup" -input_file="$source_root/tests/ministack/inputs/$example.tfvars" - -fixture_data_dir="$runtime_root/fixture-data" -fixture_state="$runtime_root/fixture.tfstate" -lambda_archive="$runtime_root/lambda.zip" -example_data_dir="$runtime_root/example-data" -example_state="$runtime_root/example.tfstate" -permissions_data_dir="$runtime_root/permissions-data" -permissions_state="$runtime_root/permissions.tfstate" - -terraform_fixture() { - subcommand="$1" - shift - TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" "$subcommand" "$@" \ - -state="$fixture_state" \ - -var="lambda_archive_path=$lambda_archive" -} - -terraform_permissions() { - subcommand="$1" - shift - TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" "$subcommand" "$@" \ - -state="$permissions_state" -} +worktree="$temporary_root/terraform-aws-github-runner-ministack-$example" +example_root="$worktree/examples/$example" +fixture_root="$worktree/tests/ministack/setup" +lambda_archive="$fixture_root/.terraform/ministack/lambda.zip" terraform_example() { - subcommand="$1" - shift - set -- "$subcommand" "$@" "-state=$example_state" - - if [ -f "$input_file" ]; then - set -- "$@" "-var-file=$input_file" - fi - - case "$example" in - default) - set -- "$@" \ - "-var=webhook_lambda_zip=$lambda_archive" \ - "-var=runners_lambda_zip=$lambda_archive" \ - "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" \ - "-var=ami_housekeeper_lambda_zip=$lambda_archive" \ - "-var=termination_watcher_lambda_zip=$lambda_archive" - ;; - ephemeral | external-managed-ssm-secrets | multi-runner) - set -- "$@" \ - "-var=webhook_lambda_zip=$lambda_archive" \ - "-var=runners_lambda_zip=$lambda_archive" \ - "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" - ;; - permissions-boundary) - set -- "$@" \ - "-var=webhook_lambda_zip=$lambda_archive" \ - "-var=runners_lambda_zip=$lambda_archive" \ - "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" \ - "-var=iam_state_path=$permissions_state" - ;; - prebuilt) - set -- "$@" \ - "-var=webhook_lambda_zip=$lambda_archive" \ - "-var=runners_lambda_zip=$lambda_archive" \ - "-var=ami_housekeeper_lambda_zip=$lambda_archive" - ;; - termination-watcher) - set -- "$@" "-var=termination_watcher_lambda_zip=$lambda_archive" - ;; - esac - - TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" "$@" + terraform -chdir="$example_root" "$@" -var="ministack_lambda_archive=$lambda_archive" } case "$action" in prepare) - if [ -e "$runtime_root" ]; then - echo "Refusing to overwrite existing MiniStack runtime: $runtime_root" >&2 + if [ -e "$worktree" ]; then + echo "Refusing to overwrite existing MiniStack worktree: $worktree" >&2 exit 73 fi + mkdir -p "$worktree" + git -C "$source_root" archive --format=tar "${MINISTACK_SOURCE_REF:-${GITHUB_SHA:-HEAD}}" | tar -xf - -C "$worktree" + if [ ! -f "$example_root/main.tf" ]; then - echo "The repository does not contain examples/$example/main.tf" >&2 + echo "The isolated worktree does not contain examples/$example/main.tf" >&2 exit 66 fi - mkdir -p "$runtime_root" + cp "$worktree/tests/ministack/overrides/common.tf" "$example_root/ministack_common.tf" + cp "$worktree/tests/ministack/overrides/${example}_override.tf" "$example_root/ministack_example_override.tf" + cp "$worktree/tests/ministack/overrides/versions_override.tf" "$example_root/ministack_versions_override.tf" + + case "$example" in + base | termination-watcher) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" + ;; + permissions-boundary) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" + cp "$worktree/tests/ministack/overrides/permissions-boundary-provider_override.tf" "$example_root/ministack_permissions_provider_override.tf" + ;; + *) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider_override.tf" + ;; + esac + ;; fixture-apply) - TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly - terraform_fixture apply -auto-approve -input=false - - if [ ! -f "$lambda_archive" ]; then - echo "The shared fixture did not create the inert Lambda archive." >&2 - exit 74 - fi + terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$fixture_root" apply -auto-approve -input=false ;; setup-apply) if [ "$example" != "permissions-boundary" ]; then exit 0 fi - TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly - terraform_permissions apply -auto-approve -input=false + terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$example_root/setup" apply -auto-approve -input=false ;; init) - TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly ;; apply) terraform_example apply -auto-approve -input=false ;; destroy) - TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly terraform_example destroy -auto-approve -input=false ;; setup-destroy) @@ -184,11 +93,11 @@ case "$action" in exit 0 fi - TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly - terraform_permissions destroy -auto-approve -input=false + terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$example_root/setup" destroy -auto-approve -input=false ;; fixture-destroy) - TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly - terraform_fixture destroy -auto-approve -input=false + terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$fixture_root" destroy -auto-approve -input=false ;; esac diff --git a/tests/ministack/setup/README.md b/tests/ministack/setup/README.md index aa1a833a37..4c39a7450a 100644 --- a/tests/ministack/setup/README.md +++ b/tests/ministack/setup/README.md @@ -31,9 +31,7 @@ No modules. ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [lambda\_archive\_path](#input\_lambda\_archive\_path) | Path where the inert Lambda archive is created. | `string` | `null` | no | +No inputs. ## Outputs diff --git a/tests/ministack/setup/main.tf b/tests/ministack/setup/main.tf index bbdaab3bd4..208e29c66d 100644 --- a/tests/ministack/setup/main.tf +++ b/tests/ministack/setup/main.tf @@ -27,32 +27,22 @@ provider "aws" { s3_use_path_style = true } -variable "lambda_archive_path" { - description = "Path where the inert Lambda archive is created." - type = string - default = null -} - -locals { - lambda_archive_path = var.lambda_archive_path != null ? var.lambda_archive_path : "${path.module}/.terraform/ministack/lambda.zip" -} - data "archive_file" "lambda" { type = "zip" source_file = "${path.module}/index.mjs" - output_path = local.lambda_archive_path + output_path = "${path.module}/.terraform/ministack/lambda.zip" } resource "aws_ssm_parameter" "al2023_x64" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64" type = "String" - value = "ami-0abcdef1234567890" + value = "ami-0a1b2c3d4e5f67890" } resource "aws_ssm_parameter" "al2023_arm64" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64" type = "String" - value = "ami-0abcdef1234567890" + value = "ami-0a1b2c3d4e5f67890" } resource "aws_ssm_parameter" "github_app_id" { From e8b6222cfdd5243291269c2e3ab17984da526f12 Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Wed, 26 Aug 2026 12:42:37 +0200 Subject: [PATCH 11/13] test(terraform): run examples against MiniStack directly --- .github/workflows/ministack.yml | 3 +- examples/default/README.md | 7 + examples/default/main.tf | 7 + examples/default/providers.tf | 3 +- examples/default/variables.tf | 47 +++++ examples/ephemeral/README.md | 5 + examples/ephemeral/main.tf | 5 + examples/ephemeral/providers.tf | 3 +- examples/ephemeral/variables.tf | 35 ++++ .../external-managed-ssm-secrets/README.md | 5 + examples/external-managed-ssm-secrets/main.tf | 5 + .../external-managed-ssm-secrets/providers.tf | 3 +- .../external-managed-ssm-secrets/variables.tf | 35 ++++ examples/multi-runner/README.md | 5 + examples/multi-runner/main.tf | 6 +- examples/multi-runner/providers.tf | 3 +- examples/multi-runner/variables.tf | 37 +++- examples/permissions-boundary/README.md | 6 + examples/permissions-boundary/main.tf | 9 +- examples/permissions-boundary/providers.tf | 5 +- examples/permissions-boundary/variables.tf | 41 ++++ examples/prebuilt/README.md | 4 + examples/prebuilt/main.tf | 4 + examples/prebuilt/providers.tf | 3 +- examples/prebuilt/variables.tf | 24 +++ examples/termination-watcher/README.md | 4 +- examples/termination-watcher/main.tf | 1 + examples/termination-watcher/variables.tf | 5 + tests/ministack/README.md | 23 ++- tests/ministack/inputs/base.tfvars | 2 + tests/ministack/inputs/default.tfvars | 13 ++ tests/ministack/inputs/ephemeral.tfvars | 13 ++ .../external-managed-ssm-secrets.tfvars | 23 +++ tests/ministack/inputs/multi-runner.tfvars | 13 ++ .../inputs/permissions-boundary.tfvars | 12 ++ tests/ministack/inputs/prebuilt.tfvars | 7 + tests/ministack/run-example.sh | 175 ++++++++++++++---- tests/ministack/setup/README.md | 4 +- tests/ministack/setup/main.tf | 16 +- 39 files changed, 557 insertions(+), 64 deletions(-) create mode 100644 examples/termination-watcher/variables.tf create mode 100644 tests/ministack/inputs/base.tfvars create mode 100644 tests/ministack/inputs/default.tfvars create mode 100644 tests/ministack/inputs/ephemeral.tfvars create mode 100644 tests/ministack/inputs/external-managed-ssm-secrets.tfvars create mode 100644 tests/ministack/inputs/multi-runner.tfvars create mode 100644 tests/ministack/inputs/permissions-boundary.tfvars create mode 100644 tests/ministack/inputs/prebuilt.tfvars diff --git a/.github/workflows/ministack.yml b/.github/workflows/ministack.yml index 3f5df29de3..a3ecfb1dfc 100644 --- a/.github/workflows/ministack.yml +++ b/.github/workflows/ministack.yml @@ -61,6 +61,7 @@ jobs: services: ministack: image: ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 + options: --network-alias 000000000000.ministack env: MINISTACK_ACCOUNT_ID: "000000000000" MINISTACK_REGION: eu-west-1 @@ -80,7 +81,7 @@ jobs: run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - id: prepare - name: Prepare isolated fixture + name: Prepare test runtime env: EXAMPLE: ${{ matrix.example }} run: tests/ministack/run-example.sh prepare "$EXAMPLE" diff --git a/examples/default/README.md b/examples/default/README.md index c75e37831f..ff2e4116ac 100644 --- a/examples/default/README.md +++ b/examples/default/README.md @@ -62,9 +62,16 @@ terraform output -raw webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | +| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | Path to the AMI housekeeper Lambda archive. Uses the module default when unset. | `string` | `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [termination\_watcher\_lambda\_zip](#input\_termination\_watcher\_lambda\_zip) | Path to the termination watcher Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/default/main.tf b/examples/default/main.tf index 71c69612c3..f3f43d541e 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -20,6 +20,7 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets + ami = var.ami prefix = local.environment tags = { @@ -32,6 +33,11 @@ module "runners" { webhook_secret = random_id.random.hex } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + ami_housekeeper_lambda_zip = var.ami_housekeeper_lambda_zip + # configure the block device mappings, default for Amazon Linux2 # block_device_mappings = [{ # device_name = "/dev/xvda" @@ -122,6 +128,7 @@ module "runners" { instance_termination_watcher = { enable = true + zip = var.termination_watcher_lambda_zip } # enable metric creation (experimental) diff --git a/examples/default/providers.tf b/examples/default/providers.tf index eca2fe96a7..c0584efe1d 100644 --- a/examples/default/providers.tf +++ b/examples/default/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { diff --git a/examples/default/variables.tf b/examples/default/variables.tf index 8a3bce0854..c310dd0dc1 100644 --- a/examples/default/variables.tf +++ b/examples/default/variables.tf @@ -20,3 +20,50 @@ variable "aws_region" { type = string default = "eu-west-1" } + +variable "ami" { + description = "AMI configuration for the action runner instances. Uses the module default when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "ami_housekeeper_lambda_zip" { + description = "Path to the AMI housekeeper Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "termination_watcher_lambda_zip" { + description = "Path to the termination watcher Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/ephemeral/README.md b/examples/ephemeral/README.md index e6bf4961b4..5e0dd7501d 100644 --- a/examples/ephemeral/README.md +++ b/examples/ephemeral/README.md @@ -61,9 +61,14 @@ terraform output webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/ephemeral/main.tf b/examples/ephemeral/main.tf index 2b9403ca4d..30d9483b15 100644 --- a/examples/ephemeral/main.tf +++ b/examples/ephemeral/main.tf @@ -20,6 +20,7 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets + ami = var.ami prefix = local.environment tags = { @@ -32,6 +33,10 @@ module "runners" { webhook_secret = random_id.random.hex } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + # When not explicitly set lambda zip files are grapped from the module requiring lambda build. # Alternatively you can set the path to the lambda zip files here. # diff --git a/examples/ephemeral/providers.tf b/examples/ephemeral/providers.tf index ccdd0b1622..55f6616e44 100644 --- a/examples/ephemeral/providers.tf +++ b/examples/ephemeral/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { Example = local.environment diff --git a/examples/ephemeral/variables.tf b/examples/ephemeral/variables.tf index f78b2c6ae2..c3f0bc0053 100644 --- a/examples/ephemeral/variables.tf +++ b/examples/ephemeral/variables.tf @@ -21,3 +21,38 @@ variable "aws_region" { type = string default = "eu-west-1" } + +variable "ami" { + description = "AMI configuration for the action runner instances. Uses the module default when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/external-managed-ssm-secrets/README.md b/examples/external-managed-ssm-secrets/README.md index af9c95a38c..5792eff17d 100644 --- a/examples/external-managed-ssm-secrets/README.md +++ b/examples/external-managed-ssm-secrets/README.md @@ -103,9 +103,14 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app\_ssm\_parameters](#input\_github\_app\_ssm\_parameters) | SSM parameters details for the GitHub App, that you've created manually on AWS. |
object({
key_base64 = optional(object({
arn = string
name = string
}))
id = optional(object({
arn = string
name = string
}))
webhook_secret = optional(object({
arn = string
name = string
}))
})
| `{}` | no | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/external-managed-ssm-secrets/main.tf b/examples/external-managed-ssm-secrets/main.tf index e390a56792..73a77fbfa1 100644 --- a/examples/external-managed-ssm-secrets/main.tf +++ b/examples/external-managed-ssm-secrets/main.tf @@ -16,6 +16,7 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets + ami = var.ami prefix = local.environment tags = { @@ -28,6 +29,10 @@ module "runners" { webhook_secret_ssm = var.github_app_ssm_parameters.webhook_secret } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + enable_organization_runners = true runner_extra_labels = ["default", "example"] diff --git a/examples/external-managed-ssm-secrets/providers.tf b/examples/external-managed-ssm-secrets/providers.tf index eca2fe96a7..c0584efe1d 100644 --- a/examples/external-managed-ssm-secrets/providers.tf +++ b/examples/external-managed-ssm-secrets/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { diff --git a/examples/external-managed-ssm-secrets/variables.tf b/examples/external-managed-ssm-secrets/variables.tf index 047f404400..4e32ed2e51 100644 --- a/examples/external-managed-ssm-secrets/variables.tf +++ b/examples/external-managed-ssm-secrets/variables.tf @@ -30,3 +30,38 @@ variable "aws_region" { type = string default = "eu-west-1" } + +variable "ami" { + description = "AMI configuration for the action runner instances. Uses the module default when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/multi-runner/README.md b/examples/multi-runner/README.md index a899015568..2073badfc1 100644 --- a/examples/multi-runner/README.md +++ b/examples/multi-runner/README.md @@ -90,9 +90,14 @@ terraform output -raw webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration applied to each runner configuration. Uses each configuration's AMI when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region to deploy to | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/multi-runner/main.tf b/examples/multi-runner/main.tf index 1921656074..102a58259e 100644 --- a/examples/multi-runner/main.tf +++ b/examples/multi-runner/main.tf @@ -54,7 +54,7 @@ locals { subnet_ids = lookup(v.runner_config, "subnet_ids", null) != null ? [module.base.vpc.private_subnets[0]] : null vpc_id = lookup(v.runner_config, "vpc_id", null) != null ? module.base.vpc.vpc_id : null ami = contains(keys(v.runner_config), "ami") ? merge( - v.runner_config.ami, + merge(concat([v.runner_config.ami], var.ami[*])...), { id_ssm_parameter_arn = lookup(local.ssm_ami_arns, k, null) != null ? local.ssm_ami_arns[k] : null } @@ -117,6 +117,10 @@ module "runners" { webhook_secret = random_id.random.hex } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + # Uncomment to distribute GitHub API rate limit usage across multiple GitHub Apps. # Each additional app must be installed on the same repos/orgs as the primary app. # The control-plane lambdas will randomly select an app for each API call. diff --git a/examples/multi-runner/providers.tf b/examples/multi-runner/providers.tf index eca2fe96a7..c0584efe1d 100644 --- a/examples/multi-runner/providers.tf +++ b/examples/multi-runner/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { diff --git a/examples/multi-runner/variables.tf b/examples/multi-runner/variables.tf index bc490ae273..36f826b9e8 100644 --- a/examples/multi-runner/variables.tf +++ b/examples/multi-runner/variables.tf @@ -19,4 +19,39 @@ variable "aws_region" { type = string default = "eu-west-1" -} \ No newline at end of file +} + +variable "ami" { + description = "AMI configuration applied to each runner configuration. Uses each configuration's AMI when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/permissions-boundary/README.md b/examples/permissions-boundary/README.md index 16ed574ed4..ea688df474 100644 --- a/examples/permissions-boundary/README.md +++ b/examples/permissions-boundary/README.md @@ -67,7 +67,13 @@ terraform apply | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | +| [iam\_state\_path](#input\_iam\_state\_path) | Path to the state produced by the permissions-boundary setup. Uses the example setup state when unset. | `string` | `null` | no | +| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. | `string` | `"../lambdas-download/runner-binaries-syncer.zip"` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. | `string` | `"../lambdas-download/runners.zip"` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. | `string` | `"../lambdas-download/webhook.zip"` | no | ## Outputs diff --git a/examples/permissions-boundary/main.tf b/examples/permissions-boundary/main.tf index 3b7348ae8c..dac02d5410 100644 --- a/examples/permissions-boundary/main.tf +++ b/examples/permissions-boundary/main.tf @@ -11,7 +11,7 @@ data "terraform_remote_state" "iam" { backend = "local" config = { - path = "${path.module}/setup/terraform.tfstate" + path = var.iam_state_path != null ? var.iam_state_path : "${path.module}/setup/terraform.tfstate" } } @@ -40,6 +40,7 @@ module "runners" { vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets kms_key_arn = aws_kms_key.github.key_id + ami = var.ami prefix = local.environment tags = { @@ -52,9 +53,9 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = "../lambdas-download/webhook.zip" - runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" - runners_lambda_zip = "../lambdas-download/runners.zip" + webhook_lambda_zip = var.webhook_lambda_zip + runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip + runners_lambda_zip = var.runners_lambda_zip enable_organization_runners = false runner_extra_labels = ["default", "example"] diff --git a/examples/permissions-boundary/providers.tf b/examples/permissions-boundary/providers.tf index c9a9238804..2fcdcb4561 100644 --- a/examples/permissions-boundary/providers.tf +++ b/examples/permissions-boundary/providers.tf @@ -1,6 +1,7 @@ provider "aws" { - alias = "terraform_role" - region = local.aws_region + alias = "terraform_role" + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style assume_role { role_arn = data.terraform_remote_state.iam.outputs.role } diff --git a/examples/permissions-boundary/variables.tf b/examples/permissions-boundary/variables.tf index d8b5356484..3d0d26e23e 100644 --- a/examples/permissions-boundary/variables.tf +++ b/examples/permissions-boundary/variables.tf @@ -6,3 +6,44 @@ variable "github_app" { key_base64 = string }) } + +variable "ami" { + description = "AMI configuration for the action runner instances. Uses the module default when unset." + type = object({ + filter = optional(map(list(string)), { state = ["available"] }) + owners = optional(list(string), ["amazon"]) + id_ssm_parameter_arn = optional(string, null) + kms_key_arn = optional(string, null) + }) + default = null +} + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive." + type = string + default = "../lambdas-download/webhook.zip" +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive." + type = string + default = "../lambdas-download/runners.zip" +} + +variable "runner_binaries_syncer_lambda_zip" { + description = "Path to the runner binaries syncer Lambda archive." + type = string + default = "../lambdas-download/runner-binaries-syncer.zip" +} + +variable "iam_state_path" { + description = "Path to the state produced by the permissions-boundary setup. Uses the example setup state when unset." + type = string + default = null +} diff --git a/examples/prebuilt/README.md b/examples/prebuilt/README.md index f90a47261e..b1c91b9b1f 100644 --- a/examples/prebuilt/README.md +++ b/examples/prebuilt/README.md @@ -108,11 +108,15 @@ terraform output webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | Path to the AMI housekeeper Lambda archive. Uses the module default when unset. | `string` | `null` | no | | [ami\_name\_filter](#input\_ami\_name\_filter) | AMI name filter for the action runner AMI. By default amazon linux 2 is used. | `string` | `"github-runner-al2023-x86_64-*"` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | +| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | | [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux, osx, windows). | `string` | `"linux"` | no | +| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | +| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/prebuilt/main.tf b/examples/prebuilt/main.tf index 62434f3f61..5aafcb39d7 100644 --- a/examples/prebuilt/main.tf +++ b/examples/prebuilt/main.tf @@ -32,6 +32,10 @@ module "runners" { webhook_secret = random_id.random.hex } + webhook_lambda_zip = var.webhook_lambda_zip + runners_lambda_zip = var.runners_lambda_zip + ami_housekeeper_lambda_zip = var.ami_housekeeper_lambda_zip + # link to downloaded lambda zip files. # When not explicitly set lambda zip files are grabbed from the module requiring lambda build. # diff --git a/examples/prebuilt/providers.tf b/examples/prebuilt/providers.tf index ccdd0b1622..55f6616e44 100644 --- a/examples/prebuilt/providers.tf +++ b/examples/prebuilt/providers.tf @@ -1,5 +1,6 @@ provider "aws" { - region = local.aws_region + region = local.aws_region + s3_use_path_style = var.aws_s3_use_path_style default_tags { tags = { Example = local.environment diff --git a/examples/prebuilt/variables.tf b/examples/prebuilt/variables.tf index 11670a5d2e..346117f2ca 100644 --- a/examples/prebuilt/variables.tf +++ b/examples/prebuilt/variables.tf @@ -34,3 +34,27 @@ variable "ami_name_filter" { type = string default = "github-runner-al2023-x86_64-*" } + +variable "aws_s3_use_path_style" { + description = "Whether the AWS provider should use path-style S3 addressing." + type = bool + default = false +} + +variable "webhook_lambda_zip" { + description = "Path to the webhook Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "runners_lambda_zip" { + description = "Path to the runners Lambda archive. Uses the module default when unset." + type = string + default = null +} + +variable "ami_housekeeper_lambda_zip" { + description = "Path to the AMI housekeeper Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/examples/termination-watcher/README.md b/examples/termination-watcher/README.md index 98f2c8783b..6c1a8be75a 100644 --- a/examples/termination-watcher/README.md +++ b/examples/termination-watcher/README.md @@ -45,7 +45,9 @@ No resources. ## Inputs -No inputs. +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [termination\_watcher\_lambda\_zip](#input\_termination\_watcher\_lambda\_zip) | Path to the termination watcher Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/termination-watcher/main.tf b/examples/termination-watcher/main.tf index 7877d04bc1..264deb1a35 100644 --- a/examples/termination-watcher/main.tf +++ b/examples/termination-watcher/main.tf @@ -12,5 +12,6 @@ module "spot_termination_watchter" { tag_filters = { "ghr:Application" = "github-action-runner" } + zip = var.termination_watcher_lambda_zip } } diff --git a/examples/termination-watcher/variables.tf b/examples/termination-watcher/variables.tf new file mode 100644 index 0000000000..562d63e8ad --- /dev/null +++ b/examples/termination-watcher/variables.tf @@ -0,0 +1,5 @@ +variable "termination_watcher_lambda_zip" { + description = "Path to the termination watcher Lambda archive. Uses the module default when unset." + type = string + default = null +} diff --git a/tests/ministack/README.md b/tests/ministack/README.md index 1b9042a575..22a6c28dbb 100644 --- a/tests/ministack/README.md +++ b/tests/ministack/README.md @@ -1,14 +1,23 @@ # MiniStack example lifecycle tests The MiniStack workflow runs explicit `terraform apply` and `terraform destroy` -commands against the repository's runnable AWS examples. Every matrix entry gets -an isolated source tree, Terraform state, and MiniStack service. +commands from each checked-in `examples/` root. MiniStack-specific values +are supplied through ordinary example inputs in `tests/ministack/inputs`; no +Terraform configuration is copied into or layered over an example. -The fixture creates synthetic SSM values through MiniStack and an inert Lambda -archive under its ignored `.terraform/` directory. Test-only Terraform override -files route each example to that archive and a MiniStack AMI. They also disable -the `webhook-github-app` local-exec module, which would otherwise update a real -GitHub App. The production example configurations are not changed. +Terraform data, state, and the inert Lambda archive live under the runner's +temporary directory. The small `tests/ministack/setup` root is a prerequisite, +not the code under test: it creates the inert archive and seeds the external SSM +parameters consumed by the external-secrets and multi-runner examples. The +archive prevents scheduled or S3-triggered Lambda functions from making GitHub +calls. The GitHub App updater is outside this AWS-only lifecycle test and is +excluded with a Terraform target. + +The runner accepts only `http://127.0.0.1:4566`, `http://localhost:4566`, or +`http://ministack:4566` as the AWS endpoint and always replaces ambient AWS +credentials with synthetic MiniStack identifiers. It also rejects +service-specific endpoint variables and ignores ambient AWS profile files so +they cannot bypass the validated global endpoint. | Example | Lifecycle coverage | | --- | --- | diff --git a/tests/ministack/inputs/base.tfvars b/tests/ministack/inputs/base.tfvars new file mode 100644 index 0000000000..8205d159f7 --- /dev/null +++ b/tests/ministack/inputs/base.tfvars @@ -0,0 +1,2 @@ +prefix = "ministack-base" +aws_region = "eu-west-1" diff --git a/tests/ministack/inputs/default.tfvars b/tests/ministack/inputs/default.tfvars new file mode 100644 index 0000000000..0fe575cdb3 --- /dev/null +++ b/tests/ministack/inputs/default.tfvars @@ -0,0 +1,13 @@ +environment = "ministack-default" +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/ephemeral.tfvars b/tests/ministack/inputs/ephemeral.tfvars new file mode 100644 index 0000000000..f0f6056ea3 --- /dev/null +++ b/tests/ministack/inputs/ephemeral.tfvars @@ -0,0 +1,13 @@ +environment = "ministack-ephemeral" +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/external-managed-ssm-secrets.tfvars b/tests/ministack/inputs/external-managed-ssm-secrets.tfvars new file mode 100644 index 0000000000..83b91acf4a --- /dev/null +++ b/tests/ministack/inputs/external-managed-ssm-secrets.tfvars @@ -0,0 +1,23 @@ +environment = "ministack-external-ssm" +github_app_ssm_parameters = { + id = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id" + name = "/ministack/terraform-aws-github-runner/github-app/id" + } + key_base64 = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64" + name = "/ministack/terraform-aws-github-runner/github-app/key-base64" + } + webhook_secret = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret" + name = "/ministack/terraform-aws-github-runner/github-app/webhook-secret" + } +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/multi-runner.tfvars b/tests/ministack/inputs/multi-runner.tfvars new file mode 100644 index 0000000000..dcdef53a6d --- /dev/null +++ b/tests/ministack/inputs/multi-runner.tfvars @@ -0,0 +1,13 @@ +environment = "ministack" +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/permissions-boundary.tfvars b/tests/ministack/inputs/permissions-boundary.tfvars new file mode 100644 index 0000000000..d8b20423a7 --- /dev/null +++ b/tests/ministack/inputs/permissions-boundary.tfvars @@ -0,0 +1,12 @@ +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] +} +aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/prebuilt.tfvars b/tests/ministack/inputs/prebuilt.tfvars new file mode 100644 index 0000000000..27c628b4eb --- /dev/null +++ b/tests/ministack/inputs/prebuilt.tfvars @@ -0,0 +1,7 @@ +environment = "ministack-prebuilt" +github_app = { + id = "0" + key_base64 = "ministack-invalid-github-app-key" +} +ami_name_filter = "amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2" +aws_s3_use_path_style = true diff --git a/tests/ministack/run-example.sh b/tests/ministack/run-example.sh index 4d30670867..869d914653 100755 --- a/tests/ministack/run-example.sh +++ b/tests/ministack/run-example.sh @@ -21,71 +21,170 @@ case "$action" in ;; esac +ministack_endpoint="${AWS_ENDPOINT_URL:-http://127.0.0.1:4566}" +case "$ministack_endpoint" in + http://127.0.0.1:4566) + # S3 Control prefixes the account ID to the endpoint hostname. The + # account-prefixed localhost name resolves locally, while 127.0.0.1 does not. + ministack_endpoint="http://localhost:4566" + ;; + http://localhost:4566 | http://ministack:4566) ;; + *) + echo "Refusing to run against non-MiniStack endpoint: $ministack_endpoint" >&2 + exit 65 + ;; +esac + +service_endpoint_variables=$( + env | awk -F= ' + $1 ~ /^AWS_ENDPOINT_URL_/ || $1 ~ /^AWS_[A-Z0-9_]+_ENDPOINT$/ { print $1 } + ' +) +if [ -n "$service_endpoint_variables" ]; then + echo "Refusing to run with service-specific AWS endpoint variables:" >&2 + printf '%s\n' "$service_endpoint_variables" >&2 + exit 65 +fi + +# Always use synthetic credentials and route every AWS client to MiniStack. +export AWS_ACCESS_KEY_ID="000000000000" +export AWS_CONFIG_FILE="/dev/null" +export AWS_DEFAULT_REGION="eu-west-1" +export AWS_EC2_METADATA_DISABLED="true" +export AWS_ENDPOINT_URL="$ministack_endpoint" +export AWS_IGNORE_CONFIGURED_ENDPOINT_URLS="false" +export AWS_REGION="eu-west-1" +export AWS_SECRET_ACCESS_KEY="ministack-test-only" +export AWS_SHARED_CREDENTIALS_FILE="/dev/null" +unset AWS_ACCESS_KEY AWS_DEFAULT_PROFILE AWS_PROFILE AWS_SECRET_KEY AWS_SECURITY_TOKEN AWS_SESSION_TOKEN + +ministack_no_proxy="localhost,127.0.0.1,ministack,.ministack,000000000000.ministack" +export NO_PROXY="${NO_PROXY:+$NO_PROXY,}$ministack_no_proxy" +export no_proxy="${no_proxy:+$no_proxy,}$ministack_no_proxy" + script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) source_root="${GITHUB_WORKSPACE:-$(CDPATH='' cd -- "$script_dir/../.." && pwd)}" temporary_root="${RUNNER_TEMP:-${TMPDIR:-/tmp}}" -worktree="$temporary_root/terraform-aws-github-runner-ministack-$example" -example_root="$worktree/examples/$example" -fixture_root="$worktree/tests/ministack/setup" -lambda_archive="$fixture_root/.terraform/ministack/lambda.zip" +runtime_root="$temporary_root/terraform-aws-github-runner-ministack-$example" +example_root="$source_root/examples/$example" +fixture_root="$source_root/tests/ministack/setup" +input_file="$source_root/tests/ministack/inputs/$example.tfvars" + +fixture_data_dir="$runtime_root/fixture-data" +fixture_state="$runtime_root/fixture.tfstate" +lambda_archive="$runtime_root/lambda.zip" +example_data_dir="$runtime_root/example-data" +example_state="$runtime_root/example.tfstate" +permissions_data_dir="$runtime_root/permissions-data" +permissions_state="$runtime_root/permissions.tfstate" + +terraform_fixture() { + subcommand="$1" + shift + TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" "$subcommand" "$@" \ + -state="$fixture_state" \ + -var="lambda_archive_path=$lambda_archive" +} + +terraform_permissions() { + subcommand="$1" + shift + TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" "$subcommand" "$@" \ + -state="$permissions_state" +} terraform_example() { - terraform -chdir="$example_root" "$@" -var="ministack_lambda_archive=$lambda_archive" + subcommand="$1" + shift + set -- "$subcommand" "$@" "-state=$example_state" + + if [ -f "$input_file" ]; then + set -- "$@" "-var-file=$input_file" + fi + + case "$example" in + default) + set -- "$@" \ + "-var=webhook_lambda_zip=$lambda_archive" \ + "-var=runners_lambda_zip=$lambda_archive" \ + "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" \ + "-var=ami_housekeeper_lambda_zip=$lambda_archive" \ + "-var=termination_watcher_lambda_zip=$lambda_archive" + ;; + ephemeral | external-managed-ssm-secrets | multi-runner) + set -- "$@" \ + "-var=webhook_lambda_zip=$lambda_archive" \ + "-var=runners_lambda_zip=$lambda_archive" \ + "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" + ;; + permissions-boundary) + set -- "$@" \ + "-var=webhook_lambda_zip=$lambda_archive" \ + "-var=runners_lambda_zip=$lambda_archive" \ + "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" \ + "-var=iam_state_path=$permissions_state" + ;; + prebuilt) + set -- "$@" \ + "-var=webhook_lambda_zip=$lambda_archive" \ + "-var=runners_lambda_zip=$lambda_archive" \ + "-var=ami_housekeeper_lambda_zip=$lambda_archive" + ;; + termination-watcher) + set -- "$@" "-var=termination_watcher_lambda_zip=$lambda_archive" + ;; + esac + + # This module calls the GitHub API through local-exec, so it is deliberately + # outside the AWS/MiniStack lifecycle coverage. + case "$example" in + default | ephemeral | multi-runner | prebuilt) + set -- "$@" "-target=module.runners" + ;; + esac + + TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" "$@" } case "$action" in prepare) - if [ -e "$worktree" ]; then - echo "Refusing to overwrite existing MiniStack worktree: $worktree" >&2 + if [ -e "$runtime_root" ]; then + echo "Refusing to overwrite existing MiniStack runtime: $runtime_root" >&2 exit 73 fi - mkdir -p "$worktree" - git -C "$source_root" archive --format=tar "${MINISTACK_SOURCE_REF:-${GITHUB_SHA:-HEAD}}" | tar -xf - -C "$worktree" - if [ ! -f "$example_root/main.tf" ]; then - echo "The isolated worktree does not contain examples/$example/main.tf" >&2 + echo "The repository does not contain examples/$example/main.tf" >&2 exit 66 fi - cp "$worktree/tests/ministack/overrides/common.tf" "$example_root/ministack_common.tf" - cp "$worktree/tests/ministack/overrides/${example}_override.tf" "$example_root/ministack_example_override.tf" - cp "$worktree/tests/ministack/overrides/versions_override.tf" "$example_root/ministack_versions_override.tf" - - case "$example" in - base | termination-watcher) - cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" - ;; - permissions-boundary) - cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" - cp "$worktree/tests/ministack/overrides/permissions-boundary-provider_override.tf" "$example_root/ministack_permissions_provider_override.tf" - ;; - *) - cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider_override.tf" - ;; - esac - + mkdir -p "$runtime_root" ;; fixture-apply) - terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly - terraform -chdir="$fixture_root" apply -auto-approve -input=false + TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform_fixture apply -auto-approve -input=false + + if [ ! -f "$lambda_archive" ]; then + echo "The shared fixture did not create the inert Lambda archive." >&2 + exit 74 + fi ;; setup-apply) if [ "$example" != "permissions-boundary" ]; then exit 0 fi - terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly - terraform -chdir="$example_root/setup" apply -auto-approve -input=false + TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly + terraform_permissions apply -auto-approve -input=false ;; init) - terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly ;; apply) terraform_example apply -auto-approve -input=false ;; destroy) - terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly terraform_example destroy -auto-approve -input=false ;; setup-destroy) @@ -93,11 +192,11 @@ case "$action" in exit 0 fi - terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly - terraform -chdir="$example_root/setup" destroy -auto-approve -input=false + TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly + terraform_permissions destroy -auto-approve -input=false ;; fixture-destroy) - terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly - terraform -chdir="$fixture_root" destroy -auto-approve -input=false + TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform_fixture destroy -auto-approve -input=false ;; esac diff --git a/tests/ministack/setup/README.md b/tests/ministack/setup/README.md index 4c39a7450a..aa1a833a37 100644 --- a/tests/ministack/setup/README.md +++ b/tests/ministack/setup/README.md @@ -31,7 +31,9 @@ No modules. ## Inputs -No inputs. +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [lambda\_archive\_path](#input\_lambda\_archive\_path) | Path where the inert Lambda archive is created. | `string` | `null` | no | ## Outputs diff --git a/tests/ministack/setup/main.tf b/tests/ministack/setup/main.tf index 208e29c66d..bbdaab3bd4 100644 --- a/tests/ministack/setup/main.tf +++ b/tests/ministack/setup/main.tf @@ -27,22 +27,32 @@ provider "aws" { s3_use_path_style = true } +variable "lambda_archive_path" { + description = "Path where the inert Lambda archive is created." + type = string + default = null +} + +locals { + lambda_archive_path = var.lambda_archive_path != null ? var.lambda_archive_path : "${path.module}/.terraform/ministack/lambda.zip" +} + data "archive_file" "lambda" { type = "zip" source_file = "${path.module}/index.mjs" - output_path = "${path.module}/.terraform/ministack/lambda.zip" + output_path = local.lambda_archive_path } resource "aws_ssm_parameter" "al2023_x64" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64" type = "String" - value = "ami-0a1b2c3d4e5f67890" + value = "ami-0abcdef1234567890" } resource "aws_ssm_parameter" "al2023_arm64" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64" type = "String" - value = "ami-0a1b2c3d4e5f67890" + value = "ami-0abcdef1234567890" } resource "aws_ssm_parameter" "github_app_id" { From d946ee13fbe0b565f8c651adacb20f8761f4360e Mon Sep 17 00:00:00 2001 From: edersonbrilhante Date: Wed, 26 Aug 2026 12:49:30 +0200 Subject: [PATCH 12/13] fix(ci): isolate MiniStack example configuration --- .github/workflows/ministack.yml | 3 +- examples/base/.terraform.lock.hcl | 35 ++-- examples/base/README.md | 2 +- examples/default/.terraform.lock.hcl | 4 - examples/default/README.md | 7 - examples/default/main.tf | 7 - examples/default/providers.tf | 3 +- examples/default/variables.tf | 47 ----- examples/ephemeral/.terraform.lock.hcl | 4 - examples/ephemeral/README.md | 5 - examples/ephemeral/main.tf | 5 - examples/ephemeral/providers.tf | 3 +- examples/ephemeral/variables.tf | 35 ---- .../.terraform.lock.hcl | 4 - .../external-managed-ssm-secrets/README.md | 5 - examples/external-managed-ssm-secrets/main.tf | 5 - .../external-managed-ssm-secrets/providers.tf | 3 +- .../external-managed-ssm-secrets/variables.tf | 35 ---- examples/multi-runner/.terraform.lock.hcl | 4 - examples/multi-runner/README.md | 5 - examples/multi-runner/main.tf | 6 +- examples/multi-runner/providers.tf | 3 +- examples/multi-runner/variables.tf | 37 +--- .../permissions-boundary/.terraform.lock.hcl | 119 ++++++------ examples/permissions-boundary/README.md | 10 +- examples/permissions-boundary/main.tf | 9 +- examples/permissions-boundary/providers.tf | 5 +- .../setup/.terraform.lock.hcl | 79 ++------ examples/permissions-boundary/setup/README.md | 2 +- examples/permissions-boundary/variables.tf | 41 ---- examples/prebuilt/.terraform.lock.hcl | 4 - examples/prebuilt/README.md | 4 - examples/prebuilt/main.tf | 4 - examples/prebuilt/providers.tf | 3 +- examples/prebuilt/variables.tf | 24 --- .../termination-watcher/.terraform.lock.hcl | 35 ++-- examples/termination-watcher/README.md | 4 +- examples/termination-watcher/main.tf | 1 - examples/termination-watcher/variables.tf | 5 - tests/ministack/README.md | 23 +-- tests/ministack/inputs/base.tfvars | 2 - tests/ministack/inputs/default.tfvars | 13 -- tests/ministack/inputs/ephemeral.tfvars | 13 -- .../external-managed-ssm-secrets.tfvars | 23 --- tests/ministack/inputs/multi-runner.tfvars | 13 -- .../inputs/permissions-boundary.tfvars | 12 -- tests/ministack/inputs/prebuilt.tfvars | 7 - tests/ministack/overrides/README.md | 39 ++++ tests/ministack/overrides/base_override.tf | 7 + tests/ministack/overrides/common.tf | 19 ++ tests/ministack/overrides/default_override.tf | 29 +++ .../ministack/overrides/ephemeral_override.tf | 23 +++ .../external-managed-ssm-secrets_override.tf | 27 +++ .../overrides/multi-runner_override.tf | 39 ++++ .../permissions-boundary-provider_override.tf | 14 ++ .../permissions-boundary_override.tf | 13 ++ .../ministack/overrides/prebuilt_override.tf | 26 +++ tests/ministack/overrides/provider.tf | 16 ++ .../overrides/termination-watcher_override.tf | 15 ++ tests/ministack/overrides/versions.tf | 10 + tests/ministack/run-example.sh | 178 ++++-------------- tests/ministack/setup/README.md | 4 +- tests/ministack/setup/main.tf | 16 +- 63 files changed, 455 insertions(+), 742 deletions(-) delete mode 100644 examples/termination-watcher/variables.tf delete mode 100644 tests/ministack/inputs/base.tfvars delete mode 100644 tests/ministack/inputs/default.tfvars delete mode 100644 tests/ministack/inputs/ephemeral.tfvars delete mode 100644 tests/ministack/inputs/external-managed-ssm-secrets.tfvars delete mode 100644 tests/ministack/inputs/multi-runner.tfvars delete mode 100644 tests/ministack/inputs/permissions-boundary.tfvars delete mode 100644 tests/ministack/inputs/prebuilt.tfvars create mode 100644 tests/ministack/overrides/README.md create mode 100644 tests/ministack/overrides/base_override.tf create mode 100644 tests/ministack/overrides/common.tf create mode 100644 tests/ministack/overrides/default_override.tf create mode 100644 tests/ministack/overrides/ephemeral_override.tf create mode 100644 tests/ministack/overrides/external-managed-ssm-secrets_override.tf create mode 100644 tests/ministack/overrides/multi-runner_override.tf create mode 100644 tests/ministack/overrides/permissions-boundary-provider_override.tf create mode 100644 tests/ministack/overrides/permissions-boundary_override.tf create mode 100644 tests/ministack/overrides/prebuilt_override.tf create mode 100644 tests/ministack/overrides/provider.tf create mode 100644 tests/ministack/overrides/termination-watcher_override.tf create mode 100644 tests/ministack/overrides/versions.tf diff --git a/.github/workflows/ministack.yml b/.github/workflows/ministack.yml index a3ecfb1dfc..3f5df29de3 100644 --- a/.github/workflows/ministack.yml +++ b/.github/workflows/ministack.yml @@ -61,7 +61,6 @@ jobs: services: ministack: image: ghcr.io/ministackorg/ministack:1.5.0@sha256:ba48c20747780605a4287a950e7bb1758ddc3b55ec92409a0c47677cbe26bbb9 - options: --network-alias 000000000000.ministack env: MINISTACK_ACCOUNT_ID: "000000000000" MINISTACK_REGION: eu-west-1 @@ -81,7 +80,7 @@ jobs: run: git config --global --add safe.directory "$GITHUB_WORKSPACE" - id: prepare - name: Prepare test runtime + name: Prepare isolated fixture env: EXAMPLE: ${{ matrix.example }} run: tests/ministack/run-example.sh prepare "$EXAMPLE" diff --git a/examples/base/.terraform.lock.hcl b/examples/base/.terraform.lock.hcl index 5fc3fb1c53..c160b58a9e 100644 --- a/examples/base/.terraform.lock.hcl +++ b/examples/base/.terraform.lock.hcl @@ -2,25 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "6.35.1" - constraints = ">= 5.0.0, 6.35.1" + version = "6.0.0" + constraints = ">= 5.0.0, >= 6.0.0" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", - "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", - "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", - "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", - "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", - "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", - "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", - "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", - "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", - "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", - "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", + "h1:dbRRZ1NzH1QV/+83xT/X3MLYaZobMXt8DNwbqnJojpo=", + "zh:16b1bb786719b7ebcddba3ab751b976ebf4006f7144afeebcb83f0c5f41f8eb9", + "zh:1fbc08b817b9eaf45a2b72ccba59f4ea19e7fcf017be29f5a9552b623eccc5bc", + "zh:304f58f3333dbe846cfbdfc2227e6ed77041ceea33b6183972f3f8ab51bd065f", + "zh:4cd447b5c24f14553bd6e1a0e4fea3c7d7b218cbb2316a3d93f1c5cb562c181b", + "zh:589472b56be8277558616075fc5480fcd812ba6dc70e8979375fc6d8750f83ef", + "zh:5d78484ba43c26f1ef6067c4150550b06fd39c5d4bfb790f92c4a6f7d9d0201b", + "zh:5f470ce664bffb22ace736643d2abe7ad45858022b652143bcd02d71d38d4e42", + "zh:7a9cbb947aaab8c885096bce5da22838ca482196cf7d04ffb8bdf7fd28003e47", + "zh:854df3e4c50675e727705a0eaa4f8d42ccd7df6a5efa2456f0205a9901ace019", + "zh:87162c0f47b1260f5969679dccb246cb528f27f01229d02fd30a8e2f9869ba2c", + "zh:9a145404d506b52078cd7060e6cbb83f8fc7953f3f63a5e7137d41f69d6317a3", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", - "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", - "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", - "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", - "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", + "zh:a4eab2649f5afe06cc406ce2aaf9fd44dcf311123f48d344c255e93454c08921", + "zh:bea09141c6186a3e133413ae3a2e3d1aaf4f43466a6a468827287527edf21710", + "zh:d7ea2a35ff55ddfe639ab3b04331556b772a8698eca01f5d74151615d9f336db", ] } diff --git a/examples/base/README.md b/examples/base/README.md index e866dea9bf..95b6fcee52 100644 --- a/examples/base/README.md +++ b/examples/base/README.md @@ -10,7 +10,7 @@ | Name | Version | |------|---------| -| [aws](#provider\_aws) | 6.35.1 | +| [aws](#provider\_aws) | 6.0.0 | ## Modules diff --git a/examples/default/.terraform.lock.hcl b/examples/default/.terraform.lock.hcl index 17012dcab0..136f5367b1 100644 --- a/examples/default/.terraform.lock.hcl +++ b/examples/default/.terraform.lock.hcl @@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -29,7 +28,6 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ - "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -51,7 +49,6 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", - "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -71,7 +68,6 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ - "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/default/README.md b/examples/default/README.md index ff2e4116ac..c75e37831f 100644 --- a/examples/default/README.md +++ b/examples/default/README.md @@ -62,16 +62,9 @@ terraform output -raw webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | -| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | Path to the AMI housekeeper Lambda archive. Uses the module default when unset. | `string` | `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [termination\_watcher\_lambda\_zip](#input\_termination\_watcher\_lambda\_zip) | Path to the termination watcher Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/default/main.tf b/examples/default/main.tf index f3f43d541e..71c69612c3 100644 --- a/examples/default/main.tf +++ b/examples/default/main.tf @@ -20,7 +20,6 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets - ami = var.ami prefix = local.environment tags = { @@ -33,11 +32,6 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - ami_housekeeper_lambda_zip = var.ami_housekeeper_lambda_zip - # configure the block device mappings, default for Amazon Linux2 # block_device_mappings = [{ # device_name = "/dev/xvda" @@ -128,7 +122,6 @@ module "runners" { instance_termination_watcher = { enable = true - zip = var.termination_watcher_lambda_zip } # enable metric creation (experimental) diff --git a/examples/default/providers.tf b/examples/default/providers.tf index c0584efe1d..eca2fe96a7 100644 --- a/examples/default/providers.tf +++ b/examples/default/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { diff --git a/examples/default/variables.tf b/examples/default/variables.tf index c310dd0dc1..8a3bce0854 100644 --- a/examples/default/variables.tf +++ b/examples/default/variables.tf @@ -20,50 +20,3 @@ variable "aws_region" { type = string default = "eu-west-1" } - -variable "ami" { - description = "AMI configuration for the action runner instances. Uses the module default when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "ami_housekeeper_lambda_zip" { - description = "Path to the AMI housekeeper Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "termination_watcher_lambda_zip" { - description = "Path to the termination watcher Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/examples/ephemeral/.terraform.lock.hcl b/examples/ephemeral/.terraform.lock.hcl index 17012dcab0..136f5367b1 100644 --- a/examples/ephemeral/.terraform.lock.hcl +++ b/examples/ephemeral/.terraform.lock.hcl @@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -29,7 +28,6 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ - "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -51,7 +49,6 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", - "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -71,7 +68,6 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ - "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/ephemeral/README.md b/examples/ephemeral/README.md index 5e0dd7501d..e6bf4961b4 100644 --- a/examples/ephemeral/README.md +++ b/examples/ephemeral/README.md @@ -61,14 +61,9 @@ terraform output webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/ephemeral/main.tf b/examples/ephemeral/main.tf index 30d9483b15..2b9403ca4d 100644 --- a/examples/ephemeral/main.tf +++ b/examples/ephemeral/main.tf @@ -20,7 +20,6 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets - ami = var.ami prefix = local.environment tags = { @@ -33,10 +32,6 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - # When not explicitly set lambda zip files are grapped from the module requiring lambda build. # Alternatively you can set the path to the lambda zip files here. # diff --git a/examples/ephemeral/providers.tf b/examples/ephemeral/providers.tf index 55f6616e44..ccdd0b1622 100644 --- a/examples/ephemeral/providers.tf +++ b/examples/ephemeral/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { Example = local.environment diff --git a/examples/ephemeral/variables.tf b/examples/ephemeral/variables.tf index c3f0bc0053..f78b2c6ae2 100644 --- a/examples/ephemeral/variables.tf +++ b/examples/ephemeral/variables.tf @@ -21,38 +21,3 @@ variable "aws_region" { type = string default = "eu-west-1" } - -variable "ami" { - description = "AMI configuration for the action runner instances. Uses the module default when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/examples/external-managed-ssm-secrets/.terraform.lock.hcl b/examples/external-managed-ssm-secrets/.terraform.lock.hcl index 17012dcab0..136f5367b1 100644 --- a/examples/external-managed-ssm-secrets/.terraform.lock.hcl +++ b/examples/external-managed-ssm-secrets/.terraform.lock.hcl @@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -29,7 +28,6 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ - "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -51,7 +49,6 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", - "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -71,7 +68,6 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ - "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/external-managed-ssm-secrets/README.md b/examples/external-managed-ssm-secrets/README.md index 5792eff17d..af9c95a38c 100644 --- a/examples/external-managed-ssm-secrets/README.md +++ b/examples/external-managed-ssm-secrets/README.md @@ -103,14 +103,9 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app\_ssm\_parameters](#input\_github\_app\_ssm\_parameters) | SSM parameters details for the GitHub App, that you've created manually on AWS. |
object({
key_base64 = optional(object({
arn = string
name = string
}))
id = optional(object({
arn = string
name = string
}))
webhook_secret = optional(object({
arn = string
name = string
}))
})
| `{}` | no | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/external-managed-ssm-secrets/main.tf b/examples/external-managed-ssm-secrets/main.tf index 73a77fbfa1..e390a56792 100644 --- a/examples/external-managed-ssm-secrets/main.tf +++ b/examples/external-managed-ssm-secrets/main.tf @@ -16,7 +16,6 @@ module "runners" { aws_region = local.aws_region vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets - ami = var.ami prefix = local.environment tags = { @@ -29,10 +28,6 @@ module "runners" { webhook_secret_ssm = var.github_app_ssm_parameters.webhook_secret } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - enable_organization_runners = true runner_extra_labels = ["default", "example"] diff --git a/examples/external-managed-ssm-secrets/providers.tf b/examples/external-managed-ssm-secrets/providers.tf index c0584efe1d..eca2fe96a7 100644 --- a/examples/external-managed-ssm-secrets/providers.tf +++ b/examples/external-managed-ssm-secrets/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { diff --git a/examples/external-managed-ssm-secrets/variables.tf b/examples/external-managed-ssm-secrets/variables.tf index 4e32ed2e51..047f404400 100644 --- a/examples/external-managed-ssm-secrets/variables.tf +++ b/examples/external-managed-ssm-secrets/variables.tf @@ -30,38 +30,3 @@ variable "aws_region" { type = string default = "eu-west-1" } - -variable "ami" { - description = "AMI configuration for the action runner instances. Uses the module default when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/examples/multi-runner/.terraform.lock.hcl b/examples/multi-runner/.terraform.lock.hcl index 17012dcab0..136f5367b1 100644 --- a/examples/multi-runner/.terraform.lock.hcl +++ b/examples/multi-runner/.terraform.lock.hcl @@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -29,7 +28,6 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ - "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -51,7 +49,6 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", - "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -71,7 +68,6 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ - "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/multi-runner/README.md b/examples/multi-runner/README.md index 2073badfc1..a899015568 100644 --- a/examples/multi-runner/README.md +++ b/examples/multi-runner/README.md @@ -90,14 +90,9 @@ terraform output -raw webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration applied to each runner configuration. Uses each configuration's AMI when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | | [aws\_region](#input\_aws\_region) | AWS region to deploy to | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/multi-runner/main.tf b/examples/multi-runner/main.tf index 102a58259e..1921656074 100644 --- a/examples/multi-runner/main.tf +++ b/examples/multi-runner/main.tf @@ -54,7 +54,7 @@ locals { subnet_ids = lookup(v.runner_config, "subnet_ids", null) != null ? [module.base.vpc.private_subnets[0]] : null vpc_id = lookup(v.runner_config, "vpc_id", null) != null ? module.base.vpc.vpc_id : null ami = contains(keys(v.runner_config), "ami") ? merge( - merge(concat([v.runner_config.ami], var.ami[*])...), + v.runner_config.ami, { id_ssm_parameter_arn = lookup(local.ssm_ami_arns, k, null) != null ? local.ssm_ami_arns[k] : null } @@ -117,10 +117,6 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - # Uncomment to distribute GitHub API rate limit usage across multiple GitHub Apps. # Each additional app must be installed on the same repos/orgs as the primary app. # The control-plane lambdas will randomly select an app for each API call. diff --git a/examples/multi-runner/providers.tf b/examples/multi-runner/providers.tf index c0584efe1d..eca2fe96a7 100644 --- a/examples/multi-runner/providers.tf +++ b/examples/multi-runner/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { diff --git a/examples/multi-runner/variables.tf b/examples/multi-runner/variables.tf index 36f826b9e8..bc490ae273 100644 --- a/examples/multi-runner/variables.tf +++ b/examples/multi-runner/variables.tf @@ -19,39 +19,4 @@ variable "aws_region" { type = string default = "eu-west-1" -} - -variable "ami" { - description = "AMI configuration applied to each runner configuration. Uses each configuration's AMI when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive. Uses the module default when unset." - type = string - default = null -} +} \ No newline at end of file diff --git a/examples/permissions-boundary/.terraform.lock.hcl b/examples/permissions-boundary/.terraform.lock.hcl index de4b9eeb40..be40c689d7 100644 --- a/examples/permissions-boundary/.terraform.lock.hcl +++ b/examples/permissions-boundary/.terraform.lock.hcl @@ -2,91 +2,84 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "6.35.1" - constraints = ">= 5.0.0, >= 6.21.0, >= 6.33.0, 6.35.1" + version = "6.22.1" + constraints = ">= 5.0.0, >= 6.21.0" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", - "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", - "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", - "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", - "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", - "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", - "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", - "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", - "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", - "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", - "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", + "h1:PTgxp+nMDBd6EFHAIH6ceFfvwa2blqkCwXglZn6Dqa8=", + "zh:3995ca97e6c2c1ed9e231c453287585d3dc1ca2a304683ac0b269b3448fda7c0", + "zh:4f69f70d2edeb0dde9c693b7cd7e8e21c781b2fac7062bed5300092dbadb71e1", + "zh:5c76042fdf3df56a1f581bc477e5d6fc3e099d4d6544fe725b3747e9990726bd", + "zh:6ff8221340955f4b3ba9230918bb026c4414a5aebe9d0967845c43e8e8908aec", + "zh:73cdd8638cb52bbe25887cd5b7946cc3fcb891867de11bcb0fde9b35c4f70a41", + "zh:7af5aec2fd01fa5e5f600f1db1bcf200aaadc05a2c8ffcbb4b6b61cd2bd3e33b", + "zh:7e055cfa7f40b667f5f7af564db9544f46aa189cdbe5530ad812e027647132f5", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", - "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", - "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", - "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", - "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", + "zh:aba898190c668ade4471da65c96db414679367174ac5b73e8ce7551056c77e3e", + "zh:aedaa8d7d71e6d58cdc09a7e3bcb8031b3ea496a7ac142376eb679d1756057f3", + "zh:cb9739952d467b3f6d72d57722943956e80ab235b58a0e34758538381dcc386c", + "zh:e12a2681028a70cb08eaf4c3364ddab386416502f966067bf99e79ba6be0d7b6", + "zh:e32a922a7d6fd5df69b3cc92932fc2689dc195b0f8b493dcd686abdd892b06cd", + "zh:f2dea7dead6f34b51e8b6aae177a8b333834a41d25529baa634a087d99ea32f6", + "zh:f6eee6df0366e8452d912cfd498792579aede88de3b67c15d36b8949e37479b1", ] } provider "registry.terraform.io/hashicorp/local" { - version = "2.9.0" + version = "2.6.1" constraints = "~> 2.0" hashes = [ - "h1:9rBZCMNpxKwMlRbWH2QpwD3kqUCAejdOZQ/aiiDObXQ=", - "h1:m24fjcInWvTVZ1XSo2MaNuKPe+X/gfG8SIi09rA7a7M=", - "zh:0baa4566cf77f1ff52f4293d1c8536202dd23edc197c3196413a28343c3ac3a0", - "zh:16b5559c3c07088ddad11a9bb9e9c0799999363c2958e9a5be2bcbbf2cd9ca64", - "zh:197c79015a10d1cce904a8ea722cbc750c42aeae2da53f44a6a0751d9fd1aa90", - "zh:29d0b03e5343a80677ebfeb2e2c31cbe4b1f65e736e53417454a4277fec2544c", - "zh:4896bfa6cf1d2fd562b47ef2e87f47862ae92a04f8ad5d764380f0c6653473b8", - "zh:531f8529cbca49f681883e57761a05a8398afaef6d1ab0d205d26bf12f4428e8", - "zh:6aaf5011d83161c86d2bfb80c0923ec934e578288758da2f37acb7aec129004b", - "zh:7430275253d3d3c40aa6179e0ec0d63212874dbbc06c5a51b9d07ec590f9756c", + "h1:DbiR/D2CPigzCGweYIyJH0N0x04oyI5xiZ9wSW/s3kQ=", + "zh:10050d08f416de42a857e4b6f76809aae63ea4ec6f5c852a126a915dede814b4", + "zh:2df2a3ebe9830d4759c59b51702e209fe053f47453cb4688f43c063bac8746b7", + "zh:2e759568bcc38c86ca0e43701d34cf29945736fdc8e429c5b287ddc2703c7b18", + "zh:6a62a34e48500ab4aea778e355e162ebde03260b7a9eb9edc7e534c84fbca4c6", + "zh:74373728ba32a1d5450a3a88ac45624579e32755b086cd4e51e88d9aca240ef6", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:be17dc611e95e26cdf6cad79dfccf1064f0e32032a2efeb939a9bbe7fb1cbfe9", - "zh:f0e3b0aa644202e1d79d2000dca91f6019425da71e9800fa23f27e51c034f195", - "zh:f62bae4519e4ead49182ddc8afe8cf61e2a4c3ba3973b0fbba967736a2696aa3", - "zh:fcafa360a5b0b96244f26f4e3a6d642b716a376557142c2442ff2fb12d11da18", + "zh:8dddae588971a996f622e7589cd8b9da7834c744ac12bfb59c97fa77ded95255", + "zh:946f82f66353bb97aefa8d95c4ca86db227f9b7c50b82415289ac47e4e74d08d", + "zh:e9a5c09e6f35e510acf15b666fd0b34a30164cecdcd81ce7cda0f4b2dade8d91", + "zh:eafe5b873ef42b32feb2f969c38ff8652507e695620cbaf03b9db714bee52249", + "zh:ec146289fa27650c9d433bb5c7847379180c0b7a323b1b94e6e7ad5d2a7dbe71", + "zh:fc882c35ce05631d76c0973b35adde26980778fc81d9da81a2fade2b9d73423b", ] } provider "registry.terraform.io/hashicorp/null" { - version = "3.3.1" + version = "3.2.4" constraints = "~> 3.0, ~> 3.2" hashes = [ - "h1:TuxJq10DVnRP7c5HBZPyyvQGcckNVfijyU1eXEu5e4M=", - "h1:m5FqidbIgh+E9OigiZh8/xbkvpUQFSj3hZo/jqNLCLQ=", - "zh:08c59776542ea16e5a8545752787b17ff412922182b4cfabe16139197be8ac44", - "zh:123109cc7e5ed6d515787fbc212f2a3fd5e75647bb24ab7c801ccd4d4ed42451", - "zh:14b3fa4372754b54844b41d5dbd4671a292d8d6828b90169061feb4d7b15dd05", - "zh:56a4daaa3212f57b764bf3d1f333141c6610c5f21abb240e0111221f7c7fa4d4", + "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", + "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:7e888a026dbacd2474a42264227ae35f639780f0f0c613529d10a95cd61988b3", - "zh:85a53646267e87d600df7124e4767ffde9bba3b6356d45d961618bdd68131cc7", - "zh:8ffa0e9c7c39b2ab0905b472465d6e35ef0b776b3f6273bb34c150340b61bff1", - "zh:9846510a1841530d4403f4818e233f91e3b3bade7441047599fbf800742f65be", - "zh:afa98d44860875f037c6def0a7e6ff208e042712ba771f620482b143cd336891", - "zh:bdca130d9ef27488ae0b13bc8fd8019e8bbdd4f2ceff29da066bd333165d68c5", - "zh:cb3b94cbca88210dd0d1f11e2b8a89333f48c3857faf8f70f589072ce7c28610", - "zh:f0c0ba87925fe32f84b80f7513b1efb1b0866f51f899ba825e95ad59ff09b018", + "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", + "zh:7b9c7b16f118fbc2b05a983817b8ce2f86df125857966ad356353baf4bff5c0a", + "zh:85e33ab43e0e1726e5f97a874b8e24820b6565ff8076523cc2922ba671492991", + "zh:9d32ac3619cfc93eb3c4f423492a8e0f79db05fec58e449dee9b2d5873d5f69f", + "zh:9e15c3c9dd8e0d1e3731841d44c34571b6c97f5b95e8296a45318b94e5287a6e", + "zh:b4c2ab35d1b7696c30b64bf2c0f3a62329107bd1a9121ce70683dec58af19615", + "zh:c43723e8cc65bcdf5e0c92581dcbbdcbdcf18b8d2037406a5f2033b1e22de442", + "zh:ceb5495d9c31bfb299d246ab333f08c7fb0d67a4f82681fbf47f2a21c3e11ab5", + "zh:e171026b3659305c558d9804062762d168f50ba02b88b231d20ec99578a6233f", + "zh:ed0fe2acdb61330b01841fa790be00ec6beaac91d41f311fb8254f74eb6a711f", ] } provider "registry.terraform.io/hashicorp/random" { - version = "3.9.0" + version = "3.7.2" constraints = "~> 3.0" hashes = [ - "h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=", - "h1:UlBuNVuCGJ39tTv2c5gz2NRZnQbXfbIWbTzWcth5o74=", - "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", - "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", - "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", - "zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0", - "zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61", - "zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc", - "zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398", + "h1:KG4NuIBl1mRWU0KD/BGfCi1YN/j3F7H4YgeeM7iSdNs=", + "zh:14829603a32e4bc4d05062f059e545a91e27ff033756b48afbae6b3c835f508f", + "zh:1527fb07d9fea400d70e9e6eb4a2b918d5060d604749b6f1c361518e7da546dc", + "zh:1e86bcd7ebec85ba336b423ba1db046aeaa3c0e5f921039b3f1a6fc2f978feab", + "zh:24536dec8bde66753f4b4030b8f3ef43c196d69cccbea1c382d01b222478c7a3", + "zh:29f1786486759fad9b0ce4fdfbbfece9343ad47cd50119045075e05afe49d212", + "zh:4d701e978c2dd8604ba1ce962b047607701e65c078cb22e97171513e9e57491f", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e", - "zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef", - "zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b", - "zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257", - "zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04", + "zh:7b8434212eef0f8c83f5a90c6d76feaf850f6502b61b53c329e85b3b281cba34", + "zh:ac8a23c212258b7976e1621275e3af7099e7e4a3d4478cf8d5d2a27f3bc3e967", + "zh:b516ca74431f3df4c6cf90ddcdb4042c626e026317a33c53f0b445a3d93b720d", + "zh:dc76e4326aec2490c1600d6871a95e78f9050f9ce427c71707ea412a2f2f1a62", + "zh:eac7b63e86c749c7d48f527671c7aee5b4e26c10be6ad7232d6860167f99dbb0", ] } diff --git a/examples/permissions-boundary/README.md b/examples/permissions-boundary/README.md index ea688df474..523e10edda 100644 --- a/examples/permissions-boundary/README.md +++ b/examples/permissions-boundary/README.md @@ -43,8 +43,8 @@ terraform apply | Name | Version | |------|---------| -| [aws](#provider\_aws) | 6.35.1 | -| [random](#provider\_random) | 3.9.0 | +| [aws](#provider\_aws) | 6.22.1 | +| [random](#provider\_random) | 3.7.2 | | [terraform](#provider\_terraform) | n/a | ## Modules @@ -67,13 +67,7 @@ terraform apply | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami](#input\_ami) | AMI configuration for the action runner instances. Uses the module default when unset. |
object({
filter = optional(map(list(string)), { state = ["available"] })
owners = optional(list(string), ["amazon"])
id_ssm_parameter_arn = optional(string, null)
kms_key_arn = optional(string, null)
})
| `null` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | -| [iam\_state\_path](#input\_iam\_state\_path) | Path to the state produced by the permissions-boundary setup. Uses the example setup state when unset. | `string` | `null` | no | -| [runner\_binaries\_syncer\_lambda\_zip](#input\_runner\_binaries\_syncer\_lambda\_zip) | Path to the runner binaries syncer Lambda archive. | `string` | `"../lambdas-download/runner-binaries-syncer.zip"` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. | `string` | `"../lambdas-download/runners.zip"` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. | `string` | `"../lambdas-download/webhook.zip"` | no | ## Outputs diff --git a/examples/permissions-boundary/main.tf b/examples/permissions-boundary/main.tf index dac02d5410..3b7348ae8c 100644 --- a/examples/permissions-boundary/main.tf +++ b/examples/permissions-boundary/main.tf @@ -11,7 +11,7 @@ data "terraform_remote_state" "iam" { backend = "local" config = { - path = var.iam_state_path != null ? var.iam_state_path : "${path.module}/setup/terraform.tfstate" + path = "${path.module}/setup/terraform.tfstate" } } @@ -40,7 +40,6 @@ module "runners" { vpc_id = module.base.vpc.vpc_id subnet_ids = module.base.vpc.private_subnets kms_key_arn = aws_kms_key.github.key_id - ami = var.ami prefix = local.environment tags = { @@ -53,9 +52,9 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runner_binaries_syncer_lambda_zip = var.runner_binaries_syncer_lambda_zip - runners_lambda_zip = var.runners_lambda_zip + webhook_lambda_zip = "../lambdas-download/webhook.zip" + runner_binaries_syncer_lambda_zip = "../lambdas-download/runner-binaries-syncer.zip" + runners_lambda_zip = "../lambdas-download/runners.zip" enable_organization_runners = false runner_extra_labels = ["default", "example"] diff --git a/examples/permissions-boundary/providers.tf b/examples/permissions-boundary/providers.tf index 2fcdcb4561..c9a9238804 100644 --- a/examples/permissions-boundary/providers.tf +++ b/examples/permissions-boundary/providers.tf @@ -1,7 +1,6 @@ provider "aws" { - alias = "terraform_role" - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + alias = "terraform_role" + region = local.aws_region assume_role { role_arn = data.terraform_remote_state.iam.outputs.role } diff --git a/examples/permissions-boundary/setup/.terraform.lock.hcl b/examples/permissions-boundary/setup/.terraform.lock.hcl index 82fd8e4c2a..9ccf7ef886 100644 --- a/examples/permissions-boundary/setup/.terraform.lock.hcl +++ b/examples/permissions-boundary/setup/.terraform.lock.hcl @@ -2,69 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "6.35.1" - constraints = ">= 6.21.0, 6.35.1" + version = "5.31.0" + constraints = "~> 5.2" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", - "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", - "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", - "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", - "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", - "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", - "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", - "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", - "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", - "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", - "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", + "h1:ltxyuBWIy9cq0kIKDJH1jeWJy/y7XJLjS4QrsQK4plA=", + "zh:0cdb9c2083bf0902442384f7309367791e4640581652dda456f2d6d7abf0de8d", + "zh:2fe4884cb9642f48a5889f8dff8f5f511418a18537a9dfa77ada3bcdad391e4e", + "zh:36d8bdd72fe61d816d0049c179f495bc6f1e54d8d7b07c45b62e5e1696882a89", + "zh:539dd156e3ec608818eb21191697b230117437a58587cbd02ce533202a4dd520", + "zh:6a53f4b57ac4eb3479fc0d8b6e301ca3a27efae4c55d9f8bd24071b12a03361c", + "zh:6faeb8ff6792ca7af1c025255755ad764667a300291cc10cea0c615479488c87", + "zh:7d9423149b323f6d0df5b90c4d9029e5455c670aea2a7eb6fef4684ba7eb2e0b", + "zh:8235badd8a5d0993421cacf5ead48fac73d3b5a25c8a68599706a404b1f70730", + "zh:860b4f60842b2879c5128b7e386c8b49adeda9287fed12c5cd74861bb659bbcd", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", - "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", - "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", - "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", - "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", - ] -} - -provider "registry.terraform.io/hashicorp/local" { - version = "2.9.0" - constraints = "~> 2.0" - hashes = [ - "h1:9rBZCMNpxKwMlRbWH2QpwD3kqUCAejdOZQ/aiiDObXQ=", - "h1:m24fjcInWvTVZ1XSo2MaNuKPe+X/gfG8SIi09rA7a7M=", - "zh:0baa4566cf77f1ff52f4293d1c8536202dd23edc197c3196413a28343c3ac3a0", - "zh:16b5559c3c07088ddad11a9bb9e9c0799999363c2958e9a5be2bcbbf2cd9ca64", - "zh:197c79015a10d1cce904a8ea722cbc750c42aeae2da53f44a6a0751d9fd1aa90", - "zh:29d0b03e5343a80677ebfeb2e2c31cbe4b1f65e736e53417454a4277fec2544c", - "zh:4896bfa6cf1d2fd562b47ef2e87f47862ae92a04f8ad5d764380f0c6653473b8", - "zh:531f8529cbca49f681883e57761a05a8398afaef6d1ab0d205d26bf12f4428e8", - "zh:6aaf5011d83161c86d2bfb80c0923ec934e578288758da2f37acb7aec129004b", - "zh:7430275253d3d3c40aa6179e0ec0d63212874dbbc06c5a51b9d07ec590f9756c", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:be17dc611e95e26cdf6cad79dfccf1064f0e32032a2efeb939a9bbe7fb1cbfe9", - "zh:f0e3b0aa644202e1d79d2000dca91f6019425da71e9800fa23f27e51c034f195", - "zh:f62bae4519e4ead49182ddc8afe8cf61e2a4c3ba3973b0fbba967736a2696aa3", - "zh:fcafa360a5b0b96244f26f4e3a6d642b716a376557142c2442ff2fb12d11da18", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.9.0" - constraints = "~> 3.0" - hashes = [ - "h1:OO+IuvQJSPmWdN8AyyIEvPJbLvDQpgX/zbktoa9KsJE=", - "h1:UlBuNVuCGJ39tTv2c5gz2NRZnQbXfbIWbTzWcth5o74=", - "zh:161ad0bd9a75768c82f53fb6e7172a9d8be2d4889b012645a34795031aaf1bf1", - "zh:19dc9a5b17729725ccfc4f45b0500af0ee5bc6b6b160c7adb8f2bf617d2c80ea", - "zh:269eda8fe42daa7974d5a34d166c3ba9defe80cde86c01e4dadcfdf2e1f05e5f", - "zh:373f7c65566f8f2cc7f45d698654feb9d988996957e1266a69ca00c52d6d16d0", - "zh:5599d16804c41c83009ec621b6d6b6f74e102f5827678a4750f8809055546b61", - "zh:583be0440469a22bff70dcfa56593b01566860b29607437264adb51060cf46fc", - "zh:5f211d8ec3f2e1f414870d9584bfe26e6995560ef81c748f8447a48164767398", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:7b547fd16216761ef86efc3ed516ac5ac0c5c42b7c7eb24a08cef2d93f69ed5e", - "zh:7e7c0679daf2a382151d05068c8c3f0dae6b7b7dccf818827b73dd08638df2ef", - "zh:8089dec888a8038b9b4fb23b3df7e1057293dbc5b60b42cc47ff690d69d4b61b", - "zh:c51f15a031edfd6f23ce8ced3446ca7f8d8d647e2499890d7d5d10d5016d7257", - "zh:c94784f005708890dc6895afd53636ec00ec1e430b15d41e5aebfb1d4b39bd04", + "zh:b021fceaf9382c8fe3c6eb608c24d01dce3d11ba7e65bb443d51ca9b90e9b237", + "zh:b38b0bfc1c69e714e80cf1c9ea06e687ee86aa9f45694be28eb07adcebbe0489", + "zh:c972d155f6c01af9690a72adfb99cfc24ef5ef311ca92ce46b9b13c5c153f572", + "zh:e0dd29920ec84fdb6026acff44dcc1fb1a24a0caa093fa04cdbc713d384c651d", + "zh:e3127ebd2cb0374cd1808f911e6bffe2f4ac4d84317061381242353f3a7bc27d", ] } diff --git a/examples/permissions-boundary/setup/README.md b/examples/permissions-boundary/setup/README.md index 4b1778c8f8..defdfa8873 100644 --- a/examples/permissions-boundary/setup/README.md +++ b/examples/permissions-boundary/setup/README.md @@ -12,7 +12,7 @@ | Name | Version | |------|---------| -| [aws](#provider\_aws) | 6.35.1 | +| [aws](#provider\_aws) | 5.31.0 | ## Modules diff --git a/examples/permissions-boundary/variables.tf b/examples/permissions-boundary/variables.tf index 3d0d26e23e..d8b5356484 100644 --- a/examples/permissions-boundary/variables.tf +++ b/examples/permissions-boundary/variables.tf @@ -6,44 +6,3 @@ variable "github_app" { key_base64 = string }) } - -variable "ami" { - description = "AMI configuration for the action runner instances. Uses the module default when unset." - type = object({ - filter = optional(map(list(string)), { state = ["available"] }) - owners = optional(list(string), ["amazon"]) - id_ssm_parameter_arn = optional(string, null) - kms_key_arn = optional(string, null) - }) - default = null -} - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive." - type = string - default = "../lambdas-download/webhook.zip" -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive." - type = string - default = "../lambdas-download/runners.zip" -} - -variable "runner_binaries_syncer_lambda_zip" { - description = "Path to the runner binaries syncer Lambda archive." - type = string - default = "../lambdas-download/runner-binaries-syncer.zip" -} - -variable "iam_state_path" { - description = "Path to the state produced by the permissions-boundary setup. Uses the example setup state when unset." - type = string - default = null -} diff --git a/examples/prebuilt/.terraform.lock.hcl b/examples/prebuilt/.terraform.lock.hcl index 17012dcab0..136f5367b1 100644 --- a/examples/prebuilt/.terraform.lock.hcl +++ b/examples/prebuilt/.terraform.lock.hcl @@ -5,7 +5,6 @@ provider "registry.terraform.io/hashicorp/aws" { version = "6.35.1" constraints = ">= 5.0.0, >= 6.21.0" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", @@ -29,7 +28,6 @@ provider "registry.terraform.io/hashicorp/local" { version = "2.7.0" constraints = "~> 2.0" hashes = [ - "h1:2RYa3j7m/0WmET2fqotY4CHxE1Hpk0fgn47/126l+Og=", "h1:sSwlfp2etjCaE9hIF7bJBDjRIhDCVFglEOVyiCI7vgs=", "zh:261fec71bca13e0a7812dc0d8ae9af2b4326b24d9b2e9beab3d2400fab5c5f9a", "zh:308da3b5376a9ede815042deec5af1050ec96a5a5410a2206ae847d82070a23e", @@ -51,7 +49,6 @@ provider "registry.terraform.io/hashicorp/null" { constraints = "~> 3.0, ~> 3.2" hashes = [ "h1:L5V05xwp/Gto1leRryuesxjMfgZwjb7oool4WS1UEFQ=", - "h1:hkf5w5B6q8e2A42ND2CjAvgvSN3puAosDmOJb3zCVQM=", "zh:59f6b52ab4ff35739647f9509ee6d93d7c032985d9f8c6237d1f8a59471bbbe2", "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", "zh:795c897119ff082133150121d39ff26cb5f89a730a2c8c26f3a9c1abf81a9c43", @@ -71,7 +68,6 @@ provider "registry.terraform.io/hashicorp/random" { version = "3.8.1" constraints = "~> 3.0" hashes = [ - "h1:Eexl06+6J+s75uD46+WnZtpJZYRVUMB0AiuPBifK6Jc=", "h1:u8AKlWVDTH5r9YLSeswoVEjiY72Rt4/ch7U+61ZDkiQ=", "zh:08dd03b918c7b55713026037c5400c48af5b9f468f483463321bd18e17b907b4", "zh:0eee654a5542dc1d41920bbf2419032d6f0d5625b03bd81339e5b33394a3e0ae", diff --git a/examples/prebuilt/README.md b/examples/prebuilt/README.md index b1c91b9b1f..f90a47261e 100644 --- a/examples/prebuilt/README.md +++ b/examples/prebuilt/README.md @@ -108,15 +108,11 @@ terraform output webhook_secret | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [ami\_housekeeper\_lambda\_zip](#input\_ami\_housekeeper\_lambda\_zip) | Path to the AMI housekeeper Lambda archive. Uses the module default when unset. | `string` | `null` | no | | [ami\_name\_filter](#input\_ami\_name\_filter) | AMI name filter for the action runner AMI. By default amazon linux 2 is used. | `string` | `"github-runner-al2023-x86_64-*"` | no | | [aws\_region](#input\_aws\_region) | AWS region. | `string` | `"eu-west-1"` | no | -| [aws\_s3\_use\_path\_style](#input\_aws\_s3\_use\_path\_style) | Whether the AWS provider should use path-style S3 addressing. | `bool` | `false` | no | | [environment](#input\_environment) | Environment name, used as prefix. | `string` | `null` | no | | [github\_app](#input\_github\_app) | GitHub for API usages. |
object({
id = string
key_base64 = string
})
| n/a | yes | | [runner\_os](#input\_runner\_os) | The EC2 Operating System type to use for action runner instances (linux, osx, windows). | `string` | `"linux"` | no | -| [runners\_lambda\_zip](#input\_runners\_lambda\_zip) | Path to the runners Lambda archive. Uses the module default when unset. | `string` | `null` | no | -| [webhook\_lambda\_zip](#input\_webhook\_lambda\_zip) | Path to the webhook Lambda archive. Uses the module default when unset. | `string` | `null` | no | ## Outputs diff --git a/examples/prebuilt/main.tf b/examples/prebuilt/main.tf index 5aafcb39d7..62434f3f61 100644 --- a/examples/prebuilt/main.tf +++ b/examples/prebuilt/main.tf @@ -32,10 +32,6 @@ module "runners" { webhook_secret = random_id.random.hex } - webhook_lambda_zip = var.webhook_lambda_zip - runners_lambda_zip = var.runners_lambda_zip - ami_housekeeper_lambda_zip = var.ami_housekeeper_lambda_zip - # link to downloaded lambda zip files. # When not explicitly set lambda zip files are grabbed from the module requiring lambda build. # diff --git a/examples/prebuilt/providers.tf b/examples/prebuilt/providers.tf index 55f6616e44..ccdd0b1622 100644 --- a/examples/prebuilt/providers.tf +++ b/examples/prebuilt/providers.tf @@ -1,6 +1,5 @@ provider "aws" { - region = local.aws_region - s3_use_path_style = var.aws_s3_use_path_style + region = local.aws_region default_tags { tags = { Example = local.environment diff --git a/examples/prebuilt/variables.tf b/examples/prebuilt/variables.tf index 346117f2ca..11670a5d2e 100644 --- a/examples/prebuilt/variables.tf +++ b/examples/prebuilt/variables.tf @@ -34,27 +34,3 @@ variable "ami_name_filter" { type = string default = "github-runner-al2023-x86_64-*" } - -variable "aws_s3_use_path_style" { - description = "Whether the AWS provider should use path-style S3 addressing." - type = bool - default = false -} - -variable "webhook_lambda_zip" { - description = "Path to the webhook Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "runners_lambda_zip" { - description = "Path to the runners Lambda archive. Uses the module default when unset." - type = string - default = null -} - -variable "ami_housekeeper_lambda_zip" { - description = "Path to the AMI housekeeper Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/examples/termination-watcher/.terraform.lock.hcl b/examples/termination-watcher/.terraform.lock.hcl index 26f5f13ef8..4f33187500 100644 --- a/examples/termination-watcher/.terraform.lock.hcl +++ b/examples/termination-watcher/.terraform.lock.hcl @@ -2,25 +2,24 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "6.35.1" - constraints = ">= 6.21.0, 6.35.1" + version = "6.22.1" + constraints = ">= 6.21.0" hashes = [ - "h1:0/uXxSpL98lpRqjRhjAvvWZVnJZnbOehfAlTrcPXURI=", - "h1:xD+5zPhF0ry3sutriARfFVIg5m38VwYt66RveI3aUyI=", - "zh:0a16d1b0ba9379e5c5295e6b3caa42f0b8ba6b9f0a7cc9dbe58c232cf995db2d", - "zh:4b2e69907a1a2c557e45ef590f9fd6187ab5bf90378346ba9f723535e49ce908", - "zh:56bdafda0d629e15dc3dd9275b54f1fb953e2e09a3bc1a34e027da9d03ea4893", - "zh:5b84e933989150249036f84faad221dce0daa9d3043ff24401547e18f00b121e", - "zh:70bac98c27a14cb2cedabd741a1f7f1bab074c127efdcf02b54dbcf0d03db3cc", - "zh:7184f48bd077eaf68e184fd44f97e2d971cb77c59a68aedb95a0f8dc01b134fe", - "zh:7367589ae8b584bfcd83c973f5003e15010a453349c017a0d2cca8772d4fcfd9", - "zh:7ec9699dee49dd31bbc2d0e50fa1fff451eee5c1d9fd59bca7412acb49ce6594", - "zh:92dd139b96977a64af0e976cd06e84921033678ab97550f1b687c0ea54a8e82c", + "h1:PTgxp+nMDBd6EFHAIH6ceFfvwa2blqkCwXglZn6Dqa8=", + "zh:3995ca97e6c2c1ed9e231c453287585d3dc1ca2a304683ac0b269b3448fda7c0", + "zh:4f69f70d2edeb0dde9c693b7cd7e8e21c781b2fac7062bed5300092dbadb71e1", + "zh:5c76042fdf3df56a1f581bc477e5d6fc3e099d4d6544fe725b3747e9990726bd", + "zh:6ff8221340955f4b3ba9230918bb026c4414a5aebe9d0967845c43e8e8908aec", + "zh:73cdd8638cb52bbe25887cd5b7946cc3fcb891867de11bcb0fde9b35c4f70a41", + "zh:7af5aec2fd01fa5e5f600f1db1bcf200aaadc05a2c8ffcbb4b6b61cd2bd3e33b", + "zh:7e055cfa7f40b667f5f7af564db9544f46aa189cdbe5530ad812e027647132f5", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:9f2df575a5b010db60068668c48806595a3d617a2c0305035283fe8b72f07b19", - "zh:a4602b7602c75c8f726bdc7e706dc5c26736e47cc8381be01386aa8d8d998403", - "zh:bc25fefeeee10425df7aebfc21dc6532d19acdf03fa97b9e6d8c113adffd0a1d", - "zh:f445592040b5fc368a12e6edeffc951b2eb41e86413c4074638a13376e25a9cc", - "zh:ff43962a48bd8f85e17188736bbd3c145b6a1320bd8303221f6b4f9ec861e1e6", + "zh:aba898190c668ade4471da65c96db414679367174ac5b73e8ce7551056c77e3e", + "zh:aedaa8d7d71e6d58cdc09a7e3bcb8031b3ea496a7ac142376eb679d1756057f3", + "zh:cb9739952d467b3f6d72d57722943956e80ab235b58a0e34758538381dcc386c", + "zh:e12a2681028a70cb08eaf4c3364ddab386416502f966067bf99e79ba6be0d7b6", + "zh:e32a922a7d6fd5df69b3cc92932fc2689dc195b0f8b493dcd686abdd892b06cd", + "zh:f2dea7dead6f34b51e8b6aae177a8b333834a41d25529baa634a087d99ea32f6", + "zh:f6eee6df0366e8452d912cfd498792579aede88de3b67c15d36b8949e37479b1", ] } diff --git a/examples/termination-watcher/README.md b/examples/termination-watcher/README.md index 6c1a8be75a..98f2c8783b 100644 --- a/examples/termination-watcher/README.md +++ b/examples/termination-watcher/README.md @@ -45,9 +45,7 @@ No resources. ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [termination\_watcher\_lambda\_zip](#input\_termination\_watcher\_lambda\_zip) | Path to the termination watcher Lambda archive. Uses the module default when unset. | `string` | `null` | no | +No inputs. ## Outputs diff --git a/examples/termination-watcher/main.tf b/examples/termination-watcher/main.tf index 264deb1a35..7877d04bc1 100644 --- a/examples/termination-watcher/main.tf +++ b/examples/termination-watcher/main.tf @@ -12,6 +12,5 @@ module "spot_termination_watchter" { tag_filters = { "ghr:Application" = "github-action-runner" } - zip = var.termination_watcher_lambda_zip } } diff --git a/examples/termination-watcher/variables.tf b/examples/termination-watcher/variables.tf deleted file mode 100644 index 562d63e8ad..0000000000 --- a/examples/termination-watcher/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "termination_watcher_lambda_zip" { - description = "Path to the termination watcher Lambda archive. Uses the module default when unset." - type = string - default = null -} diff --git a/tests/ministack/README.md b/tests/ministack/README.md index 22a6c28dbb..1b9042a575 100644 --- a/tests/ministack/README.md +++ b/tests/ministack/README.md @@ -1,23 +1,14 @@ # MiniStack example lifecycle tests The MiniStack workflow runs explicit `terraform apply` and `terraform destroy` -commands from each checked-in `examples/` root. MiniStack-specific values -are supplied through ordinary example inputs in `tests/ministack/inputs`; no -Terraform configuration is copied into or layered over an example. +commands against the repository's runnable AWS examples. Every matrix entry gets +an isolated source tree, Terraform state, and MiniStack service. -Terraform data, state, and the inert Lambda archive live under the runner's -temporary directory. The small `tests/ministack/setup` root is a prerequisite, -not the code under test: it creates the inert archive and seeds the external SSM -parameters consumed by the external-secrets and multi-runner examples. The -archive prevents scheduled or S3-triggered Lambda functions from making GitHub -calls. The GitHub App updater is outside this AWS-only lifecycle test and is -excluded with a Terraform target. - -The runner accepts only `http://127.0.0.1:4566`, `http://localhost:4566`, or -`http://ministack:4566` as the AWS endpoint and always replaces ambient AWS -credentials with synthetic MiniStack identifiers. It also rejects -service-specific endpoint variables and ignores ambient AWS profile files so -they cannot bypass the validated global endpoint. +The fixture creates synthetic SSM values through MiniStack and an inert Lambda +archive under its ignored `.terraform/` directory. Test-only Terraform override +files route each example to that archive and a MiniStack AMI. They also disable +the `webhook-github-app` local-exec module, which would otherwise update a real +GitHub App. The production example configurations are not changed. | Example | Lifecycle coverage | | --- | --- | diff --git a/tests/ministack/inputs/base.tfvars b/tests/ministack/inputs/base.tfvars deleted file mode 100644 index 8205d159f7..0000000000 --- a/tests/ministack/inputs/base.tfvars +++ /dev/null @@ -1,2 +0,0 @@ -prefix = "ministack-base" -aws_region = "eu-west-1" diff --git a/tests/ministack/inputs/default.tfvars b/tests/ministack/inputs/default.tfvars deleted file mode 100644 index 0fe575cdb3..0000000000 --- a/tests/ministack/inputs/default.tfvars +++ /dev/null @@ -1,13 +0,0 @@ -environment = "ministack-default" -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/ephemeral.tfvars b/tests/ministack/inputs/ephemeral.tfvars deleted file mode 100644 index f0f6056ea3..0000000000 --- a/tests/ministack/inputs/ephemeral.tfvars +++ /dev/null @@ -1,13 +0,0 @@ -environment = "ministack-ephemeral" -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/external-managed-ssm-secrets.tfvars b/tests/ministack/inputs/external-managed-ssm-secrets.tfvars deleted file mode 100644 index 83b91acf4a..0000000000 --- a/tests/ministack/inputs/external-managed-ssm-secrets.tfvars +++ /dev/null @@ -1,23 +0,0 @@ -environment = "ministack-external-ssm" -github_app_ssm_parameters = { - id = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id" - name = "/ministack/terraform-aws-github-runner/github-app/id" - } - key_base64 = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64" - name = "/ministack/terraform-aws-github-runner/github-app/key-base64" - } - webhook_secret = { - arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret" - name = "/ministack/terraform-aws-github-runner/github-app/webhook-secret" - } -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/multi-runner.tfvars b/tests/ministack/inputs/multi-runner.tfvars deleted file mode 100644 index dcdef53a6d..0000000000 --- a/tests/ministack/inputs/multi-runner.tfvars +++ /dev/null @@ -1,13 +0,0 @@ -environment = "ministack" -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/permissions-boundary.tfvars b/tests/ministack/inputs/permissions-boundary.tfvars deleted file mode 100644 index d8b20423a7..0000000000 --- a/tests/ministack/inputs/permissions-boundary.tfvars +++ /dev/null @@ -1,12 +0,0 @@ -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami = { - filter = { - name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] - state = ["available"] - } - owners = ["self"] -} -aws_s3_use_path_style = true diff --git a/tests/ministack/inputs/prebuilt.tfvars b/tests/ministack/inputs/prebuilt.tfvars deleted file mode 100644 index 27c628b4eb..0000000000 --- a/tests/ministack/inputs/prebuilt.tfvars +++ /dev/null @@ -1,7 +0,0 @@ -environment = "ministack-prebuilt" -github_app = { - id = "0" - key_base64 = "ministack-invalid-github-app-key" -} -ami_name_filter = "amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2" -aws_s3_use_path_style = true diff --git a/tests/ministack/overrides/README.md b/tests/ministack/overrides/README.md new file mode 100644 index 0000000000..16f52b5086 --- /dev/null +++ b/tests/ministack/overrides/README.md @@ -0,0 +1,39 @@ + +## Requirements + +| Name | Version | +|------|---------| +| [aws](#requirement\_aws) | = 6.35.1 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [runners](#module\_runners) | | n/a | +| [spot\_termination\_watchter](#module\_spot\_termination\_watchter) | | n/a | +| [webhook\_github\_app](#module\_webhook\_github\_app) | | n/a | + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [ami\_name\_filter](#input\_ami\_name\_filter) | n/a | `string` | `"amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"` | no | +| [aws\_region](#input\_aws\_region) | n/a | `string` | `"eu-west-1"` | no | +| [environment](#input\_environment) | n/a | `string` | `"ministack-prebuilt"` | no | +| [github\_app](#input\_github\_app) | n/a | `map` |
{
"id": "0",
"key_base64": "ministack-invalid-key"
}
| no | +| [github\_app\_ssm\_parameters](#input\_github\_app\_ssm\_parameters) | n/a | `map` |
{
"id": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id",
"name": "/ministack/terraform-aws-github-runner/github-app/id"
},
"key_base64": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64",
"name": "/ministack/terraform-aws-github-runner/github-app/key-base64"
},
"webhook_secret": {
"arn": "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret",
"name": "/ministack/terraform-aws-github-runner/github-app/webhook-secret"
}
}
| no | +| [ministack\_lambda\_archive](#input\_ministack\_lambda\_archive) | Absolute path to the inert Lambda archive created by the MiniStack fixture. | `string` | n/a | yes | +| [prefix](#input\_prefix) | n/a | `string` | `"ministack-base"` | no | + +## Outputs + +No outputs. + \ No newline at end of file diff --git a/tests/ministack/overrides/base_override.tf b/tests/ministack/overrides/base_override.tf new file mode 100644 index 0000000000..7450840076 --- /dev/null +++ b/tests/ministack/overrides/base_override.tf @@ -0,0 +1,7 @@ +variable "prefix" { + default = "ministack-base" +} + +variable "aws_region" { + default = "eu-west-1" +} diff --git a/tests/ministack/overrides/common.tf b/tests/ministack/overrides/common.tf new file mode 100644 index 0000000000..8cec884357 --- /dev/null +++ b/tests/ministack/overrides/common.tf @@ -0,0 +1,19 @@ +variable "ministack_lambda_archive" { + description = "Absolute path to the inert Lambda archive created by the MiniStack fixture." + type = string + + validation { + condition = endswith(var.ministack_lambda_archive, "/tests/ministack/setup/.terraform/ministack/lambda.zip") + error_message = "The MiniStack Lambda archive must come from the isolated test fixture." + } +} + +locals { + ministack_ami = { + filter = { + name = ["amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2"] + state = ["available"] + } + owners = ["self"] + } +} diff --git a/tests/ministack/overrides/default_override.tf b/tests/ministack/overrides/default_override.tf new file mode 100644 index 0000000000..654aa37161 --- /dev/null +++ b/tests/ministack/overrides/default_override.tf @@ -0,0 +1,29 @@ +variable "environment" { + default = "ministack-default" +} + +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +module "runners" { + ami = local.ministack_ami + ami_housekeeper_lambda_zip = var.ministack_lambda_archive + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive + + instance_termination_watcher = { + enable = true + zip = var.ministack_lambda_archive + } +} + +# The production example updates GitHub through a local-exec provisioner. +# A zero count structurally prevents any external GitHub API call in this test. +module "webhook_github_app" { + count = 0 +} diff --git a/tests/ministack/overrides/ephemeral_override.tf b/tests/ministack/overrides/ephemeral_override.tf new file mode 100644 index 0000000000..ab85df74b1 --- /dev/null +++ b/tests/ministack/overrides/ephemeral_override.tf @@ -0,0 +1,23 @@ +variable "environment" { + default = "ministack-ephemeral" +} + +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +module "runners" { + ami = local.ministack_ami + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} + +# The production example updates GitHub through a local-exec provisioner. +# A zero count structurally prevents any external GitHub API call in this test. +module "webhook_github_app" { + count = 0 +} diff --git a/tests/ministack/overrides/external-managed-ssm-secrets_override.tf b/tests/ministack/overrides/external-managed-ssm-secrets_override.tf new file mode 100644 index 0000000000..701b8b61b8 --- /dev/null +++ b/tests/ministack/overrides/external-managed-ssm-secrets_override.tf @@ -0,0 +1,27 @@ +variable "environment" { + default = "ministack-external-ssm" +} + +variable "github_app_ssm_parameters" { + default = { + id = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/id" + name = "/ministack/terraform-aws-github-runner/github-app/id" + } + key_base64 = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/key-base64" + name = "/ministack/terraform-aws-github-runner/github-app/key-base64" + } + webhook_secret = { + arn = "arn:aws:ssm:eu-west-1:000000000000:parameter/ministack/terraform-aws-github-runner/github-app/webhook-secret" + name = "/ministack/terraform-aws-github-runner/github-app/webhook-secret" + } + } +} + +module "runners" { + ami = local.ministack_ami + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} diff --git a/tests/ministack/overrides/multi-runner_override.tf b/tests/ministack/overrides/multi-runner_override.tf new file mode 100644 index 0000000000..0516d6f33d --- /dev/null +++ b/tests/ministack/overrides/multi-runner_override.tf @@ -0,0 +1,39 @@ +variable "environment" { + default = "ministack" +} + +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +locals { + # The production example consumes this override after it is copied into the + # example root; it is intentionally unused in this standalone fixture folder. + # tflint-ignore: terraform_unused_declarations + multi_runner_config = { + for name, config in local.multi_runner_config_files : name => merge(config, { + runner_config = merge(config.runner_config, { + ami = contains(keys(config.runner_config), "ami") ? merge(local.ministack_ami, { + id_ssm_parameter_arn = lookup(local.ssm_ami_arns, name, null) + }) : null + subnet_ids = lookup(config.runner_config, "subnet_ids", null) != null ? [module.base.vpc.private_subnets[0]] : null + vpc_id = lookup(config.runner_config, "vpc_id", null) != null ? module.base.vpc.vpc_id : null + }) + }) + } +} + +module "runners" { + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} + +# The production example updates GitHub through a local-exec provisioner. +# A zero count structurally prevents any external GitHub API call in this test. +module "webhook_github_app" { + count = 0 +} diff --git a/tests/ministack/overrides/permissions-boundary-provider_override.tf b/tests/ministack/overrides/permissions-boundary-provider_override.tf new file mode 100644 index 0000000000..1c1a2ea07d --- /dev/null +++ b/tests/ministack/overrides/permissions-boundary-provider_override.tf @@ -0,0 +1,14 @@ +provider "aws" { + alias = "terraform_role" + region = "eu-west-1" + + # These values are MiniStack test identifiers and cannot authenticate to AWS. + access_key = "000000000000" + secret_key = "ministack-test-only" + + skip_credentials_validation = true + skip_metadata_api_check = true + skip_region_validation = true + skip_requesting_account_id = true + s3_use_path_style = true +} diff --git a/tests/ministack/overrides/permissions-boundary_override.tf b/tests/ministack/overrides/permissions-boundary_override.tf new file mode 100644 index 0000000000..b45b581f6b --- /dev/null +++ b/tests/ministack/overrides/permissions-boundary_override.tf @@ -0,0 +1,13 @@ +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +module "runners" { + ami = local.ministack_ami + runner_binaries_syncer_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} diff --git a/tests/ministack/overrides/prebuilt_override.tf b/tests/ministack/overrides/prebuilt_override.tf new file mode 100644 index 0000000000..32c35b7f4d --- /dev/null +++ b/tests/ministack/overrides/prebuilt_override.tf @@ -0,0 +1,26 @@ +variable "environment" { + default = "ministack-prebuilt" +} + +variable "github_app" { + default = { + id = "0" + key_base64 = "ministack-invalid-key" + } +} + +variable "ami_name_filter" { + default = "amzn2-ami-hvm-2.0.20231116.0-x86_64-gp2" +} + +module "runners" { + ami_housekeeper_lambda_zip = var.ministack_lambda_archive + runners_lambda_zip = var.ministack_lambda_archive + webhook_lambda_zip = var.ministack_lambda_archive +} + +# The production example updates GitHub through a local-exec provisioner. +# A zero count structurally prevents any external GitHub API call in this test. +module "webhook_github_app" { + count = 0 +} diff --git a/tests/ministack/overrides/provider.tf b/tests/ministack/overrides/provider.tf new file mode 100644 index 0000000000..0a33ab2dbd --- /dev/null +++ b/tests/ministack/overrides/provider.tf @@ -0,0 +1,16 @@ +# The permissions-boundary override merges an alias into this provider when +# TFLint evaluates this standalone fixture directory. +# tflint-ignore: terraform_unused_declarations +provider "aws" { + region = "eu-west-1" + + # These values are MiniStack test identifiers and cannot authenticate to AWS. + access_key = "000000000000" + secret_key = "ministack-test-only" + + skip_credentials_validation = true + skip_metadata_api_check = true + skip_region_validation = true + skip_requesting_account_id = true + s3_use_path_style = true +} diff --git a/tests/ministack/overrides/termination-watcher_override.tf b/tests/ministack/overrides/termination-watcher_override.tf new file mode 100644 index 0000000000..b4f4a6833c --- /dev/null +++ b/tests/ministack/overrides/termination-watcher_override.tf @@ -0,0 +1,15 @@ +module "spot_termination_watchter" { + config = { + metrics = { + enable = true + metric = { + enable_spot_termination_warning = true + } + } + prefix = "global" + tag_filters = { + "ghr:Application" = "github-action-runner" + } + zip = var.ministack_lambda_archive + } +} diff --git a/tests/ministack/overrides/versions.tf b/tests/ministack/overrides/versions.tf new file mode 100644 index 0000000000..db7f916fb6 --- /dev/null +++ b/tests/ministack/overrides/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.10.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "= 6.35.1" + } + } +} diff --git a/tests/ministack/run-example.sh b/tests/ministack/run-example.sh index 869d914653..21c66a0f15 100755 --- a/tests/ministack/run-example.sh +++ b/tests/ministack/run-example.sh @@ -21,170 +21,74 @@ case "$action" in ;; esac -ministack_endpoint="${AWS_ENDPOINT_URL:-http://127.0.0.1:4566}" -case "$ministack_endpoint" in - http://127.0.0.1:4566) - # S3 Control prefixes the account ID to the endpoint hostname. The - # account-prefixed localhost name resolves locally, while 127.0.0.1 does not. - ministack_endpoint="http://localhost:4566" - ;; - http://localhost:4566 | http://ministack:4566) ;; - *) - echo "Refusing to run against non-MiniStack endpoint: $ministack_endpoint" >&2 - exit 65 - ;; -esac - -service_endpoint_variables=$( - env | awk -F= ' - $1 ~ /^AWS_ENDPOINT_URL_/ || $1 ~ /^AWS_[A-Z0-9_]+_ENDPOINT$/ { print $1 } - ' -) -if [ -n "$service_endpoint_variables" ]; then - echo "Refusing to run with service-specific AWS endpoint variables:" >&2 - printf '%s\n' "$service_endpoint_variables" >&2 - exit 65 -fi - -# Always use synthetic credentials and route every AWS client to MiniStack. -export AWS_ACCESS_KEY_ID="000000000000" -export AWS_CONFIG_FILE="/dev/null" -export AWS_DEFAULT_REGION="eu-west-1" -export AWS_EC2_METADATA_DISABLED="true" -export AWS_ENDPOINT_URL="$ministack_endpoint" -export AWS_IGNORE_CONFIGURED_ENDPOINT_URLS="false" -export AWS_REGION="eu-west-1" -export AWS_SECRET_ACCESS_KEY="ministack-test-only" -export AWS_SHARED_CREDENTIALS_FILE="/dev/null" -unset AWS_ACCESS_KEY AWS_DEFAULT_PROFILE AWS_PROFILE AWS_SECRET_KEY AWS_SECURITY_TOKEN AWS_SESSION_TOKEN - -ministack_no_proxy="localhost,127.0.0.1,ministack,.ministack,000000000000.ministack" -export NO_PROXY="${NO_PROXY:+$NO_PROXY,}$ministack_no_proxy" -export no_proxy="${no_proxy:+$no_proxy,}$ministack_no_proxy" - script_dir=$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd) source_root="${GITHUB_WORKSPACE:-$(CDPATH='' cd -- "$script_dir/../.." && pwd)}" temporary_root="${RUNNER_TEMP:-${TMPDIR:-/tmp}}" -runtime_root="$temporary_root/terraform-aws-github-runner-ministack-$example" -example_root="$source_root/examples/$example" -fixture_root="$source_root/tests/ministack/setup" -input_file="$source_root/tests/ministack/inputs/$example.tfvars" - -fixture_data_dir="$runtime_root/fixture-data" -fixture_state="$runtime_root/fixture.tfstate" -lambda_archive="$runtime_root/lambda.zip" -example_data_dir="$runtime_root/example-data" -example_state="$runtime_root/example.tfstate" -permissions_data_dir="$runtime_root/permissions-data" -permissions_state="$runtime_root/permissions.tfstate" - -terraform_fixture() { - subcommand="$1" - shift - TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" "$subcommand" "$@" \ - -state="$fixture_state" \ - -var="lambda_archive_path=$lambda_archive" -} - -terraform_permissions() { - subcommand="$1" - shift - TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" "$subcommand" "$@" \ - -state="$permissions_state" -} +worktree="$temporary_root/terraform-aws-github-runner-ministack-$example" +example_root="$worktree/examples/$example" +fixture_root="$worktree/tests/ministack/setup" +lambda_archive="$fixture_root/.terraform/ministack/lambda.zip" terraform_example() { - subcommand="$1" - shift - set -- "$subcommand" "$@" "-state=$example_state" - - if [ -f "$input_file" ]; then - set -- "$@" "-var-file=$input_file" - fi - - case "$example" in - default) - set -- "$@" \ - "-var=webhook_lambda_zip=$lambda_archive" \ - "-var=runners_lambda_zip=$lambda_archive" \ - "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" \ - "-var=ami_housekeeper_lambda_zip=$lambda_archive" \ - "-var=termination_watcher_lambda_zip=$lambda_archive" - ;; - ephemeral | external-managed-ssm-secrets | multi-runner) - set -- "$@" \ - "-var=webhook_lambda_zip=$lambda_archive" \ - "-var=runners_lambda_zip=$lambda_archive" \ - "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" - ;; - permissions-boundary) - set -- "$@" \ - "-var=webhook_lambda_zip=$lambda_archive" \ - "-var=runners_lambda_zip=$lambda_archive" \ - "-var=runner_binaries_syncer_lambda_zip=$lambda_archive" \ - "-var=iam_state_path=$permissions_state" - ;; - prebuilt) - set -- "$@" \ - "-var=webhook_lambda_zip=$lambda_archive" \ - "-var=runners_lambda_zip=$lambda_archive" \ - "-var=ami_housekeeper_lambda_zip=$lambda_archive" - ;; - termination-watcher) - set -- "$@" "-var=termination_watcher_lambda_zip=$lambda_archive" - ;; - esac - - # This module calls the GitHub API through local-exec, so it is deliberately - # outside the AWS/MiniStack lifecycle coverage. - case "$example" in - default | ephemeral | multi-runner | prebuilt) - set -- "$@" "-target=module.runners" - ;; - esac - - TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" "$@" + terraform -chdir="$example_root" "$@" -var="ministack_lambda_archive=$lambda_archive" } case "$action" in prepare) - if [ -e "$runtime_root" ]; then - echo "Refusing to overwrite existing MiniStack runtime: $runtime_root" >&2 + if [ -e "$worktree" ]; then + echo "Refusing to overwrite existing MiniStack worktree: $worktree" >&2 exit 73 fi + mkdir -p "$worktree" + git -C "$source_root" archive --format=tar "${MINISTACK_SOURCE_REF:-${GITHUB_SHA:-HEAD}}" | tar -xf - -C "$worktree" + if [ ! -f "$example_root/main.tf" ]; then - echo "The repository does not contain examples/$example/main.tf" >&2 + echo "The isolated worktree does not contain examples/$example/main.tf" >&2 exit 66 fi - mkdir -p "$runtime_root" + cp "$worktree/tests/ministack/overrides/common.tf" "$example_root/ministack_common.tf" + cp "$worktree/tests/ministack/overrides/${example}_override.tf" "$example_root/ministack_example_override.tf" + cp "$worktree/tests/ministack/overrides/versions.tf" "$example_root/ministack_versions_override.tf" + + case "$example" in + base | termination-watcher) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" + ;; + permissions-boundary) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider.tf" + cp "$worktree/tests/ministack/overrides/permissions-boundary-provider_override.tf" "$example_root/ministack_permissions_provider_override.tf" + ;; + *) + cp "$worktree/tests/ministack/overrides/provider.tf" "$example_root/ministack_provider_override.tf" + ;; + esac + ;; fixture-apply) - TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly - terraform_fixture apply -auto-approve -input=false - - if [ ! -f "$lambda_archive" ]; then - echo "The shared fixture did not create the inert Lambda archive." >&2 - exit 74 - fi + terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$fixture_root" apply -auto-approve -input=false ;; setup-apply) if [ "$example" != "permissions-boundary" ]; then exit 0 fi - TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly - terraform_permissions apply -auto-approve -input=false + # The isolated archive may update its lockfile for the Linux test platform. + terraform -chdir="$example_root/setup" init -backend=false -input=false + terraform -chdir="$example_root/setup" apply -auto-approve -input=false ;; init) - TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + # The isolated archive may update its lockfile for the Linux test platform + # and the MiniStack-specific provider constraint. + terraform -chdir="$example_root" init -backend=false -input=false ;; apply) terraform_example apply -auto-approve -input=false ;; destroy) - TF_DATA_DIR="$example_data_dir" terraform -chdir="$example_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$example_root" init -backend=false -input=false terraform_example destroy -auto-approve -input=false ;; setup-destroy) @@ -192,11 +96,11 @@ case "$action" in exit 0 fi - TF_DATA_DIR="$permissions_data_dir" terraform -chdir="$example_root/setup" init -backend=false -input=false -lockfile=readonly - terraform_permissions destroy -auto-approve -input=false + terraform -chdir="$example_root/setup" init -backend=false -input=false + terraform -chdir="$example_root/setup" destroy -auto-approve -input=false ;; fixture-destroy) - TF_DATA_DIR="$fixture_data_dir" terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly - terraform_fixture destroy -auto-approve -input=false + terraform -chdir="$fixture_root" init -backend=false -input=false -lockfile=readonly + terraform -chdir="$fixture_root" destroy -auto-approve -input=false ;; esac diff --git a/tests/ministack/setup/README.md b/tests/ministack/setup/README.md index aa1a833a37..4c39a7450a 100644 --- a/tests/ministack/setup/README.md +++ b/tests/ministack/setup/README.md @@ -31,9 +31,7 @@ No modules. ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [lambda\_archive\_path](#input\_lambda\_archive\_path) | Path where the inert Lambda archive is created. | `string` | `null` | no | +No inputs. ## Outputs diff --git a/tests/ministack/setup/main.tf b/tests/ministack/setup/main.tf index bbdaab3bd4..208e29c66d 100644 --- a/tests/ministack/setup/main.tf +++ b/tests/ministack/setup/main.tf @@ -27,32 +27,22 @@ provider "aws" { s3_use_path_style = true } -variable "lambda_archive_path" { - description = "Path where the inert Lambda archive is created." - type = string - default = null -} - -locals { - lambda_archive_path = var.lambda_archive_path != null ? var.lambda_archive_path : "${path.module}/.terraform/ministack/lambda.zip" -} - data "archive_file" "lambda" { type = "zip" source_file = "${path.module}/index.mjs" - output_path = local.lambda_archive_path + output_path = "${path.module}/.terraform/ministack/lambda.zip" } resource "aws_ssm_parameter" "al2023_x64" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64" type = "String" - value = "ami-0abcdef1234567890" + value = "ami-0a1b2c3d4e5f67890" } resource "aws_ssm_parameter" "al2023_arm64" { name = "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64" type = "String" - value = "ami-0abcdef1234567890" + value = "ami-0a1b2c3d4e5f67890" } resource "aws_ssm_parameter" "github_app_id" { From a27b8ff9af758105e0a60d84589f5a746e1052f0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 10:50:24 +0000 Subject: [PATCH 13/13] docs: auto update terraform docs --- tests/ministack/overrides/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ministack/overrides/README.md b/tests/ministack/overrides/README.md index 16f52b5086..a51e9f4e43 100644 --- a/tests/ministack/overrides/README.md +++ b/tests/ministack/overrides/README.md @@ -3,6 +3,7 @@ | Name | Version | |------|---------| +| [terraform](#requirement\_terraform) | >= 1.10.0 | | [aws](#requirement\_aws) | = 6.35.1 | ## Providers