Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/terraform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ jobs:
sudo snap install just --classic
- name: Validate the Terraform modules
run: just validate-terraform
test-unit:
name: Terraform unit tests
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo snap install terraform --classic
sudo snap install just --classic
- name: Unit test the Terraform modules
run: just unit
test-integration-cos-lite:
name: COS Lite Terraform integration
uses: canonical/observability-stack/.github/workflows/_integration.yml@main
Expand Down
15 changes: 14 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ lint: lint-workflows lint-terraform lint-terraform-docs
[group("Format")]
fmt: format-terraform format-terraform-docs

# Run unit tests
[group("Unit")]
unit: (unit-test "cos") (unit-test "cos-lite")

# Lint the Github workflows
[group("Lint")]
lint-workflows:
Expand All @@ -35,7 +39,7 @@ lint-terraform:
# Lint the Terraform documentation
[group("Lint")]
lint-terraform-docs:
terraform-docs --config .tfdocs-config.yml .
terraform-docs --config .tfdocs-config.yml --output-check .

# Format the Terraform modules
[group("Format")]
Expand All @@ -50,12 +54,21 @@ format-terraform-docs:
terraform-docs --config .tfdocs-config.yml .

# Validate the Terraform modules
[group("Static")]
[working-directory("./terraform")]
validate-terraform:
if [ -z "${terraform}" ]; then echo "ERROR: please install terraform or opentofu"; exit 1; fi
set -e; for repo in */; do (cd "$repo" && echo "Processing ${repo%/}..." && $terraform init -upgrade && $terraform validate) || exit 1; done

# Run a unit test
[group("Unit")]
[working-directory("./terraform")]
unit-test module:
if [ -z "${terraform}" ]; then echo "ERROR: please install terraform or opentofu"; exit 1; fi
$terraform -chdir={{module}} init -upgrade && $terraform -chdir={{module}} test

# Run integration tests
[group("Integration")]
[working-directory("./tests/integration")]
integration *args='':
uv run ${uv_flags} pytest -vv --capture=no --exitfirst "${args}"
14 changes: 7 additions & 7 deletions terraform/cos-lite/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ This is a Terraform module facilitating the deployment of the COS Lite solution,

