Skip to content

Commit 2ed3311

Browse files
committed
Checkout compose project based on repo name
to allow multiple projects on the same VM
1 parent b82f724 commit 2ed3311

13 files changed

Lines changed: 158 additions & 47 deletions

File tree

examples/ojs/main.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ resource "random_shuffle" "zone" {
44
}
55

66
module "production" {
7-
source = "git::https://github.com/libops/cloud-compose?ref=0.0.1"
7+
source = "git::https://github.com/libops/cloud-compose?ref=0.3.0"
88

99
name = "ojs-production"
1010
project_id = var.project_id
@@ -18,7 +18,7 @@ module "production" {
1818
}
1919

2020
module "staging" {
21-
source = "git::https://github.com/libops/cloud-compose?ref=0.0.1"
21+
source = "git::https://github.com/libops/cloud-compose?ref=0.3.0"
2222

2323
name = "ojs-staging"
2424
project_id = var.project_id

examples/ojs/variables.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ variable "docker_compose_repo" {
2020
}
2121

2222
variable "docker_compose_init" {
23-
type = string
24-
default = ""
23+
type = list(string)
24+
default = []
2525
description = "After cloning the docker compose git repo, any initialization that needs to happen before the docker compose project can start"
2626
}
2727

main.tf

Lines changed: 93 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,19 @@ resource "time_static" "snapshot_time_static" {}
1919
locals {
2020
rootFs = "${path.module}/rootfs"
2121
additional_rootfs = var.rootfs != "" ? var.rootfs : ""
22+
# Input example: "https://github.com/my-org/my-repo.git"
23+
# This regex removes everything from the start up to the first single slash (after the protocol)
24+
repo_path = replace(var.docker_compose_repo, "/^[^:]+://[^/]+/", "")
25+
26+
# base the docker compose project name on the repo + branch
27+
clean_repo_path = replace(format("%s-%s", trim(local.repo_path, "/"), var.docker_compose_branch), "/^[^:]+://[^/]+/", "")
28+
compose_project_name = lower(
29+
replace(
30+
replace(local.clean_repo_path, ".git", ""),
31+
"/[^a-zA-Z0-9]/",
32+
"-"
33+
)
34+
)
2235

2336
# Get files from base rootfs
2437
base_files = fileset(local.rootFs, "**")
@@ -41,7 +54,7 @@ locals {
4154
EOT
4255
])
4356
docker_compose_scripts = join("\n", [
44-
for name, cmd in {
57+
for name, cmds in {
4558
"init" = var.docker_compose_init
4659
"up" = var.docker_compose_up
4760
"down" = var.docker_compose_down
@@ -53,8 +66,12 @@ EOT
5366
5467
set -eou pipefail
5568
69+
source /home/cloud-compose/profile.sh
70+
pushd "$${DOCKER_COMPOSE_DIR}"
71+
5672
echo "Running docker compose ${name}"
57-
${cmd}
73+
${join("\n ", cmds)}
74+
popd
5875
EOT
5976
])
6077
env_file_content = <<-EOT
@@ -67,7 +84,8 @@ EOT
6784
GCP_INSTANCE_NAME="${var.name}"
6885
GCP_REGION="${var.region}"
6986
GCP_ZONE="${var.zone}"
70-
DOCKER_COMPOSE_DIR=/mnt/disks/data/compose
87+
COMPOSE_PROJECT_NAME=${replace(local.compose_project_name, "/-+/", "-")}
88+
DOCKER_COMPOSE_DIR=/mnt/disks/data${local.repo_path}/${var.docker_compose_branch}
7189
DOCKER_COMPOSE_REPO="${var.docker_compose_repo}"
7290
DOCKER_COMPOSE_BRANCH="${var.docker_compose_branch}"
7391
EOT
@@ -134,7 +152,7 @@ resource "google_compute_disk" "boot" {
134152
# force re-create VM when cloud-init changes
135153
name = format("%s-boot-%s", var.name, md5(data.cloudinit_config.ci.rendered))
136154
project = var.project_id
137-
type = "hyperdisk-balanced"
155+
type = var.disk_type
138156
zone = var.zone
139157
size = 15
140158
image = "projects/cos-cloud/global/images/${var.os}"
@@ -144,7 +162,7 @@ resource "google_compute_disk" "boot" {
144162
resource "google_compute_disk" "data" {
145163
name = format("%s-data-disk", var.name)
146164
project = var.project_id
147-
type = "hyperdisk-balanced"
165+
type = var.disk_type
148166
zone = var.zone
149167
size = 20
150168
image = "debian-13-trixie-v20251111"
@@ -154,14 +172,13 @@ resource "google_compute_disk" "data" {
154172
resource "google_compute_disk" "docker-volumes" {
155173
name = format("%s-docker-volumes", var.name)
156174
project = var.project_id
157-
type = "hyperdisk-balanced"
175+
type = var.disk_type
158176
zone = var.zone
159177
size = var.disk_size_gb
160178
image = "debian-13-trixie-v20251111"
161179
physical_block_size_bytes = 4096
162180
}
163181

164-
165182
# Daily snapshot schedule for production docker volume disk
166183
resource "google_compute_resource_policy" "daily_snapshot" {
167184
count = var.run_snapshots ? 1 : 0
@@ -192,13 +209,6 @@ resource "google_compute_resource_policy" "daily_snapshot" {
192209
}
193210
}
194211
}
195-
resource "google_compute_disk_resource_policy_attachment" "daily_snapshot" {
196-
count = var.run_snapshots ? 1 : 0
197-
name = google_compute_resource_policy.daily_snapshot[0].name
198-
disk = google_compute_disk.docker-volumes.name
199-
project = var.project_id
200-
zone = var.zone
201-
}
202212

203213
resource "google_compute_resource_policy" "weekly_snapshot" {
204214
count = var.run_snapshots ? 1 : 0
@@ -228,10 +238,26 @@ resource "google_compute_resource_policy" "weekly_snapshot" {
228238
}
229239
}
230240

241+
resource "google_compute_disk_resource_policy_attachment" "daily_snapshot" {
242+
for_each = var.run_snapshots ? toset([
243+
google_compute_disk.docker-volumes.name,
244+
google_compute_disk.data.name
245+
]) : []
246+
247+
name = google_compute_resource_policy.daily_snapshot[0].name
248+
disk = each.value
249+
project = var.project_id
250+
zone = var.zone
251+
}
252+
231253
resource "google_compute_disk_resource_policy_attachment" "weekly_snapshot" {
232-
count = var.run_snapshots ? 1 : 0
254+
for_each = var.run_snapshots ? toset([
255+
google_compute_disk.docker-volumes.name,
256+
google_compute_disk.data.name
257+
]) : []
258+
233259
name = google_compute_resource_policy.weekly_snapshot[0].name
234-
disk = google_compute_disk.docker-volumes.name
260+
disk = each.value
235261
project = var.project_id
236262
zone = var.zone
237263
}
@@ -251,7 +277,7 @@ resource "google_compute_disk" "overlay_disk" {
251277
count = local.use_overlay ? 1 : 0
252278
name = data.google_compute_snapshot.latest_prod[0].name
253279
project = var.project_id
254-
type = "hyperdisk-balanced"
280+
type = var.disk_type
255281
zone = var.zone
256282
snapshot = data.google_compute_snapshot.latest_prod[0].self_link
257283
physical_block_size_bytes = 4096
@@ -322,10 +348,7 @@ resource "google_compute_instance" "cloud-compose" {
322348
service_account {
323349
email = google_service_account.cloud-compose.email
324350
scopes = [
325-
"https://www.googleapis.com/auth/logging.write",
326-
"https://www.googleapis.com/auth/monitoring.write",
327-
"https://www.googleapis.com/auth/devstorage.read_only",
328-
"https://www.googleapis.com/auth/iam",
351+
"https://www.googleapis.com/auth/cloud-platform"
329352
]
330353
}
331354

@@ -335,12 +358,18 @@ resource "google_compute_instance" "cloud-compose" {
335358
enable_vtpm = "true"
336359
}
337360

338-
depends_on = [google_compute_disk.overlay_disk]
339361
lifecycle {
340-
replace_triggered_by = [
341-
google_compute_disk.overlay_disk
342-
]
362+
precondition {
363+
condition = (
364+
startswith(var.machine_type, "e2") ?
365+
contains(["pd-ssd", "pd-standard"], var.disk_type) :
366+
true
367+
)
368+
error_message = "When using an 'e2' machine type, 'disk_type' must be 'pd-ssd' or 'pd-standard'."
369+
}
343370
}
371+
372+
depends_on = [google_compute_disk.overlay_disk]
344373
}
345374

346375
# machine needs to be able to suspend itself
@@ -394,6 +423,12 @@ resource "google_service_account_iam_member" "app-keys" {
394423
member = "serviceAccount:${google_service_account.cloud-compose.email}"
395424
}
396425

426+
resource "google_service_account_iam_member" "self_jwt_signer_policy" {
427+
service_account_id = google_service_account.app.id
428+
role = "roles/iam.serviceAccountTokenCreator"
429+
member = format("serviceAccount:%s", google_service_account.app.email)
430+
}
431+
397432
# =============================================================================
398433
# CLOUD RUN INGRESS
399434
# =============================================================================
@@ -486,3 +521,36 @@ resource "google_project_iam_member" "gce-start" {
486521
role = data.google_project_iam_custom_role.gce-start.name
487522
member = "serviceAccount:${google_service_account.ppb.email}"
488523
}
524+
525+
resource "google_compute_firewall" "allow_ssh_ipv4" {
526+
project = var.project_id
527+
name = format("allow-ssh-ipv4-%s", var.name)
528+
network = "default"
529+
priority = 10
530+
direction = "INGRESS"
531+
532+
allow {
533+
protocol = "tcp"
534+
ports = ["22"]
535+
}
536+
target_tags = [var.name]
537+
538+
source_ranges = length(var.allowed_ssh_ipv4) > 0 ? var.allowed_ssh_ipv4 : ["127.0.0.1/32"]
539+
}
540+
541+
resource "google_compute_firewall" "allow_ssh_ipv6" {
542+
project = var.project_id
543+
name = format("allow-ssh-ipv6-%s", var.name)
544+
network = "default"
545+
priority = 10
546+
direction = "INGRESS"
547+
548+
allow {
549+
protocol = "tcp"
550+
ports = ["22"]
551+
}
552+
553+
target_tags = [var.name]
554+
555+
source_ranges = length(var.allowed_ssh_ipv6) > 0 ? var.allowed_ssh_ipv6 : ["127.0.0.1/32"]
556+
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ StartLimitIntervalSec=120
44
StartLimitBurst=3
55

66
[Service]
7-
Environment="HOME=/home/cloud-compose"
8-
WorkingDirectory=/mnt/disks/data/compose
9-
ExecStartPre=-/bin/bash /home/cloud-compose/rotate-keys-app.sh
7+
EnvironmentFile=/home/cloud-compose/.env
108
ExecStart=/mnt/disks/data/up
119
ExecStop=/mnt/disks/data/down
1210
Restart=on-failure

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ StartLimitBurst=3
99

1010
[Service]
1111
Environment="HOME=/home/cloud-compose"
12-
WorkingDirectory=/mnt/disks/data/libops
12+
WorkingDirectory=/mnt/disks/data/libops-internal
1313
ExecStartPre=/bin/bash /home/cloud-compose/rotate-keys-internal.sh
14-
ExecStartPre=/usr/bin/test -f /mnt/disks/data/libops/GOOGLE_APPLICATION_CREDENTIALS
14+
ExecStartPre=/usr/bin/test -f /mnt/disks/data/libops-internal/GOOGLE_APPLICATION_CREDENTIALS
1515
ExecStart=/usr/bin/docker compose up
1616
ExecStop=/usr/bin/docker compose down
1717
Restart=on-failure

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@ source /home/cloud-compose/profile.sh
77
export HOME
88

99
if [ ! -d "$DOCKER_COMPOSE_DIR" ]; then
10+
mkdir -p "$DOCKER_COMPOSE_DIR"
1011
echo "Directory '$DOCKER_COMPOSE_DIR' not found. Cloning repository."
1112
retry_until_success git clone -b "$DOCKER_COMPOSE_BRANCH" "$DOCKER_COMPOSE_REPO" "$DOCKER_COMPOSE_DIR"
1213
fi
1314

1415
pushd "$DOCKER_COMPOSE_DIR"
1516
retry_until_success git pull origin "$DOCKER_COMPOSE_BRANCH"
17+
# set COMPOSE_PROJECT_NAME from value set in cloud-compose
18+
# sourced from /home/cloud-compose/profile.sh which loads /home/cloud-compose/.env
19+
update_env COMPOSE_PROJECT_NAME "$COMPOSE_PROJECT_NAME"
20+
update_env SITE_NAME "$GCP_INSTANCE_NAME"
1621
retry_until_success /mnt/disks/data/init
1722
popd

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ curl -sf \
2626

2727
if ! diff <(md5sum .env.tmp) <(md5sum .env); then
2828
mv .env.tmp .env
29-
cp .env /mnt/disks/data/libops/
29+
cp .env /mnt/disks/data/libops-internal/
3030
fi

rootfs/home/cloud-compose/profile.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,21 @@ retry_until_success() {
3434
sleep "$SLEEP"
3535
done
3636
}
37+
38+
# update .env variables
39+
# usage:
40+
# update_env var value
41+
# e.g. update_env DOCKER_COMPOSE_PROJECT foo
42+
# will created/override DOCKER_COMPOSE_PROJECT=foo in $(pwd)/.env
43+
update_env() {
44+
VAR_NAME="$1"
45+
VALUE="$2"
46+
if [ ! -f .env ]; then
47+
touch .env
48+
fi
49+
if grep -Eq "^${VAR_NAME}=" .env; then
50+
sed -i "s/^$VAR_NAME=.*/$VAR_NAME=$VALUE/" .env
51+
else
52+
echo "${VAR_NAME}=${VALUE}" | tee -a .env
53+
fi
54+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ pushd /home/cloud-compose
77
# shellcheck disable=SC1091
88
source /home/cloud-compose/profile.sh
99

10-
if [ -d "$DOCKER_COMPOSE_DIR/secrets" ]; then
11-
exit 0
10+
if [ ! -d "$DOCKER_COMPOSE_DIR/secrets" ]; then
11+
mkdir "$DOCKER_COMPOSE_DIR/secrets"
1212
fi
1313

1414
bash rotate-keys.sh \

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ source /home/cloud-compose/profile.sh
1010
bash rotate-keys.sh \
1111
"internal-$GCP_INSTANCE_NAME@$GCP_PROJECT.iam.gserviceaccount.com" \
1212
"$GCP_PROJECT" \
13-
/mnt/disks/data/libops/GOOGLE_APPLICATION_CREDENTIALS
13+
/mnt/disks/data/libops-internal/GOOGLE_APPLICATION_CREDENTIALS
1414

1515
popd

0 commit comments

Comments
 (0)