Start to auto-fill cloudinit fields
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2025-06-16 19:31:13 +02:00
parent 9f1f4b44ca
commit 92f187bf91
3 changed files with 83 additions and 2 deletions

View File

@ -29,7 +29,8 @@
"react-syntax-highlighter": "^15.6.1",
"react-vnc": "^3.1.0",
"uuid": "^11.1.0",
"xml-formatter": "^3.6.6"
"xml-formatter": "^3.6.6",
"yaml": "^2.8.0"
},
"devDependencies": {
"@eslint/js": "^9.27.0",

View File

@ -31,7 +31,8 @@
"react-syntax-highlighter": "^15.6.1",
"react-vnc": "^3.1.0",
"uuid": "^11.1.0",
"xml-formatter": "^3.6.6"
"xml-formatter": "^3.6.6",
"yaml": "^2.8.0"
},
"devDependencies": {
"@eslint/js": "^9.27.0",

View File

@ -2,7 +2,9 @@ import Editor from "@monaco-editor/react";
import BookIcon from "@mui/icons-material/Book";
import RefreshIcon from "@mui/icons-material/Refresh";
import { Grid, IconButton, InputAdornment, Tooltip } from "@mui/material";
import React from "react";
import { v4 as uuidv4 } from "uuid";
import YAML from "yaml";
import { VMInfo } from "../../api/VMApi";
import { RouterLink } from "../RouterLink";
import { CheckboxInput } from "./CheckboxInput";
@ -44,6 +46,10 @@ export function CloudInitEditor(p: CloudInitProps): React.ReactElement {
{...p}
editable={p.editable && p.vm.cloud_init.attach_config}
/>
<CloudInitUserDataAssistant
{...p}
editable={p.editable && p.vm.cloud_init.attach_config}
/>
</Grid>
</>
);
@ -183,3 +189,76 @@ function CloudInitNetworkConfig(p: CloudInitProps): React.ReactElement {
</EditSection>
);
}
function CloudInitUserDataAssistant(p: CloudInitProps): React.ReactElement {
const user_data = React.useMemo(() => {
return YAML.parseDocument(p.vm.cloud_init.user_data);
}, [p.vm.cloud_init.user_data]);
const onChange = () => {
p.vm.cloud_init.user_data = user_data.toString();
if (!p.vm.cloud_init.user_data.startsWith("#cloud-config"))
p.vm.cloud_init.user_data = `#cloud-config\n${p.vm.cloud_init.user_data}`;
p.onChange?.();
};
return (
<EditSection title="User data assistant">
<CloudInitTextInput
editable={p.editable}
name="Default user password"
refUrl="https://cloudinit.readthedocs.io/en/latest/reference/modules.html#set-passwords"
attrPath={["password"]}
onChange={onChange}
yaml={user_data}
/>
<CloudInitTextInput
editable={p.editable}
name="Keyboard layout"
refUrl="https://cloudinit.readthedocs.io/en/latest/reference/modules.html#keyboard"
attrPath={["keyboard", "layout"]}
onChange={onChange}
yaml={user_data}
/>
<CloudInitTextInput
editable={p.editable}
name="Final message"
refUrl="https://cloudinit.readthedocs.io/en/latest/reference/modules.html#final-message"
attrPath={["final_message"]}
onChange={onChange}
yaml={user_data}
/>
</EditSection>
);
}
function CloudInitTextInput(p: {
editable: boolean;
name: string;
refUrl: string;
attrPath: Iterable<unknown>;
yaml: YAML.Document;
onChange: () => void;
}): React.ReactElement {
return (
<TextInput
editable={p.editable}
label={p.name}
value={String(p.yaml.getIn(p.attrPath) ?? "")}
onValueChange={(v) => {
if (v !== undefined) p.yaml.setIn(p.attrPath, v);
else p.yaml.deleteIn(p.attrPath);
p.onChange?.();
}}
endAdornment={
<RouterLink to={p.refUrl} target="_blank">
<IconButton size="small">
<BookIcon />
</IconButton>
</RouterLink>
}
/>
);
}