Merge pull request 'split list machines into show machine command' (#1521) from machines-show into main

This commit is contained in:
clan-bot
2024-05-31 15:00:03 +00:00
7 changed files with 90 additions and 37 deletions

View File

@@ -5,6 +5,7 @@ from .create import register_create_parser
from .delete import register_delete_parser from .delete import register_delete_parser
from .install import register_install_parser from .install import register_install_parser
from .list import register_list_parser from .list import register_list_parser
from .show import register_show_parser
from .update import register_update_parser from .update import register_update_parser
@@ -62,6 +63,17 @@ Examples:
) )
register_list_parser(list_parser) register_list_parser(list_parser)
show_parser = subparser.add_parser(
"show",
help="Show a machine",
epilog=(
"""
This subcommand shows the details of a machine managed by this clan like icon, description, etc
"""
),
)
register_show_parser(show_parser)
install_parser = subparser.add_parser( install_parser = subparser.add_parser(
"install", "install",
help="Install a machine", help="Install a machine",

View File

@@ -1,5 +1,4 @@
import argparse import argparse
import dataclasses
import json import json
import logging import logging
from pathlib import Path from pathlib import Path
@@ -12,24 +11,15 @@ from ..nix import nix_config, nix_eval
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@dataclasses.dataclass
class MachineInfo:
machine_name: str
machine_description: str | None
machine_icon: str | None
@API.register @API.register
def list_machines(flake_url: str | Path, debug: bool) -> dict[str, MachineInfo]: def list_machines(flake_url: str | Path, debug: bool) -> list[str]:
config = nix_config() config = nix_config()
system = config["system"] system = config["system"]
cmd = nix_eval( cmd = nix_eval(
[ [
f"{flake_url}#clanInternals.machines.{system}", f"{flake_url}#clanInternals.machines.{system}",
"--apply", "--apply",
"""builtins.mapAttrs (name: attrs: { "builtins.attrNames",
inherit (attrs.config.clanCore) machineDescription machineIcon machineName;
})""",
"--json", "--json",
] ]
) )
@@ -37,27 +27,13 @@ def list_machines(flake_url: str | Path, debug: bool) -> dict[str, MachineInfo]:
proc = run_no_stdout(cmd) proc = run_no_stdout(cmd)
res = proc.stdout.strip() res = proc.stdout.strip()
machines_dict = json.loads(res) return json.loads(res)
return {
k: MachineInfo(
machine_name=v.get("machineName"),
machine_description=v.get("machineDescription", None),
machine_icon=v.get("machineIcon", None),
)
for k, v in machines_dict.items()
}
def list_command(args: argparse.Namespace) -> None: def list_command(args: argparse.Namespace) -> None:
flake_path = Path(args.flake).resolve() flake_path = Path(args.flake).resolve()
print("Listing all machines:\n") for name in list_machines(flake_path, args.debug):
print("Source: ", flake_path) print(name)
print("-" * 40)
for name, machine in list_machines(flake_path, args.debug).items():
description = machine.machine_description or "[no description]"
print(f"{name}\n: {description}\n")
print("-" * 40)
def register_list_parser(parser: argparse.ArgumentParser) -> None: def register_list_parser(parser: argparse.ArgumentParser) -> None:

View File

@@ -0,0 +1,58 @@
import argparse
import dataclasses
import json
import logging
from pathlib import Path
from clan_cli.api import API
from ..cmd import run_no_stdout
from ..nix import nix_config, nix_eval
from .types import machine_name_type
log = logging.getLogger(__name__)
@dataclasses.dataclass
class MachineInfo:
machine_name: str
machine_description: str | None
machine_icon: str | None
@API.register
def show_machine(flake_url: str | Path, machine_name: str, debug: bool) -> MachineInfo:
config = nix_config()
system = config["system"]
cmd = nix_eval(
[
f"{flake_url}#clanInternals.machines.{system}.{machine_name}",
"--apply",
"machine: { inherit (machine.config.clanCore) machineDescription machineIcon machineName; }",
"--json",
]
)
proc = run_no_stdout(cmd)
res = proc.stdout.strip()
machine = json.loads(res)
return MachineInfo(
machine_name=machine.get("machineName"),
machine_description=machine.get("machineDescription", None),
machine_icon=machine.get("machineIcon", None),
)
def show_command(args: argparse.Namespace) -> None:
flake_path = Path(args.flake).resolve()
machine = show_machine(flake_path, args.machine, args.debug)
print(f"Name: {machine.machine_name}")
print(f"Description: {machine.machine_description or ''}")
print(f"Icon: {machine.machine_icon or ''}")
def register_show_parser(parser: argparse.ArgumentParser) -> None:
parser.set_defaults(func=show_command)
parser.add_argument(
"machine", help="the name of the machine", type=machine_name_type
)

View File

@@ -176,7 +176,7 @@ def register_machines_parser(parser: argparse.ArgumentParser) -> None:
"remove-secret", help="remove a group's access to a secret" "remove-secret", help="remove a group's access to a secret"
) )
remove_secret_parser.add_argument( remove_secret_parser.add_argument(
"machine", help="the name of the group", type=machine_name_type "machine", help="the name of the machine", type=machine_name_type
) )
remove_secret_parser.add_argument( remove_secret_parser.add_argument(
"secret", help="the name of the secret", type=secret_name_type "secret", help="the name of the secret", type=secret_name_type

View File

@@ -21,6 +21,13 @@ def test_machine_subcommands(
assert "vm1" in out.out assert "vm1" in out.out
assert "vm2" in out.out assert "vm2" in out.out
capsys.readouterr()
cli.run(["machines", "show", "--flake", str(test_flake_with_core.path), "machine1"])
out = capsys.readouterr()
assert "machine1" in out.out
assert "Description" in out.out
print(out)
cli.run( cli.run(
["machines", "delete", "--flake", str(test_flake_with_core.path), "machine1"] ["machines", "delete", "--flake", str(test_flake_with_core.path), "machine1"]
) )

View File

@@ -10,7 +10,7 @@ import { OperationResponse, pyApi } from "./message";
export const makeCountContext = () => { export const makeCountContext = () => {
const [machines, setMachines] = createSignal< const [machines, setMachines] = createSignal<
OperationResponse<"list_machines"> OperationResponse<"list_machines">
>({}); >([]);
const [loading, setLoading] = createSignal(false); const [loading, setLoading] = createSignal(false);
pyApi.list_machines.receive((machines) => { pyApi.list_machines.receive((machines) => {
@@ -41,7 +41,7 @@ export const CountContext = createContext<CountContextType>([
loading: () => false, loading: () => false,
// eslint-disable-next-line // eslint-disable-next-line
machines: () => ({}), machines: () => ([]),
}, },
{ {
// eslint-disable-next-line // eslint-disable-next-line

View File

@@ -5,8 +5,6 @@ import { route } from "@/src/App";
export const MachineListView: Component = () => { export const MachineListView: Component = () => {
const [{ machines, loading }, { getMachines }] = useCountContext(); const [{ machines, loading }, { getMachines }] = useCountContext();
const list = () => Object.values(machines());
createEffect(() => { createEffect(() => {
if (route() === "machines") getMachines(); if (route() === "machines") getMachines();
}); });
@@ -34,12 +32,12 @@ export const MachineListView: Component = () => {
</div> </div>
</div> </div>
</Match> </Match>
<Match when={!loading() && Object.entries(machines()).length === 0}> <Match when={!loading() && machines().length === 0}>
No machines found No machines found
</Match> </Match>
<Match when={!loading()}> <Match when={!loading()}>
<ul> <ul>
<For each={list()}> <For each={machines()}>
{(entry) => ( {(entry) => (
<li> <li>
<div class="card card-side m-2 bg-base-100 shadow-lg"> <div class="card card-side m-2 bg-base-100 shadow-lg">
@@ -50,7 +48,8 @@ export const MachineListView: Component = () => {
</figure> </figure>
<div class="card-body flex-row justify-between"> <div class="card-body flex-row justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<h2 class="card-title">{entry.machine_name}</h2> <h2 class="card-title">{entry}</h2>
{/*
<p <p
classList={{ classList={{
"text-gray-400": !entry.machine_description, "text-gray-400": !entry.machine_description,
@@ -59,6 +58,7 @@ export const MachineListView: Component = () => {
> >
{entry.machine_description || "No description"} {entry.machine_description || "No description"}
</p> </p>
*/}
</div> </div>
<div> <div>
<button class="btn btn-ghost"> <button class="btn btn-ghost">