Everything moved again.

This commit is contained in:
Greyscale 2024-11-23 05:06:26 +01:00
parent 1f7947dd95
commit cb74c92781
Signed by: grey
GPG key ID: DDB392AE64B32D89
20 changed files with 258 additions and 72 deletions

9
docker/config/config.tf Normal file
View file

@ -0,0 +1,9 @@
resource "docker_config" "config" {
name = local.config_name
data = base64encode(var.value)
lifecycle {
create_before_destroy = true
}
}

5
docker/config/debug.tf Normal file
View file

@ -0,0 +1,5 @@
resource "local_file" "config" {
count = var.debug ? 1 : 0
content = var.value
filename = "${path.root}/.debug/docker/${var.stack_name}/configs/${local.file_name}"
}

22
docker/config/inputs.tf Normal file
View file

@ -0,0 +1,22 @@
variable "stack_name" {
type = string
description = "The name of the stack to deploy the service to."
}
variable "name" {
type = string
description = "The name of the docker config."
}
variable "value" {
type = string
description = "The value of the docker config."
}
variable "labels" {
type = map(string)
default = {}
description = "A map of labels to apply to the service"
}
variable "debug" {
type = bool
default = true
description = "Emit debug files in .debug directory"
}

24
docker/config/locals.tf Normal file
View file

@ -0,0 +1,24 @@
locals {
path = var.name
file_name = element(split("/", local.path), length(split("/", local.path)) - 1)
// Name can be 64 bytes long, including a null byte seemingly, limiting the length to 63.
// The hash is 7 bytes long. We lose 2 more bytes to the dashes. So we have 54 bytes left.
// I will share that into 20 bytes for the stack name, remaining bytes for the config name
config_name = join("-", [
substr(var.stack_name, 0, 20),
substr(local.file_name, 0, 64 - 1 - 7 - 2 - 20),
substr(sha1(var.value), 0, 7)
])
// define config labels
labels = merge(var.labels, {
"com.docker.stack.namespace" = var.stack_name
"ooo.grey.config.stack" = var.stack_name
#"ooo.grey.config.created" = timestamp()
"ooo.grey.config.bytes" = length(var.value)
"ooo.grey.config.name" = local.config_name
"ooo.grey.config.hash" = sha1(var.value)
"ooo.grey.config.file" = local.file_name
"ooo.grey.config.path" = local.path
})
}

6
docker/config/outputs.tf Normal file
View file

@ -0,0 +1,6 @@
output "id" {
value = docker_config.config.id
}
output "name" {
value = docker_config.config.name
}

View file

@ -0,0 +1,16 @@
terraform {
required_version = "~> 1.6"
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~>3.0"
}
local = {
source = "hashicorp/local"
version = "~>2.1"
}
}
}

View file

@ -1,3 +1,9 @@
variable "stack_name" {
type = string
}
description = "The name of the collective stack"
type = string
}
variable "labels" {
type = map(string)
default = {}
description = "A map of labels to apply to the service"
}

9
docker/network/locals.tf Normal file
View file

@ -0,0 +1,9 @@
locals {
network_name = var.stack_name
labels = merge(var.labels, {
"com.docker.stack.namespace" = var.stack_name
"ooo.grey.network.stack" = var.stack_name
"ooo.grey.network.name" = local.network_name
#"ooo.grey.network.created" = timestamp()
})
}

View file

