Skip to content

Commit a0feba2

Browse files
committed
move dynamic templates from bash to terraform
1 parent 32ceefc commit a0feba2

14 files changed

Lines changed: 137 additions & 107 deletions

File tree

main.tf

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,43 @@ locals {
2222
permissions: "0644"
2323
content: |
2424
${indent(4, file("${local.rootFs}/${file}"))}
25-
EOT
25+
EOT
2626
])
27+
docker_compose_scripts = join("\n", [
28+
for name, cmd in {
29+
"init" = var.docker_compose_init
30+
"up" = var.docker_compose_up
31+
"down" = var.docker_compose_down
32+
} : <<-EOT
33+
- path: "/mnt/disks/data/${name}"
34+
permissions: "0755"
35+
content: |
36+
#!/usr/bin/env bash
37+
38+
set -eou pipefail
39+
40+
echo "Running docker compose ${name}"
41+
${cmd}
42+
EOT
43+
])
44+
env_file_content = <<-EOT
45+
- path: "/home/cloud-compose/.env"
46+
permissions: "0640"
47+
content: |
48+
HOME=/home/cloud-compose
49+
GCP_PROJECT="${var.project_id}"
50+
GCP_PROJECT_NUMBER="${var.project_number}"
51+
GCP_INSTANCE_NAME="${var.name}"
52+
GCP_REGION="${var.region}"
53+
GCP_ZONE="${var.zone}"
54+
DOCKER_COMPOSE_DIR=/mnt/disks/data/compose
55+
DOCKER_COMPOSE_REPO="${var.docker_compose_repo}"
56+
DOCKER_COMPOSE_BRANCH="${var.docker_compose_branch}"
57+
EOT
2758
cloud_init_yaml = templatefile("${path.module}/templates/cloud-init.yml", {
28-
WRITE_FILES_CONTENT = local.write_files_content,
59+
WRITE_FILES_CONTENT = local.write_files_content,
60+
DOCKER_COMPOSE_SCRIPTS = local.docker_compose_scripts,
61+
ENV_FILE_CONTENT = local.env_file_content,
2962
})
3063
}
3164

@@ -115,16 +148,6 @@ resource "google_compute_instance" "cloud-compose" {
115148
google-logging-use-fluentbit = "true"
116149
google-monitoring-enabled = "true"
117150
user-data = data.cloudinit_config.ci.part[0].content
118-
GCP_PROJECT = var.project_id
119-
GCP_PROJECT_NUMBER = var.project_number
120-
GCP_INSTANCE_NAME = var.name
121-
GCP_REGION = var.region
122-
GCP_ZONE = var.zone
123-
DOCKER_COMPOSE_REPO = var.docker_compose_repo
124-
DOCKER_COMPOSE_BRANCH = var.docker_compose_branch
125-
DOCKER_COMPOSE_INIT_CMD = var.docker_compose_init
126-
DOCKER_COMPOSE_UP_CMD = var.docker_compose_up
127-
DOCKER_COMPOSE_DOWN_CMD = var.docker_compose_down
128151
}
129152

