Start to auto-fill cloudinit fields
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
3
virtweb_frontend/package-lock.json
generated
3
virtweb_frontend/package-lock.json
generated
@ -29,7 +29,8 @@
|
|||||||
"react-syntax-highlighter": "^15.6.1",
|
"react-syntax-highlighter": "^15.6.1",
|
||||||
"react-vnc": "^3.1.0",
|
"react-vnc": "^3.1.0",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"xml-formatter": "^3.6.6"
|
"xml-formatter": "^3.6.6",
|
||||||
|
"yaml": "^2.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.27.0",
|
"@eslint/js": "^9.27.0",
|
||||||
|
@ -31,7 +31,8 @@
|
|||||||
"react-syntax-highlighter": "^15.6.1",
|
"react-syntax-highlighter": "^15.6.1",
|
||||||
"react-vnc": "^3.1.0",
|
"react-vnc": "^3.1.0",
|
||||||
"uuid": "^11.1.0",
|
"uuid": "^11.1.0",
|
||||||
"xml-formatter": "^3.6.6"
|
"xml-formatter": "^3.6.6",
|
||||||
|
"yaml": "^2.8.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.27.0",
|
"@eslint/js": "^9.27.0",
|
||||||
|
@ -2,7 +2,9 @@ import Editor from "@monaco-editor/react";
|
|||||||
import BookIcon from "@mui/icons-material/Book";
|
import BookIcon from "@mui/icons-material/Book";
|
||||||
import RefreshIcon from "@mui/icons-material/Refresh";
|
import RefreshIcon from "@mui/icons-material/Refresh";
|
||||||
import { Grid, IconButton, InputAdornment, Tooltip } from "@mui/material";
|
import { Grid, IconButton, InputAdornment, Tooltip } from "@mui/material";
|
||||||
|
import React from "react";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import YAML from "yaml";
|
||||||
import { VMInfo } from "../../api/VMApi";
|
import { VMInfo } from "../../api/VMApi";
|
||||||
import { RouterLink } from "../RouterLink";
|
import { RouterLink } from "../RouterLink";
|
||||||
import { CheckboxInput } from "./CheckboxInput";
|
import { CheckboxInput } from "./CheckboxInput";
|
||||||
@ -44,6 +46,10 @@ export function CloudInitEditor(p: CloudInitProps): React.ReactElement {
|
|||||||
{...p}
|
{...p}
|
||||||
editable={p.editable && p.vm.cloud_init.attach_config}
|
editable={p.editable && p.vm.cloud_init.attach_config}
|
||||||
/>
|
/>
|
||||||
|
<CloudInitUserDataAssistant
|
||||||
|
{...p}
|
||||||
|
editable={p.editable && p.vm.cloud_init.attach_config}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -183,3 +189,76 @@ function CloudInitNetworkConfig(p: CloudInitProps): React.ReactElement {
|
|||||||
</EditSection>
|
</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>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user