Merge pull request 'pkgs/clan/lib(install): implement separate nixos-anywhere install phases' (#4710) from ke-install-phases into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4710
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
&[data-expanded] {
|
||||
@apply outline-def-2 outline-1 outline;
|
||||
z-index: var(--z-index + 5);
|
||||
z-index: calc(var(--z-index) + 5);
|
||||
}
|
||||
|
||||
&[data-highlighted] {
|
||||
|
||||
@@ -146,6 +146,7 @@ export const Select = (props: SelectProps) => {
|
||||
<KSelect.HiddenSelect {...selectProps} />
|
||||
<KSelect.Trigger
|
||||
class={cx(styles.trigger)}
|
||||
style={{ "--z-index": zIndex() }}
|
||||
data-loading={loading() || undefined}
|
||||
>
|
||||
<KSelect.Value<Option>>
|
||||
|
||||
@@ -251,6 +251,10 @@ export const Onboarding: Component<RouteSectionProps> = (props) => {
|
||||
},
|
||||
}).result;
|
||||
|
||||
await client.fetch("create_secrets_user", {
|
||||
flake_dir: path,
|
||||
}).result;
|
||||
|
||||
if (resp.status === "error") {
|
||||
setWelcomeError(resp.errors[0].message);
|
||||
setState("welcome");
|
||||
|
||||
@@ -18,29 +18,64 @@ type ResultDataMap = {
|
||||
[K in OperationNames]: SuccessQuery<K>["data"];
|
||||
};
|
||||
|
||||
export const mockFetcher: Fetcher = <K extends OperationNames>(
|
||||
const mockFetcher: Fetcher = <K extends OperationNames>(
|
||||
name: K,
|
||||
_args: unknown,
|
||||
): ApiCall<K> => {
|
||||
// TODO: Make this configurable for every story
|
||||
const resultData: Partial<ResultDataMap> = {
|
||||
get_machine_flash_options: {
|
||||
keymaps: ["DE_de", "US_en"],
|
||||
languages: ["en", "de"],
|
||||
},
|
||||
get_system_file: ["id_rsa.pub"],
|
||||
list_system_storage_devices: {
|
||||
blockdevices: [
|
||||
{
|
||||
name: "sda_bla_bla",
|
||||
path: "/dev/sda",
|
||||
id_link: "sda_bla_bla",
|
||||
},
|
||||
{
|
||||
name: "sdb_foo_foo",
|
||||
path: "/dev/sdb",
|
||||
id_link: "sdb_foo_foo",
|
||||
},
|
||||
] as SuccessQuery<"list_system_storage_devices">["data"]["blockdevices"],
|
||||
},
|
||||
get_machine_disk_schemas: {
|
||||
"single-disk": {
|
||||
readme: "This is a single disk installation schema",
|
||||
frontmatter: {
|
||||
description: "Single disk installation schema",
|
||||
},
|
||||
name: "single-disk",
|
||||
placeholders: {
|
||||
mainDisk: {
|
||||
label: "Main Disk",
|
||||
required: true,
|
||||
options: ["disk1", "usb1"],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
get_generators: [
|
||||
{
|
||||
name: "funny.gritty",
|
||||
prompts: [
|
||||
{
|
||||
name: "gritty.name",
|
||||
description: "Name of the gritty",
|
||||
prompt_type: "line",
|
||||
display: {
|
||||
label: "Gritty Name",
|
||||
group: "User",
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
run_generators: true,
|
||||
get_machine_hardware_summary: {
|
||||
hardware_config: "nixos-facter",
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { StepLayout } from "../../Steps";
|
||||
const ChoiceLocalOrRemote = () => {
|
||||
const stepSignal = useStepper<InstallSteps>();
|
||||
return (
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex flex-col gap-3 size-full">
|
||||
<div class="flex flex-col gap-6 rounded-md px-4 py-6 text-fg-def-1 bg-def-2">
|
||||
<div class="flex justify-between gap-2">
|
||||
<div class="flex flex-col justify-center gap-1 px-1">
|
||||
|
||||
@@ -16,10 +16,7 @@ import { Alert } from "@/src/components/Alert/Alert";
|
||||
import { LoadingBar } from "@/src/components/LoadingBar/LoadingBar";
|
||||
import { Button } from "@/src/components/Button/Button";
|
||||
import Icon from "@/src/components/Icon/Icon";
|
||||
import {
|
||||
useMachineFlashOptions,
|
||||
useSystemStorageOptions,
|
||||
} from "@/src/hooks/queries";
|
||||
import { useSystemStorageOptions } from "@/src/hooks/queries";
|
||||
import { useApiClient } from "@/src/hooks/ApiClient";
|
||||
import { onMount } from "solid-js";
|
||||
|
||||
@@ -144,8 +141,6 @@ const ConfigureImage = () => {
|
||||
throw new Error("No data returned from api call");
|
||||
};
|
||||
|
||||
const optionsQuery = useMachineFlashOptions();
|
||||
|
||||
let content: Node;
|
||||
|
||||
return (
|
||||
@@ -309,15 +304,17 @@ const FlashProgress = () => {
|
||||
});
|
||||
|
||||
const handleCancel = async () => {
|
||||
if (store.flash) {
|
||||
const progress = store.flash.progress;
|
||||
if (progress) {
|
||||
await progress.cancel();
|
||||
}
|
||||
}
|
||||
stepSignal.previous();
|
||||
};
|
||||
|
||||
return (
|
||||
<div class="flex size-full h-60 flex-col items-center justify-end bg-inv-4">
|
||||
<div class="flex size-full flex-col items-center justify-center bg-inv-4">
|
||||
<div class="mb-6 flex w-full max-w-md flex-col items-center gap-3 fg-inv-1">
|
||||
<Typography
|
||||
hierarchy="title"
|
||||
@@ -344,7 +341,7 @@ const FlashDone = () => {
|
||||
const stepSignal = useStepper<InstallSteps>();
|
||||
return (
|
||||
<div class="flex size-full flex-col items-center justify-between bg-inv-4">
|
||||
<div class="flex w-full max-w-md flex-col items-center gap-3 py-6 fg-inv-1">
|
||||
<div class="flex size-full max-w-md flex-col items-center justify-center gap-3 py-6 fg-inv-1">
|
||||
<div class="rounded-full bg-semantic-success-4">
|
||||
<Icon icon="Checkmark" class="size-9" />
|
||||
</div>
|
||||
|
||||
@@ -70,7 +70,6 @@ const ConfigureAddress = () => {
|
||||
|
||||
// Here you would typically trigger the ISO creation process
|
||||
stepSignal.next();
|
||||
console.log("Shit doesnt work", values);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -318,6 +317,25 @@ interface PromptForm extends FieldValues {
|
||||
promptValues: PromptValues;
|
||||
}
|
||||
|
||||
const sanitize = (name: string) => {
|
||||
return name.replace(".", "__dot__");
|
||||
};
|
||||
const restore = (name: string) => {
|
||||
return name.replace("__dot__", ".");
|
||||
};
|
||||
|
||||
const transformPromptValues = (
|
||||
values: PromptValues,
|
||||
transform: (s: string) => string,
|
||||
): PromptValues =>
|
||||
Object.fromEntries(
|
||||
Object.entries(values).map(([key, value]) => [
|
||||
transform(key),
|
||||
Object.fromEntries(
|
||||
Object.entries(value).map(([k, v]) => [transform(k), v]),
|
||||
),
|
||||
]),
|
||||
);
|
||||
interface PromptsFieldsProps {
|
||||
generators: MachineGenerators;
|
||||
}
|
||||
@@ -338,8 +356,11 @@ const PromptsFields = (props: PromptsFieldsProps) => {
|
||||
if (!acc[groupName]) acc[groupName] = { fields: [], name: groupName };
|
||||
|
||||
acc[groupName].fields.push({
|
||||
prompt,
|
||||
generator: generator.name,
|
||||
prompt: {
|
||||
...prompt,
|
||||
name: sanitize(prompt.name),
|
||||
},
|
||||
generator: sanitize(generator.name),
|
||||
value: prompt.previous_value,
|
||||
});
|
||||
}
|
||||
@@ -351,16 +372,24 @@ const PromptsFields = (props: PromptsFieldsProps) => {
|
||||
|
||||
const [formStore, { Form, Field }] = createForm<PromptForm>({
|
||||
initialValues: {
|
||||
promptValues: store.install?.promptValues || {},
|
||||
promptValues: transformPromptValues(
|
||||
store.install?.promptValues || {},
|
||||
sanitize,
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
console.log(groups);
|
||||
|
||||
const handleSubmit: SubmitHandler<PromptForm> = (values, event) => {
|
||||
console.log("vars submitted", values);
|
||||
const restoredValues: PromptValues = transformPromptValues(
|
||||
values.promptValues,
|
||||
restore,
|
||||
);
|
||||
|
||||
set("install", (s) => ({ ...s, promptValues: values.promptValues }));
|
||||
console.log("vars submitted", restoredValues);
|
||||
|
||||
set("install", (s) => ({ ...s, promptValues: restoredValues }));
|
||||
console.log("vars preloaded");
|
||||
// Here you would typically trigger the ISO creation process
|
||||
stepSignal.next();
|
||||
@@ -545,7 +574,14 @@ const InstallSummary = () => {
|
||||
);
|
||||
};
|
||||
|
||||
type InstallTopic = "generators" | "upload-secrets" | "nixos-anywhere";
|
||||
type InstallTopic = [
|
||||
"generators",
|
||||
"upload-secrets",
|
||||
"nixos-anywhere",
|
||||
"formatting",
|
||||
"rebooting",
|
||||
"installing",
|
||||
][number];
|
||||
|
||||
const InstallProgress = () => {
|
||||
const stepSignal = useStepper<InstallSteps>();
|
||||
@@ -563,7 +599,7 @@ const InstallProgress = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<div class="flex size-full h-60 flex-col items-center justify-end bg-inv-4">
|
||||
<div class="flex size-full flex-col items-center justify-center bg-inv-4">
|
||||
<div class="mb-6 flex w-full max-w-md flex-col items-center gap-3 fg-inv-1">
|
||||
<Typography
|
||||
hierarchy="title"
|
||||
@@ -599,6 +635,15 @@ const InstallProgress = () => {
|
||||
<Match when={installState()?.topic === "nixos-anywhere"}>
|
||||
Running nixos-anywhere ...
|
||||
</Match>
|
||||
<Match when={installState()?.topic === "formatting"}>
|
||||
Formatting ...
|
||||
</Match>
|
||||
<Match when={installState()?.topic === "installing"}>
|
||||
Installing ...
|
||||
</Match>
|
||||
<Match when={installState()?.topic === "rebooting"}>
|
||||
Rebooting ...
|
||||
</Match>
|
||||
</Switch>
|
||||
</Match>
|
||||
</Switch>
|
||||
@@ -625,7 +670,7 @@ const InstallDone = (props: InstallDoneProps) => {
|
||||
const [store, get] = getStepStore<InstallStoreType>(stepSignal);
|
||||
|
||||
return (
|
||||
<div class="flex w-full flex-col items-center bg-inv-4">
|
||||
<div class="flex size-full flex-col items-center justify-center bg-inv-4">
|
||||
<div class="flex w-full max-w-md flex-col items-center gap-3 py-6 fg-inv-1">
|
||||
<div class="rounded-full bg-semantic-success-4">
|
||||
<Icon icon="Checkmark" class="size-9" />
|
||||
|
||||
@@ -22,7 +22,14 @@ log = logging.getLogger(__name__)
|
||||
BuildOn = Literal["auto", "local", "remote"]
|
||||
|
||||
|
||||
Step = Literal["generators", "upload-secrets", "nixos-anywhere"]
|
||||
Step = Literal[
|
||||
"generators",
|
||||
"upload-secrets",
|
||||
"nixos-anywhere",
|
||||
"formatting",
|
||||
"rebooting",
|
||||
"installing",
|
||||
]
|
||||
|
||||
|
||||
def notify_install_step(current: Step) -> None:
|
||||
@@ -195,4 +202,22 @@ def run_machine_install(opts: InstallOptions, target_host: Remote) -> None:
|
||||
)
|
||||
|
||||
notify_install_step("nixos-anywhere")
|
||||
run(cmd, RunOpts(log=Log.BOTH, prefix=machine.name, needs_user_terminal=True))
|
||||
run(
|
||||
[*cmd, "--phases", "kexec"],
|
||||
RunOpts(log=Log.BOTH, prefix=machine.name, needs_user_terminal=True),
|
||||
)
|
||||
notify_install_step("formatting")
|
||||
run(
|
||||
[*cmd, "--phases", "disko"],
|
||||
RunOpts(log=Log.BOTH, prefix=machine.name, needs_user_terminal=True),
|
||||
)
|
||||
notify_install_step("installing")
|
||||
run(
|
||||
[*cmd, "--phases", "install"],
|
||||
RunOpts(log=Log.BOTH, prefix=machine.name, needs_user_terminal=True),
|
||||
)
|
||||
notify_install_step("rebooting")
|
||||
run(
|
||||
[*cmd, "--phases", "reboot"],
|
||||
RunOpts(log=Log.BOTH, prefix=machine.name, needs_user_terminal=True),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user