Skip to content
Merged
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
17 changes: 16 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,22 @@ on:
jobs:
lint:
name: Lint
uses: canonical/data-platform-workflows/.github/workflows/[email protected]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install terraform
run: |
sudo snap install terraform --classic
- name: Install tox & poetry
run: |
pipx install tox
pipx install poetry
- name: Run linters
run: |
tox run -e lint
tox run -e lint-terraform

unit-test:
name: Unit test charm
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,8 @@ build
# local pyright settings
pyrightconfig.json

# Terraform
.terraform
.terraform.lock.hcl

wt*/
84 changes: 30 additions & 54 deletions docs/how-to/deploy/terraform.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,30 @@
# How to deploy using Terraform

[Terraform](https://www.terraform.io/) is an infrastructure automation tool to provision and manage resources in clouds or data centers. To deploy Charmed MySQL K8s using Terraform and Juju, you can use the [Juju Terraform Provider](https://registry.terraform.io/providers/juju/juju/latest).
# How to deploy using Terraform

The easiest way is to start from [these examples of terraform modules](https://github.com/canonical/terraform-modules) prepared by Canonical. This page will guide you through a deployment using an example module for MySQL on Kubernetes.
[Terraform](https://www.terraform.io/) is an infrastructure automation tool to provision and manage resources in clouds or data centers.
To deploy Charmed MySQL using Terraform and Juju, you can use the [Juju Terraform Provider](https://registry.terraform.io/providers/juju/juju/latest).

For an in-depth introduction to the Juju Terraform Provider, read [this Discourse post](https://discourse.charmhub.io/t/6939).

```{note}
**Note**: Storage support was added in [Juju Terraform Provider version 0.13+](https://github.com/juju/terraform-provider-juju/releases/tag/v0.13.0).
```

## Install Terraform tooling

This guide assumes Juju is installed and you have a K8s controller already bootstrapped. For more information, check the [Charmed MySQL K8s tutorial](/tutorial/index).
This guide assumes Juju is installed, and you have a K8s controller already bootstrapped. For more information, check the [Charmed MySQL K8s tutorial](/tutorial/index).

Let's install Terraform Provider and example modules:
```shell
sudo snap install terraform --classic
```

Switch to the K8s provider and create a new model:
```shell
juju switch microk8s
juju add-model my-model
```
Clone examples and navigate to the MySQL machine module:

Clone the MySQL K8s operator repository and navigate to the terraform module:
```shell
git clone https://github.com/canonical/terraform-modules.git
cd terraform-modules/modules/k8s/mysql
git clone https://github.com/canonical/mysql-k8s-operator.git
cd terraform
```

Initialise the Juju Terraform Provider:
Expand All @@ -36,35 +34,18 @@ terraform init

## Verify the deployment

Open the `main.tf` file to see the brief contents of the Terraform module:

```tf
resource "juju_application" "k8s_mysql" {
name = var.mysql_application_name
model = var.juju_model_name
trust = true

charm {
name = "mysql-k8s"
channel = var.mysql_charm_channel
}

units = 1
}
```

Run `terraform plan` to get a preview of the changes that will be made:
Open the `main.tf` file to see the brief contents of the Terraform module, and run `terraform plan` to get a preview of the changes that will be made:

```shell
terraform plan -var "juju_model_name=my-model"
terraform plan -var "model_name=my-model"
```

## Apply the deployment

If everything looks correct, deploy the resources (skip the approval):

```shell
terraform apply -auto-approve -var "juju_model_name=my-model"
terraform apply -auto-approve -var "model_name=my-model"
```

## Check deployment status
Expand All @@ -78,48 +59,47 @@ juju status --model k8s:my-model --watch 1s
Sample output:

```shell
Model Controller Cloud/Region Version SLA Timestamp
my-model k8s-controller microk8s/localhost 3.5.3 unsupported 12:37:25Z
Model Controller Cloud/Region Version SLA Timestamp
my-model k8s-controller microk8s/localhost 3.5.3 unsupported 12:37:25Z

App Version Status Scale Charm Channel Rev Address Exposed Message
mysql-k8s 8.0.36-0ubuntu0.22.04.1 active 1 mysql-k8s 8.0/stable 153 10.152.183.112 no
mysql-k8s 8.0.41-0ubuntu0.22.04.1 active 1 mysql-k8s 8.0/stable 255 10.152.183.112 no

Unit Workload Agent Address Ports Message
mysql-k8s/0* active idle 10.1.77.76 Primary

```

Continue to operate the charm as usual from here or apply further Terraform changes.

## Clean up

To keep the house clean, remove the newly deployed Charmed MySQL K8s by running
To keep the house clean, remove the newly deployed MySQL K8s charm by running
```shell
terraform destroy -var "juju_model_name=my-model"
terraform destroy -var "model_name=my-model"
```

Sample output:
```shell
juju_application.k8s_mysql: Refreshing state... [id=terra-k8s:mysql-k8s]
juju_application.mysql_server: Refreshing state... [id=my-model:mysql-k8s]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy

Terraform will perform the following actions:

# juju_application.k8s_mysql will be destroyed
- resource "juju_application" "k8s_mysql" {
# juju_application.mysql_server will be destroyed
- resource "juju_application" "mysql_server" {
- constraints = "arch=amd64" -> null
- id = "terra-k8s:mysql-k8s" -> null
- model = "terra-k8s" -> null
- id = "my-model:mysql-k8s" -> null
- model = "my-model" -> null
- name = "mysql-k8s" -> null
- placement = "" -> null
- storage = [
- {
- count = 1 -> null
- label = "database-1" -> null
- label = "database" -> null
- pool = "kubernetes" -> null
- size = "1G" -> null
- size = "10G" -> null
},
] -> null
- trust = true -> null
Expand All @@ -129,32 +109,28 @@ Terraform will perform the following actions:
- base = "[email protected]" -> null
- channel = "8.0/stable" -> null
- name = "mysql-k8s" -> null
- revision = 153 -> null
- revision = 255 -> null
- series = "jammy" -> null
}
}

Plan: 0 to add, 0 to change, 1 to destroy.

Changes to Outputs:
- application_name = "mysql-k8s" -> null
- application_name = "mysql" -> null

Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.

Enter a value: yes

juju_application.k8s_mysql: Destroying... [id=terra-k8s:mysql-k8s]
juju_application.k8s_mysql: Destruction complete after 0s
juju_application.mysql_server: Destroying... [id=my-model:mysql-k8s]
juju_application.mysql_server: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.
```
---

```{note}
For more examples of Terraform modules for K8s, see the other directories in the [`terraform-modules` repository](https://github.com/canonical/terraform-modules/tree/main/modules/k8s).
```

Feel free to [contact us](/reference/contacts) if you have any question and [collaborate with us on GitHub](https://github.com/canonical/terraform-modules)!
---

Feel free to [contact us](/reference/contacts) if you have any question and collaborate with us on GitHub!
12 changes: 5 additions & 7 deletions terraform/main.tf
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
resource "juju_application" "k8s_mysql" {
resource "juju_application" "mysql_server" {
name = var.app_name
model = var.juju_model_name
trust = true
model = var.model_name

charm {
name = "mysql-k8s"
base = var.base
channel = var.channel
revision = var.revision
base = var.base
}

storage_directives = {
database = var.storage_size
}

units = var.units
constraints = var.constraints
config = var.config
resources = var.resources
constraints = var.constraints
units = var.units
}
15 changes: 9 additions & 6 deletions terraform/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
output "application_name" {
value = juju_application.k8s_mysql.name
output "app_name" {
description = "Name of the MySQL Server K8s application"
value = juju_application.mysql_server.name
}


output "provides" {
description = "Map of all the provided endpoints"
value = {
database = "database",
metrics_endpoint = "metrics-endpoint",
database = "database"
grafana_dashboard = "grafana-dashboard"
metrics_endpoint = "metrics-endpoint"
}
}

output "requires" {
description = "Map of all the required endpoints"
value = {
logging = "logging"
certificates = "certificates"
s3_parameters = "s3-parameters"
logging = "logging"
tracing = "tracing"
}
}
54 changes: 24 additions & 30 deletions terraform/variables.tf
Original file line number Diff line number Diff line change
@@ -1,58 +1,52 @@
variable "juju_model_name" {
description = "Juju model name"
variable "model_name" {
description = "Juju model to deploy to"
type = string
}

variable "app_name" {
description = "Name of the application in the Juju model."
description = "Name of the juju application"
type = string
default = "mysql-k8s"
}

variable "base" {
description = "Application base"
type = string
default = "[email protected]"
}

variable "config" {
description = "Application configuration. Details at https://charmhub.io/mysql-k8s/configurations"
type = map(string)
default = {}
}

variable "constraints" {
description = "Juju constraints for the application"
type = string
default = "arch=amd64"
}

variable "channel" {
description = "Charm channel to use when deploying"
description = "Charm channel to deploy from"
type = string
default = "8.0/stable"
}

variable "revision" {
description = "Revision number to deploy charm"
description = "Charm revision to deploy"
type = number
default = null
}

variable "base" {
description = "Application base"
type = string
default = "[email protected]"
}

variable "units" {
description = "Number of units to deploy"
type = number
default = 1
}

variable "constraints" {
description = "Juju constraints to apply for this application."
type = string
default = "arch=amd64"
default = 3
}

variable "storage_size" {
description = "Storage size"
type = string
default = "10G"
}

variable "config" {
description = "Application configuration. Details at https://charmhub.io/mysql-k8s/configurations"
type = map(string)
default = {}
}

variable "resources" {
description = "Resources to use with the application"
type = map(string)
default = {}
}
3 changes: 2 additions & 1 deletion terraform/versions.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
terraform {
required_version = ">= 1.6.6"

required_providers {
juju = {
source = "juju/juju"
version = ">= 0.14.0"
version = ">= 0.20.0, < 1.0.0"
}
}
}
11 changes: 11 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ env_list = lint, unit
src_path = "{tox_root}/src"
tests_path = "{tox_root}/tests"
scripts_path = "{tox_root}/scripts"
terraform_path = "{tox_root}/terraform"
all_path = {[vars]src_path} {[vars]tests_path} {[vars]scripts_path}

[testenv]
Expand Down Expand Up @@ -41,6 +42,16 @@ commands =
poetry run ruff format --check --diff {[vars]all_path}
find {[vars]all_path} -type f \( -name "*.sh" -o -name "*.bash" \) -exec poetry run shellcheck --color=always \{\} +

[testenv:lint-terraform]
description = Check code against Terraform style standards
allowlist_externals =
{[testenv]allowlist_externals}
terraform
commands =
terraform fmt -check -diff -recursive {[vars]terraform_path}
terraform -chdir={[vars]terraform_path} init -backend=false
terraform -chdir={[vars]terraform_path} validate

[testenv:unit]
description = Run unit tests
commands_pre =
Expand Down
Loading