add toplevel machines-json that can deploy all hosts

This commit is contained in:
Jörg Thalheim
2023-09-28 14:13:23 +02:00
parent 08cfa7d7b2
commit 82bf417e17
6 changed files with 132 additions and 82 deletions

View File

@@ -2,15 +2,17 @@ import argparse
import json
import os
import subprocess
from pathlib import Path
from typing import Any
from ..dirs import get_clan_flake_toplevel
from ..nix import nix_command, nix_config, nix_eval
from ..secrets.generate import generate_secrets
from ..secrets.upload import upload_secrets
from ..nix import nix_build, nix_command, nix_config
from ..secrets.generate import run_generate_secrets
from ..secrets.upload import run_upload_secrets
from ..ssh import Host, HostGroup, HostKeyCheck, parse_deployment_address
def deploy_nixos(hosts: HostGroup) -> None:
def deploy_nixos(hosts: HostGroup, clan_dir: Path) -> None:
"""
Deploy to all hosts in parallel
"""
@@ -38,8 +40,11 @@ def deploy_nixos(hosts: HostGroup) -> None:
flake_attr = h.meta.get("flake_attr", "")
generate_secrets(flake_attr)
upload_secrets(flake_attr)
if generate_secrets_script := h.meta.get("generate_secrets"):
run_generate_secrets(generate_secrets_script, clan_dir)
if upload_secrets_script := h.meta.get("upload_secrets"):
run_upload_secrets(upload_secrets_script, clan_dir)
target_host = h.meta.get("target_host")
if target_host:
@@ -74,31 +79,65 @@ def deploy_nixos(hosts: HostGroup) -> None:
hosts.run_function(deploy)
# FIXME: we want some kind of inventory here.
def update(args: argparse.Namespace) -> None:
clan_dir = get_clan_flake_toplevel().as_posix()
machine = args.machine
def build_json(targets: list[str]) -> list[dict[str, Any]]:
outpaths = subprocess.run(
nix_build(targets),
stdout=subprocess.PIPE,
check=True,
text=True,
).stdout
parsed = []
for outpath in outpaths.splitlines():
parsed.append(json.loads(Path(outpath).read_text()))
return parsed
def get_all_machines(clan_dir: Path) -> HostGroup:
config = nix_config()
system = config["system"]
what = f'{clan_dir}#clanInternals.machines-json."{system}"'
machines = build_json([what])[0]
address = json.loads(
subprocess.run(
nix_eval(
[
f'{clan_dir}#clanInternals.machines."{system}"."{machine}".deploymentAddress'
]
),
stdout=subprocess.PIPE,
check=True,
text=True,
).stdout
)
host = parse_deployment_address(machine, address)
print(f"deploying {machine}")
deploy_nixos(HostGroup([host]))
hosts = []
for name, machine in machines.items():
host = parse_deployment_address(
name, machine["deploymentAddress"], meta=machine
)
hosts.append(host)
return HostGroup(hosts)
def get_selected_machines(machine_names: list[str], clan_dir: Path) -> HostGroup:
config = nix_config()
system = config["system"]
what = []
for name in machine_names:
what.append(f'{clan_dir}#clanInternals.machines."{system}"."{name}".json')
machines = build_json(what)
hosts = []
for i, machine in enumerate(machines):
host = parse_deployment_address(machine_names[i], machine["deploymentAddress"])
hosts.append(host)
return HostGroup(hosts)
# FIXME: we want some kind of inventory here.
def update(args: argparse.Namespace) -> None:
clan_dir = get_clan_flake_toplevel()
if len(args.machines) == 0:
machines = get_all_machines(clan_dir)
else:
machines = get_selected_machines(args.machines, clan_dir)
deploy_nixos(machines, clan_dir)
def register_update_parser(parser: argparse.ArgumentParser) -> None:
parser.add_argument("machine", type=str)
parser.add_argument(
"machines",
type=str,
help="machine to update. if empty, update all machines",
nargs="*",
default=[],
)
parser.set_defaults(func=update)