| Name | Source | Version |
|------|--------|---------|
| <a name="module_alertmanager"></a> [alertmanager](#module\_alertmanager) | git::https://github.com/canonical/alertmanager-k8s-operator//terraform | n/a |
| <a name="module_catalogue"></a> [catalogue](#module\_catalogue) | git::https://github.com/canonical/catalogue-k8s-operator//terraform | n/a |
| <a name="module_grafana"></a> [grafana](#module\_grafana) | git::https://github.com/canonical/grafana-k8s-operator//terraform | n/a |
| <a name="module_loki"></a> [loki](#module\_loki) | git::https://github.com/canonical/loki-k8s-operator//terraform | n/a |
| <a name="module_prometheus"></a> [prometheus](#module\_prometheus) | git::https://github.com/canonical/prometheus-k8s-operator//terraform | n/a |
| <a name="module_alertmanager"></a> [alertmanager](#module\_alertmanager) | git::https://github.com/canonical/alertmanager-k8s-operator//terraform | track/2 |
| <a name="module_catalogue"></a> [catalogue](#module\_catalogue) | git::https://github.com/canonical/catalogue-k8s-operator//terraform | track/2 |
| <a name="module_grafana"></a> [grafana](#module\_grafana) | git::https://github.com/canonical/grafana-k8s-operator//terraform | track/2 |
| <a name="module_loki"></a> [loki](#module\_loki) | git::https://github.com/canonical/loki-k8s-operator//terraform | track/2 |
| <a name="module_prometheus"></a> [prometheus](#module\_prometheus) | git::https://github.com/canonical/prometheus-k8s-operator//terraform | track/2 |
| <a name="module_ssc"></a> [ssc](#module\_ssc) | git::https://github.com/canonical/self-signed-certificates-operator//terraform | n/a |
| <a name="module_traefik"></a> [traefik](#module\_traefik) | git::https://github.com/canonical/traefik-k8s-operator//terraform | n/a |

Expand All @@ -27,13 +27,13 @@ This is a Terraform module facilitating the deployment of the COS Lite solution,
|------|-------------|------|---------|:--------:|
| <a name="input_alertmanager"></a> [alertmanager](#input\_alertmanager) | Application configuration for Alertmanager. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "alertmanager")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_catalogue"></a> [catalogue](#input\_catalogue) | Application configuration for Catalogue. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "catalogue")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_channel"></a> [channel](#input\_channel) | Channel that the applications are (unless overwritten by external\_channels) deployed from | `string` | n/a | yes |
| <a name="input_channel"></a> [channel](#input\_channel) | Channel that the applications are (unless overwritten by external\_channels) deployed from | `string` | `"2/stable"` | no |
| <a name="input_external_ca_cert_offer_url"></a> [external\_ca\_cert\_offer\_url](#input\_external\_ca\_cert\_offer\_url) | A Juju offer URL (e.g. admin/external-ca.send-ca-cert) of a CA providing the 'certificate\_transfer' integration for applications to trust ingress via Traefik. | `string` | `null` | no |
| <a name="input_external_certificates_offer_url"></a> [external\_certificates\_offer\_url](#input\_external\_certificates\_offer\_url) | A Juju offer URL (e.g. admin/external-ca.certificates) of a CA providing the 'tls\_certificates' integration for Traefik to supply it with server certificates. | `string` | `null` | no |
| <a name="input_grafana"></a> [grafana](#input\_grafana) | Application configuration for Grafana. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "grafana")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_internal_tls"></a> [internal\_tls](#input\_internal\_tls) | Specify whether to use TLS or not for internal COS communication. By default, TLS is enabled using self-signed-certificates | `bool` | `true` | no |
| <a name="input_loki"></a> [loki](#input\_loki) | Application configuration for Loki. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "loki")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_model_uuid"></a> [model\_uuid](#input\_model\_uuid) | Reference to an existing model resource or data source for the model to deploy to | `string` | n/a | yes |
| <a name="input_model_uuid"></a> [model\_uuid](#input\_model\_uuid) | Reference to an existing model resource or data source for the model to deploy to | `string` | `"foo"` | no |
| <a name="input_prometheus"></a> [prometheus](#input\_prometheus) | Application configuration for Prometheus. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "prometheus")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_ssc"></a> [ssc](#input\_ssc) | Application configuration for self-signed-certificates. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "ca")<br/> channel = optional(string, "1/stable")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_traefik"></a> [traefik](#input\_traefik) | Application configuration for Traefik. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "traefik")<br/> channel = optional(string, "latest/stable")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
Expand Down
85 changes: 85 additions & 0 deletions terraform/cos-lite/tests/channel_validation.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
mock_provider "juju" {}

# ---Happy path---

run "valid_channel_track" {
command = plan

variables {
channel = "2/stable"
model_uuid = "00000000-0000-0000-0000-000000000000"
}
}

run "valid_channel_stable" {
command = plan

variables {
channel = "2/candidate"
model_uuid = "00000000-0000-0000-0000-000000000000"
}
}

run "valid_channel_candidate" {
command = plan

variables {
channel = "2/beta"
model_uuid = "00000000-0000-0000-0000-000000000000"
}
}

run "valid_channel_beta" {
command = plan

variables {
channel = "2/edge"
model_uuid = "00000000-0000-0000-0000-000000000000"
}
}

# ---Failure path---

run "invalid_channel_track" {
command = plan

variables {
channel = "1/stable"
model_uuid = "00000000-0000-0000-0000-000000000000"
}

expect_failures = [var.channel]
}

run "invalid_channel_track_numeric" {
command = plan

variables {
channel = "123/risk"
model_uuid = "00000000-0000-0000-0000-000000000000"
}

expect_failures = [var.channel]
}

run "invalid_channel_track_string" {
command = plan

variables {
channel = "foo/risk"
model_uuid = "00000000-0000-0000-0000-000000000000"
}

expect_failures = [var.channel]
}

run "invalid_channel_track_dev" {
command = plan

variables {
channel = "dev/risk"
model_uuid = "00000000-0000-0000-0000-000000000000"
}

expect_failures = [var.channel]
}
5 changes: 5 additions & 0 deletions terraform/cos-lite/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ variable "channel" {
description = "Channel that the applications are (unless overwritten by external_channels) deployed from"
type = string
default = "2/stable"

validation {
condition = startswith(var.channel, "2/")
error_message = "The track of the channel must be '2/'. e.g. '2/stable'."
}
}

variable "model_uuid" {
Expand Down
16 changes: 8 additions & 8 deletions terraform/cos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ This is a Terraform module facilitating the deployment of the COS solution, usin

| Name | Source | Version |
|------|--------|---------|
| <a name="module_alertmanager"></a> [alertmanager](#module\_alertmanager) | git::https://github.com/canonical/alertmanager-k8s-operator//terraform | n/a |
| <a name="module_catalogue"></a> [catalogue](#module\_catalogue) | git::https://github.com/canonical/catalogue-k8s-operator//terraform | n/a |
| <a name="module_grafana"></a> [grafana](#module\_grafana) | git::https://github.com/canonical/grafana-k8s-operator//terraform | n/a |
| <a name="module_loki"></a> [loki](#module\_loki) | git::https://github.com/canonical/observability-stack//terraform/loki | n/a |
| <a name="module_mimir"></a> [mimir](#module\_mimir) | git::https://github.com/canonical/observability-stack//terraform/mimir | n/a |
| <a name="module_opentelemetry_collector"></a> [opentelemetry\_collector](#module\_opentelemetry\_collector) | git::https://github.com/canonical/opentelemetry-collector-k8s-operator//terraform | n/a |
| <a name="module_alertmanager"></a> [alertmanager](#module\_alertmanager) | git::https://github.com/canonical/alertmanager-k8s-operator//terraform | track/2 |
| <a name="module_catalogue"></a> [catalogue](#module\_catalogue) | git::https://github.com/canonical/catalogue-k8s-operator//terraform | track/2 |
| <a name="module_grafana"></a> [grafana](#module\_grafana) | git::https://github.com/canonical/grafana-k8s-operator//terraform | track/2 |
| <a name="module_loki"></a> [loki](#module\_loki) | git::https://github.com/canonical/observability-stack//terraform/loki | track/2 |
| <a name="module_mimir"></a> [mimir](#module\_mimir) | git::https://github.com/canonical/observability-stack//terraform/mimir | track/2 |
| <a name="module_opentelemetry_collector"></a> [opentelemetry\_collector](#module\_opentelemetry\_collector) | git::https://github.com/canonical/opentelemetry-collector-k8s-operator//terraform | track/2 |
| <a name="module_ssc"></a> [ssc](#module\_ssc) | git::https://github.com/canonical/self-signed-certificates-operator//terraform | n/a |
| <a name="module_tempo"></a> [tempo](#module\_tempo) | git::https://github.com/canonical/tempo-operators//terraform | n/a |
| <a name="module_tempo"></a> [tempo](#module\_tempo) | git::https://github.com/canonical/tempo-operators//terraform | track/2 |
| <a name="module_traefik"></a> [traefik](#module\_traefik) | git::https://github.com/canonical/traefik-k8s-operator//terraform | n/a |

## Inputs
Expand All @@ -33,7 +33,7 @@ This is a Terraform module facilitating the deployment of the COS solution, usin
| <a name="input_alertmanager"></a> [alertmanager](#input\_alertmanager) | Application configuration for Alertmanager. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "alertmanager")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_anti_affinity"></a> [anti\_affinity](#input\_anti\_affinity) | Enable anti-affinity constraints across all HA modules (Mimir, Loki, Tempo) | `bool` | `true` | no |
| <a name="input_catalogue"></a> [catalogue](#input\_catalogue) | Application configuration for Catalogue. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application | <pre>object({<br/> app_name = optional(string, "catalogue")<br/> config = optional(map(string), {})<br/> constraints = optional(string, "arch=amd64")<br/> revision = optional(number, null)<br/> storage_directives = optional(map(string), {})<br/> units = optional(number, 1)<br/> })</pre> | `{}` | no |
| <a name="input_channel"></a> [channel](#input\_channel) | Channel that the applications are (unless overwritten by external\_channels) deployed from | `string` | n/a | yes |
| <a name="input_channel"></a> [channel](#input\_channel) | Channel that the applications are (unless overwritten by external\_channels) deployed from | `string` | `"2/stable"` | no |
| <a name="input_cloud"></a> [cloud](#input\_cloud) | Kubernetes cloud or environment where this COS module will be deployed (e.g self-managed, aws) | `string` | `"self-managed"` | no |
| <a name="input_external_ca_cert_offer_url"></a> [external\_ca\_cert\_offer\_url](#input\_external\_ca\_cert\_offer\_url) | A Juju offer URL (e.g. admin/external-ca.send-ca-cert) of a CA providing the 'certificate\_transfer' integration for applications to trust ingress via Traefik. | `string` | `null` | no |
| <a name="input_external_certificates_offer_url"></a> [external\_certificates\_offer\_url](#input\_external\_certificates\_offer\_url) | A Juju offer URL of a CA providing the 'tls\_certificates' integration for Traefik to supply it with server certificates | `string` | `null` | no |
Expand Down
109 changes: 109 additions & 0 deletions terraform/cos/tests/channel_validation.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
mock_provider "juju" {}

# ---Happy path---

run "valid_channel_track" {
command = plan

variables {
channel = "2/stable"
model_uuid = "00000000-0000-0000-0000-000000000000"
s3_endpoint = "foo"
s3_access_key = "foo"
s3_secret_key = "foo"
}
}

run "valid_channel_stable" {
command = plan

variables {
channel = "2/candidate"
model_uuid = "00000000-0000-0000-0000-000000000000"
s3_endpoint = "foo"
s3_access_key = "foo"
s3_secret_key = "foo"
}
}

run "valid_channel_candidate" {
command = plan

variables {
channel = "2/beta"
model_uuid = "00000000-0000-0000-0000-000000000000"
s3_endpoint = "foo"
s3_access_key = "foo"
s3_secret_key = "foo"
}
}

run "valid_channel_beta" {
command = plan

variables {
channel = "2/edge"
model_uuid = "00000000-0000-0000-0000-000000000000"
s3_endpoint = "foo"
s3_access_key = "foo"
s3_secret_key = "foo"
}
}

# ---Failure path---

run "invalid_channel_track" {
command = plan

variables {
channel = "1/stable"
model_uuid = "00000000-0000-0000-0000-000000000000"
s3_endpoint = "foo"
s3_access_key = "foo"
s3_secret_key = "foo"
}

expect_failures = [var.channel]
}

run "invalid_channel_track_numeric" {
command = plan

variables {
channel = "123/risk"
model_uuid = "00000000-0000-0000-0000-000000000000"
s3_endpoint = "foo"
s3_access_key = "foo"
s3_secret_key = "foo"
}

expect_failures = [var.channel]
}

run "invalid_channel_track_string" {
command = plan

variables {
channel = "foo/risk"
model_uuid = "00000000-0000-0000-0000-000000000000"
s3_endpoint = "foo"
s3_access_key = "foo"
s3_secret_key = "foo"
}

expect_failures = [var.channel]
}

run "invalid_channel_track_dev" {
command = plan

variables {
channel = "dev/risk"
model_uuid = "00000000-0000-0000-0000-000000000000"
s3_endpoint = "foo"
s3_access_key = "foo"
s3_secret_key = "foo"
}

expect_failures = [var.channel]
}
5 changes: 5 additions & 0 deletions terraform/cos/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ variable "channel" {
description = "Channel that the applications are (unless overwritten by external_channels) deployed from"
type = string
default = "2/stable"

validation {
condition = split("/", var.channel)[0] == split("/", "2/stable")[0]
error_message = "The track (the part before the '/') of the channel must match the default."
}
}

variable "model_uuid" {
Expand Down
Loading
Loading