mirror of
https://github.com/imjasonh/terraform-playground
synced 2026-07-21 06:48:08 +00:00
Merge pull request #6 from imjasonh/copilot/sub-pr-3-another-one
This commit is contained in:
commit
c20be36cd2
3 changed files with 51 additions and 71 deletions
|
|
@ -1,60 +1,61 @@
|
||||||
#cloud-config
|
#cloud-config
|
||||||
# This cloud-init configuration defines a systemd service to run the Docker container
|
# This cloud-init configuration defines systemd services to run Docker containers
|
||||||
# on Container-Optimized OS (COS).
|
# on Container-Optimized OS (COS).
|
||||||
|
|
||||||
write_files:
|
write_files:
|
||||||
- path: /etc/systemd/system/${container_name}.service
|
%{ for name, container in containers ~}
|
||||||
|
- path: /etc/systemd/system/${name}.service
|
||||||
permissions: 0644
|
permissions: 0644
|
||||||
owner: root
|
owner: root
|
||||||
content: |
|
content: |
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Containerized application: ${container_name}
|
Description=Containerized application: ${name}
|
||||||
# Wait for the Docker socket to be ready
|
# Wait for the Docker socket to be ready
|
||||||
Wants=docker.socket
|
Wants=docker.socket
|
||||||
After=docker.service
|
After=docker.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
# Crucial for persistence: ensure the service restarts on exit.
|
# Crucial for persistence: ensure the service restarts on exit.
|
||||||
Restart=${restart_policy}
|
Restart=${container.restart_policy}
|
||||||
RestartSec=5s
|
RestartSec=5s
|
||||||
|
|
||||||
# Stop and remove any pre-existing container with the same name.
|
# Stop and remove any pre-existing container with the same name.
|
||||||
ExecStartPre=/usr/bin/docker stop ${container_name} || true
|
ExecStartPre=/usr/bin/docker stop ${name} || true
|
||||||
ExecStartPre=/usr/bin/docker rm ${container_name} || true
|
ExecStartPre=/usr/bin/docker rm ${name} || true
|
||||||
|
|
||||||
# Pull the latest version of the image before starting.
|
# Pull the image before starting.
|
||||||
ExecStartPre=/usr/bin/docker pull ${container_image}
|
ExecStartPre=/usr/bin/docker pull ${container.image}
|
||||||
|
|
||||||
# The main execution command: docker run.
|
# The main execution command: docker run.
|
||||||
# We use 'docker run --rm' to ensure clean removal after failure/stop.
|
|
||||||
ExecStart=/usr/bin/docker run \
|
ExecStart=/usr/bin/docker run \
|
||||||
--name ${container_name} \
|
--name ${name} \
|
||||||
%{ for key, value in container_env ~}
|
%{ for e in container.env ~}
|
||||||
-e ${key}="${value}" \
|
-e ${e.name}="${e.value}" \
|
||||||
%{ endfor ~}
|
%{ endfor ~}
|
||||||
${container_image} \
|
${container.image} \
|
||||||
%{ if container_command != "" ~}
|
%{ if container.command != "" ~}
|
||||||
"${container_command}" \
|
"${container.command}" \
|
||||||
%{ endif ~}
|
%{ endif ~}
|
||||||
%{ if length(container_args) > 0 ~}
|
%{ for arg in container.args ~}
|
||||||
%{ for arg in container_args ~}
|
# Escape single quotes: end quoted string, add escaped quote, resume quoted string
|
||||||
# Escape single quotes in arguments by ending the quoted string, inserting an escaped quote, and resuming the quoted string.
|
|
||||||
# This pattern: replace(arg, "'", "'\\''") is standard for safely passing single quotes in shell.
|
|
||||||
'${replace(arg, "'", "'\\''")}' \
|
'${replace(arg, "'", "'\\''")}' \
|
||||||
%{ endfor ~}
|
%{ endfor ~}
|
||||||
%{ endif ~}
|
|
||||||
|
|
||||||
# ExecStop is called when the service is stopped manually.
|
# ExecStop is called when the service is stopped manually.
|
||||||
ExecStop=/usr/bin/docker stop ${container_name}
|
ExecStop=/usr/bin/docker stop ${name}
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
||||||
runcmd:
|
%{ endfor ~}
|
||||||
# Reload the systemd configuration to recognize the new service file.
|
|
||||||
- systemctl daemon-reload
|
runcmd:
|
||||||
# Enable the service to start automatically on subsequent boots.
|
# Reload the systemd configuration to recognize the new service files.
|
||||||
- systemctl enable ${container_name}.service
|
- systemctl daemon-reload
|
||||||
# Start the service immediately.
|
%{ for name, container in containers ~}
|
||||||
- systemctl start ${container_name}.service
|
# Enable and start ${name} service.
|
||||||
|
- systemctl enable ${name}.service
|
||||||
|
- systemctl start ${name}.service
|
||||||
|
%{ endfor ~}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,7 @@ data "google_compute_image" "source_image" {
|
||||||
# Render the cloud-init YAML template using dynamic module inputs
|
# Render the cloud-init YAML template using dynamic module inputs
|
||||||
locals {
|
locals {
|
||||||
rendered_cloud_init = templatefile("${path.module}/cloud-init.yaml.tftpl", {
|
rendered_cloud_init = templatefile("${path.module}/cloud-init.yaml.tftpl", {
|
||||||
container_name = var.container_name,
|
containers = var.containers,
|
||||||
container_image = var.container_image,
|
|
||||||
restart_policy = var.restart_policy,
|
|
||||||
container_env = var.container_env,
|
|
||||||
container_command = var.container_command,
|
|
||||||
container_args = var.container_args,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,44 +15,28 @@ variable "machine_type" {
|
||||||
default = "e2-medium"
|
default = "e2-medium"
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "container_image" {
|
variable "containers" {
|
||||||
description = "The container image to run, must be referenced by digest (e.g., 'gcr.io/my-project/my-app@sha256:abc123...')."
|
description = "A map of containers to run on the VM. Each key is the container name, and the value specifies the container configuration."
|
||||||
type = string
|
type = map(object({
|
||||||
|
image = string
|
||||||
|
command = optional(string, "")
|
||||||
|
args = optional(list(string), [])
|
||||||
|
env = optional(list(object({
|
||||||
|
name = string
|
||||||
|
value = string
|
||||||
|
})), [])
|
||||||
|
restart_policy = optional(string, "always")
|
||||||
|
}))
|
||||||
|
|
||||||
validation {
|
validation {
|
||||||
condition = can(regex("^.+@sha256:[a-f0-9]{64}$", var.container_image))
|
condition = length(var.containers) > 0
|
||||||
error_message = "The container_image must be referenced by digest (e.g., 'gcr.io/my-project/my-app@sha256:<64 hex chars>')."
|
error_message = "At least one container must be specified."
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
variable "container_name" {
|
validation {
|
||||||
description = "The name to assign to the running Docker container."
|
condition = alltrue([for name, c in var.containers : can(regex("^.+@sha256:[a-f0-9]{64}$", c.image))])
|
||||||
type = string
|
error_message = "All container images must be referenced by digest (e.g., 'gcr.io/my-project/my-app@sha256:<64 hex chars>')."
|
||||||
default = "gce-container-app"
|
}
|
||||||
}
|
|
||||||
|
|
||||||
variable "restart_policy" {
|
|
||||||
description = "The systemd/Docker restart policy (e.g., 'always', 'on-failure', 'no')."
|
|
||||||
type = string
|
|
||||||
default = "always"
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "container_env" {
|
|
||||||
description = "A map of environment variables to set in the container."
|
|
||||||
type = map(string)
|
|
||||||
default = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "container_command" {
|
|
||||||
description = "The optional command to override the ENTRYPOINT (e.g., '/bin/bash')."
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "container_args" {
|
|
||||||
description = "Optional arguments to pass to the container command."
|
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "service_account_email" {
|
variable "service_account_email" {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue