Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Craft the juju model-config for suppressing fan-config #22

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/plan-terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
yaml: test/vanilla.yaml
cloud_integration: ''
env:
TF_VAR_model: test
TF_VAR_model: '{"name": "test", "cloud": "prod-k8s-openstack", "config": {"test": true}}'
TF_VAR_manifest_yaml: ${{ matrix.test.yaml }}
TF_VAR_cloud_integration: ${{ matrix.test.cloud_integration }}
WORKING_DIR: 'terraform'
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ main/.charmcraft_output_packages.txt
**/.terraform
**/.terraform.lock.hcl
**/*.tfstate
**/*.tfstate.backup
**/tfplan
61 changes: 39 additions & 22 deletions terraform/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,32 @@ charm configuration.
## TODO
- [ ] Set outputs for each charm deployed
- [ ] Add COS integration
- [ ] Find a home for this module
- [ ] Add required subordinate (Landscape, NTP, etc..) see [This private Terraform Plan for details](https://git.launchpad.net/canonical-terraform-modules/tree/services/compute/canonical_k8s_cluster/main.tf#n214)
- [ ] Add required subordinate (Landscape, NTP, etc..) see [This private Terraform Plan for details][private-details]

## Applications
* [k8s](https://charmhub.io/k8s)
* [k8s-worker](https://charmhub.io/k8s-worker)

## Inputs
| Name | Type | Description | Required |
| - | - | - | - |
| `manifest_yaml` | string | Absolute path to the manifest yaml for the deployment | True |
| `model` | string | Name of the Juju model to deploy into | True |
| `cloud_integration` | string | Selection of a cloud integration | False |
| Name | Type | Description | Required |
| --- | --- | --- | --- |
| `manifest_yaml` | string | Absolute path to the manifest yaml for the deployment | True |
| `model` | object | Juju model attributes | True |
| `cloud_integration` | bool | Enablement of a cloud integration | False |

### Model Input:
Juju Model resource definition borrows its schema from [Juju Model Resource].

The schema requires only:
- **name**: Name of the model
- **cloud**: Cloud name

Default fields are:
- **region**: Region name (optional)
- **config**: Configuration map (optional)
- **constraints**: Constraints string (optional)
- **credential**: Credential name (optional)


## Outputs
TODO
Expand All @@ -30,29 +43,33 @@ TODO

Add the following to your main.tf for the canonical k8s solution:

```
```hcl
module "k8s" {
source = "git::https://github.com/canonical/k8s-bundles//terraform?ref=main"
model = "my-canonical-k8s"
model = {
name = "my-canonical-k8s"
cloud = "prod-example-openstack"
}
cloud_integration = "openstack"
manifest_yaml = "/path/to/manifest.yaml"
}
```

Define your manifest.yaml based on the requirements for your deployment. Specific configuration
options can be found under the charm URLs linked above.
Define your manifest.yaml based on the requirements for your deployment. Specific configuration options can be found under the charm URLs linked above.

```
```yaml
k8s:
units: 2
base: [email protected]
constraints: arch=amd64 cores=2 mem=4096M root-disk=16384M
channel: 1.31/beta
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=4096M root-disk=16384M
channel: 1.32/stable
k8s_worker:
units: 2
base: [email protected]
constraints: arch=amd64 cores=2 mem=8192M root-disk=16384M
channel: 1.31/beta
units: 2
base: [email protected]
constraints: arch=amd64 cores=2 mem=8192M root-disk=16384M
channel: 1.32/stable
```



<!--LINKS -->
[Juju Model Resource]: https://registry.terraform.io/providers/juju/juju/0.16.0/docs/resources/model
[private-details]: https://git.launchpad.net/canonical-terraform-modules/tree/services/compute/canonical_k8s_cluster/main.tf#n214
12 changes: 6 additions & 6 deletions terraform/applications.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# See LICENSE file for licensing details.

module "k8s" {
source = "git::https://github.com/canonical/k8s-operator//charms/worker/k8s/terraform"
source = "git::https://github.com/canonical/k8s-operator//charms/worker/k8s/terraform?ref=main"
app_name = module.k8s_config.config.app_name
channel = module.k8s_config.config.channel
# This currently just sets the bootstrap-node-taints to have the right no schedule value
Expand All @@ -13,30 +13,30 @@ module "k8s" {
{"bootstrap-node-taints": "node-role.kubernetes.io/control-plane:NoSchedule"}
)
constraints = module.k8s_config.config.constraints
model = var.model
model = resource.juju_model.this.name
resources = module.k8s_config.config.resources
revision = module.k8s_config.config.revision
base = module.k8s_config.config.base
units = module.k8s_config.config.units
}

module "k8s_worker" {
source = "git::https://github.com/canonical/k8s-operator//charms/worker/terraform"
source = "git::https://github.com/canonical/k8s-operator//charms/worker/terraform?ref=main"
app_name = module.k8s_worker_config.config.app_name
base = coalesce(module.k8s_worker_config.config.base, module.k8s_config.config.base)
constraints = coalesce(module.k8s_worker_config.config.constraints, module.k8s_config.config.constraints)
channel = coalesce(module.k8s_worker_config.config.channel, module.k8s_config.config.channel)
config = module.k8s_worker_config.config.config
model = var.model
model = resource.juju_model.this.name
resources = module.k8s_worker_config.config.resources
revision = module.k8s_worker_config.config.revision
units = module.k8s_worker_config.config.units
}

module "openstack" {
count = var.cloud_integration == "openstack" ? 1 : 0
count = (var.cloud_integration == "openstack" ) ? 1 : 0
source = "./openstack"
model = var.model
model = resource.juju_model.this.name
manifest_yaml = var.manifest_yaml
k8s = {
app_name = module.k8s.app_name
Expand Down
4 changes: 2 additions & 2 deletions terraform/configs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
# See LICENSE file for licensing details.

module "k8s_config" {
source = "git::https://github.com/canonical/k8s-bundles//terraform/manifest?ref=main"
source = "./manifest/"
manifest = var.manifest_yaml
app = "k8s"
}

module "k8s_worker_config" {
source = "git::https://github.com/canonical/k8s-bundles//terraform/manifest?ref=main"
source = "./manifest/"
manifest = var.manifest_yaml
app = "k8s_worker"
}
41 changes: 38 additions & 3 deletions terraform/integrations.tf
Original file line number Diff line number Diff line change
@@ -1,8 +1,43 @@
# Copyright 2024 Canonical Ltd.
# See LICENSE file for licensing details.

resource "juju_model" "this" {
name = var.model.name

cloud {
name = var.model.cloud
region = var.model.region
}

config = merge(
# Here we drop 2 model-config options the user may naively set
# fan-config
# container-networking-method
{
for k, v in var.model.config != null ? var.model.config : {} :
k => v
if !contains(["fan-config", "container-networking-method"], k)
},
# Then we merge in the required settings
# fan-config - required to be empty for k8s
# container-networking-method - required to be local for k8s
{
fan-config = ""
container-networking-method = "local"
}
)

constraints = var.model.constraints
credential = var.model.credential

provisioner "local-exec" {
# workaround for https://github.com/juju/terraform-provider-juju/issues/667
command = "juju model-config fan-config=''"
}
}

resource "juju_integration" "k8s_cluster_integration" {
model = var.model
model = resource.juju_model.this.name
application {
name = module.k8s.app_name
endpoint = module.k8s.provides.k8s_cluster
Expand All @@ -14,7 +49,7 @@ resource "juju_integration" "k8s_cluster_integration" {
}

resource "juju_integration" "k8s_containerd" {
model = var.model
model = resource.juju_model.this.name
application {
name = module.k8s.app_name
endpoint = module.k8s.provides.containerd
Expand All @@ -26,7 +61,7 @@ resource "juju_integration" "k8s_containerd" {
}

resource "juju_integration" "k8s_cos_worker_tokens" {
model = var.model
model = resource.juju_model.this.name
application {
name = module.k8s.app_name
endpoint = module.k8s.provides.cos_worker_tokens
Expand Down
6 changes: 3 additions & 3 deletions terraform/openstack/configs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
# See LICENSE file for licensing details.

module "openstack_integrator_config" {
source = "git::https://github.com/canonical/k8s-bundles//terraform/manifest?ref=main"
source = "../manifest/"
manifest = var.manifest_yaml
app = "openstack_integrator"
}

module "cinder_csi_config" {
source = "git::https://github.com/canonical/k8s-bundles//terraform/manifest?ref=main"
source = "../manifest/"
manifest = var.manifest_yaml
app = "cinder_csi"
}

module "openstack_cloud_controller_config" {
source = "git::https://github.com/canonical/k8s-bundles//terraform/manifest?ref=main"
source = "../manifest"
manifest = var.manifest_yaml
app = "openstack_cloud_controller"
}
2 changes: 1 addition & 1 deletion terraform/openstack/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ terraform {
required_providers {
juju = {
source = "juju/juju"
version = "~> 0.14.0"
version = ">= 0.14.0, < 1.0.0"
}
}
}
20 changes: 10 additions & 10 deletions terraform/test/openstack.yaml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
k8s:
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=8G root-disk=16G
channel: latest/edge
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=8192M root-disk=16384M
channel: latest/edge
k8s_worker:
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=8G root-disk=16G
channel: latest/edge
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=8192M root-disk=16384M
channel: latest/edge
openstack_integrator:
channel: 1.31/stable
base: [email protected]
channel: 1.31/stable
base: [email protected]
cinder_csi: {}
openstack_cloud_controller: {}
16 changes: 8 additions & 8 deletions terraform/test/vanilla.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
k8s:
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=8G root-disk=16G
channel: latest/edge
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=8192M root-disk=16384M
channel: latest/edge
k8s_worker:
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=8G root-disk=16G
channel: latest/edge
units: 3
base: [email protected]
constraints: arch=amd64 cores=2 mem=8192M root-disk=16384M
channel: latest/edge
45 changes: 37 additions & 8 deletions terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,48 @@ variable "manifest_yaml" {
type = string
}

variable "model" {
description = "Name of the Juju model to deploy to."
type = string
}

variable "cloud_integration" {
description = "Selection of a cloud integration"
description = "Selection of a cloud integration."
type = string
default = ""

validation {
condition = contains(["", "openstack"], var.cloud_integration)
error_message = "Cloud must be one of '', or 'openstack'"
condition = can(regex("^(|openstack)$", var.cloud_integration))
error_message = "Cloud integration must be one of: '', openstack."
}
}

variable "model" {
description = <<EOT
Juju Model resource definition.

Schema represented by the juju model resource:
- name: Name of the model
- cloud: Cloud name
- region: Region name (optional)
- config: Configuration map (optional)
- constraints: Constraints string (optional)
- credential: Credential name (optional)

https://registry.terraform.io/providers/juju/juju/0.16.0/docs/resources/model
EOT

type = object({
name = string
cloud = string
region = optional(string)
config = optional(map(any))
constraints = optional(string)
credential = optional(string)
})

validation {
condition = (
var.model.config == null || alltrue([
for k, v in var.model.config:
v == null || can(tostring(v)) || can(tonumber(v)) || can(tobool(v))
])
)
error_message = "Config must be a map where values are only strings, numbers, or bools."
}
}
2 changes: 1 addition & 1 deletion terraform/versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ terraform {
required_providers {
juju = {
source = "juju/juju"
version = "~> 0.14.0"
version = ">= 0.14.0, < 1.0.0"
}
}
}
Loading