1
0
forked from clan/clan-core

API: migrate add machine to inventory

This commit is contained in:
Johannes Kirschbauer 2024-07-01 21:55:42 +02:00
parent d8380ebb98
commit df934334a2
Signed by: hsjobeki
SSH Key Fingerprint: SHA256:vX3utDqig7Ph5L0JPv87ZTPb/w7cMzREKVZzzLFg9qU
2 changed files with 78 additions and 15 deletions

View File

@ -1,30 +1,85 @@
import argparse
import json
import logging
from dataclasses import dataclass
import re
from pathlib import Path
from typing import Any
from clan_cli.api import API
from clan_cli.config.machine import set_config_for_machine
from clan_cli.errors import ClanError
from clan_cli.git import commit_file
from clan_cli.inventory import Inventory, Machine, dataclass_to_dict
log = logging.getLogger(__name__)
@dataclass
class MachineCreateRequest:
name: str
config: dict[str, Any]
@API.register
def create_machine(flake_dir: str | Path, machine: MachineCreateRequest) -> None:
set_config_for_machine(Path(flake_dir), machine.name, machine.config)
def create_machine(flake_dir: str | Path, machine: Machine) -> None:
hostname_regex = r"^(?!-)[A-Za-z0-9-]{1,63}(?<!-)$"
if not re.match(hostname_regex, machine.name):
raise ClanError("Machine name must be a valid hostname")
inventory = Inventory(machines={}, services={})
inventory_file = Path(flake_dir) / "inventory.json"
if inventory_file.exists():
with open(inventory_file) as f:
try:
res = json.load(f)
inventory = Inventory.from_dict(res)
except json.JSONDecodeError as e:
raise ClanError(f"Error decoding inventory file: {e}")
inventory.machines.update({machine.name: machine})
with open(inventory_file, "w") as g:
d = dataclass_to_dict(inventory)
json.dump(d, g, indent=2)
if flake_dir is not None:
commit_file(inventory_file, Path(flake_dir))
def create_command(args: argparse.Namespace) -> None:
create_machine(args.flake, MachineCreateRequest(args.machine, dict()))
create_machine(
args.flake,
Machine(
name=args.machine,
system=args.system,
description=args.description,
tags=args.tags,
icon=args.icon,
),
)
def register_create_parser(parser: argparse.ArgumentParser) -> None:
parser.add_argument("machine", type=str)
parser.set_defaults(func=create_command)
parser.add_argument(
"--system",
type=str,
default=None,
help="Host platform to use. i.e. 'x86_64-linux' or 'aarch64-darwin' etc.",
metavar="PLATFORM",
)
parser.add_argument(
"--description",
type=str,
default=None,
help="A description of the machine.",
)
parser.add_argument(
"--icon",
type=str,
default=None,
help="Path to an icon to use for the machine. - Must be a path to icon file relative to the flake directory, or a public url.",
metavar="PATH",
)
parser.add_argument(
"--tags",
nargs="+",
default=[],
help="Tags to associate with the machine. Can be used to assign multiple machines to services.",
)

View File

@ -7,7 +7,8 @@ from clan_cli.config.machine import (
verify_machine_config,
)
from clan_cli.config.schema import machine_schema
from clan_cli.machines.create import MachineCreateRequest, create_machine
from clan_cli.inventory import Machine
from clan_cli.machines.create import create_machine
from clan_cli.machines.list import list_machines
@ -22,14 +23,21 @@ def test_create_machine_on_minimal_clan(test_flake_minimal: FlakeForTest) -> Non
assert list_machines(test_flake_minimal.path) == []
create_machine(
test_flake_minimal.path,
MachineCreateRequest(
name="foo", config=dict(nixpkgs=dict(hostSystem="x86_64-linux"))
Machine(
name="foo",
system="x86_64-linux",
description="A test machine",
tags=["test"],
icon=None,
),
)
assert list_machines(test_flake_minimal.path) == ["foo"]
# Writes into settings.json
set_config_for_machine(
test_flake_minimal.path, "foo", dict(services=dict(openssh=dict(enable=True)))
)
config = config_for_machine(test_flake_minimal.path, "foo")
assert config["services"]["openssh"]["enable"]
assert verify_machine_config(test_flake_minimal.path, "foo") is None