Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
aa244a2
feat: Charmhub module for upgrades
MichaelThamm Jan 15, 2026
6a5e192
chore: README
MichaelThamm Jan 15, 2026
d8b0fbd
feat: add an upgrade doc
MichaelThamm Jan 15, 2026
0634ec8
chore: doc improvements
MichaelThamm Jan 16, 2026
2c634d1
feat: charmhub inside COS Lite
MichaelThamm Jan 19, 2026
424447a
chore: update tutorial
MichaelThamm Jan 19, 2026
b3b6492
chore: revert apps to remote source
MichaelThamm Jan 19, 2026
91dcf5f
chore
MichaelThamm Jan 21, 2026
188e4f5
chore: dump ideas
MichaelThamm Feb 9, 2026
97f585a
chore: remove charmhub module
MichaelThamm Mar 20, 2026
440dbee
chore: implement juju_data
MichaelThamm Mar 22, 2026
f4ffc38
fix: remove ubuntu/litestream from list of oci images (#177)
sinapah Feb 4, 2026
5c7bf3a
fix: Outdated docs (#178)
MichaelThamm Feb 4, 2026
055a627
chore: add blackbox exporter machine to list of charms in docs (#176)
sinapah Feb 4, 2026
42999c2
docs: fix extra double quote in cloud-init script (#181)
Copilot Feb 5, 2026
f2b3517
Separates the storage directives for different worker roles (#182)
Gmerold Feb 12, 2026
3f6cffc
Update source URL for cos-lite module (#190)
Abuelodelanada Feb 17, 2026
7078c6e
fix: READMEs (#191)
MichaelThamm Feb 17, 2026
2170e02
feat(doc): troubleshoot grafana admin password (#194)
sed-i Feb 23, 2026
61f716f
feat(docs): update otelcol docs (#199)
sed-i Mar 5, 2026
1d27584
feat: Tests for product module `channel` input (#202)
MichaelThamm Mar 10, 2026
dba3cef
docs: point to correct file for cos-lite variables.tf (#205)
sinapah Mar 11, 2026
51dd4b7
docs: deprecation notice in tutorial for migrating from GA to otelcol…
sinapah Mar 11, 2026
db994ce
fix: Tiering HowTo doc with OTLP endpoints (#211)
MichaelThamm Mar 16, 2026
c7cfe08
add cookie banner and Google Analytics tags (#213)
YanisaHS Mar 18, 2026
b76242e
docs: Troubleshooting compressed alerts and OTLP topology labels (#215)
MichaelThamm Mar 19, 2026
911c30b
docs(explanation): add dashboard upgrade guidance for deduplication a…
Copilot Mar 20, 2026
42ac9a5
chore: cleanup
MichaelThamm Mar 23, 2026
0187773
Merge remote-tracking branch 'origin/main' into feat/charmhub-module
MichaelThamm Mar 23, 2026
8903f5b
chore: cleanup
MichaelThamm Mar 23, 2026
fa6561d
chore: cleanup
MichaelThamm Mar 23, 2026
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
16 changes: 13 additions & 3 deletions docs/tutorial/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ or COS Lite, Juju-based observability stacks running on Kubernetes.

1. Deploy the observability stack <installation/index>

Refresh
=============

In this part of the tutorial you will learn how to refresh COS (or COS Lite) to a new channel using Terraform.

.. toctree::
:maxdepth: 1

2. Refresh COS to a new channel <refresh-product-module>

Configuration
=============

Expand All @@ -29,7 +39,7 @@ charm.
.. toctree::
:maxdepth: 1

2. Sync alert rules from Git <sync-alert-rules-from-git>
3. Sync alert rules from Git <sync-alert-rules-from-git>

Instrumentation
===============
Expand All @@ -41,7 +51,7 @@ application using the Grafana Agent machine charm.
.. toctree::
:maxdepth: 1

3. Instrument machine charms <instrument-machine-charms>
4. Instrument machine charms <instrument-machine-charms>


Redaction
Expand All @@ -52,4 +62,4 @@ By implementing a solid redaction strategy you can mitigate the risk of unwanted
.. toctree::
:maxdepth: 1

4. Redact sensitive data <redact-sensitive-data.md>
5. Redact sensitive data <redact-sensitive-data.md>
2 changes: 2 additions & 0 deletions docs/tutorial/installation/cos-lite-microk8s-sandbox.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ $ juju deploy cos-lite \
--overlay ./storage-small-overlay.yaml
```

(deploy-cos-ref)=
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Iirc we haven't started using these our docs yet.
Remind me - it's an anchor or cross-sphinx ref?
I think juju had this and it turned out to be brittle and difficult to maintain, but maybe I'm missing something.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's an anchor, but it can also be used as a cross-sphinx/project ref for projects that have that enabled.

You haven't started using them in the COS docs yet, but it is the standard approach to cross-linking for sphinx docs projects, so at some point, you should change your links to use these refs. Juju uses them in their docs, but I don't know what conversations happened around it

Using ref targets/anchors is nicer because otherwise anytime you change the filename/path, it'll break any of those links in your docs.

IMO, it could go either way in this PR (add it or don't add it), but the future goal should be that all docs have a ref target, and you use those for linking instead of file path. (Copilot should be able to handle it well when you do make this initiative)


## Deploy COS Lite using Terraform

Create a `cos-lite-microk8s-sandbox.tf` file with the following Terraform module, or include it in your Terraform plan:
Expand Down
2 changes: 2 additions & 0 deletions docs/tutorial/installation/cos-lite-microk8s-sandbox.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ terraform {
}
}

# before-cos

resource "juju_model" "cos" {
name = "cos"
config = { logging-config = "<root>=WARNING; unit=DEBUG" }
Expand Down
111 changes: 111 additions & 0 deletions docs/tutorial/refresh-product-module.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Refresh COS to a new channel

In this example, you will learn how to deploy COS Lite and refresh from channel `2/stable` to `2/edge`. To do this, we can deploy COS Lite via Terraform in the same way as [in the tutorial](https://documentation.ubuntu.com/observability/track-2/tutorial/installation/cos-lite-microk8s-sandbox).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Assuming this gets refactored into a tutorial, the language/framing should change so it's not like "In this example, you'll learn...". How-to guides aren't really "learning" experiences, it's more just like "here's the steps you need to do XYZ".

Example: Charmed Kafka: How to upgrade


## Prerequisites

This tutorial assumes that you already:

- Know how to deploy {ref}`COS Lite with Terraform <deploy-cos-ref>`

## Introduction
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Similar to a comment I made above, this section can be less narrative if being refactored into a how-to guide

(btw I'm happy to meet and discuss my comments with you if you want!)


Imagine you have COS Lite (or COS) deployed on a specific channel like `2/stable` and want to
refresh to a different channel (or track) e.g., `2/edge`. To do so, an admin would have to manually
`juju refresh` each COS charm and address any refresh errors. Alternatively, they can determine the
correct charm `channel` and `revision`(s), update the Terraform module, and apply.

This is simplified within COS (and COS Lite) by mimicking the `juju refresh` behavior on a product
level, allowing the juju admin to specify a list of charms to refresh within the specified
`track/channel`. The rest is handled by Terraform.

## Update the COS Lite Terraform module

Once deployed, we can determine which charms to refresh with the `charms_to_refresh` input variable, detailed in the [README](https://github.com/canonical/observability-stack/tree/main/terraform/cos-lite). This defaults to: all charms owned by the `observability-team`.

```{note}
This tutorial assumed you have deployed COS Lite from a root module located at `./main.tf`.
```

Then, replace `2/stable` with `2/edge` in your `cos-lite` module within the existing `./main.tf` file:

```{literalinclude} /tutorial/installation/cos-lite-microk8s-sandbox.tf
---
language: hcl
start-after: "# before-cos"
---
```

```{note}
The `base` input variable for the `cos-lite` module is important if the `track/channel` deploys charms to a different base than the default, detailed in the [README](https://github.com/canonical/observability-stack/tree/main/terraform/cos-lite).
```

Finally, add the provider definitions into the same `./main.tf` file:

```hcl
terraform {
required_providers {
juju = {
source = "juju/juju"
version = "~> 1.0"
}
http = {
source = "hashicorp/http"
version = "~> 3.0"
}
}
}
```

At this point, you will have one `main.tf` file ready for deployment. Now you can plan these changes with:

```shell
terraform plan
```

and Terraform plans to update each charm to the latest revision in the `2/edge` channel:

```shell
Terraform used the selected providers to generate the following
execution plan. Resource actions are indicated with the following
symbols:
+ create
~ update in-place

Terraform will perform the following actions:

# module.cos.module.alertmanager.juju_application.alertmanager will be updated in-place
~ resource "juju_application" "alertmanager" {

# snip ...

~ charm {
~ channel = "2/stable" -> "2/edge"
name = "alertmanager-k8s"
~ revision = 191 -> 192
# (1 unchanged attribute hidden)
}

# snip ...

Plan: 0 to add, 5 to change, 0 to destroy.
```

and finally apply the changes with:

```shell
terraform apply
```

At this point, you will have successfully upgraded COS Lite from `2/stable` to `2/edge`!
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The steps overall seem fine and pretty straightforward. I can provide some better feedback once it gets refactored into a how-to


## Refresh information

This tutorial only considers upgrading COS Lite. However, the `charmhub` module is product-agnostic
and can be used to refresh charms, and other products e.g., COS.

You can consult the follow release documentation for refresh compatibility:

- [how-to cross-track upgrade](/how-to/upgrade/)
- [release policy](/reference/release-policy/)
- [release notes](/reference/release-notes/)
2 changes: 1 addition & 1 deletion terraform/cos-lite/applications.tf
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module "grafana" {
config = var.grafana.config
constraints = var.grafana.constraints
model_uuid = var.model_uuid
revision = var.grafana.revision
revision = data.juju_charm.grafana_info.revision
storage_directives = var.grafana.storage_directives
units = var.grafana.units
}
Expand Down
5 changes: 4 additions & 1 deletion terraform/cos-lite/integrations.tf
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,16 @@ resource "juju_integration" "grafana_ingress" {

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

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

lifecycle {
replace_triggered_by = [terraform_data.grafana_ingress_interface]
}
}

resource "juju_integration" "prometheus_ingress" {
Expand Down
16 changes: 16 additions & 0 deletions terraform/cos-lite/upgrades.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -------------- Upgrade logic --------------

## -------- grafana.revision >= 174 ----------
# the ingress endpoint changes from traefik_route to ingress_per_app so we need a lifecycle to
# trigger integration replacement, otherwise the upgrade will fail
data "juju_charm" "grafana_info" {
charm = "grafana-k8s"
channel = var.channel
base = var.base
}

resource "terraform_data" "grafana_ingress_interface" {
input = data.juju_charm.grafana_info.requires["ingress"]
}

# -------------- End upgrade logic --------------
19 changes: 14 additions & 5 deletions terraform/cos-lite/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,23 @@ locals {
tls_termination = var.external_certificates_offer_url != null ? true : false
}

# TODO: Discuss how this was missed bc we don't have any base terraform tests. TF plan would catch this error
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."
default = "ubuntu@24.04"
type = string
}

variable "channel" {
description = "Channel that the applications are (unless overwritten by individual channels) deployed from"
type = string
default = "dev/edge"

validation {
# the TF Juju provider correctly identifies invalid risks; no need to validate it
condition = startswith(var.channel, "dev/")
error_message = "The track of the channel must be 'dev/'. e.g. 'dev/edge'."
}
# validation {
# # the TF Juju provider correctly identifies invalid risks; no need to validate it
# condition = startswith(var.channel, "dev/")
# error_message = "The track of the channel must be 'dev/'. e.g. 'dev/edge'."
# }
}

variable "model_uuid" {
Expand Down Expand Up @@ -81,6 +88,8 @@ variable "catalogue" {
description = "Application configuration for Catalogue. For more details: https://registry.terraform.io/providers/juju/juju/latest/docs/resources/application"
}

# TODO: Update all charms to surface their channel input, since we will have fine-grained channels per charm
# TODO: Update the channel defaults to be the track
variable "grafana" {
type = object({
app_name = optional(string, "grafana")
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos/tls_external/track-2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module "cos" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2"
model_uuid = data.juju_model.cos-model.uuid
channel = "2/stable"
internal_tls = "false"
internal_tls = false
external_certificates_offer_url = "admin/${var.ca_model}.certificates"
external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert"

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos/tls_external/track-dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module "cos" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos"
model_uuid = data.juju_model.cos-model.uuid
channel = "dev/edge"
internal_tls = "false"
internal_tls = false
external_certificates_offer_url = "admin/${var.ca_model}.certificates"
external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert"

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos/tls_full/track-2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module "cos" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2"
model_uuid = data.juju_model.cos-model.uuid
channel = "2/stable"
internal_tls = "true"
internal_tls = true
external_certificates_offer_url = "admin/${var.ca_model}.certificates"
external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert"

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos/tls_full/track-dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module "cos" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos"
model_uuid = data.juju_model.cos-model.uuid
channel = "dev/edge"
internal_tls = "true"
internal_tls = true
external_certificates_offer_url = "admin/${var.ca_model}.certificates"
external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert"

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos/tls_internal/track-2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module "cos" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2"
model_uuid = data.juju_model.model.uuid
channel = "2/stable"
internal_tls = "true"
internal_tls = true

s3_endpoint = var.s3_endpoint
s3_secret_key = var.s3_secret_key
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos/tls_internal/track-dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module "cos" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos"
model_uuid = data.juju_model.model.uuid
channel = "dev/edge"
internal_tls = "true"
internal_tls = true

s3_endpoint = var.s3_endpoint
s3_secret_key = var.s3_secret_key
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos/tls_none/track-2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module "cos" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos?ref=track/2"
model_uuid = data.juju_model.model.uuid
channel = "2/stable"
internal_tls = "false"
internal_tls = false

s3_endpoint = var.s3_endpoint
s3_secret_key = var.s3_secret_key
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos/tls_none/track-dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module "cos" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos"
model_uuid = data.juju_model.model.uuid
channel = "dev/edge"
internal_tls = "false"
internal_tls = false

s3_endpoint = var.s3_endpoint
s3_secret_key = var.s3_secret_key
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos_lite/tls_external/track-2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module "cos-lite" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2"
model_uuid = data.juju_model.cos-model.uuid
channel = "2/stable"
internal_tls = "false"
internal_tls = false
external_certificates_offer_url = "admin/${var.ca_model}.certificates"
external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert"

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos_lite/tls_external/track-dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module "cos-lite" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite"
model_uuid = data.juju_model.cos-model.uuid
channel = "dev/edge"
internal_tls = "false"
internal_tls = false
external_certificates_offer_url = "admin/${var.ca_model}.certificates"
external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert"

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos_lite/tls_full/track-2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module "cos-lite" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2"
model_uuid = data.juju_model.cos-model.uuid
channel = "2/stable"
internal_tls = "true"
internal_tls = true
external_certificates_offer_url = "admin/${var.ca_model}.certificates"
external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert"

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos_lite/tls_full/track-dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ module "cos-lite" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite"
model_uuid = data.juju_model.cos-model.uuid
channel = "dev/edge"
internal_tls = "true"
internal_tls = true
external_certificates_offer_url = "admin/${var.ca_model}.certificates"
external_ca_cert_offer_url = "admin/${var.ca_model}.send-ca-cert"

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cos_lite/tls_internal/track-2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module "cos-lite" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2"
model_uuid = data.juju_model.model.uuid
channel = "2/stable"
internal_tls = "true"
internal_tls = true

traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable
}
2 changes: 1 addition & 1 deletion tests/integration/cos_lite/tls_internal/track-dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module "cos-lite" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite"
model_uuid = data.juju_model.model.uuid
channel = "dev/edge"
internal_tls = "true"
internal_tls = true

traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable
}
2 changes: 1 addition & 1 deletion tests/integration/cos_lite/tls_none/track-2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module "cos-lite" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite?ref=track/2"
model_uuid = data.juju_model.model.uuid
channel = "2/stable"
internal_tls = "false"
internal_tls = false

traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable
}
2 changes: 1 addition & 1 deletion tests/integration/cos_lite/tls_none/track-dev.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module "cos-lite" {
source = "git::https://github.com/canonical/observability-stack//terraform/cos-lite"
model_uuid = data.juju_model.model.uuid
channel = "dev/edge"
internal_tls = "false"
internal_tls = false

traefik = { channel = "latest/edge" } # TODO: Switch to latest/stable when rev257 hits stable
}
Loading