From 99ecc0b2b2a5749576580cee5658a3858c492fe1 Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sun, 22 Oct 2023 16:03:11 +0200 Subject: [PATCH 01/12] Add devcontainer configuration Dev container is well integrated to VS Code and Github, so it's interesting to configure it to make it more developper-friendly. Signed-off-by: Alexandre Nicolaie --- .devcontainer/devcontainer.json | 26 ++++++++++++++++++++++++++ .tool-versions | 4 ++++ 2 files changed, 30 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 .tool-versions diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..4dc977a --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +{ + "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json", + "name": "k3s Terraform module - Dev Container", + "image": "mcr.microsoft.com/vscode/devcontainers/universal", + + "features": { + "ghcr.io/devcontainers-contrib/features/yamllint:2.0.9": {}, + "ghcr.io/devcontainers/features/terraform:1.3.5": { "version": "1.6.2" }, + "ghcr.io/dhoeric/features/terraform-docs:1.0.0": { "version": "0.16.0" }, + "ghcr.io/itsmechlark/features/act:1.0.0": {}, + "ghcr.io/itsmechlark/features/trivy:1.0.0": {} + }, + + "customizations": { + "vscode": { + "extensions": [ + "bierner.github-markdown-preview", + "github.copilot", + "ms-vscode.makefile-tools", + "redhat.vscode-yaml", + "tylerharris.terraform-link-docs", + "yzhang.markdown-all-in-one" + ] + } + } +} diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..f39eeda --- /dev/null +++ b/.tool-versions @@ -0,0 +1,4 @@ +act 0.2.52 +terraform 1.6.2 +terraform-docs 0.16.0 +trivy 0.46.0 From 43b4aff7966c53a3f58b1837081aa925b5bfde5d Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sun, 22 Oct 2023 18:25:18 +0200 Subject: [PATCH 02/12] Make all examples consistent Signed-off-by: Alexandre Nicolaie --- examples/civo-k3s/README.md | 14 ++++++ examples/civo-k3s/k3s.tf | 33 ++++++++++++ examples/civo-k3s/main.tf | 67 +++---------------------- examples/civo-k3s/outputs.tf | 8 +++ examples/civo-k3s/versions.tf | 9 ++++ examples/hcloud-k3s/README.md | 30 ++++------- examples/hcloud-k3s/agent_instances.tf | 22 -------- examples/hcloud-k3s/main.tf | 46 +++++++++++++++++ examples/hcloud-k3s/outputs.tf | 7 ++- examples/hcloud-k3s/server_instances.tf | 21 -------- examples/hcloud-k3s/versions.tf | 1 + 11 files changed, 132 insertions(+), 126 deletions(-) create mode 100644 examples/civo-k3s/README.md create mode 100644 examples/civo-k3s/k3s.tf create mode 100644 examples/civo-k3s/outputs.tf create mode 100644 examples/civo-k3s/versions.tf delete mode 100644 examples/hcloud-k3s/agent_instances.tf delete mode 100644 examples/hcloud-k3s/server_instances.tf diff --git a/examples/civo-k3s/README.md b/examples/civo-k3s/README.md new file mode 100644 index 0000000..e68a4d5 --- /dev/null +++ b/examples/civo-k3s/README.md @@ -0,0 +1,14 @@ +# K3S example for Civo + +Configuration in this directory creates a k3s cluster resources instances. + +## Usage + +> [!warning] +> **Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.** + +```bash +$ export CIVO_TOKEN=... +$ terraform init +$ terraform apply +``` diff --git a/examples/civo-k3s/k3s.tf b/examples/civo-k3s/k3s.tf new file mode 100644 index 0000000..4df3e7a --- /dev/null +++ b/examples/civo-k3s/k3s.tf @@ -0,0 +1,33 @@ +module "k3s" { + source = "./../.." + + depends_on_ = civo_instance.node_instances + k3s_version = "latest" + cluster_domain = "civo_k3s" + + drain_timeout = "60s" + managed_fields = ["label"] + generate_ca_certificates = true + + global_flags = [for instance in civo_instance.node_instances : "--tls-san ${instance.public_ip}"] + + servers = { + # The node name will be automatically provided by + # the module using the field name... any usage of + # --node-name in additional_flags will be ignored + + for instance in civo_instance.node_instances : + instance.hostname => { + ip = instance.private_ip + connection = { + timeout = "60s" + type = "ssh" + host = instance.public_ip + password = instance.initial_password + user = "root" + } + + labels = { "node.kubernetes.io/type" = "master" } + } + } +} diff --git a/examples/civo-k3s/main.tf b/examples/civo-k3s/main.tf index 35dcfca..9365818 100644 --- a/examples/civo-k3s/main.tf +++ b/examples/civo-k3s/main.tf @@ -1,27 +1,10 @@ -terraform { - required_providers { - civo = { - source = "civo/civo" - version = "~>0.10.10" - } - } -} - -provider "civo" { - token = var.civo_token -} - -variable "civo_token" { - type = string - description = "Civo api token" -} - -data "civo_template" "ubuntu" { +data "civo_disk_image" "ubuntu" { filter { key = "name" values = ["ubuntu"] match_by = "re" } + sort { key = "version" direction = "desc" @@ -36,46 +19,8 @@ data "civo_instances_size" "node_size" { } resource "civo_instance" "node_instances" { - count = 3 - hostname = "node-${count.index + 1}" - size = element(data.civo_instances_size.node_size.sizes, 0).name - template = element(data.civo_template.ubuntu.templates, 0).id -} - -module "k3s" { - source = "./../.." - k3s_version = "v1.21.4+k3s1" - - cluster_domain = "civo_k3s" - - drain_timeout = "60s" - managed_fields = ["label"] - generate_ca_certificates = true - - global_flags = [for instance in civo_instance.node_instances : "--tls-san ${instance.public_ip}"] - - servers = { - # The node name will be automatically provided by - # the module using the field name... any usage of - # --node-name in additional_flags will be ignored - - for instance in civo_instance.node_instances : - instance.hostname => { - ip = instance.private_ip - connection = { - timeout = "60s" - type = "ssh" - host = instance.public_ip - password = instance.initial_password - user = "root" - } - - labels = { "node.kubernetes.io/type" = "master" } - } - } -} - -output "kube_config" { - value = module.k3s.kube_config - sensitive = true + count = 3 + hostname = "node-${count.index + 1}" + size = data.civo_instances_size.node_size.sizes[0].name + disk_image = data.civo_disk_image.ubuntu[count.index].id } diff --git a/examples/civo-k3s/outputs.tf b/examples/civo-k3s/outputs.tf new file mode 100644 index 0000000..32809be --- /dev/null +++ b/examples/civo-k3s/outputs.tf @@ -0,0 +1,8 @@ +output "summary" { + value = module.k3s.summary +} + +output "kubeconfig" { + value = module.k3s.kube_config + sensitive = true +} diff --git a/examples/civo-k3s/versions.tf b/examples/civo-k3s/versions.tf new file mode 100644 index 0000000..825613b --- /dev/null +++ b/examples/civo-k3s/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + civo = { + source = "civo/civo" + version = "~>0.10.10" + } + } + required_version = "~> 1.0" +} diff --git a/examples/hcloud-k3s/README.md b/examples/hcloud-k3s/README.md index 97347d7..0e60c6f 100644 --- a/examples/hcloud-k3s/README.md +++ b/examples/hcloud-k3s/README.md @@ -2,32 +2,20 @@ Configuration in this directory creates a k3s cluster resources including network, subnet and instances. -## Preparations - -Make sure your [SSH-Agent](https://docs.github.com/en/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent#adding-your-ssh-key-to-the-ssh-agent) is running (it is neccessary for Terraform), and if not, start it and add your ssh-key: - -```bash -# example, with active ssh-agent -$ ssh-add -L -> ssh-rsa AAAAB4NzaC4Xc2FA2A...Me3IABDICy+WANsg5Mc= /home/user/.ssh/id_rsa -> ssh-rsa AAAAB4NzaC4Xc2FA2A...VpJaZ5EawNpQaPvqEw== /home/user/.ssh/another_user_key -# if nothing is loaded -# start the ssh-agent in the background -$ eval `ssh-agent -s` -> Agent pid 59566 -# add your SSH private key to the ssh-agent -$ ssh-add ~./ssh/path-to-sshkey -> Identity added: ~./ssh/path-to-sshkey (~./ssh/path-to-sshkey) -``` - ## Usage -After checking/enabling ssh-agent, to run this example you need to execute: +> [!warning] +> **Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.** ```bash +$ export HCLOUD_TOKEN=... $ terraform init -$ terraform plan $ terraform apply ``` -Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources. +## How to connect to a node ? + +```bash +terraform output -raw ssh_private_key | ssh-add - +ssh root@NODE-IP +``` diff --git a/examples/hcloud-k3s/agent_instances.tf b/examples/hcloud-k3s/agent_instances.tf deleted file mode 100644 index 87fb4ff..0000000 --- a/examples/hcloud-k3s/agent_instances.tf +++ /dev/null @@ -1,22 +0,0 @@ -resource "hcloud_server" "agents" { - count = var.agents_num - name = "k3s-agent-${count.index}" - - image = data.hcloud_image.ubuntu.name - server_type = "cx11" - - ssh_keys = [hcloud_ssh_key.default.id] - labels = { - provisioner = "terraform", - engine = "k3s", - node_type = "agent", - nodepool = count.index % 3 == 0 ? "gpu" : "general", - } -} - -resource "hcloud_server_network" "agents_network" { - count = length(hcloud_server.agents) - server_id = hcloud_server.agents[count.index].id - subnet_id = hcloud_network_subnet.k3s_nodes.id - ip = cidrhost(hcloud_network_subnet.k3s_nodes.ip_range, 1 + var.servers_num + count.index) -} diff --git a/examples/hcloud-k3s/main.tf b/examples/hcloud-k3s/main.tf index 424e783..5362e90 100644 --- a/examples/hcloud-k3s/main.tf +++ b/examples/hcloud-k3s/main.tf @@ -22,3 +22,49 @@ resource "hcloud_network_subnet" "k3s_nodes" { network_zone = "eu-central" ip_range = "10.254.1.0/24" } + +resource "hcloud_server_network" "control_planes" { + count = var.servers_num + subnet_id = hcloud_network_subnet.k3s_nodes.id + server_id = hcloud_server.control_planes[count.index].id + ip = cidrhost(hcloud_network_subnet.k3s_nodes.ip_range, 1 + count.index) +} + +resource "hcloud_server_network" "agents_network" { + count = length(hcloud_server.agents) + server_id = hcloud_server.agents[count.index].id + subnet_id = hcloud_network_subnet.k3s_nodes.id + ip = cidrhost(hcloud_network_subnet.k3s_nodes.ip_range, 1 + var.servers_num + count.index) +} + +resource "hcloud_server" "control_planes" { + count = var.servers_num + name = "k3s-control-plane-${count.index}" + + image = data.hcloud_image.ubuntu.name + server_type = "cx11" + + ssh_keys = [hcloud_ssh_key.default.id] + labels = { + provisioner = "terraform", + engine = "k3s", + node_type = "control-plane" + } +} + + +resource "hcloud_server" "agents" { + count = var.agents_num + name = "k3s-agent-${count.index}" + + image = data.hcloud_image.ubuntu.name + server_type = "cx11" + + ssh_keys = [hcloud_ssh_key.default.id] + labels = { + provisioner = "terraform", + engine = "k3s", + node_type = "agent", + nodepool = count.index % 3 == 0 ? "gpu" : "general", + } +} \ No newline at end of file diff --git a/examples/hcloud-k3s/outputs.tf b/examples/hcloud-k3s/outputs.tf index 28650fd..24710df 100644 --- a/examples/hcloud-k3s/outputs.tf +++ b/examples/hcloud-k3s/outputs.tf @@ -2,8 +2,13 @@ output "summary" { value = module.k3s.summary } +output "kubeconfig" { + value = module.k3s.kube_config + sensitive = true +} + output "ssh_private_key" { description = "Generated SSH private key." value = tls_private_key.ed25519-provisioning.private_key_openssh sensitive = true -} \ No newline at end of file +} diff --git a/examples/hcloud-k3s/server_instances.tf b/examples/hcloud-k3s/server_instances.tf deleted file mode 100644 index 0724b8a..0000000 --- a/examples/hcloud-k3s/server_instances.tf +++ /dev/null @@ -1,21 +0,0 @@ -resource "hcloud_server" "control_planes" { - count = var.servers_num - name = "k3s-control-plane-${count.index}" - - image = data.hcloud_image.ubuntu.name - server_type = "cx11" - - ssh_keys = [hcloud_ssh_key.default.id] - labels = { - provisioner = "terraform", - engine = "k3s", - node_type = "control-plane" - } -} - -resource "hcloud_server_network" "control_planes" { - count = var.servers_num - subnet_id = hcloud_network_subnet.k3s_nodes.id - server_id = hcloud_server.control_planes[count.index].id - ip = cidrhost(hcloud_network_subnet.k3s_nodes.ip_range, 1 + count.index) -} diff --git a/examples/hcloud-k3s/versions.tf b/examples/hcloud-k3s/versions.tf index 1342cf8..08c7f36 100644 --- a/examples/hcloud-k3s/versions.tf +++ b/examples/hcloud-k3s/versions.tf @@ -2,6 +2,7 @@ terraform { required_providers { hcloud = { source = "hetznercloud/hcloud" + version = "1.44.1" } } required_version = "~> 1.0" From 674be21d9f2898e330e4eefc154be2696193077c Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Tue, 24 Oct 2023 21:28:02 +0200 Subject: [PATCH 03/12] Rewrite some part of the README - Move the security disclosure at the begin of the README - Add "real" example based on working examples fixes #136 Signed-off-by: Alexandre Nicolaie --- .terraform-docs.yaml | 26 +++++++ .terraform-docs.yml | 13 ---- README.md | 161 +++++++++++++++---------------------------- 3 files changed, 82 insertions(+), 118 deletions(-) create mode 100644 .terraform-docs.yaml delete mode 100644 .terraform-docs.yml diff --git a/.terraform-docs.yaml b/.terraform-docs.yaml new file mode 100644 index 0000000..7e7211f --- /dev/null +++ b/.terraform-docs.yaml @@ -0,0 +1,26 @@ +formatter: "markdown table" + +content: |- + ## Example _(based on [Hetzner Cloud example](examples/hcloud-k3s))_ + + ```hcl + {{ include "examples/hcloud-k3s/k3s.tf" | replace "./../.." "xunleii/k3s/module" }} + ``` + + {{ .Inputs | replace "\"|\"" "\"\\|\"" }} + + {{ .Outputs }} + + {{ .Providers }} + +output: + file: README.md + mode: inject + template: |- + + {{ .Content }} + + +sort: + enabled: true + by: required diff --git a/.terraform-docs.yml b/.terraform-docs.yml deleted file mode 100644 index 058f8de..0000000 --- a/.terraform-docs.yml +++ /dev/null @@ -1,13 +0,0 @@ -formatter: markdown table -output: - file: README.md - mode: inject -sections: - show: - - inputs - - outputs - - providers - - requirements -sort: - enabled: true - by: required diff --git a/README.md b/README.md index 29f6c0d..ff3fc7b 100644 --- a/README.md +++ b/README.md @@ -5,116 +5,67 @@ [![Open Source Helpers](https://www.codetriage.com/xunleii/terraform-module-k3s/badges/users.svg)](https://www.codetriage.com/xunleii/terraform-module-k3s) [![MIT Licensed](https://img.shields.io/badge/license-MIT-green.svg)](https://tldrlegal.com/license/mit-license) -Terraform module which creates a [k3s](https://k3s.io/) cluster, with multi-server -and annotations/labels/taints management features. +Terraform module to create a [k3s](https://k3s.io/) cluster with multi-server and annotations/labels/taints management features. -## Usage -``` hcl + +## :warning: Security disclosure + +Because the use of external references on the `destroy` provisioner is deprecated by Terraform, storing information inside each resource is mandatory in order to manage several functionalities such as automatic node draining and field management. As a result, several fields such as the `connection` block will be available in your TF state. +This means that the password or private key used will be **clearly readable** in this TF state. +**Please be very careful to store your TF state securely if you use a private key or password in the `connection` block.** + + +## Example _(based on [Hetzner Cloud example](examples/hcloud-k3s))_ + +```hcl module "k3s" { - source = "xunleii/k3s/module" - k3s_version = "v1.0.0" - name = "my.k3s.local" + source = "xunleii/k3s/module" + + depends_on_ = hcloud_server.agents + k3s_version = "latest" + cluster_domain = "cluster.local" cidr = { - pods = "10.0.0.0/16" - services = "10.1.0.0/16" + pods = "10.42.0.0/16" + services = "10.43.0.0/16" } - drain_timeout = "30s" - managed_fields = ["label", "taint"] + drain_timeout = "30s" + managed_fields = ["label", "taint"] // ignore annotations + global_flags = [ - "--tls-san k3s.my.domain.com" + "--flannel-iface ens10", + "--kubelet-arg cloud-provider=external" // required to use https://github.com/hetznercloud/hcloud-cloud-controller-manager ] + servers = { - # The node name will be automatically provided by - # the module using the field name... any usage of - # --node-name in additional_flags will be ignored - server-one = { - ip = "10.123.45.67" // internal node IP - connection = { - host = "203.123.45.67" // public node IP - user = "ubuntu" - } - flags = ["--flannel-backend=none"] - labels = {"node.kubernetes.io/type" = "master"} - taints = {"node.k3s.io/type" = "server:NoSchedule"} - } - server-two = { - ip = "10.123.45.68" + for i in range(length(hcloud_server.control_planes)) : + hcloud_server.control_planes[i].name => { + ip = hcloud_server_network.control_planes[i].ip connection = { - host = "203.123.45.68" // bastion node - user = "ubuntu" + host = hcloud_server.control_planes[i].ipv4_address + private_key = trimspace(tls_private_key.ed25519-provisioning.private_key_pem) } - flags = ["--flannel-backend=none"] - labels = {"node.kubernetes.io/type" = "master"} - taints = {"node.k3s.io/type" = "server:NoSchedule"} + flags = ["--disable-cloud-controller"] + annotations = { "server_id" : i } // theses annotations will not be managed by this module } - server-three = { - ip = "10.123.45.69" + } + + agents = { + for i in range(length(hcloud_server.agents)) : + "${hcloud_server.agents[i].name}_node" => { + name = hcloud_server.agents[i].name + ip = hcloud_server_network.agents_network[i].ip connection = { - host = "203.123.45.69" // bastion node - user = "ubuntu" + host = hcloud_server.agents[i].ipv4_address + private_key = trimspace(tls_private_key.ed25519-provisioning.private_key_pem) } - flags = ["--flannel-backend=none"] - labels = {"node.kubernetes.io/type" = "master"} - taints = {"node.k3s.io/type" = "server:NoSchedule"} + + labels = { "node.kubernetes.io/pool" = hcloud_server.agents[i].labels.nodepool } + taints = { "dedicated" : hcloud_server.agents[i].labels.nodepool == "gpu" ? "gpu:NoSchedule" : null } } } - agents = { - # The node name will be automatically provided by - # the module using the field name... any usage of - # --node-name in additional_flags will be ignored - agent-one = { - ip = "10.123.45.70" - connection = { - user = "root" - bastion_host = "203.123.45.67" // server_one node used as bastion - bastion_user = "ubuntu" - } - labels = {"node.kubernetes.io/pool" = "service-pool"} - }, - agent-two = { - ip = "10.123.45.71" - connection = { - user = "root" - bastion_host = "203.123.45.67" - bastion_user = "ubuntu" - } - labels = {"node.kubernetes.io/pool" = "service-pool"} - }, - agent-three = { - name = "gpu-agent-one" - ip = "10.123.45.72" - connection = { - user = "root" - bastion_host = "203.123.45.67" - bastion_user = "ubuntu" - } - labels = {"node.kubernetes.io/pool" = "gpu-pool"} - taints = {dedicated = "gpu:NoSchedule"} - }, - } } ``` - -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | ~> 1.0 | -| [http](#requirement\_http) | ~> 3.0 | -| [null](#requirement\_null) | ~> 3.0 | -| [random](#requirement\_random) | ~> 3.0 | -| [tls](#requirement\_tls) | ~> 4.0 | - -## Providers - -| Name | Version | -|------|---------| -| [http](#provider\_http) | 3.3.0 | -| [null](#provider\_null) | 3.2.1 | -| [random](#provider\_random) | 3.5.1 | -| [tls](#provider\_tls) | 4.0.4 | - ## Inputs | Name | Description | Type | Default | Required | @@ -127,12 +78,12 @@ module "k3s" { | [drain\_timeout](#input\_drain\_timeout) | The length of time to wait before giving up the node draining. Infinite by default. | `string` | `"0s"` | no | | [generate\_ca\_certificates](#input\_generate\_ca\_certificates) | If true, this module will generate the CA certificates (see https://github.com/rancher/k3s/issues/1868#issuecomment-639690634). Otherwise rancher will generate it. This is required to generate kubeconfig | `bool` | `true` | no | | [global\_flags](#input\_global\_flags) | Add additional installation flags, used by all nodes (see https://rancher.com/docs/k3s/latest/en/installation/install-options/). | `list(string)` | `[]` | no | -| [k3s\_install\_env\_vars](#input\_k3s\_install\_env\_vars) | map of enviroment variables that are passed to the k3s installation script (see https://docs.k3s.io/reference/env-variables) | `map(string)` | `null` | no | +| [k3s\_install\_env\_vars](#input\_k3s\_install\_env\_vars) | map of enviroment variables that are passed to the k3s installation script (see https://docs.k3s.io/reference/env-variables) | `map(string)` | `{}` | no | | [k3s\_version](#input\_k3s\_version) | Specify the k3s version. You can choose from the following release channels or pin the version directly | `string` | `"latest"` | no | | [kubernetes\_certificates](#input\_kubernetes\_certificates) | A list of maps of cerificate-name.[crt/key] : cerficate-value to copied to /var/lib/rancher/k3s/server/tls, if this option is used generate\_ca\_certificates will be treat as false |
list(
object({
file_name = string,
file_content = string
})
)
| `[]` | no | | [managed\_fields](#input\_managed\_fields) | List of fields which must be managed by this module (can be annotation, label and/or taint). | `list(string)` |
[
"annotation",
"label",
"taint"
]
| no | | [name](#input\_name) | K3s cluster domain name (see https://rancher.com/docs/k3s/latest/en/installation/install-options/). This input is deprecated and will be remove in the next major release. Use `cluster_domain` instead. | `string` | `"!!!DEPRECATED!!!"` | no | -| [separator](#input\_separator) | Separator used to separates node name and field name (used to manage annotations, labels and taints). | `string` | `"|"` | no | +| [separator](#input\_separator) | Separator used to separates node name and field name (used to manage annotations, labels and taints). | `string` | `"\|"` | no | | [use\_sudo](#input\_use\_sudo) | Whether or not to use kubectl with sudo during cluster setup. | `bool` | `false` | no | ## Outputs @@ -144,19 +95,19 @@ module "k3s" { | [kubernetes\_cluster\_secret](#output\_kubernetes\_cluster\_secret) | Secret token used to join nodes to the cluster | | [kubernetes\_ready](#output\_kubernetes\_ready) | Dependency endpoint to synchronize k3s installation and provisioning. | | [summary](#output\_summary) | Current state of k3s (version & nodes). | - -## Security warning -Because using external references on `destroy` provisionner is deprecated by Terraform, storing information -inside each resources will be mandatory in order to manage several features like auto-draining node -and fields management. So, several fields like `connection` block will be available in your TF state. -This means that used password or private key will be **clearly readable** in this TF state. -**Please do not use -this module if you need to pass private key or password in the connection block, even if your TF state is -securely stored**. +## Providers + +| Name | Version | +|------|---------| +| [http](#provider\_http) | 3.4.0 | +| [null](#provider\_null) | 3.2.1 | +| [random](#provider\_random) | 3.5.1 | +| [tls](#provider\_tls) | 4.0.4 | + ## License -terraform-module-k3s is released under the **MIT License**. See the bundled [LICENSE](LICENSE) file for details. +`terraform-module-k3s` is released under the **MIT License**. See the bundled [LICENSE](LICENSE) file for details. # *Generated with :heart: by [terraform-docs](https://github.com/terraform-docs/terraform-docs)* From 306993bc111a6e80f3684a964b3ff4b390bdfe8e Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sun, 29 Oct 2023 17:35:01 +0100 Subject: [PATCH 04/12] Refresh Github Actions workflows - Add stale bot - Prefix all "bot" worflows - Migrate all external workflows locally - Add security check with Trivy Signed-off-by: Alexandre Nicolaie --- .github/labels.yaml | 7 + .github/workflows/github.documentation.yaml | 7 +- .github/workflows/github.labeler.yaml | 7 +- .github/workflows/github.stale.yaml | 25 +++ .github/workflows/security.terraform.yaml | 16 ++ .github/workflows/security.workflows.yaml | 17 +- .../terraform.pull_requests.lint.yaml | 121 +++++++++++++ .../terraform.pull_requests.plan.yaml | 163 ++++++++++++++++++ .github/workflows/terraform.lint.yaml | 6 +- .github/workflows/terraform.plan.yaml | 2 +- 10 files changed, 360 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/github.stale.yaml create mode 100644 .github/workflows/security.terraform.yaml create mode 100644 .github/workflows/templates/terraform.pull_requests.lint.yaml create mode 100644 .github/workflows/templates/terraform.pull_requests.plan.yaml diff --git a/.github/labels.yaml b/.github/labels.yaml index 827b247..b0624ea 100644 --- a/.github/labels.yaml +++ b/.github/labels.yaml @@ -25,6 +25,13 @@ - name: size/XL color: FF0000 +- name: status/stale + description: This issue has not had recent activity + color: 6A5ACD +- name: no-stale + description: This issue cannot be marked as stale + color: 6A5ACD + - name: terraform:plan description: Invoke Terraform plan workflow on the current PR color: 7A55CC diff --git a/.github/workflows/github.documentation.yaml b/.github/workflows/github.documentation.yaml index ed67fef..b95a7ef 100644 --- a/.github/workflows/github.documentation.yaml +++ b/.github/workflows/github.documentation.yaml @@ -1,4 +1,5 @@ -name: Update documentation assets (master only) +--- +name: '[bot] Update documentation assets (master only)' on: push: branches: [master] @@ -11,7 +12,7 @@ jobs: contents: write steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - uses: heinrichreimer/github-changelog-generator-action@6f5b9494dd265d6fb7243a10c53dc0169c55f247 # renovate: tag=v2.3 + - uses: heinrichreimer/github-changelog-generator-action@6f5b9494dd265d6fb7243a10c53dc0169c55f247 # v2.3 with: token: ${{ secrets.GITHUB_TOKEN }} # NOTE: seems impossible to use terraform-docs/gh-actions with EndBug/add-and-commit... so @@ -19,7 +20,7 @@ jobs: - name: Generate README.md with terraform-docs run: | mkdir .terraform-docs - curl -L https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-$(uname)-amd64.tar.gz | tar -xvzC .terraform-docs + curl -L "https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-$(uname)-amd64.tar.gz" | tar -xvzC .terraform-docs chmod +x .terraform-docs/terraform-docs .terraform-docs/terraform-docs . diff --git a/.github/workflows/github.labeler.yaml b/.github/workflows/github.labeler.yaml index 808e048..e0426ef 100644 --- a/.github/workflows/github.labeler.yaml +++ b/.github/workflows/github.labeler.yaml @@ -1,8 +1,11 @@ -name: Synchronize labels +--- +name: '[bot] Synchronize labels' on: push: branches: [master] paths: [.github/workflows/github.labeler.yaml, .github/labels.yaml] + schedule: + - cron: '0 0 * * *' jobs: sync: @@ -10,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - uses: micnncim/action-label-syncer@3abd5ab72fda571e69fffd97bd4e0033dd5f495c # renovate: tag=v1.3.0 + - uses: micnncim/action-label-syncer@3abd5ab72fda571e69fffd97bd4e0033dd5f495c # v1.3.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/github.stale.yaml b/.github/workflows/github.stale.yaml new file mode 100644 index 0000000..6071a44 --- /dev/null +++ b/.github/workflows/github.stale.yaml @@ -0,0 +1,25 @@ +--- +name: '[bot] Close stale issues and PRs' +on: + schedule: + - cron: '0 0 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + permissions: + contents: write + issues: write + pull-requests: write + steps: + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 + with: + days-before-close: 7 + days-before-stale: 30 + exempt-issue-labels: no-stale + exempt-pr-labels: no-stale + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-label: status/stale + stale-issue-message: 'This issue has been automatically marked as stale because it has not had recent activity. If the issue still persists, please leave a comment and it will be reopened.' + stale-pr-label: status/stale + stale-pr-message: 'This pull request has been automatically marked as stale because it has not had recent activity. If the pull request still needs attention, please leave a comment and it will be reopened.' diff --git a/.github/workflows/security.terraform.yaml b/.github/workflows/security.terraform.yaml new file mode 100644 index 0000000..259d8d9 --- /dev/null +++ b/.github/workflows/security.terraform.yaml @@ -0,0 +1,16 @@ +name: Security hardening (Terraform) + +on: + pull_request: + +jobs: + trivy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - uses: aquasecurity/trivy-action@b77b85c0254bba6789e787844f0585cde1e56320 # v0.13.0 + with: + scan-type: config + scan-ref: . + exit-code: 1 + severity: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL diff --git a/.github/workflows/security.workflows.yaml b/.github/workflows/security.workflows.yaml index f8da3ae..22f7ec8 100644 --- a/.github/workflows/security.workflows.yaml +++ b/.github/workflows/security.workflows.yaml @@ -7,7 +7,20 @@ on: jobs: ci_harden_security: - name: Security hardening + name: Github Action security hardening + runs-on: ubuntu-latest permissions: security-events: write - uses: xunleii/github-actions-grimoire/.github/workflows/security.workflows.yaml@0ab2cd93e86642397ecdfb2da1e5b97594ab9905 + steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Lint your Github Actions + run: | + curl -O https://raw.githubusercontent.com/rhysd/actionlint/main/.github/actionlint-matcher.json + + echo "::add-matcher::actionlint-matcher.json" + bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) + ./actionlint -color + + - name: Ensure SHA pinned actions + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@6ca5574367befbc9efdb2fa25978084159c5902d # v1.3.0 diff --git a/.github/workflows/templates/terraform.pull_requests.lint.yaml b/.github/workflows/templates/terraform.pull_requests.lint.yaml new file mode 100644 index 0000000..da3cd2d --- /dev/null +++ b/.github/workflows/templates/terraform.pull_requests.lint.yaml @@ -0,0 +1,121 @@ +name: IaaS - Terraform CI (for pull requests) - Lint + +on: + workflow_call: + inputs: + terraform_workdir: + description: Working directory where Terraform files are + required: false + default: "." + type: string + terraform_version: + description: Terraform version that should we use (latest by default) + required: false + type: string + +jobs: + # Terraform validate checks if your TF files are in a canonical format and without HCL issues + terraform_validate: + name: Terraform files validation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0 + - uses: hashicorp/setup-terraform@bbe167fbdaa1a3bd046bdd70eba9dd3dddcca99c # tag=v2.0.2 + with: + terraform_version: ${{ inputs.terraform_version }} + - name: Pre-hook Terraform workflow + id: pre + run: | + # Setup `workdir` suffix used to give more information during execution + if [[ '${{ inputs.terraform_workdir }}' == '.' ]]; then + echo "workdir=" >> "${GITHUB_OUTPUT}" + else + echo "workdir=(${{ inputs.terraform_workdir }})" >> "${GITHUB_OUTPUT}" + fi + + # --- `terraform fmt` + - name: Check if all Terraform configuration files are in a canonical format ${{ steps.pre.outputs.workdir }} + id: fmt + run: terraform fmt -check -recursive -diff -no-color + working-directory: ${{ inputs.terraform_workdir }} + - uses: marocchino/sticky-pull-request-comment@97bddef64db61b9d80edc69593cc4e4c415c3362 # tag=v2.2.1 + if: failure() && steps.fmt.outcome == 'failure' + with: + recreate: true + header: tf::${{ steps.pre.outputs.workdir }} + message: | + # Terraform CI/CD ${{ steps.pre.outputs.workdir }} + + - [ ] :paintbrush: Check if all Terraform configuration files are in a canonical format + + ### 🚫 Failure reason + ```terraform + ${{ steps.fmt.outputs.stdout }} + ``` +
+ + > _Report based on commit ${{ github.sha }} (authored by **@${{ github.actor }}**). See [`actions#${{ github.run_id }}`](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details._ + + # --- `terraform init` + - name: Initialize Terraform working directory ${{ steps.pre.outputs.workdir }} + id: init + env: + TF_IN_AUTOMATION: yes + run: terraform init -no-color -backend=false + working-directory: ${{ inputs.terraform_workdir }} + - uses: marocchino/sticky-pull-request-comment@97bddef64db61b9d80edc69593cc4e4c415c3362 # tag=v2.2.1 + if: failure() && steps.init.outcome == 'failure' + with: + recreate: true + header: tf::${{ steps.pre.outputs.workdir }} + message: | + # Terraform CI/CD ${{ steps.pre.outputs.workdir }} + + - [x] :paintbrush: Check if all Terraform configuration files are in a canonical format + - [ ] :hammer_and_wrench: Validate the configuration files + + ### 🚫 Failure reason + ``` + ${{ steps.init.outputs.stderr }} + ``` +
+ + > _Report based on commit ${{ github.sha }} (authored by **@${{ github.actor }}**). See [`actions#${{ github.run_id }}`](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details._ + + # --- `terraform validate` + - name: Validate the configuration files ${{ steps.pre.outputs.workdir }} + id: validate + env: + TF_IN_AUTOMATION: yes + run: terraform validate -no-color + working-directory: ${{ inputs.terraform_workdir }} + - uses: marocchino/sticky-pull-request-comment@97bddef64db61b9d80edc69593cc4e4c415c3362 # tag=v2.2.1 + if: failure() && steps.validate.outcome == 'failure' + with: + recreate: true + header: tf::${{ steps.pre.outputs.workdir }} + message: | + # Terraform CI/CD ${{ steps.pre.outputs.workdir }} + + - [x] :paintbrush: Check if all Terraform configuration files are in a canonical format + - [ ] :hammer_and_wrench: Validate the configuration files + + ### 🚫 Failure reason + ``` + ${{ steps.validate.outputs.stderr }} + ``` +
+ + > _Report based on commit ${{ github.sha }} (authored by **@${{ github.actor }}**). See [`actions#${{ github.run_id }}`](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details._ + - uses: marocchino/sticky-pull-request-comment@97bddef64db61b9d80edc69593cc4e4c415c3362 # tag=v2.2.1 + if: success() + with: + recreate: true + header: tf::${{ steps.pre.outputs.workdir }} + message: | + # Terraform CI/CD ${{ steps.pre.outputs.workdir }} + + - [x] :paintbrush: Check if all Terraform configuration files are in a canonical format + - [x] :hammer_and_wrench: Validate the configuration files + + > _Report based on commit ${{ github.sha }} (authored by **@${{ github.actor }}**). See [`actions#${{ github.run_id }}`](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details._ \ No newline at end of file diff --git a/.github/workflows/templates/terraform.pull_requests.plan.yaml b/.github/workflows/templates/terraform.pull_requests.plan.yaml new file mode 100644 index 0000000..a461c2a --- /dev/null +++ b/.github/workflows/templates/terraform.pull_requests.plan.yaml @@ -0,0 +1,163 @@ +name: IaaS - Terraform CI (for pull requests) - Plan + +on: + workflow_call: + inputs: + after_lint: + default: true + description: Is this workflow run after lint? + required: false + type: boolean + + env: + description: List of environment variables to set (YAML formatted) + required: false + type: string + + terraform_vars: + description: Terraform variables (YAML formatted) + required: false + type: string + + terraform_version: + description: Terraform version that should we use (latest by default) + required: false + type: string + terraform_workdir: + description: Working directory where Terraform files are + required: false + default: "." + type: string + + secrets: + env: + description: List of sensitive environment variables to set (YAML formatted) + required: false + + terraform_vars: + description: Sensitive Terraform variables (YAML formatted) + required: false + +jobs: + # Terraform plan generated the speculative execution plan + terraform_plan: + name: Generate a speculative execution plan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag=v3.1.0 + - uses: hashicorp/setup-terraform@bbe167fbdaa1a3bd046bdd70eba9dd3dddcca99c # tag=v2.0.2 + with: + terraform_version: ${{ inputs.terraform_version }} + - name: Pre-hook Terraform workflow + id: pre + run: | + # Setup `workdir` suffix used to give more information during execution + if [[ '${{ inputs.terraform_workdir }}' == '.' ]]; then + echo "workdir=" >> "${GITHUB_OUTPUT}" + else + echo "workdir=(${{ inputs.terraform_workdir }})" >> "${GITHUB_OUTPUT}" + fi + + if [[ '${{ inputs.after_lint }}' == 'true' ]]; then + echo 'lint_fmt_success="- [x] :paintbrush: Check if all Terraform configuration files are in a canonical format"' >> "${GITHUB_OUTPUT}" + echo 'lint_val_success="- [x] :hammer_and_wrench: Validate the configuration files"' >> "${GITHUB_OUTPUT}" + else + echo 'lint_fmt_success=""' >> "${GITHUB_OUTPUT}" + echo 'lint_val_success=""' >> "${GITHUB_OUTPUT}" + fi + + # Import Terraform variables + import yaml + import os + + tf_env = ''' + ${{ inputs.env }} + ${{ secrets.env }} + ''' + + tf_vars = ''' + ${{ inputs.terraform_vars }} + ${{ secrets.terraform_vars }} + ''' + + with open(os.getenv('GITHUB_ENV'), 'a') as env: + if tf_env.strip(): + for var in yaml.safe_load(tf_env).items(): + env.write('%s=%s\n' % var) + if tf_vars.strip(): + for var in yaml.safe_load(tf_vars).items(): + env.write('TF_VAR_%s=%s\n' % var) + shell: python + + # --- `terraform init` + - name: Initialize Terraform working directory ${{ steps.pre.outputs.workdir }} + id: init + env: + TF_IN_AUTOMATION: yes + run: terraform init -no-color -backend=false + working-directory: ${{ inputs.terraform_workdir }} + - uses: marocchino/sticky-pull-request-comment@97bddef64db61b9d80edc69593cc4e4c415c3362 # tag=v2.2.1 + if: failure() && steps.init.outcome == 'failure' + with: + recreate: true + header: tf::${{ steps.pre.outputs.workdir }} + message: | + # Terraform CI/CD ${{ steps.pre.outputs.workdir }} + + ${{ steps.pre.outputs.lint_fmt_success }} + ${{ steps.pre.outputs.lint_val_success }} + - [ ] :scroll: Generate a speculative execution plan + + ### 🚫 Failure reason + ``` + ${{ steps.init.outputs.stderr }} + ``` +
+ + > _Report based on commit ${{ github.sha }} (authored by **@${{ github.actor }}**). See [`actions#${{ github.run_id }}`](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details._ + + # --- `terraform plan` + - name: Generate a speculative execution plan ${{ steps.pre.outputs.workdir }} + id: plan + env: + TF_IN_AUTOMATION: yes + run: terraform plan -input=false -no-color -parallelism=30 -compact-warnings + working-directory: ${{ inputs.terraform_workdir }} + - uses: marocchino/sticky-pull-request-comment@97bddef64db61b9d80edc69593cc4e4c415c3362 # tag=v2.2.1 + if: failure() && steps.plan.outcome == 'failure' + with: + recreate: true + header: tf::${{ steps.pre.outputs.workdir }} + message: | + # Terraform CI/CD ${{ steps.pre.outputs.workdir }} + + ${{ steps.pre.outputs.lint_fmt_success }} + ${{ steps.pre.outputs.lint_val_success }} + - [ ] :scroll: Generate a speculative execution plan + + ### 🚫 Failure reason + ``` + ${{ steps.plan.outputs.stderr }} + ``` +
+ + > _Report based on commit ${{ github.sha }} (authored by **@${{ github.actor }}**). See [`actions#${{ github.run_id }}`](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details._ + - uses: marocchino/sticky-pull-request-comment@97bddef64db61b9d80edc69593cc4e4c415c3362 # tag=v2.2.1 + if: success() + with: + recreate: true + header: tf::${{ steps.pre.outputs.workdir }} + message: | + # Terraform CI/CD ${{ steps.pre.outputs.workdir }} + + ${{ steps.pre.outputs.lint_fmt_success }} + ${{ steps.pre.outputs.lint_val_success }} + - [x] :scroll: Generate a speculative execution plan + + ### Terraform Plan output + ```terraform + ${{ steps.plan.outputs.stdout }} + ``` +
+ + > _Report based on commit ${{ github.sha }} (authored by **@${{ github.actor }}**). See [`actions#${{ github.run_id }}`](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details._ \ No newline at end of file diff --git a/.github/workflows/terraform.lint.yaml b/.github/workflows/terraform.lint.yaml index 53b0963..0ff7d60 100644 --- a/.github/workflows/terraform.lint.yaml +++ b/.github/workflows/terraform.lint.yaml @@ -10,18 +10,18 @@ permissions: jobs: terraform-module-k3s: name: Terraform module - uses: xunleii/github-actions-grimoire/.github/workflows/terraform.pull_requests.lint.yaml@0ab2cd93e86642397ecdfb2da1e5b97594ab9905 + uses: ./.github/workflows/templates/terraform.pull_requests.lint.yaml examples_hcloud-k3s: name: Hetzner Cloud needs: [terraform-module-k3s] - uses: xunleii/github-actions-grimoire/.github/workflows/terraform.pull_requests.lint.yaml@0ab2cd93e86642397ecdfb2da1e5b97594ab9905 + uses: ./.github/workflows/templates/terraform.pull_requests.lint.yaml with: terraform_workdir: examples/hcloud-k3s examples_civo-k3s: name: CIVO needs: [terraform-module-k3s] - uses: xunleii/github-actions-grimoire/.github/workflows/terraform.pull_requests.lint.yaml@0ab2cd93e86642397ecdfb2da1e5b97594ab9905 + uses: ./.github/workflows/templates/terraform.pull_requests.lint.yaml with: terraform_workdir: examples/civo-k3s diff --git a/.github/workflows/terraform.plan.yaml b/.github/workflows/terraform.plan.yaml index d7de3b4..9efd4cf 100644 --- a/.github/workflows/terraform.plan.yaml +++ b/.github/workflows/terraform.plan.yaml @@ -16,7 +16,7 @@ jobs: secrets: env: | HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }} - uses: xunleii/github-actions-grimoire/.github/workflows/terraform.pull_requests.plan.yaml@0ab2cd93e86642397ecdfb2da1e5b97594ab9905 + uses: ./.github/workflows/templates/terraform.pull_requests.plan.yaml with: terraform_vars: | ssh_key: '' From 3e69512ae8372806fb9dfd241f37b0bf5d2cc6a4 Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sun, 29 Oct 2023 18:51:46 +0100 Subject: [PATCH 05/12] Add Github issue form Signed-off-by: Alexandre Nicolaie --- .github/ISSUE_TEMPLATE/bug-report.yaml | 68 ++++++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yaml | 1 + 2 files changed, 69 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yaml create mode 100644 .github/ISSUE_TEMPLATE/config.yaml diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml new file mode 100644 index 0000000..c23d868 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -0,0 +1,68 @@ +name: Bug Report +description: File a bug report for this project +title: ":bug: " +labels: ["kind/bug"] +projects: ["xunleii/2"] + +body: + - type: markdown + attributes: + value: | + Before opening a new issue, please search existing issues. + + ---- + + Thank you for filing a bug report! Please fill out the sections below to help us reproduce the bug. + + - type: textarea + id: what_happened + attributes: + label: ":fire: What happened?" + description: Describe the issue you are experiencing here + validations: + required: true + - type: textarea + id: what_expected + attributes: + label: ":+1: What did you expect to happen?" + description: Describe what you expected to happen here + validations: + required: false + - type: textarea + id: how_reproduce + attributes: + label: ":mag: How can we reproduce the issue?" + description: Describe how to reproduce the problem in as much detail as possible + validations: + required: true + + - type: input + id: module_version + attributes: + label: ":wrench: Module version" + description: Please provide the version of the module you are using + validations: + required: true + - type: input + id: terraform_version + attributes: + label: ":wrench: Terraform version" + description: Please provide the version of Terraform you are using + validations: + required: true + + - type: textarea + id: provider_list + attributes: + label: ":wrench: Terraform providers" + description: List all the providers you are using with their version (copy the output of `terraform providers`) + validations: + required: true + + - type: textarea + id: additional_info + attributes: + label: ":clipboard: Additional information" + description: Please provide any additional information that might be useful + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yaml b/.github/ISSUE_TEMPLATE/config.yaml new file mode 100644 index 0000000..0086358 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yaml @@ -0,0 +1 @@ +blank_issues_enabled: true From 35b4d166578ba4aa7c8604ae5c2a16d225fae2c9 Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sun, 29 Oct 2023 21:50:12 +0100 Subject: [PATCH 06/12] Add example for Digital Ocean Signed-off-by: Alexandre Nicolaie --- examples/do-k3s/README.md | 14 ++++++++++++++ examples/do-k3s/k3s.tf | 32 ++++++++++++++++++++++++++++++++ examples/do-k3s/main.tf | 22 ++++++++++++++++++++++ examples/do-k3s/outputs.tf | 14 ++++++++++++++ examples/do-k3s/versions.tf | 9 +++++++++ 5 files changed, 91 insertions(+) create mode 100644 examples/do-k3s/README.md create mode 100644 examples/do-k3s/k3s.tf create mode 100644 examples/do-k3s/main.tf create mode 100644 examples/do-k3s/outputs.tf create mode 100644 examples/do-k3s/versions.tf diff --git a/examples/do-k3s/README.md b/examples/do-k3s/README.md new file mode 100644 index 0000000..aef41ee --- /dev/null +++ b/examples/do-k3s/README.md @@ -0,0 +1,14 @@ +# K3S example for Digital Ocean + +Configuration in this directory creates a k3s cluster resources instances. + +## Usage + +> [!warning] +> **Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.** + +```bash +$ export DIGITALOCEAN_TOKEN=... +$ terraform init +$ terraform apply +``` diff --git a/examples/do-k3s/k3s.tf b/examples/do-k3s/k3s.tf new file mode 100644 index 0000000..4bfc538 --- /dev/null +++ b/examples/do-k3s/k3s.tf @@ -0,0 +1,32 @@ +module "k3s" { + source = "./../.." + + depends_on_ = digitalocean_droplet.node_instances + k3s_version = "latest" + cluster_domain = "do_k3s" + + drain_timeout = "60s" + managed_fields = ["label"] + generate_ca_certificates = true + + global_flags = [for instance in digitalocean_droplet.node_instances : "--tls-san ${instance.ipv4_address}"] + + servers = { + # The node name will be automatically provided by + # the module using the field name... any usage of + # --node-name in additional_flags will be ignored + + for instance in digitalocean_droplet.node_instances : + instance.name => { + ip = instance.ipv4_address_private + connection = { + timeout = "60s" + type = "ssh" + host = instance.ipv4_address + private_key = trimspace(tls_private_key.ed25519_provisioning.private_key_pem) + } + + labels = { "node.kubernetes.io/type" = "master" } + } + } +} diff --git a/examples/do-k3s/main.tf b/examples/do-k3s/main.tf new file mode 100644 index 0000000..0034da4 --- /dev/null +++ b/examples/do-k3s/main.tf @@ -0,0 +1,22 @@ +data "digitalocean_image" "ubuntu" { + slug = "ubuntu-22-04-x64" +} + +resource "tls_private_key" "ed25519_provisioning" { + algorithm = "ED25519" +} + +resource "digitalocean_ssh_key" "default" { + name = "K3S terraform module - Provisionning SSH key" + public_key = trimspace(tls_private_key.ed25519_provisioning.public_key_openssh) +} + +resource "digitalocean_droplet" "node_instances" { + count = 3 + + image = data.digitalocean_image.ubuntu.slug + name = "k3s-node-${count.index}" + region = "ams3" + size = "s-1vcpu-2gb" + ssh_keys = [digitalocean_ssh_key.default.fingerprint] +} diff --git a/examples/do-k3s/outputs.tf b/examples/do-k3s/outputs.tf new file mode 100644 index 0000000..4fb7bf0 --- /dev/null +++ b/examples/do-k3s/outputs.tf @@ -0,0 +1,14 @@ +output "summary" { + value = module.k3s.summary +} + +output "kubeconfig" { + value = module.k3s.kube_config + sensitive = true +} + +output "ssh_private_key" { + description = "Generated SSH private key." + value = tls_private_key.ed25519_provisioning.private_key_openssh + sensitive = true +} diff --git a/examples/do-k3s/versions.tf b/examples/do-k3s/versions.tf new file mode 100644 index 0000000..9507a98 --- /dev/null +++ b/examples/do-k3s/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + digitalocean = { + source = "digitalocean/digitalocean" + version = "2.31.0" + } + } + required_version = "~> 1.0" +} From 975a2117ab8c3c4f83b17a56fd4b4af95c7f82d5 Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sat, 11 Nov 2023 13:58:06 +0100 Subject: [PATCH 07/12] Make k3s token as non-sensitive value In order to have more information during provisionning, I make this token as non-sensitive value. This didn't have any issue on security because it is never showed on logs. Signed-off-by: Alexandre Nicolaie --- agent_nodes.tf | 2 +- server_nodes.tf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/agent_nodes.tf b/agent_nodes.tf index 805f8f5..777cce1 100644 --- a/agent_nodes.tf +++ b/agent_nodes.tf @@ -47,7 +47,7 @@ locals { "--node-ip ${agent.ip}", "--node-name '${try(agent.name, key)}'", "--server https://${local.root_advertise_ip_k3s}:6443", - "--token ${random_password.k3s_cluster_secret.result}", + "--token ${nonsensitive(random_password.k3s_cluster_secret.result)}", # NOTE: nonsensitive is used to show logs during provisioning ], var.global_flags, try(agent.flags, []), diff --git a/server_nodes.tf b/server_nodes.tf index 074c062..3d4b85d 100644 --- a/server_nodes.tf +++ b/server_nodes.tf @@ -94,7 +94,7 @@ locals { "--cluster-domain '${var.cluster_domain}'", "--cluster-cidr ${var.cidr.pods}", "--service-cidr ${var.cidr.services}", - "--token ${random_password.k3s_cluster_secret.result}", + "--token ${nonsensitive(random_password.k3s_cluster_secret.result)}", # NOTE: nonsensitive is used to show logs during provisioning length(var.servers) > 1 ? "--cluster-init" : "", ] : // For other server nodes, use agent flags (because the first node manage the cluster configuration) @@ -105,7 +105,7 @@ locals { "--cluster-domain '${var.cluster_domain}'", "--cluster-cidr ${var.cidr.pods}", "--service-cidr ${var.cidr.services}", - "--token ${random_password.k3s_cluster_secret.result}", + "--token ${nonsensitive(random_password.k3s_cluster_secret.result)}", # NOTE: nonsensitive is used to show logs during provisioning ], var.global_flags, try(server.flags, []), From bd1f2e3100324c02b456d248e71659012bca4de8 Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sat, 11 Nov 2023 14:11:29 +0100 Subject: [PATCH 08/12] Add an example of customized `kubeconfig` Fixes #144 Signed-off-by: Alexandre Nicolaie --- README.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/README.md b/README.md index ff3fc7b..55e7429 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,47 @@ module "k3s" { | [tls](#provider\_tls) | 4.0.4 | +## Frequently Asked Questions + +### How to customise the generated `kubeconfig` + +It is sometimes necessary to modify the context or the cluster name to adapt `kubeconfig` to a third-party tool or to avoid conflicts with existing tools. Although this is not the role of this module, it can easily be done with its outputs : + +```hcl +module "k3s" { + ... +} + +local { + kubeconfig = yamlencode({ + apiVersion = "v1" + kind = "Config" + current-context = "my-context-name" + contexts = [{ + context = { + cluster = "my-cluster-name" + user : "my-user-name" + } + name = "my-context-name" + }] + clusters = [{ + cluster = { + certificate-authority-data = base64encode(module.k3s.kubernetes.cluster_ca_certificate) + server = module.k3s.kubernetes.api_endpoint + } + name = "my-cluster-name" + }] + users = [{ + user = { + client-certificate-data : base64encode(module.k3s.kubernetes.client_certificate) + client-key-data : base64encode(module.k3s.kubernetes.client_key) + } + name : "my-user-name" + }] + }) +} +``` + ## License `terraform-module-k3s` is released under the **MIT License**. See the bundled [LICENSE](LICENSE) file for details. From 5f1b57ec5a35ec181b1cbad523b251b5ce94c7fd Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sat, 11 Nov 2023 14:19:29 +0100 Subject: [PATCH 09/12] TF lint all files Signed-off-by: Alexandre Nicolaie --- README.md | 4 ++-- examples/hcloud-k3s/k3s.tf | 4 ++-- examples/hcloud-k3s/main.tf | 4 ++-- examples/hcloud-k3s/outputs.tf | 2 +- examples/hcloud-k3s/versions.tf | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 55e7429..efc7bff 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ module "k3s" { ip = hcloud_server_network.control_planes[i].ip connection = { host = hcloud_server.control_planes[i].ipv4_address - private_key = trimspace(tls_private_key.ed25519-provisioning.private_key_pem) + private_key = trimspace(tls_private_key.ed25519_provisioning.private_key_pem) } flags = ["--disable-cloud-controller"] annotations = { "server_id" : i } // theses annotations will not be managed by this module @@ -56,7 +56,7 @@ module "k3s" { ip = hcloud_server_network.agents_network[i].ip connection = { host = hcloud_server.agents[i].ipv4_address - private_key = trimspace(tls_private_key.ed25519-provisioning.private_key_pem) + private_key = trimspace(tls_private_key.ed25519_provisioning.private_key_pem) } labels = { "node.kubernetes.io/pool" = hcloud_server.agents[i].labels.nodepool } diff --git a/examples/hcloud-k3s/k3s.tf b/examples/hcloud-k3s/k3s.tf index 4c02466..f43f3aa 100644 --- a/examples/hcloud-k3s/k3s.tf +++ b/examples/hcloud-k3s/k3s.tf @@ -22,7 +22,7 @@ module "k3s" { ip = hcloud_server_network.control_planes[i].ip connection = { host = hcloud_server.control_planes[i].ipv4_address - private_key = trimspace(tls_private_key.ed25519-provisioning.private_key_pem) + private_key = trimspace(tls_private_key.ed25519_provisioning.private_key_pem) } flags = ["--disable-cloud-controller"] annotations = { "server_id" : i } // theses annotations will not be managed by this module @@ -36,7 +36,7 @@ module "k3s" { ip = hcloud_server_network.agents_network[i].ip connection = { host = hcloud_server.agents[i].ipv4_address - private_key = trimspace(tls_private_key.ed25519-provisioning.private_key_pem) + private_key = trimspace(tls_private_key.ed25519_provisioning.private_key_pem) } labels = { "node.kubernetes.io/pool" = hcloud_server.agents[i].labels.nodepool } diff --git a/examples/hcloud-k3s/main.tf b/examples/hcloud-k3s/main.tf index 5362e90..931d119 100644 --- a/examples/hcloud-k3s/main.tf +++ b/examples/hcloud-k3s/main.tf @@ -2,13 +2,13 @@ data "hcloud_image" "ubuntu" { name = "ubuntu-20.04" } -resource "tls_private_key" "ed25519-provisioning" { +resource "tls_private_key" "ed25519_provisioning" { algorithm = "ED25519" } resource "hcloud_ssh_key" "default" { name = "K3S terraform module - Provisionning SSH key" - public_key = trimspace(tls_private_key.ed25519-provisioning.public_key_openssh) + public_key = trimspace(tls_private_key.ed25519_provisioning.public_key_openssh) } resource "hcloud_network" "k3s" { diff --git a/examples/hcloud-k3s/outputs.tf b/examples/hcloud-k3s/outputs.tf index 24710df..4fb7bf0 100644 --- a/examples/hcloud-k3s/outputs.tf +++ b/examples/hcloud-k3s/outputs.tf @@ -9,6 +9,6 @@ output "kubeconfig" { output "ssh_private_key" { description = "Generated SSH private key." - value = tls_private_key.ed25519-provisioning.private_key_openssh + value = tls_private_key.ed25519_provisioning.private_key_openssh sensitive = true } diff --git a/examples/hcloud-k3s/versions.tf b/examples/hcloud-k3s/versions.tf index 08c7f36..6e3d8f5 100644 --- a/examples/hcloud-k3s/versions.tf +++ b/examples/hcloud-k3s/versions.tf @@ -1,7 +1,7 @@ terraform { required_providers { hcloud = { - source = "hetznercloud/hcloud" + source = "hetznercloud/hcloud" version = "1.44.1" } } From 2ffa9aa5c301e20706d2af6ca64df6a001d6cce4 Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sat, 11 Nov 2023 16:20:54 +0100 Subject: [PATCH 10/12] Add Taskfile to simplify management Signed-off-by: Alexandre Nicolaie --- .devcontainer/devcontainer.json | 16 ++- .gitignore | 208 +++++++++----------------------- .tool-versions | 1 + Taskfile.yaml | 51 ++++++++ examples/hcloud-k3s/k3s.tf | 5 +- 5 files changed, 123 insertions(+), 158 deletions(-) create mode 100644 Taskfile.yaml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4dc977a..10e2009 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,15 +2,18 @@ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.schema.json", "name": "k3s Terraform module - Dev Container", "image": "mcr.microsoft.com/vscode/devcontainers/universal", - "features": { "ghcr.io/devcontainers-contrib/features/yamllint:2.0.9": {}, - "ghcr.io/devcontainers/features/terraform:1.3.5": { "version": "1.6.2" }, - "ghcr.io/dhoeric/features/terraform-docs:1.0.0": { "version": "0.16.0" }, + "ghcr.io/devcontainers/features/terraform:1.3.5": { + "version": "1.6.2" + }, + "ghcr.io/devcontainers-contrib/features/go-task:1.0.5": {}, + "ghcr.io/dhoeric/features/terraform-docs:1.0.0": { + "version": "0.16.0" + }, "ghcr.io/itsmechlark/features/act:1.0.0": {}, "ghcr.io/itsmechlark/features/trivy:1.0.0": {} }, - "customizations": { "vscode": { "extensions": [ @@ -19,8 +22,9 @@ "ms-vscode.makefile-tools", "redhat.vscode-yaml", "tylerharris.terraform-link-docs", - "yzhang.markdown-all-in-one" + "yzhang.markdown-all-in-one", + "task.vscode-task" ] } } -} +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8ef62a6..d1c5660 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,21 @@ +# Created by https://www.toptal.com/developers/gitignore/api/linux,windows,macos,terraform +# Edit at https://www.toptal.com/developers/gitignore?templates=linux,windows,macos,terraform + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + ### macOS ### # General .DS_Store @@ -27,20 +45,45 @@ Network Trash Folder Temporary Items .apdisk -### Linux ### -*~ +### macOS Patch ### +# iCloud generated files +*.icloud -# temporary files which can be created if a process still has a handle open of a deleted file -.fuse_hidden* +### Terraform ### +# Local .terraform directories +**/.terraform/* -# KDE directory preferences -.directory +# .tfstate files +*.tfstate +*.tfstate.* -# Linux trash folder which might appear on any partition or disk -.Trash-* +# Crash log files +crash.log +crash.*.log -# .nfs files are created when an open file is removed but is still being accessed -.nfs* +# Exclude all .tfvars files, which are likely to contain sensitive data, such as +# password, private keys, and other secrets. These should not be part of version +# control as they are data points which are potentially sensitive and subject +# to change depending on the environment. +*.tfvars +*.tfvars.json + +# Ignore override files as they are usually used to override resources locally and so +# are not checked in +override.tf +override.tf.json +*_override.tf +*_override.tf.json + +# Include override files you do wish to add to version control using negated pattern +# !example_override.tf + +# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan +# example: *tfplan* + +# Ignore CLI configuration files +.terraformrc +terraform.rc ### Windows ### # Windows thumbnail cache files @@ -68,145 +111,8 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk -### Node ### -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov +# End of https://www.toptal.com/developers/gitignore/api/linux,windows,macos,terraform -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -.env -.env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and not Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Stores VSCode versions used for testing VSCode extensions -.vscode-test - -### Terraform ### -# Local .terraform directories -**/.terraform/* - -# .tfstate files -*.tfstate -*.tfstate.* - -# .terraform.lock.hcl on examples folders -examples/**/.terraform.lock.hcl - -# Crash log files -crash.log - -# Ignore any .tfvars files that are generated automatically for each Terraform run. Most -# .tfvars files are managed as part of configuration and so should be included in -# version control. -# -# example.tfvars - -# Ignore override files as they are usually used to override resources locally and so -# are not checked in -override.tf -override.tf.json -*_override.tf -*_override.tf.json - -# Include override files you do wish to add to version control using negated pattern -# -# !example_override.tf - -# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan -# example: *tfplan* +### Taskfile ### +# Ignore taskfile generated files +.task/ diff --git a/.tool-versions b/.tool-versions index f39eeda..8009c07 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,4 +1,5 @@ act 0.2.52 +task 3.31.0 terraform 1.6.2 terraform-docs 0.16.0 trivy 0.46.0 diff --git a/Taskfile.yaml b/Taskfile.yaml new file mode 100644 index 0000000..e5d7f2e --- /dev/null +++ b/Taskfile.yaml @@ -0,0 +1,51 @@ +# yaml-language-server: $schema=https://taskfile.dev/schema.json +version: "3" + +tasks: + default: { cmds: [task --list], silent: true } + + dev:lint: + aliases: [lint] + cmds: + - terraform fmt -recursive + desc: Lint terraform code + + examples:hcloud:setup: + aliases: [test, dev:test] + cmds: + - terraform init + - terraform validate + - terraform apply -auto-approve + - terraform output -raw kubeconfig > kubeconfig~ + desc: Test this terraform module on Hetzner Cloud + dir: examples/hcloud-k3s + generates: + - kubeconfig~ + interactive: true + requires: + vars: [HCLOUD_TOKEN] + sources: + # - "../../*.tf" + - "*.tf" + + examples:hcloud:teardown: + cmds: + - terraform destroy -auto-approve + - rm -f kubeconfig~ + desc: Remove all resources created by test:hcloud:setup + dir: examples/hcloud-k3s + interactive: true + preconditions: + - sh: test -f kubeconfig~ + msg: Run `test:hcloud:setup` first + prompt: Are you sure you want to destroy all resources created by `test:hcloud:setup`? + requires: + vars: [HCLOUD_TOKEN] + + e2e:hcloud: + aliases: [e2e] + cmds: + - task: examples:hcloud:setup + - defer: task examples:hcloud:teardown + - kubectl --kubeconfig examples/hcloud-k3s/kubeconfig~ get nodes + desc: Run e2e tests on Hetzner Cloud diff --git a/examples/hcloud-k3s/k3s.tf b/examples/hcloud-k3s/k3s.tf index f43f3aa..1bb1d88 100644 --- a/examples/hcloud-k3s/k3s.tf +++ b/examples/hcloud-k3s/k3s.tf @@ -24,7 +24,10 @@ module "k3s" { host = hcloud_server.control_planes[i].ipv4_address private_key = trimspace(tls_private_key.ed25519_provisioning.private_key_pem) } - flags = ["--disable-cloud-controller"] + flags = [ + "--disable-cloud-controller", + "--tls-san ${hcloud_server.control_planes[0].ipv4_address}", + ] annotations = { "server_id" : i } // theses annotations will not be managed by this module } } From b8c94d14410f0a2d73760da9ff3e4bd608fe19b3 Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sat, 11 Nov 2023 16:37:58 +0100 Subject: [PATCH 11/12] Move all templates workflows to .github/workflows Signed-off-by: Alexandre Nicolaie --- ...int.yaml => templates.terraform.pull_requests.lint.yaml} | 0 ...lan.yaml => templates.terraform.pull_requests.plan.yaml} | 0 .github/workflows/terraform.lint.yaml | 6 +++--- .github/workflows/terraform.plan.yaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename .github/workflows/{templates/terraform.pull_requests.lint.yaml => templates.terraform.pull_requests.lint.yaml} (100%) rename .github/workflows/{templates/terraform.pull_requests.plan.yaml => templates.terraform.pull_requests.plan.yaml} (100%) diff --git a/.github/workflows/templates/terraform.pull_requests.lint.yaml b/.github/workflows/templates.terraform.pull_requests.lint.yaml similarity index 100% rename from .github/workflows/templates/terraform.pull_requests.lint.yaml rename to .github/workflows/templates.terraform.pull_requests.lint.yaml diff --git a/.github/workflows/templates/terraform.pull_requests.plan.yaml b/.github/workflows/templates.terraform.pull_requests.plan.yaml similarity index 100% rename from .github/workflows/templates/terraform.pull_requests.plan.yaml rename to .github/workflows/templates.terraform.pull_requests.plan.yaml diff --git a/.github/workflows/terraform.lint.yaml b/.github/workflows/terraform.lint.yaml index 0ff7d60..5549f3e 100644 --- a/.github/workflows/terraform.lint.yaml +++ b/.github/workflows/terraform.lint.yaml @@ -10,18 +10,18 @@ permissions: jobs: terraform-module-k3s: name: Terraform module - uses: ./.github/workflows/templates/terraform.pull_requests.lint.yaml + uses: ./.github/workflows/templates.terraform.pull_requests.lint.yaml examples_hcloud-k3s: name: Hetzner Cloud needs: [terraform-module-k3s] - uses: ./.github/workflows/templates/terraform.pull_requests.lint.yaml + uses: ./.github/workflows/templates.terraform.pull_requests.lint.yaml with: terraform_workdir: examples/hcloud-k3s examples_civo-k3s: name: CIVO needs: [terraform-module-k3s] - uses: ./.github/workflows/templates/terraform.pull_requests.lint.yaml + uses: ./.github/workflows/templates.terraform.pull_requests.lint.yaml with: terraform_workdir: examples/civo-k3s diff --git a/.github/workflows/terraform.plan.yaml b/.github/workflows/terraform.plan.yaml index 9efd4cf..74da950 100644 --- a/.github/workflows/terraform.plan.yaml +++ b/.github/workflows/terraform.plan.yaml @@ -16,7 +16,7 @@ jobs: secrets: env: | HCLOUD_TOKEN: ${{ secrets.HCLOUD_TOKEN }} - uses: ./.github/workflows/templates/terraform.pull_requests.plan.yaml + uses: ./.github/workflows/templates.terraform.pull_requests.plan.yaml with: terraform_vars: | ssh_key: '' From 51331e90e35ac910e0dac9c47af6329daf988b43 Mon Sep 17 00:00:00 2001 From: Alexandre Nicolaie Date: Sat, 11 Nov 2023 16:47:27 +0100 Subject: [PATCH 12/12] Use python ... in python script Signed-off-by: Alexandre Nicolaie --- ...emplates.terraform.pull_requests.plan.yaml | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/.github/workflows/templates.terraform.pull_requests.plan.yaml b/.github/workflows/templates.terraform.pull_requests.plan.yaml index a461c2a..ce3ce2e 100644 --- a/.github/workflows/templates.terraform.pull_requests.plan.yaml +++ b/.github/workflows/templates.terraform.pull_requests.plan.yaml @@ -51,25 +51,26 @@ jobs: - name: Pre-hook Terraform workflow id: pre run: | + import os + import yaml + # Setup `workdir` suffix used to give more information during execution - if [[ '${{ inputs.terraform_workdir }}' == '.' ]]; then - echo "workdir=" >> "${GITHUB_OUTPUT}" - else - echo "workdir=(${{ inputs.terraform_workdir }})" >> "${GITHUB_OUTPUT}" - fi - - if [[ '${{ inputs.after_lint }}' == 'true' ]]; then - echo 'lint_fmt_success="- [x] :paintbrush: Check if all Terraform configuration files are in a canonical format"' >> "${GITHUB_OUTPUT}" - echo 'lint_val_success="- [x] :hammer_and_wrench: Validate the configuration files"' >> "${GITHUB_OUTPUT}" - else - echo 'lint_fmt_success=""' >> "${GITHUB_OUTPUT}" - echo 'lint_val_success=""' >> "${GITHUB_OUTPUT}" - fi - # Import Terraform variables - import yaml - import os + with open(os.getenv('GITHUB_OUTPUT'), 'a') as output: + if '${{ inputs.terraform_workdir }}' == '.': + output.write('workdir=\n') + else: + output.write('workdir=(${{ inputs.terraform_workdir }})\n') + if '${{ inputs.after_lint }}' == 'true': + output.write('- [x] :paintbrush: Check if all Terraform configuration files are in a canonical format\n') + output.write('- [x] :hammer_and_wrench: Validate the configuration files\n') + else: + output.write('lint_fmt_success=""\n') + output.write('lint_val_success=""\n') + + # Import Terraform variables + tf_env = ''' ${{ inputs.env }} ${{ secrets.env }}