add mysql + memcached products

This commit is contained in:
Greyscale 2025-01-21 13:38:58 +01:00
parent a856bc990c
commit bb47276b62
Signed by: grey
GPG key ID: DDB392AE64B32D89
9 changed files with 285 additions and 0 deletions

View file

@ -0,0 +1,68 @@
variable "memcached_image" {
default = "memcached"
type = string
description = "The docker image to use for the MemcacheD service."
}
variable "memcached_version" {
default = "1"
type = string
description = "The version of the docker image to use for the MemcacheD service."
}
variable "connection_limit" {
default = 1024
type = number
description = "The maximum number of connections to allow."
}
variable "memory_limit_mb" {
default = 128
type = number
description = "The maximum amount of memory to use in megabytes."
}
variable "threads" {
default = 8
type = number
description = "The number of threads to use."
}
# Pass-thru variables
variable "stack_name" {
type = string
}
variable "networks" {
type = list(object({
name = string
id = string
}))
default = []
description = "A list of network names to attach the service to."
}
variable "ports" {
type = list(object({
host = optional(number)
container = number
protocol = optional(string, "tcp")
}))
default = []
description = "A map of port mappings to expose on the host. The key is the host port, and the value is the container port."
validation {
error_message = "Host Ports must be between 1024 and 65535 or null."
condition = alltrue([for port in var.ports : port.host == null ? true : (port.host >= 1024 && port.host <= 65535)])
}
validation {
error_message = "Container Ports must be between 1 and 65535."
condition = alltrue([for port in var.ports : port.container >= 1 && port.container <= 65535])
}
validation {
error_message = "Protocol must be either 'tcp' or 'udp'."
condition = alltrue([for port in var.ports : port.protocol == "tcp" || port.protocol == "udp"])
}
}
variable "placement_constraints" {
default = []
type = list(string)
description = "Docker Swarm placement constraints"
}
variable "data_persist_path" {
default = null
description = "Path on host machine to persist data. Leaving this blank will provision an ephemeral volume."
type = string
}

View file

@ -0,0 +1,27 @@
module "service" {
source = "../../docker/service"
image = "${var.memcached_image}:${var.memcached_version}"
stack_name = var.stack_name
service_name = "mysql"
networks = var.networks
command = ["memcached", "--memory-limit", var.memory_limit_mb, "--threads", var.threads, "--connection-limit", var.connection_limit]
healthcheck = ["CMD-SHELL", "echo \"version\" | nc -vn -w 1 127.0.0.1 11211"]
healthcheck_start_period = "10s"
healthcheck_interval = "10s"
healthcheck_timeout = "5s"
healthcheck_retries = 3
volumes = local.volumes
mounts = local.mounts
ports = var.ports
placement_constraints = var.placement_constraints
}
locals {
volumes = var.data_persist_path == null ? {
"data" = "/var/lib/mysql"
} : {}
mounts = var.data_persist_path != null ? {
"${var.data_persist_path}" = "/var/lib/mysql"
} : {}
}

View file

@ -0,0 +1,12 @@
output "service_name" {
value = module.service.service_name
}
output "ports" {
value = module.service.ports
}
output "docker_service" {
value = module.service.docker_service
}
output "endpoint" {
value = "memcached://${module.service.service_name}:11211/"
}

View file

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

View file

@ -0,0 +1,16 @@
resource "random_pet" "username" {
length = 2
}
resource "random_password" "password" {
length = 32
special = false
}
resource "random_pet" "database" {
length = 2
}
locals {
root_password = var.root_password != null ? var.root_password : nonsensitive(random_password.password.result)
username = var.username != null ? var.username : replace(random_pet.username.id, "-", "")
password = var.password != null ? var.password : nonsensitive(random_password.password.result)
database = var.database != null ? var.database : replace(random_pet.database.id, "-", "")
}

74
products/mysql/inputs.tf Normal file
View file

@ -0,0 +1,74 @@
variable "mysql_image" {
default = "mariadb"
type = string
description = "The docker image to use for the MySQL-alike service."
}
variable "mysql_version" {
default = "11.6"
type = string
description = "The version of the docker image to use for the MySQL-alike service."
}
variable "root_password" {
default = null
type = string
description = "The root user password for the database. If none is provided, a random root password will be generated."
}
variable "username" {
default = null
type = string
description = "The username for the database. If none is provided, a random username will be generated."
}
variable "password" {
default = null
type = string
description = "The password for the database. If none is provided, a random password will be generated."
}
variable "database" {
default = null
type = string
description = "The name of the database. If none is provided, a random name will be generated."
}
# Pass-thru variables
variable "stack_name" {
type = string
}
variable "networks" {
type = list(object({
name = string
id = string
}))
default = []
description = "A list of network names to attach the service to."
}
variable "ports" {
type = list(object({
host = optional(number)
container = number
protocol = optional(string, "tcp")
}))
default = []
description = "A map of port mappings to expose on the host. The key is the host port, and the value is the container port."
validation {
error_message = "Host Ports must be between 1024 and 65535 or null."
condition = alltrue([for port in var.ports : port.host == null ? true : (port.host >= 1024 && port.host <= 65535)])
}
validation {
error_message = "Container Ports must be between 1 and 65535."
condition = alltrue([for port in var.ports : port.container >= 1 && port.container <= 65535])
}
validation {
error_message = "Protocol must be either 'tcp' or 'udp'."
condition = alltrue([for port in var.ports : port.protocol == "tcp" || port.protocol == "udp"])
}
}
variable "placement_constraints" {
default = []
type = list(string)
description = "Docker Swarm placement constraints"
}
variable "data_persist_path" {
default = null
description = "Path on host machine to persist data. Leaving this blank will provision an ephemeral volume."
type = string
}

32
products/mysql/mysql.tf Normal file
View file

@ -0,0 +1,32 @@
module "service" {
source = "../../docker/service"
image = "${var.mysql_image}:${var.mysql_version}"
stack_name = var.stack_name
service_name = "mysql"
networks = var.networks
healthcheck = ["CMD", "/usr/local/bin/healthcheck.sh", "--connect", "--mariadbupgrade", "--innodb_initialized"]
healthcheck_start_period = "10s"
healthcheck_interval = "10s"
healthcheck_timeout = "5s"
healthcheck_retries = 3
environment_variables = {
MARIADB_ROOT_PASSWORD = local.root_password
MARIADB_USER = local.username
MARIADB_PASSWORD = local.password
MARIADB_DATABASE = local.database
}
volumes = local.volumes
mounts = local.mounts
ports = var.ports
placement_constraints = var.placement_constraints
}
locals {
volumes = var.data_persist_path == null ? {
"data" = "/var/lib/mysql"
} : {}
mounts = var.data_persist_path != null ? {
"${var.data_persist_path}" = "/var/lib/mysql"
} : {}
}

24
products/mysql/outputs.tf Normal file
View file

@ -0,0 +1,24 @@
output "root_password" {
value = local.root_password
}
output "username" {
value = local.username
}
output "password" {
value = local.password
}
output "database" {
value = local.database
}
output "service_name" {
value = module.service.service_name
}
output "ports" {
value = module.service.ports
}
output "docker_service" {
value = module.service.docker_service
}
output "endpoint" {
value = "mysql://${local.username}:${local.password}@${module.service.service_name}:3306/${local.database}"
}

View file

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