Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use config api for server settings WD-7389 instance defaults WD-7390 and project defaults #543

Merged
merged 2 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
471 changes: 0 additions & 471 deletions public/assets/data/config-options.json

This file was deleted.

11 changes: 10 additions & 1 deletion src/api/server.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { handleResponse } from "util/helpers";
import { LxdSettings } from "types/server";
import { LxdApiResponse } from "types/apiResponse";
import { LxdConfigPair } from "types/config";
import { LxdConfigOptions, LxdConfigPair } from "types/config";
import { LxdResources } from "types/resources";

export const fetchSettings = (): Promise<LxdSettings> => {
Expand Down Expand Up @@ -35,3 +35,12 @@ export const fetchResources = (): Promise<LxdResources> => {
.catch(reject);
});
};

export const fetchConfigOptions = (): Promise<LxdConfigOptions> => {
return new Promise((resolve, reject) => {
fetch("/1.0/metadata/configuration")
.then(handleResponse)
.then((data: LxdApiResponse<LxdConfigOptions>) => resolve(data.metadata))
.catch(reject);
});
};
18 changes: 13 additions & 5 deletions src/components/ConfigurationRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CpuLimit, MemoryLimit } from "types/limits";
import { MainTableRow } from "@canonical/react-components/dist/components/MainTable/MainTable";
import classnames from "classnames";
import { FormikProps } from "formik/dist/types";
import ConfigFieldDescription from "pages/settings/ConfigFieldDescription";

