tvl-depot/ops/terraform/deploy-nixos/main.tf
Florian Klink 774194652b feat(ops/terraform): add trigger to deploy-nixos, remove target_name
This allows passing in custom triggers to trigger a (re)deploy.

For example, a caller can put an AWS instance ID into the triggers to
cause a redeploy whenever the instance ID has changed.

The `target_name` terraform variable was doing something similar, but
`triggers` is more generic, allowing multiple triggers, without having
to stringify them.

We also don't need to trigger on the attrpath - it can be changed, and
as long as it still evaluates to the same
`data.external.nixos_system.result.drv` (which is checked on every
plan), no redeploy needs to be made.

Change-Id: I94ce787a50830b87b6f53c08e042e4abe4036bdd
Reviewed-on: https://cl.tvl.fyi/c/depot/+/8191
Tested-by: BuildkiteCI
Reviewed-by: tazjin <tazjin@tvl.su>
Autosubmit: flokli <flokli@flokli.de>
2023-03-03 14:53:43 +00:00

108 lines
2.8 KiB
HCL

# This module deploys a NixOS host by building a system closure
# located at the specified attribute in the current repository.
#
# The closure's derivation path is persisted in the Terraform state to
# determine after Nix evaluation whether the system closure has
# changed and needs to be built/deployed.
#
# The system configuration is then built (or substituted) on the
# machine that runs `terraform apply`, then copied and activated on
# the target machine using `nix-copy-closure`.
variable "attrpath" {
description = "attribute set path pointing to the NixOS system closure"
type = string
}
variable "target_host" {
description = "address (IP or hostname) at which the target is reachable"
type = string
}
variable "entrypoint" {
description = <<EOT
Path to a .nix file (or directory containing `default.nix` file)
that provides the attrset specified in `closure`.
If unset, asks git for the root of the repository.
EOT
type = string
default = ""
}
variable "target_user" {
description = "username on the target machine"
type = string
}
variable "target_user_ssh_key" {
description = "SSH key to use for connecting to the target"
type = string
sensitive = true
}
variable "triggers" {
type = map(string)
description = "Triggers for deploy"
default = {}
}
# Fetch the derivation hash for the NixOS system.
data "external" "nixos_system" {
program = ["${path.module}/nixos-eval.sh"]
query = {
attrpath = var.attrpath
entrypoint = var.entrypoint
}
}
# Deploy the NixOS configuration if anything changed.
resource "null_resource" "nixos_deploy" {
connection {
type = "ssh"
host = var.target_host
user = var.target_user
private_key = var.target_user_ssh_key
}
# 1. Wait for SSH to become available.
provisioner "remote-exec" {
inline = ["true"]
}
# 2. Build NixOS system.
provisioner "local-exec" {
command = "nix-build ${data.external.nixos_system.result.drv} --no-out-link"
}
# 3. Copy closure to the target.
provisioner "local-exec" {
command = "${path.module}/nixos-copy.sh"
environment = {
SYSTEM_DRV = data.external.nixos_system.result.drv
TARGET_HOST = var.target_host
DEPLOY_KEY = var.target_user_ssh_key
TARGET_USER = var.target_user
}
}
# 4. Activate closure on the target.
provisioner "remote-exec" {
inline = [
"set -eu",
"SYSTEM=$(nix-build ${data.external.nixos_system.result.drv} --no-out-link)",
"sudo nix-env --profile /nix/var/nix/profiles/system --set $SYSTEM",
"sudo $SYSTEM/bin/switch-to-configuration switch",
]
}
triggers = merge({
nixos_drv = data.external.nixos_system.result.drv
target_host = var.target_host
}, var.triggers)
}
output "nixos_drv" {
value = data.external.nixos_system.result
}