Skip to content

Commit

Permalink
change default snr template to be determined according to label remed…
Browse files Browse the repository at this point in the history
…iation.medik8s.io/default-template
  • Loading branch information
batzionb committed Dec 26, 2023
1 parent 15bdf86 commit d106454
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 55 deletions.
28 changes: 20 additions & 8 deletions src/apis/useSNRTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
} from "data/types";
import * as React from "react";

const DEFAULT_TEMPLATE_LABEL = "remediation.medik8s.io/default-template";

const useSnrTemplate = (): SnrTemplateResult => {
const [templates, loaded, error] = useK8sWatchResource<
SelfNodeRemediationTemplate[]
Expand All @@ -18,19 +20,29 @@ const useSnrTemplate = (): SnrTemplateResult => {
if (error) {
return undefined;
}
const templateCR = templates.find(

let defaultTemplate = templates.find(
(template) =>
template.spec?.template?.spec?.remediationStrategy ===
"ResourceDeletion"
template.metadata?.labels?.[DEFAULT_TEMPLATE_LABEL] === "true"
);
if (!templateCR) {

if (!defaultTemplate) {
// fallback to resource deletion for backward compatibility of versions without label
defaultTemplate = templates.find(
(template) =>
template.spec?.template?.spec?.remediationStrategy ===
"ResourceDeletion"
);
}

if (!defaultTemplate) {
return undefined;
}
return {
apiVersion: templateCR.apiVersion,
kind: templateCR.kind,
namespace: templateCR.metadata?.namespace,
name: templateCR.metadata?.name,
apiVersion: defaultTemplate.apiVersion,
kind: defaultTemplate.kind,
namespace: defaultTemplate.metadata?.namespace,
name: defaultTemplate.metadata?.name,
};
}, [templates, error]);

Expand Down
55 changes: 39 additions & 16 deletions src/components/editor/NodeHealthCheckForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,28 @@ import { getFormValues, getNodeHealthCheck } from "data/formValues";
import { LoadingInline } from "copiedFromConsole/utils/status-box";
import "./nhc-form.css";
import { useOpenShiftVersion } from "copiedFromConsole/hooks/useOpenShiftVersion";
import useSnrTemplate from "../../apis/useSNRTemplate";
import { range } from "lodash-es";
import { Skeleton } from "@patternfly/react-core";
export interface NodeHealthCheckProps {
title: string;
name: string;
nodeHealthCheck: NodeHealthCheck;
isCreateFlow: boolean;
}

const FormLoading = () => (
<>
<br />
{range(0, 20).map((idx) => (
<>
<Skeleton key={idx} width="50%" />
<br />
</>
))}
</>
);

const LearnMoreLink: React.FC = () => {
const { t } = useNodeHealthCheckTranslation();
const [version, loaded, error] = useOpenShiftVersion();
Expand Down Expand Up @@ -68,10 +83,13 @@ const NodeHealthCheckForm__: React.FC<NodeHealthCheckProps> = ({
isCreateFlow,
}) => {
const { t } = useNodeHealthCheckTranslation();
const initialValues = React.useMemo(
() => getFormValues(nodeHealthCheck, isCreateFlow),
[]
);
const [snrTemplate, loaded] = useSnrTemplate();
const initialValues = React.useMemo(() => {
if (!loaded) {
return undefined;
}
return getFormValues(nodeHealthCheck, isCreateFlow, snrTemplate);
}, [isCreateFlow, loaded, nodeHealthCheck, snrTemplate]);

const navigation = useNodeHealthCheckNavigation();

Expand Down Expand Up @@ -109,18 +127,23 @@ const NodeHealthCheckForm__: React.FC<NodeHealthCheckProps> = ({
return (
<>
<PageHeading title={title} helpText={<HelpText />} />
<Formik
enableReinitialize
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={getValidationSchema(t)}
validateOnMount={true}
>
<NodeHealthCheckSyncedEditor
originalNodeHealthCheck={nodeHealthCheck}
handleCancel={() => navigation.goBack()}
/>
</Formik>
{!loaded ? (
<FormLoading />
) : (
<Formik
enableReinitialize
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={getValidationSchema(t)}
validateOnMount={true}
>
<NodeHealthCheckSyncedEditor
originalNodeHealthCheck={nodeHealthCheck}
handleCancel={() => navigation.goBack()}
snrTemplate={snrTemplate}
/>
</Formik>
)}
</>
);
};
Expand Down
27 changes: 22 additions & 5 deletions src/components/editor/NodeHealthCheckSyncedEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import * as React from "react";

import { useFormikContext } from "formik";
import { useNodeHealthCheckTranslation } from "localization/useNodeHealthCheckTranslation";
import { NodeHealthCheck, NodeHealthCheckFormValues } from "../../data/types";
import {
NodeHealthCheck,
NodeHealthCheckFormValues,
RemediationTemplate,
} from "../../data/types";
import { EditorType } from "../../copiedFromConsole/synced-editor/editor-toggle";
import {
FlexForm,
Expand All @@ -18,6 +22,7 @@ import { dump } from "js-yaml";
import { Alert, FormSection } from "@patternfly/react-core";
import { getFormValues } from "data/formValues";
import { isEmpty } from "lodash-es";

const sanitizeToYaml = (
values: NodeHealthCheckFormValues,
originalNodeHealthCheck: NodeHealthCheck
Expand All @@ -40,11 +45,12 @@ const LAST_VIEWED_EDITOR_TYPE_USERSETTING_KEY =
type NodeHealthCheckFormSyncedEditorProps = {
handleCancel: () => void;
originalNodeHealthCheck: NodeHealthCheck;
snrTemplate: RemediationTemplate;
};

export const NodeHealthCheckSyncedEditor: React.FC<
NodeHealthCheckFormSyncedEditorProps
> = ({ originalNodeHealthCheck, handleCancel }) => {
> = ({ originalNodeHealthCheck, handleCancel, snrTemplate }) => {
const {
values,
status,
Expand Down Expand Up @@ -96,7 +102,11 @@ export const NodeHealthCheckSyncedEditor: React.FC<

const onReload = () => {
const curEditorType = values.editorType;
const resetValues = getFormValues(originalNodeHealthCheck, false);
const resetValues = getFormValues(
originalNodeHealthCheck,
false,
snrTemplate
);
resetValues.editorType = curEditorType;
resetValues.reloadCount++;
resetForm({ values: resetValues });
Expand All @@ -105,6 +115,7 @@ export const NodeHealthCheckSyncedEditor: React.FC<
React.useEffect(() => {
setStatus({ submitError: null });
}, [setStatus, values.editorType]);

return (
<>
<FlexForm className="nhc-form">
Expand All @@ -115,11 +126,17 @@ export const NodeHealthCheckSyncedEditor: React.FC<
editor: formEditor,
sanitizeTo: (yamlNodeHealthCheck: NodeHealthCheck) => {
try {
return formViewValues.getFormViewValues(yamlNodeHealthCheck);
return formViewValues.getFormViewValues(
yamlNodeHealthCheck,
snrTemplate
);
} catch (err) {
//return a function so SyncedEditorField will handle the error properly
return () =>
formViewValues.getFormViewValues(originalNodeHealthCheck);
formViewValues.getFormViewValues(
originalNodeHealthCheck,
snrTemplate
);
}
},
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,6 @@ import {
RemediationTemplate,
} from "../../../../data/types";
import { useNodeHealthCheckTranslation } from "../../../../localization/useNodeHealthCheckTranslation";
import HelpIcon from "../../../shared/HelpIcon";

const SNRRadioButtonLabel: React.FC = () => {
const { t } = useNodeHealthCheckTranslation();
return (
<>
{getSNRLabel(t)}
<HelpIcon
helpText={t(
"Self node remediation template uses the remediation strategy 'Resource Deletion'."
)}
/>
</>
);
};

const RemediatorKindRadioGroup: React.FC<{
snrTemplatesExist: boolean;
Expand All @@ -50,7 +35,7 @@ const RemediatorKindRadioGroup: React.FC<{
>
<RadioButtonField
value={RemediatorRadioOption.SNR}
label={<SNRRadioButtonLabel />}
label={getSNRLabel(t)}
isDisabled={!snrTemplatesExist}
aria-describedby={"SNR remediator kind"}
name={fieldName}
Expand Down
6 changes: 4 additions & 2 deletions src/data/formValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
FormViewValues,
NodeHealthCheck,
NodeHealthCheckFormValues,
RemediationTemplate,
} from "./types";
import { dump } from "js-yaml";
import { isParseError } from "./parseErrors";
Expand All @@ -13,7 +14,8 @@ import * as yamlText from "./yamlText";

export const getFormValues = (
nodeHealthCheck: NodeHealthCheck,
isCreateFlow: boolean
isCreateFlow: boolean,
snrTemplate: RemediationTemplate | undefined
): NodeHealthCheckFormValues => {
const yamlData = dump(nodeHealthCheck, {
skipInvalid: true,
Expand All @@ -22,7 +24,7 @@ export const getFormValues = (
let formData: FormViewValues | null = null;
let editorType = EditorType.YAML;
try {
formData = getFormViewValues(nodeHealthCheck);
formData = getFormViewValues(nodeHealthCheck, snrTemplate);
editorType = EditorType.Form;
} catch (err) {
if (isParseError(err)) {
Expand Down
21 changes: 13 additions & 8 deletions src/data/formViewValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
selectorToStringArray,
} from "copiedFromConsole/module/selector";
import { defaultUnhealthyConditions, DEFAULT_MIN_HEALTHY } from "./defaults";
import { snrTemplateKind } from "./model";
import { ParseErrorCode, throwParseError } from "./parseErrors";
import { getSortedRemediators } from "./remediator";
import {
Expand All @@ -17,19 +16,20 @@ import {
EscalatingRemediator,
} from "./types";
import { MIN_HEALTHY_REGEX } from "./validationSchema";
import { isEqual } from "lodash-es";

const getRemediationTemplateFormValues = (
snrTemplate: RemediationTemplate | undefined,
template?: RemediationTemplate,
timeout?: string,
order?: number
): Remediator | undefined => {
if (!template) {
return undefined;
}
const radioOption =
template.kind === snrTemplateKind.kind
? RemediatorRadioOption.SNR
: RemediatorRadioOption.CUSTOM;
const radioOption = isEqual(snrTemplate, template)
? RemediatorRadioOption.SNR
: RemediatorRadioOption.CUSTOM;
return {
radioOption,
template,
Expand Down Expand Up @@ -58,14 +58,16 @@ const getUnhealthyConditionsValue = (
};

const getescalatingRemediationsFormValues = (
escalatingRemediations?: EscalatingRemediator[]
escalatingRemediations?: EscalatingRemediator[],
snrTemplate?: RemediationTemplate
): Remediator[] => {
if (!escalatingRemediations) return [];
const sortedescalatingRemediations = getSortedRemediators(
escalatingRemediations
);
return sortedescalatingRemediations.map((remediator) => {
return getRemediationTemplateFormValues(
snrTemplate,
remediator.remediationTemplate,
remediator.timeout,
remediator.order
Expand All @@ -74,7 +76,8 @@ const getescalatingRemediationsFormValues = (
};

export const getFormViewValues = (
nodeHealthCheck: NodeHealthCheck
nodeHealthCheck: NodeHealthCheck,
snrTemplate: RemediationTemplate | undefined
): FormViewValues => {
const useEscalating = !!nodeHealthCheck.spec?.escalatingRemediations;
return {
Expand All @@ -86,11 +89,13 @@ export const getFormViewValues = (
unhealthyConditions: getUnhealthyConditionsValue(nodeHealthCheck),
remediator: !useEscalating
? getRemediationTemplateFormValues(
snrTemplate,
nodeHealthCheck?.spec?.remediationTemplate
)
: undefined,
escalatingRemediations: getescalatingRemediationsFormValues(
nodeHealthCheck.spec?.escalatingRemediations
nodeHealthCheck.spec?.escalatingRemediations,
snrTemplate
),
useEscalating: !!nodeHealthCheck.spec?.escalatingRemediations,
};
Expand Down

0 comments on commit d106454

Please sign in to comment.