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
5 changes: 3 additions & 2 deletions terraform/cos-lite/README.md
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run terraform docs on the READMEs before merging

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This is a Terraform module facilitating the deployment of the COS Lite solution,
| Name | Version |
|------|---------|
| <a name="provider_juju"></a> [juju](#provider\_juju) | ~> 1.0 |
| <a name="provider_terraform"></a> [terraform](#provider\_terraform) | n/a |

## Modules

Expand All @@ -26,7 +27,7 @@ This is a Terraform module facilitating the deployment of the COS Lite solution,
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <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_base"></a> [base](#input\_base) | The operating system on which to deploy. E.g. ubuntu@22.04. Changing this value for machine charms will trigger a replace by terraform. Check Charmhub for per-charm base support. | `string` | `"ubuntu@24.04"` | no |
| <a name="input_base"></a> [base](#input\_base) | The operating system on which to deploy. E.g. ubuntu@24.04. Check Charmhub for per-charm base support. | `string` | `"ubuntu@24.04"` | 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_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 |
Expand Down Expand Up @@ -63,7 +64,7 @@ Otherwise, you can deploy from main (without `?ref`) which uses the Terraform Ju

### Basic usage

To deploy the COS HA solution in a model named `cos`, create this root module:
To deploy the COS Lite solution in a model named `cos`, create this root module:
```hcl
terraform {
required_version = ">= 1.5"
Expand Down
1 change: 1 addition & 0 deletions terraform/cos-lite/applications.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module "grafana" {
revision = local.revisions.grafana
storage_directives = var.grafana.storage_directives
units = var.grafana.units
replace_triggers = [terraform_data.grafana_litestream_resource.id]
Comment thread
MichaelThamm marked this conversation as resolved.
}

module "loki" {
Expand Down
22 changes: 18 additions & 4 deletions terraform/cos-lite/integrations.tf
Original file line number Diff line number Diff line change
Expand Up @@ -217,10 +217,6 @@ resource "juju_integration" "ingress" {
app_name = module.catalogue.app_name
endpoint = module.catalogue.requires.ingress
}
grafana = {
app_name = module.grafana.app_name
endpoint = module.grafana.requires.ingress
}
} : k => v if var.ingress[k]
}

Expand All @@ -237,6 +233,24 @@ resource "juju_integration" "ingress" {
}
}

resource "juju_integration" "grafana_ingress" {
count = var.ingress["grafana"] ? 1 : 0
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See if this works

Suggested change
count = var.ingress["grafana"] ? 1 : 0
count = var.ingress.grafana ? 1 : 0


model_uuid = var.model_uuid

application {
name = module.grafana.app_name
endpoint = module.grafana.requires.ingress
}

application {
name = module.traefik.app_name
endpoint = module.traefik.endpoints.ingress
}

lifecycle { replace_triggered_by = [terraform_data.grafana_ingress_interface] }
}

resource "juju_integration" "ingress_per_unit" {
for_each = {
for k, v in {
Expand Down
2 changes: 2 additions & 0 deletions terraform/cos-lite/offers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ resource "juju_offer" "grafana_dashboards" {
model_uuid = var.model_uuid
application_name = module.grafana.app_name
endpoints = ["grafana-dashboard"]

lifecycle { replace_triggered_by = [terraform_data.grafana_litestream_resource] }
}

resource "juju_offer" "loki_logging" {
Expand Down
32 changes: 24 additions & 8 deletions terraform/cos-lite/tests/conditional_ingress.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ run "default_ingress_all_enabled" {
command = plan

assert {
condition = length(juju_integration.ingress) == 3
error_message = "Expected 3 ingress integrations (alertmanager, catalogue, grafana), got ${length(juju_integration.ingress)}"
condition = length(juju_integration.ingress) == 2
error_message = "Expected 2 ingress integrations (alertmanager, catalogue), got ${length(juju_integration.ingress)}"
}

# Grafana uses a separate count-based resource due to lifecycle replace_triggered_by
assert {
condition = length(juju_integration.grafana_ingress) == 1
error_message = "Expected 1 grafana_ingress integration, got ${length(juju_integration.grafana_ingress)}"
}

assert {
Expand Down Expand Up @@ -38,6 +44,11 @@ run "ingress_all_disabled" {
error_message = "Expected 0 ingress integrations, got ${length(juju_integration.ingress)}"
}

assert {
condition = length(juju_integration.grafana_ingress) == 0
error_message = "Expected 0 grafana_ingress integrations, got ${length(juju_integration.grafana_ingress)}"
}

assert {
condition = length(juju_integration.ingress_per_unit) == 0
error_message = "Expected 0 ingress_per_unit integrations, got ${length(juju_integration.ingress_per_unit)}"
Expand All @@ -60,13 +71,13 @@ run "ingress_only_grafana" {
}

assert {
condition = length(juju_integration.ingress) == 1
error_message = "Expected 1 ingress integration (grafana only), got ${length(juju_integration.ingress)}"
condition = length(juju_integration.ingress) == 0
error_message = "Expected 0 ingress integrations, got ${length(juju_integration.ingress)}"
}

assert {
condition = contains(keys(juju_integration.ingress), "grafana")
error_message = "Expected ingress to contain 'grafana' key"
condition = length(juju_integration.grafana_ingress) == 1
error_message = "Expected 1 grafana_ingress integration, got ${length(juju_integration.grafana_ingress)}"
}

assert {
Expand Down Expand Up @@ -124,15 +135,20 @@ run "ingress_partial_override" {
}

assert {
condition = length(juju_integration.ingress) == 2
error_message = "Expected 2 ingress integrations (catalogue, grafana), got ${length(juju_integration.ingress)}"
condition = length(juju_integration.ingress) == 1
error_message = "Expected 1 ingress integration (catalogue), got ${length(juju_integration.ingress)}"
}

assert {
condition = !contains(keys(juju_integration.ingress), "alertmanager")
error_message = "Expected ingress to NOT contain 'alertmanager' key"
}

assert {
condition = length(juju_integration.grafana_ingress) == 1
error_message = "Expected 1 grafana_ingress integration, got ${length(juju_integration.grafana_ingress)}"
}

assert {
condition = length(juju_integration.ingress_per_unit) == 1
error_message = "Expected 1 ingress_per_unit integration (loki only), got ${length(juju_integration.ingress_per_unit)}"
Expand Down
20 changes: 20 additions & 0 deletions terraform/cos-lite/upgrades.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
# -------------- # Replace triggers -------------- #

# -- Grafana -- #

# [application] Removed the litestream-image resource
# Given a Juju bug, we need to trigger application replacement, otherwise the upgrade will fail
# https://github.com/juju/juju/issues/21648
# https://github.com/juju/juju/issues/22071
resource "terraform_data" "grafana_litestream_resource" {
triggers_replace = contains(keys(data.juju_charm.grafana_info.resources), "litestream-image")
}

# [integration] Ingress interface changed
# The ingress endpoint interface changes from traefik_route to ingress_per_app so we need to
# trigger integration replacement, otherwise the upgrade will fail
# https://github.com/canonical/observability-stack/issues/165
resource "terraform_data" "grafana_ingress_interface" {
triggers_replace = lookup(data.juju_charm.grafana_info.requires, "ingress", "")
Comment thread
MichaelThamm marked this conversation as resolved.
}

# -------------- # CharmHub API -------------- #

data "juju_charm" "alertmanager_info" {
Expand Down
2 changes: 1 addition & 1 deletion terraform/cos-lite/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ variable "risk" {
}

variable "base" {
description = "The operating system on which to deploy. E.g. ubuntu@22.04. Changing this value for machine charms will trigger a replace by terraform. Check Charmhub for per-charm base support."
description = "The operating system on which to deploy. E.g. ubuntu@24.04. Check Charmhub for per-charm base support."
default = "ubuntu@24.04"
type = string
}
Expand Down
3 changes: 2 additions & 1 deletion terraform/cos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This is a Terraform module facilitating the deployment of the COS solution, usin
| Name | Version |
|------|---------|
| <a name="provider_juju"></a> [juju](#provider\_juju) | ~> 1.0 |
| <a name="provider_terraform"></a> [terraform](#provider\_terraform) | n/a |

## Modules

Expand All @@ -32,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_base"></a> [base](#input\_base) | The operating system on which to deploy. E.g. ubuntu@22.04. Changing this value for machine charms will trigger a replace by terraform. Check Charmhub for per-charm base support. | `string` | `"ubuntu@24.04"` | no |
| <a name="input_base"></a> [base](#input\_base) | The operating system on which to deploy. E.g. ubuntu@24.04. Check Charmhub for per-charm base support. | `string` | `"ubuntu@24.04"` | 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_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 |
Expand Down
1 change: 1 addition & 0 deletions terraform/cos/applications.tf
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module "grafana" {
revision = local.revisions.grafana
storage_directives = var.grafana.storage_directives
units = var.grafana.units
replace_triggers = [terraform_data.grafana_litestream_resource.id]
}

module "loki" {
Expand Down
64 changes: 52 additions & 12 deletions terraform/cos/integrations.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ resource "juju_integration" "grafana_dashboards" {
name = module.grafana.app_name
endpoint = module.grafana.requires.grafana_dashboard
}

lifecycle { replace_triggered_by = [terraform_data.grafana_litestream_resource] }
}
# -------------- # Charm Tracing ------------------------

Expand All @@ -44,10 +46,6 @@ resource "juju_integration" "charm_tracing" {
app_name = module.loki.app_names.loki_coordinator
endpoint = module.loki.requires.charm_tracing
}
grafana = {
app_name = module.grafana.app_name
endpoint = module.grafana.requires.charm_tracing
}
}
model_uuid = var.model_uuid

Expand All @@ -62,6 +60,22 @@ resource "juju_integration" "charm_tracing" {
}
}

resource "juju_integration" "charm_tracing_grafana" {
model_uuid = var.model_uuid

application {
name = module.grafana.app_name
endpoint = module.grafana.requires.charm_tracing
}

application {
name = module.opentelemetry_collector.app_name
endpoint = module.opentelemetry_collector.provides.receive_traces
}

lifecycle { replace_triggered_by = [terraform_data.grafana_litestream_resource] }
}

# -------------- # Metrics Endpoint ----------------------
resource "juju_integration" "otelcol_metrics_endpoint" {
for_each = {
Expand Down Expand Up @@ -128,6 +142,8 @@ resource "juju_integration" "grafana_sources" {
name = module.grafana.app_name
endpoint = module.grafana.requires.grafana_source
}

lifecycle { replace_triggered_by = [terraform_data.grafana_litestream_resource] }
}

# -------------- # Receive Loki Logs ---------------------
Expand Down Expand Up @@ -242,10 +258,6 @@ resource "juju_integration" "catalogue_integrations" {
app_name = module.alertmanager.app_name
endpoint = module.alertmanager.requires.catalogue
}
grafana = {
app_name = module.grafana.app_name
endpoint = module.grafana.requires.catalogue
}
tempo = {
app_name = module.tempo.app_names.tempo_coordinator
endpoint = module.tempo.requires.catalogue
Expand All @@ -269,6 +281,21 @@ resource "juju_integration" "catalogue_integrations" {
}
}

resource "juju_integration" "catalogue_integration_grafana" {
model_uuid = var.model_uuid

application {
name = module.catalogue.app_name
endpoint = module.catalogue.provides.catalogue
}

application {
name = module.grafana.app_name
endpoint = module.grafana.requires.catalogue
}

lifecycle { replace_triggered_by = [terraform_data.grafana_litestream_resource] }
}

# -------------- # Provided by Traefik --------------

Expand All @@ -292,10 +319,6 @@ resource "juju_integration" "ingress" {
app_name = module.loki.app_names.loki_coordinator
endpoint = module.loki.requires.ingress
}
grafana = {
app_name = module.grafana.app_name
endpoint = module.grafana.requires.ingress
}
} : k => v if var.ingress[k]
}
model_uuid = var.model_uuid
Expand All @@ -311,6 +334,23 @@ resource "juju_integration" "ingress" {
}
}

resource "juju_integration" "grafana_ingress" {
count = var.ingress["grafana"] ? 1 : 0

model_uuid = var.model_uuid

application {
name = module.grafana.app_name
endpoint = module.grafana.requires.ingress
}

application {
name = module.traefik.app_name
endpoint = module.traefik.endpoints.ingress
}

lifecycle { replace_triggered_by = [terraform_data.grafana_ingress_interface, terraform_data.grafana_litestream_resource] }
}

resource "juju_integration" "traefik_route" {
for_each = {
Expand Down
2 changes: 2 additions & 0 deletions terraform/cos/offers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ resource "juju_offer" "grafana_dashboards" {
model_uuid = var.model_uuid
application_name = module.grafana.app_name
endpoints = ["grafana-dashboard"]

lifecycle { replace_triggered_by = [terraform_data.grafana_litestream_resource] }
}

resource "juju_offer" "loki_logging" {
Expand Down
Loading
Loading