@ -1,8 +1,13 @@
resource "docker_network" "instance" {
name = var.stack_name
name = local.network_name
driver = "overlay"
labels {
label = "com.docker.stack.namespace"
value = var.stack_name
# Attach labels
dynamic "labels" {
for_each = local.labels
content {
label = labels.key
value = labels.value
}
}
}

7
docker/service/config.tf Normal file
View file

@ -0,0 +1,7 @@
module "config" {
for_each = var.configs
source = "../../docker/config"
stack_name = var.stack_name
name = each.key
value = each.value
}

View file

@ -5,6 +5,15 @@ variable "command" {
type = list(string)
default = null
}
variable "restart_policy" {
type = string
default = "any"
description = "The restart policy for the service."
validation {
error_message = "Restart policy must be either 'any', 'on-failure', or 'none'."
condition = var.restart_policy == "any" || var.restart_policy == "on-failure" || var.restart_policy == "none"
}
}
variable "one_shot" {
type = bool
default = false
@ -38,19 +47,20 @@ variable "volumes" {
default = {}
description = "A map of volume names to create and mount. The key is the volume name, and the value is the mount point."
}
variable "remote_volumes" {
type = map(string)
default = {}
description = "A map of remote volumes to mount into the container."
}
variable "mounts" {
type = map(string)
default = {}
description = "A map of host paths to container paths to mount. The key is the host path, and the value is the container path."
}
variable "configs" {
type = map(object({
name_prefix = list(string),
contents = string,
path = string
}))
type = map(string)
default = {}
description = "A map of config names to create and mount. The key is the config name, and the value is the config contents."
description = "A map of config files to create. Key being the path to the file, and the value being the content. The config will be created using the truncated file name and a timestamp."
}
variable "ports" {
type = list(object({
@ -120,6 +130,11 @@ variable "operating_system" {
type = string
description = "The operating system to use for the service. Almost always 'linux'."
}
variable "converge_enable" {
default = true
type = bool
description = "Whether to enable the converge configuration."
}
variable "converge_timeout" {
default = "2m"
type = string

19
docker/service/locals.tf Normal file
View file

@ -0,0 +1,19 @@
locals {
// Name can be 64 bytes long, including a null byte seemingly, limiting the length to 63.
service_name = join("-", [
substr(var.stack_name, 0, 20),
substr(var.service_name, 0, 63 - 1 - 20),
])
# Define service labels en-masse
labels = merge(var.labels, {
"com.docker.stack.namespace" = var.stack_name
"com.docker.stack.image" = data.docker_registry_image.image.name
"com.docker.stack.hash" = data.docker_registry_image.image.sha256_digest
"ooo.grey.service.stack" = var.stack_name
"ooo.grey.service.name" = var.service_name
#"ooo.grey.service.created" = timestamp()
"ooo.grey.service.image" = data.docker_registry_image.image.name
"ooo.grey.service.hash" = data.docker_registry_image.image.sha256_digest
})
}

View file

@ -1,21 +1,10 @@
resource "docker_volume" "volume" {
for_each = var.volumes
name = lower("${var.stack_name}-${replace(each.key, "/", "-")}")
}
variable "remote_volumes" {
type = map(string)
description = "A map of remote volumes to mount into the container."
default = {}
}
data "docker_registry_image" "image" {
name = var.image
}
resource "docker_service" "instance" {
# The name of the service is the stack name and the service name combined
name = "${var.stack_name}-${var.service_name}"
name = local.service_name
# Define the task spec
task_spec {
@ -33,14 +22,18 @@ resource "docker_service" "instance" {
type = "volume"
}
}
# Mount all the volumes being remotely attached to the container
dynamic "mounts" {
for_each = var.remote_volumes
content {
target = mounts.value
source = mounts.key
type = "bind"
type = "volume"
}
}
# Iterate through "mounts" to bind host paths to container paths
dynamic "mounts" {
for_each = var.mounts
content {
@ -50,12 +43,13 @@ resource "docker_service" "instance" {
}
}
# Iterate through configs and attach the docker configs
dynamic "configs" {
for_each = var.configs
content {
config_id = docker_config.config[configs.key].id
config_name = docker_config.config[configs.key].name
file_name = configs.value.path
config_id = module.config[configs.key].id
config_name = module.config[configs.key].name
file_name = configs.value
}
}
@ -67,26 +61,18 @@ resource "docker_service" "instance" {
}
}
# Apply the healthcheck
dynamic "healthcheck" {
for_each = var.healthcheck != null ? [var.healthcheck] : []
content {
test = healthcheck.value
interval = "10s"
timeout = "3s"
retries = 0
start_period = "0s"
}
}
# Container labels
labels {
label = "com.docker.stack.namespace"
value = var.stack_name
# Apply the healthcheck settings
healthcheck {
test = var.healthcheck != null ? var.healthcheck : []
interval = var.healthcheck != null ? "10s" : "0s"
timeout = var.healthcheck != null ? "3s" : "0s"
retries = 0
start_period = "0s"
}
# Apply the list of Container Labels
dynamic "labels" {
for_each = var.labels
for_each = local.labels
content {
label = labels.key
value = labels.value
@ -104,7 +90,7 @@ resource "docker_service" "instance" {
# Apply restart policy
restart_policy {
condition = var.one_shot ? "none" : "any"
condition = var.one_shot ? "none" : var.restart_policy
delay = "0s"
window = "0s"
max_attempts = 0
@ -136,9 +122,14 @@ resource "docker_service" "instance" {
}
}
# Behaviour regarding startup and delaying/waiting. Not possible in global deploy mode.
# Behaviour regarding startup and delaying/waiting.
# Converging is not possible when:
# * in global deploy mode
# * in one-shot mode
# * converging is disabled
# * the service does not have a well-defined healthcheck, maybe you should add one to the service, or to the container itself ideally.
dynamic "converge_config" {
for_each = !var.global && !var.one_shot ? [{}] : []
for_each = var.converge_enable && !var.global && !var.one_shot ? [{}] : []
content {
delay = "5s"
timeout = var.converge_timeout
@ -172,27 +163,11 @@ resource "docker_service" "instance" {
}
# Service Labels
labels {
label = "com.docker.stack.namespace"
value = var.stack_name
}
labels {
label = "com.docker.stack.image"
value = var.image
dynamic "labels" {
for_each = local.labels
content {
label = labels.key
value = labels.value
}
}
}
resource "docker_config" "config" {
for_each = var.configs
data = base64encode(each.value.contents)
name = join("-", concat(each.value.name_prefix, [substr(sha1(each.value.contents), 0, 7)]))
lifecycle {
create_before_destroy = true
}
}
resource "local_file" "config" {
for_each = var.configs
content = each.value.contents
filename = "${path.root}/.debug/docker-service/${var.stack_name}-${var.service_name}/configs/${each.key}"
}

8
docker/service/volume.tf Normal file
View file

@ -0,0 +1,8 @@
resource "docker_volume" "volume" {
for_each = var.volumes
name = lower(join("-", [
substr(var.stack_name, 0, 20),
substr(var.service_name, 0, 20),
substr(replace(trim(each.key, "/"), "/", "-"), 0, 20)
]))
}

13
docker/volume/inputs.tf Normal file
View file

@ -0,0 +1,13 @@
variable "stack_name" {
description = "The name of the collective stack"
type = string
}
variable "volume_name" {
description = "The name of the volume"
type = string
}
variable "labels" {
type = map(string)
default = {}
description = "A map of labels to apply to the service"
}

15
docker/volume/locals.tf Normal file
View file

@ -0,0 +1,15 @@
locals {
volume_name = substr(join("-", [
substr(var.stack_name, 0, 20),
substr(var.volume_name, 0, 64 - 1 - 3 - 20 - 6 - 6),
formatdate("YYMMDD", timestamp()),
formatdate("hhmmss", timestamp()),
]), 0, 63)
labels = merge(var.labels, {
"com.docker.stack.namespace" = var.stack_name
"ooo.grey.volume.stack" = var.stack_name
"ooo.grey.volume.name" = var.volume_name
#"ooo.grey.volume.created" = timestamp()
})
}

3
docker/volume/output.tf Normal file
View file

@ -0,0 +1,3 @@
output "source" {
value = docker_volume.volume.id
}

View file

@ -0,0 +1,11 @@
terraform {
required_version = "~> 1.6"
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~>3.0"
}
}
}

17
docker/volume/volume.tf Normal file
View file

@ -0,0 +1,17 @@
resource "docker_volume" "volume" {
name = local.volume_name
# Attach labels
dynamic "labels" {
for_each = local.labels
content {
label = labels.key
value = labels.value
}
}
lifecycle {
create_before_destroy = true
ignore_changes = [name]
}
}

View file

@ -5,6 +5,7 @@ module "forgejo_actions_runner" {
placement_constraints = var.placement_constraints
image = "${var.forgejo_actions_runner_image}:${var.forgejo_actions_runner_version}"
parallelism = var.parallelism
converge_enable = false
environment_variables = {
forgejo_INSTANCE_URL = var.forgejo_instance_url
forgejo_RUNNER_NAME = var.forgejo_runner_name
@ -16,7 +17,7 @@ module "forgejo_actions_runner" {
"/var/run/docker.sock" = "/var/run/docker.sock"
}
configs = {
forgejo-config = {
forgejo-config = yamlencode({
name_prefix = ["forgejo-config", var.stack_name, var.service_name]
path = "/config.yaml"
contents = yamlencode({
@ -54,6 +55,6 @@ module "forgejo_actions_runner" {
workdir_parent : null
}
})
}
})
}
}