130153
network_interface {

rootfs/etc/systemd/system/cloud-compose.service

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
[Unit]
22
Description=Docker Compose Application
3-
BindsTo=docker.service
4-
After=docker.service
53
StartLimitIntervalSec=120
64
StartLimitBurst=3
75

rootfs/etc/systemd/system/internal-services.timer

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
Description=Delay Internal Services until 10m after initial boot
33

44
[Timer]
5-
OnBootSec=10min
6-
RuntimeMaxSec=10min
5+
OnBootSec=20min
6+
RuntimeMaxSec=20min
77
Unit=internal-services.service
88

99
[Install]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/usr/bin/env bash
2+
3+
set -eou pipefail
4+
5+
# shellcheck disable=SC1091
6+
source /home/cloud-compose/profile.sh
7+
export HOME
8+
9+
if [ ! -d "$DOCKER_COMPOSE_DIR" ]; then
10+
echo "Directory '$DOCKER_COMPOSE_DIR' not found. Cloning repository."
11+
retry_until_success git clone -b "$DOCKER_COMPOSE_BRANCH" "$DOCKER_COMPOSE_REPO" "$DOCKER_COMPOSE_DIR"
12+
fi
13+
14+
pushd "$DOCKER_COMPOSE_DIR"
15+
retry_until_success git pull origin "$DOCKER_COMPOSE_BRANCH"
16+
retry_until_success /mnt/disks/data/init
17+
popd
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,31 @@
22

33
set -eou pipefail
44

5-
pushd "$DIR"
5+
# shellcheck disable=SC1091
6+
source /home/cloud-compose/profile.sh
7+
8+
pushd "$DOCKER_COMPOSE_DIR"
9+
10+
retry_until_success git pull origin "$DOCKER_COMPOSE_BRANCH"
11+
retry_until_success docker info
612

713
# Pull all images and check if any were updated
814
shopt -s nullglob
915
RESTART=0
10-
grep "image:" ./*.{yml,yaml} | awk -F': ' '{print $2}' | while read -r IMAGE; do
16+
while read -r IMAGE; do
1117
# Skip empty lines and comments
1218
if [ -z "$IMAGE" ] || [[ "$IMAGE" =~ ^# ]]; then
1319
continue
1420
fi
1521

1622
current_image_id=$(docker images --format "{{.ID}}" "$IMAGE" || echo "")
17-
docker pull "$IMAGE"
23+
retry_until_success docker pull "$IMAGE"
1824
new_image_id=$(docker images --format "{{.ID}}" "$IMAGE")
1925

2026
if [ "$current_image_id" != "$new_image_id" ]; then
2127
RESTART=1
2228
fi
23-
done
29+
done < <(grep "image:" ./*.{yml,yaml} 2>/dev/null| awk -F': ' '{print $2}')
2430
shopt -u nullglob
2531

2632
if [ "$RESTART" -eq 1 ]; then

rootfs/home/cloud-compose/host-conf.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22

33
set -eou pipefail
44

5+
# block metadata server from docker and non-root
6+
/sbin/iptables -I FORWARD -d 169.254.169.254/32 -i docker0 -j DROP
7+
/sbin/iptables -A OUTPUT -m owner ! --uid-owner 0 -d 169.254.169.254/32 -p tcp --dport 80 -j DROP
8+
59
# restart services we've overwritten files for
610
systemctl restart fluent-bit
7-
systemctl restart --no-block docker
11+
systemctl restart docker
812

913
# since COS is read only FS, install docker compose/buildx in home directory
1014
if [ ! -f "/home/cloud-compose/.docker/cli-plugins/docker-compose" ]; then

rootfs/home/cloud-compose/host-init.sh

Lines changed: 7 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,68 +3,28 @@
33
set -euo pipefail
44

55
cleanup() {
6-
rm tmp.attr env.tmp || echo ""
6+
rm tmp.attr .env.tmp || echo ""
77
popd
88
}
99

10-
# make sure out internal services dir exists
11-
DIR=/mnt/disks/data/libops
12-
if [ ! -d "$DIR" ]; then
13-
mkdir "$DIR"
14-
fi
15-
cp /etc/libops/docker-compose.yaml /mnt/disks/data/libops
16-
1710
pushd /home/cloud-compose
1811

1912
trap cleanup EXIT
2013

21-
if [ ! -f env ]; then
22-
touch env
14+
if [ -f .env ]; then
15+
cp .env .env.tmp
2316
fi
2417

2518
curl -sf \
2619
-H "Metadata-Flavor: Google" \
2720
"http://metadata.google.internal/computeMetadata/v1/?recursive=true" > tmp.attr
2821

29-
echo "HOME=/home/cloud-compose" > env.tmp
30-
for K in $(jq -r '.instance.attributes | keys | .[]' tmp.attr | grep -E '(DOCKER|GCP|LIBOPS)'); do
31-
V=$(jq -r .instance.attributes."$K" tmp.attr)
32-
if [[ "$V" =~ [[:space:]\$\`\\\"\'\(\)\{\}\[\]\|\&\;\<\>\*\?] ]]; then
33-
echo "$K=\"$V\"" >> env.tmp
34-
else
35-
echo "$K=$V" >> env.tmp
36-
fi
37-
done
38-
3922
{
4023
echo "GCP_PUBLIC_IP=$(jq -r '.instance.networkInterfaces[0].accessConfigs[0].externalIp' tmp.attr)"
4124
echo "GCP_PRIVATE_IP=$(jq -r '.instance.networkInterfaces[0].ip' tmp.attr)"
42-
} >> env.tmp
25+
} >> .env.tmp
4326

44-
if ! diff <(md5sum env.tmp) <(md5sum env); then
45-
mv env.tmp env
46-
cp env /mnt/disks/data/libops/.env
27+
if ! diff <(md5sum .env.tmp) <(md5sum .env); then
28+
mv .env.tmp .env
29+
cp .env /mnt/disks/data/libops/
4730
fi
48-
49-
# shellcheck disable=SC1091
50-
. ./env
51-
52-
# generate the docker compose init/up/down commands
53-
# used by the systemd service
54-
SCRIPT_DIR="/mnt/disks/data"
55-
declare -A SCRIPTS=(
56-
["init"]="${DOCKER_COMPOSE_INIT_CMD}"
57-
["up"]="${DOCKER_COMPOSE_UP_CMD}"
58-
["down"]="${DOCKER_COMPOSE_DOWN_CMD}"
59-
)
60-
for name in "${!SCRIPTS[@]}"; do
61-
cat << EOT > "${SCRIPT_DIR}/${name}"
62-
#!/usr/bin/env bash
63-
64-
set -eou pipefail
65-
66-
echo "Running dokcer compose ${name}"
67-
${SCRIPTS[${name}]}
68-
EOT
69-
chmod +x "${SCRIPT_DIR}/${name}"
70-
done

rootfs/home/cloud-compose/init-app.sh

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env bash
2+
3+
# shellcheck disable=SC1091
4+
. /home/cloud-compose/.env
5+
6+
DEFAULT_MAX_RETRIES=10
7+
DEFAULT_SLEEP_INCREMENT=5
8+
9+
retry_until_success() {
10+
local command_to_run=("$@")
11+
local MAX_RETRIES="${MAX_RETRIES:-$DEFAULT_MAX_RETRIES}"
12+
local SLEEP_INCREMENT="${SLEEP_INCREMENT:-$DEFAULT_SLEEP_INCREMENT}"
13+
local RETRIES=0
14+
15+
while true; do
16+
timeout 300 "${command_to_run[@]}"
17+
local exit_code=$?
18+
19+
if [ "$exit_code" -eq 0 ]; then
20+
return 0
21+
fi
22+
23+
RETRIES=$((RETRIES + 1))
24+
25+
if [ "$RETRIES" -ge "$MAX_RETRIES" ]; then
26+
echo "FAILURE: Command '${command_to_run[*]}' failed after $MAX_RETRIES attempts (Last exit code: $exit_code)." >&2
27+
return 1
28+
fi
29+
30+
local SLEEP=$(( SLEEP_INCREMENT * RETRIES ))
31+
echo "Command '${command_to_run[*]}' failed (Exit code: $exit_code). Retrying in $SLEEP seconds... (Attempt $RETRIES/$MAX_RETRIES)" >&2
32+
sleep "$SLEEP"
33+
done
34+
}

rootfs/home/cloud-compose/rotate-keys-app.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ set -eou pipefail
55
pushd /home/cloud-compose
66

77
# shellcheck disable=SC1091
8-
. ./env
8+
source /home/cloud-compose/profile.sh
99

10-
if [ -d /mnt/disks/data/compose/secrets ]; then
10+
if [ -d "$DOCKER_COMPOSE_DIR/secrets" ]; then
1111
exit 0
1212
fi
1313

1414
bash rotate-keys.sh \
1515
"$GCP_INSTANCE_NAME@$GCP_PROJECT.iam.gserviceaccount.com" \
1616
"$GCP_PROJECT" \
17-
/mnt/disks/data/compose/secrets/GOOGLE_APPLICATION_CREDENTIALS
17+
"$DOCKER_COMPOSE_DIR/secrets/GOOGLE_APPLICATION_CREDENTIALS"
1818

1919
popd

0 commit comments

Comments
 (0)