interface Props {
formik: FormikProps<unknown>;
Expand All @@ -14,6 +15,7 @@ interface Props {
disabled?: boolean;
disabledReason?: string;
help?: string;
inputHelp?: string;
isOverridden: boolean;
inheritedValue: string | ReactNode;
inheritSource: string;
Expand All @@ -31,6 +33,7 @@ export const getConfigurationRow = ({
disabled = false,
disabledReason,
help,
inputHelp,
isOverridden,
inheritedValue,
inheritSource,
Expand Down Expand Up @@ -59,6 +62,12 @@ export const getConfigurationRow = ({
onChange: formik.handleChange,
value,
disabled,
help: (
<ConfigFieldDescription
description={inputHelp}
className="p-form-help-text"
/>
),
})}
</div>,
)}
Expand All @@ -85,10 +94,6 @@ export const getConfigurationRow = ({
<b>{label}</b>
);

const helpText = help ? (
<div className="configuration-help">{help}</div>
) : null;

const wrapDisabledTooltip = (children: ReactNode): ReactNode => {
if (disabled && disabledReason) {
return (
Expand All @@ -104,7 +109,10 @@ export const getConfigurationRow = ({
configuration: (
<>
{displayLabel}
{helpText}
<ConfigFieldDescription
description={help}
className="configuration-help"
/>
</>
),
inherited: (
Expand Down
4 changes: 2 additions & 2 deletions src/components/forms/CloudInitForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ interface Props {

const CloudInitForm: FC<Props> = ({ formik }) => {
const codeRenderer = (value?: unknown) =>
value === "" || value === undefined ? (
value
value === "-" || value === undefined ? (
""
) : (
<CloudInitConfig config={value as string} />
);
Expand Down
30 changes: 25 additions & 5 deletions src/components/forms/InstanceConfigurationRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,20 @@ import { LxdProfile } from "types/profile";
import { figureInheritedValue } from "util/instanceConfigInheritance";
import { getConfigurationRow } from "components/ConfigurationRow";
import { FormikProps } from "formik/dist/types";
import { fetchConfigOptions } from "api/server";
import { toConfigFields } from "util/config";
import { ProjectFormValues } from "pages/projects/CreateProject";
import { getProjectKey } from "util/projectConfigFields";
import { getInstanceKey } from "util/instanceConfigFields";

interface Props {
formik: SharedFormikTypes;
formik: SharedFormikTypes | FormikProps<ProjectFormValues>;
name: string;
label: string | ReactNode;
children: ReactElement;
defaultValue?: string | CpuLimit | MemoryLimit;
disabled?: boolean;
readOnlyRenderer?: (value: unknown) => string | ReactNode;
help?: string;
}

export const getInstanceConfigurationRow = ({
edlerd marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -32,7 +36,6 @@ export const getInstanceConfigurationRow = ({
defaultValue,
disabled = false,
readOnlyRenderer,
help,
}: Props): MainTableRow => {
const notify = useNotify();
const { project } = useParams<{ project: string }>();
Expand All @@ -49,14 +52,30 @@ export const getInstanceConfigurationRow = ({
}
}

const { data: configOptions } = useQuery({
queryKey: [queryKeys.configOptions],
queryFn: fetchConfigOptions,
});
const configFields =
formik.values.type === "project"
? toConfigFields(configOptions?.configs.project ?? {})
: toConfigFields(configOptions?.configs.instance ?? {});

const values = formik.values as unknown as Record<string, string | undefined>;
const value = values[name];
const isOverridden = value !== undefined;

const configKey =
values.type === "project" ? getProjectKey(name) : getInstanceKey(name);
const configEntry = configFields.find(
(configField) => configField.key === configKey,
);

const [inheritedValue, inheritSource] = figureInheritedValue(
formik.values,
name,
configKey,
profiles,
configEntry?.default,
);
const isReadOnly = (formik.values as EditInstanceFormValues).readOnly;

Expand All @@ -76,7 +95,8 @@ export const getInstanceConfigurationRow = ({
children,
defaultValue,
disabled,
help,
help: configEntry?.shortdesc,
inputHelp: configEntry?.longdesc,
isOverridden,
inheritedValue: getInheritedValue(),
inheritSource,
Expand Down
1 change: 0 additions & 1 deletion src/components/forms/ResourceLimitsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ const ResourceLimitsForm: FC<Props> = ({ formik }) => {
getInstanceConfigurationRow({
formik: formik,
name: "limits_disk_priority",
help: "Controls how much priority to give to the instance’s I/O requests when under load",
label: "Disk priority",
defaultValue: "",
children: <Select options={diskPriorities} />,
Expand Down
9 changes: 4 additions & 5 deletions src/components/forms/SecurityPoliciesForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ const SecurityPoliciesForm: FC<Props> = ({ formik }) => {
rows={[
getInstanceConfigurationRow({
formik: formik,
label: "Prevent the instance from being deleted",
label: "Protect deletion",
name: "security_protection_delete",
defaultValue: "",
readOnlyRenderer: (val) => optionRenderer(val, optionYesNo),
Expand All @@ -70,7 +70,7 @@ const SecurityPoliciesForm: FC<Props> = ({ formik }) => {

getInstanceConfigurationRow({
formik: formik,
label: "Run the instance in privileged mode (Containers only)",
label: "Privileged (Containers only)",
name: "security_privileged",
defaultValue: "",
disabled: isContainerOnlyDisabled,
Expand All @@ -85,8 +85,7 @@ const SecurityPoliciesForm: FC<Props> = ({ formik }) => {

getInstanceConfigurationRow({
formik: formik,
label:
"Prevent instance file system from being UID/GID shifted on startup (Containers only)",
label: "Protect UID/GID shift (Containers only)",
name: "security_protection_shift",
defaultValue: "",
disabled: isContainerOnlyDisabled,
Expand Down Expand Up @@ -135,7 +134,7 @@ const SecurityPoliciesForm: FC<Props> = ({ formik }) => {

getInstanceConfigurationRow({
formik: formik,
label: "Unique idmap usage (Containers only)",
label: "Unique idmap (Containers only)",
name: "security_idmap_isolated",
defaultValue: "",
disabled: isContainerOnlyDisabled,
Expand Down
32 changes: 2 additions & 30 deletions src/components/forms/SnapshotsForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import InstanceConfigurationTable from "components/forms/InstanceConfigurationTa
import { getInstanceKey } from "util/instanceConfigFields";
import { optionRenderer } from "util/formFields";
import SnapshotScheduleInput from "components/SnapshotScheduleInput";
import { useDocs } from "context/useDocs";

export interface SnapshotFormValues {
snapshots_pattern?: string;
Expand All @@ -32,8 +31,6 @@ interface Props {
}

const SnapshotsForm: FC<Props> = ({ formik }) => {
const docBaseLink = useDocs();

return (
<InstanceConfigurationTable
rows={[
Expand All @@ -42,40 +39,15 @@ const SnapshotsForm: FC<Props> = ({ formik }) => {
label: "Snapshot name pattern",
name: "snapshots_pattern",
defaultValue: "",
children: (
<Input
placeholder="Enter name pattern"
help={
<>
Pongo2 template string that represents the snapshot name (used
for scheduled snapshots and unnamed snapshots), see{" "}
<a
href={`${docBaseLink}/reference/instance_options/#instance-options-snapshots-names`}
target="_blank"
rel="noreferrer"
>
Automatic snapshot names
</a>
</>
}
type="text"
/>
),
children: <Input placeholder="Enter name pattern" type="text" />,
}),

getInstanceConfigurationRow({
formik: formik,
label: "Expire after",
name: "snapshots_expiry",
help: "Controls when snapshots are to be deleted",
defaultValue: "",
children: (
<Input
placeholder="Enter expiry expression"
type="text"
help="Expects an expression like 1M 2H 3d 4w 5m 6y"
/>
),
children: <Input placeholder="Enter expiry expression" type="text" />,
}),

getInstanceConfigurationRow({
Expand Down
7 changes: 2 additions & 5 deletions src/pages/projects/forms/ClusterRestrictionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import InstanceConfigurationTable from "components/forms/InstanceConfigurationTa
import { ProjectFormValues } from "pages/projects/CreateProject";
import { FormikProps } from "formik/dist/types";
import { optionAllowBlock } from "util/projectOptions";
import { SharedFormikTypes } from "components/forms/sharedFormTypes";
import { optionRenderer } from "util/formFields";
import { getProjectKey } from "util/projectConfigFields";

Expand All @@ -32,19 +31,17 @@ const ClusterRestrictionForm: FC<Props> = ({ formik }) => {
<InstanceConfigurationTable
rows={[
getInstanceConfigurationRow({
formik: formik as unknown as SharedFormikTypes,
formik: formik,
edlerd marked this conversation as resolved.
Show resolved Hide resolved
name: "restricted_cluster_groups",
label: "Cluster groups targeting",
help: "Prevents targeting cluster groups other than the provided ones.",
defaultValue: "",
children: <Input placeholder="Enter value" type="text" />,
}),

getInstanceConfigurationRow({
formik: formik as unknown as SharedFormikTypes,
formik: formik,
edlerd marked this conversation as resolved.
Show resolved Hide resolved
name: "restricted_cluster_target",
label: "Direct cluster targeting",
help: "Direct targeting of cluster members when creating or moving instances.",
defaultValue: "",
readOnlyRenderer: (val) => optionRenderer(val, optionAllowBlock),
children: <Select options={optionAllowBlock} />,
Expand Down
Loading
Loading