diff --git a/frontend/packages/console-shared/src/hooks/previous.ts b/frontend/packages/console-shared/src/hooks/previous.ts
new file mode 100644
index 00000000000..2c220f01c37
--- /dev/null
+++ b/frontend/packages/console-shared/src/hooks/previous.ts
@@ -0,0 +1,5 @@
+import { useMemo } from 'react';
+
+export const usePrevious =
(value: P, deps: any[] = []): P =>
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ useMemo(() => value, deps);
diff --git a/frontend/packages/metal3-plugin/src/components/baremetal-hosts/BareMetalHostStatus.tsx b/frontend/packages/metal3-plugin/src/components/baremetal-hosts/BareMetalHostStatus.tsx
index 3a404227e47..27b0517b2f8 100644
--- a/frontend/packages/metal3-plugin/src/components/baremetal-hosts/BareMetalHostStatus.tsx
+++ b/frontend/packages/metal3-plugin/src/components/baremetal-hosts/BareMetalHostStatus.tsx
@@ -34,7 +34,7 @@ export const HOST_STATUS_ACTIONS = {
BareMetalHostModel,
host.metadata.name,
host.metadata.namespace,
- )}/edit`}
+ )}/edit?powerMgmt`}
>
Add credentials
diff --git a/frontend/packages/metal3-plugin/src/components/baremetal-hosts/add-baremetal-host/AddBareMetalHost.tsx b/frontend/packages/metal3-plugin/src/components/baremetal-hosts/add-baremetal-host/AddBareMetalHost.tsx
index 6c37e3a47e7..9cc7bfb2977 100644
--- a/frontend/packages/metal3-plugin/src/components/baremetal-hosts/add-baremetal-host/AddBareMetalHost.tsx
+++ b/frontend/packages/metal3-plugin/src/components/baremetal-hosts/add-baremetal-host/AddBareMetalHost.tsx
@@ -1,11 +1,17 @@
import * as React from 'react';
import * as Yup from 'yup';
import * as _ from 'lodash';
-import { Formik } from 'formik';
-import { history, resourcePathFromModel, FirehoseResult } from '@console/internal/components/utils';
+import { Formik, FormikHelpers } from 'formik';
+import {
+ history,
+ resourcePathFromModel,
+ LoadingBox,
+ LoadError,
+} from '@console/internal/components/utils';
import { nameValidationSchema } from '@console/dev-console/src/components/import/validation-schema';
import { getName } from '@console/shared/src';
-import { K8sResourceKind } from '@console/internal/module/k8s';
+import { usePrevious } from '@console/shared/src/hooks/previous';
+import { referenceForModel, SecretKind } from '@console/internal/module/k8s';
import { createBareMetalHost, updateBareMetalHost } from '../../../k8s/requests/bare-metal-host';
import { BareMetalHostModel } from '../../../models';
import { BareMetalHostKind } from '../../../types';
@@ -17,15 +23,20 @@ import {
isHostOnline,
} from '../../../selectors';
import { getSecretPassword, getSecretUsername } from '../../../selectors/secret';
-import { getLoadedData } from '../../../utils';
-import { usePrevious } from '../../../hooks';
import AddBareMetalHostForm from './AddBareMetalHostForm';
import { AddBareMetalHostFormValues } from './types';
import { MAC_REGEX, BMC_ADDRESS_REGEX } from './utils';
+import {
+ useK8sWatchResource,
+ WatchK8sResource,
+} from '@console/internal/components/utils/k8s-watch-hook';
+import { SecretModel } from '@console/internal/models';
const getInitialValues = (
host: BareMetalHostKind,
- secret: K8sResourceKind,
+ secret: SecretKind,
+ isEditing: boolean,
+ enablePowerMgmt: boolean,
): AddBareMetalHostFormValues => ({
name: getName(host) || '',
BMCAddress: getHostBMCAddress(host) || '',
@@ -35,67 +46,112 @@ const getInitialValues = (
bootMACAddress: getHostBootMACAddress(host) || '',
online: isHostOnline(host) || true,
description: getHostDescription(host) || '',
+ enablePowerManagement: isEditing ? !!host?.spec?.bmc || enablePowerMgmt : true,
});
type AddBareMetalHostProps = {
namespace: string;
- isEditing: boolean;
- loaded?: boolean;
- hosts?: FirehoseResult;
- host?: FirehoseResult;
- secret?: FirehoseResult;
+ name?: string;
+ enablePowerMgmt: boolean;
};
const AddBareMetalHost: React.FC = ({
namespace,
- isEditing,
- hosts,
- host: resultHost,
- secret: resultSecret,
+ name,
+ enablePowerMgmt,
}) => {
- const [reload, setReload] = React.useState(false);
- const hostNames = _.flatMap(getLoadedData(hosts, []), (host) => getName(host));
- const initialHost = getLoadedData(resultHost);
- const initialSecret = getLoadedData(resultSecret);
- const prevInitialHost = usePrevious(initialHost);
- const prevInitialSecret = usePrevious(initialSecret);
+ const bmhResource = React.useMemo(
+ () =>
+ name
+ ? {
+ kind: referenceForModel(BareMetalHostModel),
+ namespace,
+ name,
+ }
+ : undefined,
+ [name, namespace],
+ );
+ const bmhResources = React.useMemo(
+ () =>
+ !name
+ ? {
+ kind: referenceForModel(BareMetalHostModel),
+ namespace,
+ isList: true,
+ }
+ : undefined,
+ [name, namespace],
+ );
+ const [host, hostLoaded, hostError] = useK8sWatchResource(bmhResource);
+ const [hosts, hostsLoaded, hostsError] = useK8sWatchResource(bmhResources);
- const initialValues = getInitialValues(initialHost, initialSecret);
- const prevInitialValues = getInitialValues(prevInitialHost, prevInitialSecret);
+ const credentialsName = host?.spec?.bmc?.credentialsName;
+ const secretResource = React.useMemo(
+ () =>
+ credentialsName
+ ? {
+ kind: SecretModel.kind,
+ namespace,
+ name: credentialsName,
+ }
+ : undefined,
+ [credentialsName, namespace],
+ );
+ const [secret, secretLoaded, secretError] = useK8sWatchResource(secretResource);
+ const [reload, setReload] = React.useState(false);
React.useEffect(() => {
if (reload) {
setReload(false);
}
}, [reload, setReload]);
- const showUpdated =
- isEditing &&
- prevInitialHost &&
- prevInitialSecret &&
- !_.isEqual(prevInitialValues, initialValues);
-
- const addHostValidationSchema = Yup.object().shape({
- name: Yup.mixed()
- .test(
- 'unique-name',
- 'Name "${value}" is already taken.', // eslint-disable-line no-template-curly-in-string
- (value) => !hostNames.includes(value),
- )
- .concat(nameValidationSchema),
- BMCAddress: Yup.string()
- .matches(BMC_ADDRESS_REGEX, 'Value provided is not a valid BMC address')
- .required('Required.'),
- username: Yup.string().required('Required.'),
- password: Yup.string().required('Required.'),
- bootMACAddress: Yup.string()
- .matches(MAC_REGEX, 'Value provided is not a valid MAC Address.')
- .required('Required.'),
- });
-
- const handleSubmit = (values, actions) => {
+ const initialHost = usePrevious(host, [hostLoaded, reload]);
+ const initialSecret = usePrevious(secret, [secretLoaded, reload]);
+
+ if (name ? !hostLoaded || (secretResource ? !secretLoaded : false) : !hostsLoaded) {
+ return ;
+ }
+
+ if (hostError || secretError || hostsError) {
+ return ;
+ }
+
+ const hostNames = !name ? hosts.map(getName) : [];
+
+ const initialValues = getInitialValues(host, secret, !!name, enablePowerMgmt);
+ const prevInitialValues = getInitialValues(initialHost, initialSecret, !!name, enablePowerMgmt);
+
+ const showUpdated = initialHost && !_.isEqual(prevInitialValues, initialValues);
+
+ const addHostValidationSchema = Yup.lazy(({ enablePowerManagement }) =>
+ Yup.object().shape({
+ name: Yup.mixed()
+ .test(
+ 'unique-name',
+ 'Name "${value}" is already taken.', // eslint-disable-line no-template-curly-in-string
+ (value) => !hostNames.includes(value),
+ )
+ .concat(nameValidationSchema),
+ BMCAddress: enablePowerManagement
+ ? Yup.string()
+ .matches(BMC_ADDRESS_REGEX, 'Value provided is not a valid BMC address')
+ .required('Required.')
+ : undefined,
+ username: enablePowerManagement ? Yup.string().required('Required.') : undefined,
+ password: enablePowerManagement ? Yup.string().required('Required.') : undefined,
+ bootMACAddress: Yup.string()
+ .matches(MAC_REGEX, 'Value provided is not a valid MAC Address.')
+ .required('Required.'),
+ }),
+ );
+
+ const handleSubmit = (
+ values: AddBareMetalHostFormValues,
+ actions: FormikHelpers,
+ ) => {
const opts = { ...values, namespace };
- const promise = isEditing
+ const promise = name
? updateBareMetalHost(initialHost, initialSecret, opts)
: createBareMetalHost(opts);
@@ -113,14 +169,12 @@ const AddBareMetalHost: React.FC = ({
return (
setReload(true)}
validationSchema={addHostValidationSchema}
>
- {(formikProps) => (
-
- )}
+ {(props) => }
);
};
diff --git a/frontend/packages/metal3-plugin/src/components/baremetal-hosts/add-baremetal-host/AddBareMetalHostForm.tsx b/frontend/packages/metal3-plugin/src/components/baremetal-hosts/add-baremetal-host/AddBareMetalHostForm.tsx
index 8077f9eb1d1..33ef2220b96 100644
--- a/frontend/packages/metal3-plugin/src/components/baremetal-hosts/add-baremetal-host/AddBareMetalHostForm.tsx
+++ b/frontend/packages/metal3-plugin/src/components/baremetal-hosts/add-baremetal-host/AddBareMetalHostForm.tsx
@@ -26,6 +26,7 @@ const AddBareMetalHostForm: React.FC = ({
dirty,
isEditing,
showUpdated,
+ values,
}) => (