diff --git a/.github/workflows/lint_terraform_webhook.yaml b/.github/workflows/lint_terraform_webhook.yaml new file mode 100644 index 00000000..c0737e85 --- /dev/null +++ b/.github/workflows/lint_terraform_webhook.yaml @@ -0,0 +1,41 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: Terraform lint test (webhook-gateway) + +on: + pull_request: + paths: + - "**/terraform/**" + +permissions: + contents: read + +jobs: + validate: + name: Validate terraform configuration files + runs-on: ubuntu-latest + env: + WORKING_DIR: "webhook-gateway/charm/terraform" + steps: + - name: Check out code + uses: actions/checkout@v5.0.0 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3.1.2 + + - name: Run terraform fmt + run: terraform fmt -check -recursive + working-directory: ${{env.WORKING_DIR}} + + - name: Setup Tflint + uses: terraform-linters/setup-tflint@v6.2.0 + with: + tflint_wrapper_enabled: true + + - name: Run tflint + run: | + tflint --version + tflint --init + tflint -f compact --recursive + working-directory: ${{env.WORKING_DIR}} diff --git a/.github/workflows/test_terraform_webhook_module.yaml b/.github/workflows/test_terraform_webhook_module.yaml new file mode 100644 index 00000000..3e1bae44 --- /dev/null +++ b/.github/workflows/test_terraform_webhook_module.yaml @@ -0,0 +1,55 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +name: Terraform module tests (webhook-gateway) + +on: + pull_request: + paths: + - "**/terraform/**" + +permissions: + contents: read + +jobs: + test-terraform: + name: Test Terraform with Juju + runs-on: ubuntu-latest + env: + WORKING_DIR: "webhook-gateway/charm/terraform/tests" + steps: + - uses: actions/checkout@v5.0.0 + - uses: charmed-kubernetes/actions-operator@main + with: + provider: "microk8s" + channel: 1.34-strict/stable + juju-channel: 3.6/stable + + - name: Prepare juju tf provider environment + run: | + set -e + CONTROLLER=$(juju whoami | yq .Controller) + JUJU_CONTROLLER_ADDRESSES="$(juju show-controller | yq '.[$CONTROLLER]'.details.\"api-endpoints\" | tr -d "[]' "|tr -d '"'|tr -d '\n')" + JUJU_USERNAME="$(cat ~/.local/share/juju/accounts.yaml | yq .controllers.$CONTROLLER.user|tr -d '"')" + JUJU_PASSWORD="$(cat ~/.local/share/juju/accounts.yaml | yq .controllers.$CONTROLLER.password|tr -d '"')" + + echo "JUJU_CONTROLLER_ADDRESSES=$JUJU_CONTROLLER_ADDRESSES" >> "$GITHUB_ENV" + echo "JUJU_USERNAME=$JUJU_USERNAME" >> "$GITHUB_ENV" + echo "JUJU_PASSWORD=$JUJU_PASSWORD" >> "$GITHUB_ENV" + { + echo 'JUJU_CA_CERT<> "$GITHUB_ENV" + - run: juju add-model stg-deploy-webhook-gateway + - uses: hashicorp/setup-terraform@v3.1.2 + - run: terraform init + working-directory: ${{env.WORKING_DIR}} + - run: terraform validate + working-directory: ${{env.WORKING_DIR}} + - run: terraform plan -out=tfplan + working-directory: ${{env.WORKING_DIR}} + - run: terraform show tfplan + working-directory: ${{env.WORKING_DIR}} + - run: terraform test + working-directory: ${{env.WORKING_DIR}} diff --git a/webhook-gateway/charm/terraform/README.md b/webhook-gateway/charm/terraform/README.md new file mode 100644 index 00000000..768eeb2a --- /dev/null +++ b/webhook-gateway/charm/terraform/README.md @@ -0,0 +1,56 @@ +# GitHub runner webhook gateway terraform module + +This folder contains a base [Terraform][Terraform] module for the GitHub runner webhook gateway charm. + +The module uses the [Terraform Juju provider][Terraform Juju provider] to model the charm +deployment onto any Kubernetes environment managed by [Juju][Juju]. + +## Module structure + +- **main.tf** - Defines the Juju application to be deployed. +- **variables.tf** - Allows customization of the deployment. Also models the charm configuration, + except for exposing the deployment options (Juju model name, channel or application name). +- **output.tf** - Integrates the module with other Terraform modules, primarily + by defining potential integration endpoints (charm integrations), but also by exposing + the Juju application name. +- **versions.tf** - Defines the Terraform provider version. + +## Using github_runner_webhook_gateway base module in higher level modules + +If you want to use `github_runner_webhook_gateway` base module as part of your Terraform module, import it +like shown below: + +```text +data "juju_model" "my_model" { + name = "test-deploy-webhook-gateway" + owner = "admin" +} + +module "github_runner_webhook_gateway" { + source = "git::https://github.com/canonical/github-runner-operators/tree/main/webhook-gateway/charm/terraform" + + model_uuid = data.juju_model.my_model.uuid + # (Customize configuration variables here if needed) +} +``` + +Create integrations, for instance: + +```text +resource "juju_integration" "webhook_rabbitmq" { + model_uuid = data.juju_model.my_model.uuid + application { + name = module.github_runner_webhook_gateway.app_name + } + application { + name = "rabbitmq" + } +} +``` + +The complete list of available integrations can be found [in the Integrations tab][github_runner_webhook_gateway-integrations]. + +[Terraform]: https://developer.hashicorp.com/terraform +[Terraform Juju provider]: https://registry.terraform.io/providers/juju/juju/latest +[Juju]: https://juju.is +[github_runner_webhook_gateway-integrations]: https://charmhub.io/github_runner_webhook_gateway/integrations diff --git a/webhook-gateway/charm/terraform/main.tf b/webhook-gateway/charm/terraform/main.tf new file mode 100644 index 00000000..ed4b4e6e --- /dev/null +++ b/webhook-gateway/charm/terraform/main.tf @@ -0,0 +1,19 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +resource "juju_application" "github_runner_webhook_gateway" { + name = var.app_name + model_uuid = var.model_uuid + + charm { + name = "github-runner-webhook-gateway" + channel = var.channel + revision = var.revision + base = var.base + } + + config = var.config + constraints = var.constraints + units = var.units + storage_directives = var.storage +} diff --git a/webhook-gateway/charm/terraform/outputs.tf b/webhook-gateway/charm/terraform/outputs.tf new file mode 100644 index 00000000..876201e6 --- /dev/null +++ b/webhook-gateway/charm/terraform/outputs.tf @@ -0,0 +1,13 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +output "app_name" { + description = "Name of the deployed application." + value = juju_application.github_runner_webhook_gateway.name +} + +output "endpoints" { + value = { + rabbitmq = "rabbitmq" + } +} diff --git a/webhook-gateway/charm/terraform/tests/main.tf b/webhook-gateway/charm/terraform/tests/main.tf new file mode 100644 index 00000000..c58b1a89 --- /dev/null +++ b/webhook-gateway/charm/terraform/tests/main.tf @@ -0,0 +1,83 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +locals { + webhook_gateway_app_name = "github-runner-webhook-gateway" + webhook_gateway_metrics_port = 9464 + juju_model_name = "stg-deploy-webhook-gateway" +} + +variable "channel" { + description = "The channel to use when deploying a charm." + type = string + default = "latest/edge" +} + +variable "revision" { + description = "Revision number of the charm." + type = number + default = null +} + +terraform { + required_version = ">= 1.6.6" + required_providers { + juju = { + source = "juju/juju" + version = ">= 1.0.0" + } + } +} + +data "juju_model" "webhook" { + name = local.juju_model_name + owner = "admin" +} + +resource "juju_application" "rabbitmq" { + name = "rabbitmq" + model_uuid = data.juju_model.webhook.uuid + + charm { + name = "rabbitmq-k8s" + channel = "3.12/stable" + } + + trust = true + config = {} + constraints = "" + units = 1 +} + +resource "juju_integration" "webhook_rabbitmq" { + model_uuid = data.juju_model.webhook.uuid + application { + name = local.webhook_gateway_app_name + } + application { + name = juju_application.rabbitmq.name + } +} + +provider "juju" {} + +module "github_runner_webhook_gateway" { + source = "./.." + app_name = local.webhook_gateway_app_name + channel = var.channel + model_uuid = data.juju_model.webhook.uuid + revision = var.revision + config = { + metrics-port = local.webhook_gateway_metrics_port + } +} + +output "app_name" { + description = "The name of the deployed github_runner_webhook_gateway charm application." + value = module.github_runner_webhook_gateway.app_name +} + +output "endpoints" { + description = "Integration endpoints exposed by github_runner_webhook_gateway charm." + value = module.github_runner_webhook_gateway.endpoints +} diff --git a/webhook-gateway/charm/terraform/tests/main.tftest.hcl b/webhook-gateway/charm/terraform/tests/main.tftest.hcl new file mode 100644 index 00000000..34dfb7d3 --- /dev/null +++ b/webhook-gateway/charm/terraform/tests/main.tftest.hcl @@ -0,0 +1,30 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +variables { + channel = "latest/edge" + # renovate: depName="github_runner_webhook_gateway" + revision = 1 +} + +run "basic_deploy" { + assert { + condition = module.github_runner_webhook_gateway.app_name == "github-runner-webhook-gateway" + error_message = "github-runner-webhook-gateway app_name did not match expected" + } + + assert { + condition = juju_application.rabbitmq.name == "rabbitmq" + error_message = "rabbitmq name did not match expected" + } + + assert { + condition = contains([for app in juju_integration.webhook_rabbitmq.application : app.name], "rabbitmq") + error_message = "Integration must include the rabbitmq application" + } + + assert { + condition = contains([for app in juju_integration.webhook_rabbitmq.application : app.name], "github-runner-webhook-gateway") + error_message = "Integration must include the webhook gateway application" + } +} diff --git a/webhook-gateway/charm/terraform/variables.tf b/webhook-gateway/charm/terraform/variables.tf new file mode 100644 index 00000000..bf3fbac0 --- /dev/null +++ b/webhook-gateway/charm/terraform/variables.tf @@ -0,0 +1,56 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +variable "app_name" { + description = "Name of the application in the Juju model." + type = string + default = "github-runner-webhook-gateway" +} + +variable "base" { + description = "The operating system on which to deploy" + type = string + default = "ubuntu@24.04" +} + +# Change to latest/stable when available +variable "channel" { + description = "The channel to use when deploying a charm." + type = string + default = "latest/edge" +} + +variable "config" { + description = "Application config. Details about available options can be found at https://charmhub.io/github-runner-webhook-gateway/configurations." + type = map(string) + default = {} +} + +variable "constraints" { + description = "Juju constraints to apply for this application." + type = string + default = "" +} + +variable "model_uuid" { + description = "Reference to a Juju model UUID." + type = string +} + +variable "revision" { + description = "Revision number of the charm" + type = number + default = null +} + +variable "storage" { + description = "Map of storage used by the application." + type = map(string) + default = {} +} + +variable "units" { + description = "Number of units to deploy" + type = number + default = 1 +} diff --git a/webhook-gateway/charm/terraform/versions.tf b/webhook-gateway/charm/terraform/versions.tf new file mode 100644 index 00000000..2a99ba1b --- /dev/null +++ b/webhook-gateway/charm/terraform/versions.tf @@ -0,0 +1,12 @@ +# Copyright 2025 Canonical Ltd. +# See LICENSE file for licensing details. + +terraform { + required_version = ">= 1.6.6" + required_providers { + juju = { + source = "juju/juju" + version = ">= 1.0.0" + } + } +}