UI: init update machine
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import dataclasses
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|||||||
@@ -249,6 +249,6 @@ def from_dict(t: type[G], data: dict[str, Any] | Any, path: list[str] = []) -> G
|
|||||||
if is_dataclass(t):
|
if is_dataclass(t):
|
||||||
if not isinstance(data, dict):
|
if not isinstance(data, dict):
|
||||||
raise ClanError(f"{data} is not a dict. Expected {t}")
|
raise ClanError(f"{data} is not a dict. Expected {t}")
|
||||||
return construct_dataclass(t, data, path)
|
return construct_dataclass(t, data, path) # type: ignore
|
||||||
else:
|
else:
|
||||||
return construct_value(t, data, path)
|
return construct_value(t, data, path)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import os
|
|||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from clan_cli.api import API
|
||||||
from clan_cli.clan_uri import FlakeId
|
from clan_cli.clan_uri import FlakeId
|
||||||
|
|
||||||
from ..cmd import run
|
from ..cmd import run
|
||||||
@@ -12,15 +13,13 @@ from ..completions import add_dynamic_completer, complete_machines
|
|||||||
from ..errors import ClanError
|
from ..errors import ClanError
|
||||||
from ..facts.generate import generate_facts
|
from ..facts.generate import generate_facts
|
||||||
from ..facts.upload import upload_secrets
|
from ..facts.upload import upload_secrets
|
||||||
from ..machines.machines import Machine
|
|
||||||
from clan_cli.inventory import from_dict
|
|
||||||
from ..inventory import Machine as InventoryMachine
|
from ..inventory import Machine as InventoryMachine
|
||||||
|
from ..machines.machines import Machine
|
||||||
from ..nix import nix_command, nix_metadata
|
from ..nix import nix_command, nix_metadata
|
||||||
from ..ssh import HostKeyCheck
|
from ..ssh import HostKeyCheck
|
||||||
from ..vars.generate import generate_vars
|
from ..vars.generate import generate_vars
|
||||||
from .inventory import get_all_machines, get_selected_machines
|
from .inventory import get_all_machines, get_selected_machines
|
||||||
from .machine_group import MachineGroup
|
from .machine_group import MachineGroup
|
||||||
from clan_cli.api import API
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,91 @@ interface MachineListItemProps {
|
|||||||
export const MachineListItem = (props: MachineListItemProps) => {
|
export const MachineListItem = (props: MachineListItemProps) => {
|
||||||
const { name, info, nixOnly } = props;
|
const { name, info, nixOnly } = props;
|
||||||
|
|
||||||
const [deploying, setDeploying] = createSignal<boolean>(false);
|
// Bootstrapping
|
||||||
|
const [installing, setInstalling] = createSignal<boolean>(false);
|
||||||
|
|
||||||
|
// Later only updates
|
||||||
|
const [updating, setUpdating] = createSignal<boolean>(false);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleInstall = async () => {
|
||||||
|
if (!info?.deploy.targetHost || installing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const active_clan = activeURI();
|
||||||
|
if (!active_clan) {
|
||||||
|
toast.error("No active clan selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!info?.deploy.targetHost) {
|
||||||
|
toast.error(
|
||||||
|
"Machine does not have a target host. Specify where the machine should be deployed.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setInstalling(true);
|
||||||
|
await toast.promise(
|
||||||
|
callApi("install_machine", {
|
||||||
|
opts: {
|
||||||
|
machine: name,
|
||||||
|
flake: {
|
||||||
|
loc: active_clan,
|
||||||
|
},
|
||||||
|
no_reboot: true,
|
||||||
|
target_host: info?.deploy.targetHost,
|
||||||
|
debug: true,
|
||||||
|
nix_options: [],
|
||||||
|
},
|
||||||
|
password: null,
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
loading: "Installing...",
|
||||||
|
success: "Installed",
|
||||||
|
error: "Failed to install",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
setInstalling(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdate = async () => {
|
||||||
|
if (!info?.deploy.targetHost || installing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const active_clan = activeURI();
|
||||||
|
if (!active_clan) {
|
||||||
|
toast.error("No active clan selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!info?.deploy.targetHost) {
|
||||||
|
toast.error(
|
||||||
|
"Machine does not have a target host. Specify where the machine should be deployed.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setUpdating(true);
|
||||||
|
await toast.promise(
|
||||||
|
callApi("update_machines", {
|
||||||
|
base_path: active_clan,
|
||||||
|
machines: [
|
||||||
|
{
|
||||||
|
name: name,
|
||||||
|
deploy: {
|
||||||
|
targetHost: info?.deploy.targetHost,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
loading: "Updating...",
|
||||||
|
success: "Updated",
|
||||||
|
error: "Failed to update",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
setUpdating(false);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<li>
|
<li>
|
||||||
<div class="card card-side m-2 bg-base-200">
|
<div class="card card-side m-2 bg-base-200">
|
||||||
@@ -73,51 +156,25 @@ export const MachineListItem = (props: MachineListItemProps) => {
|
|||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
classList={{
|
classList={{
|
||||||
disabled: !info?.deploy.targetHost || deploying(),
|
disabled: !info?.deploy.targetHost || installing(),
|
||||||
}}
|
|
||||||
onClick={async (e) => {
|
|
||||||
if (!info?.deploy.targetHost || deploying()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const active_clan = activeURI();
|
|
||||||
if (!active_clan) {
|
|
||||||
toast.error("No active clan selected");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!info?.deploy.targetHost) {
|
|
||||||
toast.error(
|
|
||||||
"Machine does not have a target host. Specify where the machine should be deployed.",
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setDeploying(true);
|
|
||||||
await toast.promise(
|
|
||||||
callApi("install_machine", {
|
|
||||||
opts: {
|
|
||||||
machine: name,
|
|
||||||
flake: {
|
|
||||||
loc: active_clan,
|
|
||||||
},
|
|
||||||
no_reboot: true,
|
|
||||||
target_host: info?.deploy.targetHost,
|
|
||||||
debug: true,
|
|
||||||
nix_options: [],
|
|
||||||
},
|
|
||||||
password: null,
|
|
||||||
}),
|
|
||||||
{
|
|
||||||
loading: "Deploying...",
|
|
||||||
success: "Deployed",
|
|
||||||
error: "Failed to deploy",
|
|
||||||
},
|
|
||||||
);
|
|
||||||
setDeploying(false);
|
|
||||||
}}
|
}}
|
||||||
|
onClick={handleInstall}
|
||||||
>
|
>
|
||||||
<a>
|
<a>
|
||||||
<Show when={info?.deploy.targetHost} fallback={"Deploy"}>
|
<Show when={info?.deploy.targetHost} fallback={"Deploy"}>
|
||||||
{(d) => `Deploy to ${d()}`}
|
{(d) => `Install to ${d()}`}
|
||||||
|
</Show>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
classList={{
|
||||||
|
disabled: !info?.deploy.targetHost || updating(),
|
||||||
|
}}
|
||||||
|
onClick={handleUpdate}
|
||||||
|
>
|
||||||
|
<a>
|
||||||
|
<Show when={info?.deploy.targetHost} fallback={"Deploy"}>
|
||||||
|
{(d) => `Update (${d()})`}
|
||||||
</Show>
|
</Show>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
Reference in New Issue
Block a user