Files
ENI-projet-piscine/infra/terraform/environments/vm-eni/main.tf
T
Johan LEROYandClaude Opus 5 357cf996ed
Infra / Formatage et validation Terraform (push) Successful in 9s
fix(infra): donne au runner un nom distinct de son label
--name reprenait runner_labels : un runner et son label portaient le meme
eni-g3. Deux machines qui reprendraient cette racine s'enregistreraient sous
le meme nom, ce que GitHub refuse. Le nom vaut desormais celui de l'hote,
resolu sur la machine, et runner_nom permet de le forcer.

Point 2 de la revue de la PR #144.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 12:36:38 +02:00

138 lines
5.0 KiB
Terraform

# Pourquoi : Terraform provisionne la machine, GitHub Actions la deploie (ADR 0010). Rien ici ne
# construit d'image ni ne lance de conteneur : la livraison reste portee par `deploy.yml` et
# `make stack-up`, et un `apply` n'interrompt pas la stack qui tourne.
# Piege : seul le bloc `triggers` d'un `null_resource` atterrit dans le state. Ni le jeton du
# runner ni la cle SSH n'y figurent, et ne doivent jamais y etre ajoutes pour forcer un rejeu.
# Contrainte : pas de provisioner `destroy` sur le runner. Il imposerait une connexion ne lisant
# que `self`, donc le chemin de la cle SSH dans le state, et `svc.sh uninstall` ne desinscrit pas
# le runner cote GitHub : le retrait reste manuel, depuis les parametres du depot.
# Ref : ADR 0009 pour les deux environnements, `scripts/provision-host.sh` pour leur contenu.
locals {
sudo = var.ssh_user == "root" ? "" : "sudo "
en_tant_que = "${var.ssh_user == "root" ? "" : "sudo "}runuser -u ${var.proprietaire} --"
provisionneur = "${path.root}/../../../../scripts/provision-host.sh"
runner_archive = "actions-runner-linux-x64-${var.runner_version}.tar.gz"
# Substitution shell, evaluee par le sh -c distant : un nom de runner doit etre unique dans
# le depot, le nom d'hote l'est deja et le reste si cette racine sert a une autre machine.
runner_nom = var.runner_nom != "" ? var.runner_nom : "$(hostname -s)"
}
resource "null_resource" "docker_engine" {
triggers = {
hote = var.ssh_host
user = var.proprietaire
}
connection {
type = "ssh"
host = var.ssh_host
port = var.ssh_port
user = var.ssh_user
private_key = file(pathexpand(var.ssh_private_key_path))
timeout = "5m"
}
provisioner "remote-exec" {
inline = [
<<-EOT
set -eu
id ${var.proprietaire} >/dev/null 2>&1 || {
echo "l'utilisateur ${var.proprietaire} n'existe pas sur la machine" >&2
exit 1
}
command -v docker >/dev/null || ${local.sudo}sh -c 'curl -fsSL https://get.docker.com | sh'
${local.sudo}systemctl enable --now docker
${local.sudo}usermod -aG docker ${var.proprietaire}
${local.sudo}docker compose version
EOT
]
}
}
# `provision-host.sh` verifie lui-meme docker, compose et la sortie HTTPS, puis prepare un clone
# par environnement, son `.env` et son certificat. Il est rejouable : un `.env` existant n'est
# jamais reecrit, un certificat present jamais regenere.
resource "null_resource" "environnements" {
depends_on = [null_resource.docker_engine]
triggers = {
script = filesha256(local.provisionneur)
racine = var.racine
depot = var.depot_url
}
connection {
type = "ssh"
host = var.ssh_host
port = var.ssh_port
user = var.ssh_user
private_key = file(pathexpand(var.ssh_private_key_path))
timeout = "5m"
}
provisioner "file" {
source = local.provisionneur
destination = "/tmp/provision-host.sh"
}
provisioner "remote-exec" {
inline = [
<<-EOT
set -eu
${local.sudo}env RACINE='${var.racine}' \
REPO_URL='${var.depot_url}' \
PROPRIETAIRE='${var.proprietaire}' \
PUBLIC_IP='${var.adresse_publique}' \
bash /tmp/provision-host.sh
rm -f /tmp/provision-host.sh
EOT
]
}
}
# Piege : le jeton d'enregistrement expire en une heure. Un `apply` rejoue cette ressource des
# que `runner_version`, `runner_labels` ou `runner_nom` change, et redemande donc un jeton frais.
resource "null_resource" "runner_github" {
depends_on = [null_resource.environnements]
triggers = {
version = var.runner_version
labels = var.runner_labels
nom = local.runner_nom
dossier = var.runner_dossier
}
connection {
type = "ssh"
host = var.ssh_host
port = var.ssh_port
user = var.ssh_user
private_key = file(pathexpand(var.ssh_private_key_path))
timeout = "5m"
}
provisioner "remote-exec" {
inline = [
<<-EOT
set -eu
${local.sudo}install -d -o ${var.proprietaire} -g ${var.proprietaire} ${var.runner_dossier}
if [ ! -x ${var.runner_dossier}/config.sh ]; then
curl -fsSL -o /tmp/${local.runner_archive} \
https://github.com/actions/runner/releases/download/v${var.runner_version}/${local.runner_archive}
${local.sudo}tar -xzf /tmp/${local.runner_archive} -C ${var.runner_dossier}
${local.sudo}chown -R ${var.proprietaire}:${var.proprietaire} ${var.runner_dossier}
rm -f /tmp/${local.runner_archive}
fi
if [ ! -f ${var.runner_dossier}/.runner ]; then
${local.en_tant_que} sh -c 'cd ${var.runner_dossier} && ./config.sh --unattended --replace \
--url ${var.runner_url} --token ${var.runner_token} \
--labels ${var.runner_labels} --name ${local.runner_nom} --work _work'
${local.sudo}${var.runner_dossier}/svc.sh install ${var.proprietaire}
fi
${local.sudo}${var.runner_dossier}/svc.sh start
EOT
]
}
}