This is an automated email from the ASF dual-hosted git repository.

arshad pushed a commit to branch frontend-refactor
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/frontend-refactor by this push:
     new ea56ea09d3 AMBARI-26542: Ambari Web React: Kerberos Wizard context & 
setup (#4052)
ea56ea09d3 is described below

commit ea56ea09d30ea3101d4a608c1d197754512a596f
Author: Sandeep  Kumar <[email protected]>
AuthorDate: Tue Sep 9 11:06:45 2025 +0530

    AMBARI-26542: Ambari Web React: Kerberos Wizard context & setup (#4052)
---
 ambari-web/latest/src/api/kerberosApi.ts           | 131 ++++++++++++
 .../latest/src/components/ConfirmationModal.tsx    |   4 +-
 ambari-web/latest/src/constants.ts                 |   3 +-
 .../KerberosWizard/KerberosStore/context.tsx       | 235 +++++++++++++++++++++
 .../KerberosWizard/KerberosStore/reducer.ts        |  49 +++++
 .../KerberosWizard/KerberosStore/types.ts}         |  24 ++-
 .../KerberosWizard/index.tsx}                      |  28 ++-
 .../screens/KerberosWizard/kerberosWizardSteps.tsx | 121 +++++++++++
 8 files changed, 571 insertions(+), 24 deletions(-)

diff --git a/ambari-web/latest/src/api/kerberosApi.ts 
b/ambari-web/latest/src/api/kerberosApi.ts
new file mode 100644
index 0000000000..9107ed9cd9
--- /dev/null
+++ b/ambari-web/latest/src/api/kerberosApi.ts
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { ambariApi } from "./config/axiosConfig";
+
+const KerberosApi = {
+  getKerberosDescriptorProperties: async function (
+    evaluate: string,
+    clusterName: string
+  ) {
+    const url = 
`/clusters/${clusterName}/kerberos_descriptors/COMPOSITE?evaluate_when=${evaluate}&_=${Date.now()}`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "GET",
+    });
+    return response.data;
+  },
+
+  getSecurityType: async function (clusterName: string) {
+    const url = `clusters/${clusterName}?fields=Clusters/security_type`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "GET",
+    });
+    return response.data;
+  },
+
+  testKdcConnection: async function (kdcHosts: string) {
+    const url = `kdc_check/${kdcHosts}`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "GET",
+    });
+    return response.data;
+  },
+
+  downloadKerberosIdentitiesCsv: async function (clusterName: string) {
+    const url = 
`clusters/${clusterName}/kerberos_identities?fields=*&format=csv`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "GET",
+    });
+    return response.data;
+  },
+  saveKerberosData: async function (clusterName: string, payload: any) {
+    const url = `clusters/${clusterName}/artifacts/kerberos_descriptor`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "POST",
+      data: payload,
+    });
+    return response.data;
+  },
+  postKDCAdminCredentials: async function (clusterName: string, payload: any) {
+    const url = `clusters/${clusterName}/credentials/kdc.admin.credential`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "POST",
+      data: payload,
+    });
+    return response.data;
+  },
+  deleteKDCAdminCredentials: async function (clusterName: string) {
+    const url = `clusters/${clusterName}/credentials/kdc.admin.credential`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "DELETE",
+    });
+    return response.data;
+  },
+  getKDCAdminCredentials: async function (clusterName: string) {
+    const url = `clusters/${clusterName}/credentials?fields=Credential/*`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "GET",
+    });
+    return response.data;
+  },
+
+  createKerberosConfigurations: async function (
+    clusterName: string,
+    payloadData: any
+  ) {
+    const url = `clusters/${clusterName}`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "PUT",
+      data: payloadData,
+    });
+    return response.data;
+  },
+
+  deleteKerberosService: async function (
+    clusterName: string,
+    serviceName: string
+  ) {
+    const url = `clusters/${clusterName}/services/${serviceName}`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "DELETE",
+    });
+    return response.data;
+  },
+
+  createAdminSession: async function (clusterName: string, payloadData: any) {
+    const url = `clusters/${clusterName}`;
+    const response = await ambariApi.request({
+      url: url,
+      method: "PUT",
+      data: payloadData,
+    });
+    return response.data;
+  },
+};
+
+export default KerberosApi;
diff --git a/ambari-web/latest/src/components/ConfirmationModal.tsx 
b/ambari-web/latest/src/components/ConfirmationModal.tsx
index a776c0cea2..43c6fd95e9 100644
--- a/ambari-web/latest/src/components/ConfirmationModal.tsx
+++ b/ambari-web/latest/src/components/ConfirmationModal.tsx
@@ -21,8 +21,8 @@ import DefaultButton from "./DefaultButton";
 type ConfirmationModalProps = {
   isOpen: boolean;
   onClose: () => void;
-  modalTitle: string;
-  modalBody: string;
+  modalTitle: any;
+  modalBody: any;
   successCallback: () => void;
   buttonVariant?: string;
   cancellable?: boolean;
diff --git a/ambari-web/latest/src/constants.ts 
b/ambari-web/latest/src/constants.ts
index 09d775ee8c..da554606cc 100644
--- a/ambari-web/latest/src/constants.ts
+++ b/ambari-web/latest/src/constants.ts
@@ -20,9 +20,10 @@ export enum ClusterProgressStatus {
   ENABLING_NAMENODE_HA = "ENABLING_NAMENODE_HA",
   ADDING_HOST = "ADDING_HOST",
   ADDING_SERVICE = "ADDING_SERVICE",
+  ENABLING_KERBEROS = "ENABLING_KERBEROS",
 }
 export enum ProgressStatus {
   IN_PROGRESS = "IN_PROGRESS",
   COMPLETED = "COMPLETED",
   FAILED = "FAILED",
-}
\ No newline at end of file
+}
diff --git 
a/ambari-web/latest/src/screens/KerberosWizard/KerberosStore/context.tsx 
b/ambari-web/latest/src/screens/KerberosWizard/KerberosStore/context.tsx
new file mode 100644
index 0000000000..d860b1cec5
--- /dev/null
+++ b/ambari-web/latest/src/screens/KerberosWizard/KerberosStore/context.tsx
@@ -0,0 +1,235 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React, {
+  createContext,
+  Dispatch,
+  // useContext,
+  useEffect,
+  useReducer,
+  useRef,
+  useState,
+} from "react";
+import { State, Action, ActionTypes } from "./types";
+import { reducer, initialState } from "./reducer";
+import ClusterApi from "../../../api/clusterApi";
+import { get, isEmpty } from "lodash";
+import { ClusterProgressStatus } from "../../../constants";
+// import ConfirmationModal from "../../../components/ConfirmationModal";
+// import { AppContext } from "../../../store/context";
+// import { translate } from "../../../Utils/Utility";
+import { useNavigate } from "react-router";
+import kerberosApi from "../../../api/kerberosApi";
+// import modalManager from "../../../store/ModalManager";
+import { RequestApi } from "../../../api/requestApi";
+
+interface KerberosWizardContextProps {
+  state: State;
+  dispatch: Dispatch<Action>;
+  stepWizardUtilities?: any;
+  flushStateToDb?: any;
+  onExitPopUp?: any;
+}
+
+export async function discardChanges(clusterName: string) {
+  const payload = {
+    Clusters: {
+      security_type: "NONE",
+    },
+  };
+  try {
+    await RequestApi.preparingOperations(clusterName, payload);
+    await kerberosApi.deleteKerberosService(clusterName, "KERBEROS");
+  } catch (error) {
+    console.log("Unable to remove kerberos", error);
+  }
+}
+
+export const EnableKerberosContext = 
createContext<KerberosWizardContextProps>({
+  state: initialState,
+  dispatch: () => undefined,
+  flushStateToDb: () => undefined,
+  onExitPopUp: () => undefined,
+});
+
+export const KerberosWizardProvider: React.FC<{
+  stepWizardUtilities: any;
+  children: React.ReactNode;
+}> = ({ stepWizardUtilities, children }) => {
+  const [state, dispatch] = useReducer(reducer, initialState);
+  const isDataPersisted = useRef(false);
+  const [currStepData, setCurrStepData] = useState({});
+  // const { clusterName } = useContext(AppContext);
+  const navigate = useNavigate();
+
+  useEffect(() => {
+    syncUserPersistedData();
+  }, []);
+
+  useEffect(() => {
+    if (isDataPersisted.current) {
+      flushCurrentData();
+    }
+  }, [state.kerberosWizardSteps, currStepData]);
+
+  async function syncUserPersistedData() {
+    try {
+      const persistedData = await ClusterApi.getPersistData(
+        "ENABLING_KERBEROS"
+      );
+      if (!isEmpty(get(persistedData, "kerberosWizardSteps", {}))) {
+        dispatch({
+          type: ActionTypes.SYNC_STATE,
+          payload: persistedData,
+        });
+      }
+      if (get(persistedData, "activeStep", "")) {
+        try {
+          const activeStepName = get(persistedData, "activeStep");
+          setCurrStepData({
+            progressStatus: ClusterProgressStatus.ENABLING_KERBEROS,
+            stepName: activeStepName,
+          });
+          let activeStepNumber = Object.keys(
+            stepWizardUtilities.wizardSteps
+          ).find((stepName) => {
+            return (
+              stepWizardUtilities.wizardSteps?.[stepName]?.name ===
+              activeStepName
+            );
+          });
+          stepWizardUtilities.jumpToStep(Number(activeStepNumber), true);
+        } catch (err) {
+          console.error("Error while jumping to step", err);
+        }
+      } else {
+        stepWizardUtilities.jumpToStep(1, true);
+      }
+    } finally {
+      isDataPersisted.current = true;
+    }
+  }
+
+  async function flushCurrentData() {
+    await ClusterApi.postPersistData(
+      JSON.stringify({
+        ENABLING_KERBEROS: JSON.stringify({
+          ...state,
+          activeStep: get(currStepData, "stepName", ""),
+        }),
+        CLUSTER_STATE: JSON.stringify(currStepData),
+      })
+    );
+  }
+
+  async function flushOnCancel() {
+    await ClusterApi.postPersistData(
+      JSON.stringify({
+        ENABLING_KERBEROS: JSON.stringify(initialState),
+        CLUSTER_STATE: JSON.stringify({}),
+      })
+    );
+    navigate(`/main/admin/kerberos/`);
+  }
+
+  async function flushOnStepChange(nextStep: number) {
+    if (nextStep >= 1) {
+      let nextStepDetails = stepWizardUtilities.wizardSteps?.[nextStep];
+      if (nextStepDetails?.keysToRemove) {
+        nextStepDetails.keysToRemove.forEach((key: string) => {
+          if (state?.kerberosWizardSteps?.[key]) {
+            dispatch({
+              type: ActionTypes.REMOVE_KEY,
+              payload: { key },
+            });
+          }
+        });
+      }
+      setCurrStepData({
+        progressStatus: ClusterProgressStatus.ENABLING_KERBEROS,
+        stepName: stepWizardUtilities?.wizardSteps?.[nextStep]?.name,
+      });
+    }
+  }
+
+  function flushStateToDb(
+    operation: string = "default",
+    jumpStep: number = -1
+  ) {
+    let activeStep = Object.keys(stepWizardUtilities.wizardSteps).find(
+      (stepName) => {
+        return (
+          stepWizardUtilities.wizardSteps?.[stepName]?.name ===
+          stepWizardUtilities.currentStep.name
+        );
+      }
+    );
+    switch (operation) {
+      case "cancel":
+        flushOnCancel();
+        break;
+      case "back":
+        flushOnStepChange(Number(activeStep) - 1);
+        break;
+      case "next":
+        flushOnStepChange(Number(activeStep) + 1);
+        break;
+      case "jump":
+        flushOnStepChange(jumpStep);
+        break;
+      default:
+        flushCurrentData();
+    }
+  }
+
+  function onExitPopUp(isCritical: boolean, skipDiscardChanges: boolean) {
+    console.log("Exit popup called", isCritical, skipDiscardChanges);
+    // TODO: will be added once modalManager PR is merged
+    // modalManager.show(
+    //   <ConfirmationModal
+    //     isOpen={true}
+    //     onClose={() => modalManager.hide()}
+    //     modalTitle={translate("popup.confirmation.commonHeader")}
+    //     modalBody={
+    //       isCritical
+    //         ? translate("admin.kerberos.wizard.exit.critical.msg")
+    //         : translate("admin.kerberos.wizard.exit.warning.msg")
+    //     }
+    //     successCallback={() => {
+    //       if (!skipDiscardChanges) discardChanges(clusterName);
+    //       flushStateToDb("cancel");
+    //       modalManager.hide();
+    //     }}
+    //   />
+    // );
+  }
+
+  return (
+    <EnableKerberosContext.Provider
+      value={{
+        state,
+        dispatch,
+        stepWizardUtilities,
+        flushStateToDb,
+        onExitPopUp,
+      }}
+    >
+      {children}
+    </EnableKerberosContext.Provider>
+  );
+};
diff --git 
a/ambari-web/latest/src/screens/KerberosWizard/KerberosStore/reducer.ts 
b/ambari-web/latest/src/screens/KerberosWizard/KerberosStore/reducer.ts
new file mode 100644
index 0000000000..82ba77c43a
--- /dev/null
+++ b/ambari-web/latest/src/screens/KerberosWizard/KerberosStore/reducer.ts
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import { cloneDeep } from "lodash";
+import { State, Action, ActionTypes } from "./types";
+
+export const initialState: State = {
+  kerberosWizardSteps: {},
+};
+
+export const reducer = (state: State, action: Action): State => {
+  switch (action.type) {
+    case ActionTypes.STORE_INFORMATION:
+      const stateCopy = cloneDeep(state);
+      if (!stateCopy.kerberosWizardSteps) {
+        stateCopy.kerberosWizardSteps = {};
+      }
+      const enableHighAvailibilityRangerAdminSteps = cloneDeep(
+        stateCopy.kerberosWizardSteps
+      );
+      enableHighAvailibilityRangerAdminSteps[action.payload.step] =
+        action.payload;
+      stateCopy.kerberosWizardSteps = enableHighAvailibilityRangerAdminSteps;
+      return stateCopy;
+    case ActionTypes.SYNC_STATE:
+      return { ...action.payload };
+    case ActionTypes.REMOVE_KEY:
+      const updatedSteps = { ...state.kerberosWizardSteps };
+      delete updatedSteps[action.payload.key];
+      return { ...state, kerberosWizardSteps: updatedSteps };
+    default:
+      return state;
+  }
+};
diff --git a/ambari-web/latest/src/constants.ts 
b/ambari-web/latest/src/screens/KerberosWizard/KerberosStore/types.ts
similarity index 68%
copy from ambari-web/latest/src/constants.ts
copy to ambari-web/latest/src/screens/KerberosWizard/KerberosStore/types.ts
index 09d775ee8c..a492493bf5 100644
--- a/ambari-web/latest/src/constants.ts
+++ b/ambari-web/latest/src/screens/KerberosWizard/KerberosStore/types.ts
@@ -15,14 +15,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-export enum ClusterProgressStatus {
-  PROVISIONING = "PROVISIONING",
-  ENABLING_NAMENODE_HA = "ENABLING_NAMENODE_HA",
-  ADDING_HOST = "ADDING_HOST",
-  ADDING_SERVICE = "ADDING_SERVICE",
+
+export interface State {
+  kerberosWizardSteps: any;
 }
-export enum ProgressStatus {
-  IN_PROGRESS = "IN_PROGRESS",
-  COMPLETED = "COMPLETED",
-  FAILED = "FAILED",
-}
\ No newline at end of file
+
+export enum ActionTypes {
+  STORE_INFORMATION = "STORE INFORMATION",
+  SYNC_STATE = "SYNC STATE",
+  REMOVE_KEY = "REMOVE KEY",
+}
+
+export type Action =
+  | { type: ActionTypes.STORE_INFORMATION; payload: any }
+  | { type: ActionTypes.SYNC_STATE; payload: any }
+  | { type: ActionTypes.REMOVE_KEY; payload: any };
diff --git a/ambari-web/latest/src/constants.ts 
b/ambari-web/latest/src/screens/KerberosWizard/index.tsx
similarity index 58%
copy from ambari-web/latest/src/constants.ts
copy to ambari-web/latest/src/screens/KerberosWizard/index.tsx
index 09d775ee8c..13cdd3e1a7 100644
--- a/ambari-web/latest/src/constants.ts
+++ b/ambari-web/latest/src/screens/KerberosWizard/index.tsx
@@ -15,14 +15,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-export enum ClusterProgressStatus {
-  PROVISIONING = "PROVISIONING",
-  ENABLING_NAMENODE_HA = "ENABLING_NAMENODE_HA",
-  ADDING_HOST = "ADDING_HOST",
-  ADDING_SERVICE = "ADDING_SERVICE",
-}
-export enum ProgressStatus {
-  IN_PROGRESS = "IN_PROGRESS",
-  COMPLETED = "COMPLETED",
-  FAILED = "FAILED",
-}
\ No newline at end of file
+
+import StepWizard from "../../components/StepWizard";
+import useStepWizard from "../../hooks/useStepWizard";
+import { KerberosWizardProvider } from "./KerberosStore/context";
+import kerberosWizardSteps from "./kerberosWizardSteps";
+
+const KerberosWizard: React.FC = () => {
+  const stepWizardUtilities = useStepWizard(kerberosWizardSteps, 1, () => {});
+
+  return (
+    <KerberosWizardProvider stepWizardUtilities={stepWizardUtilities}>
+      <StepWizard wizardUtilities={stepWizardUtilities} />
+    </KerberosWizardProvider>
+  );
+};
+
+export default KerberosWizard;
diff --git 
a/ambari-web/latest/src/screens/KerberosWizard/kerberosWizardSteps.tsx 
b/ambari-web/latest/src/screens/KerberosWizard/kerberosWizardSteps.tsx
new file mode 100644
index 0000000000..7b91ce869e
--- /dev/null
+++ b/ambari-web/latest/src/screens/KerberosWizard/kerberosWizardSteps.tsx
@@ -0,0 +1,121 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+export default {
+  1: {
+    label: "Get Started",
+    completed: false,
+    Component: <h1>Get Started</h1>,
+    canGoBack: false,
+    isNextEnabled: false,
+    name: "GET_STARTED",
+    keysToRemove: [
+      "CONFIGURE_KERBEROS",
+      "CONFIGURE_IDENTITIES",
+      "INSTALL_AND_TEST_KERBEROS_CLIENT",
+      "CONFIRM_CONFIGURATION",
+      "STOP_SERVICES",
+      "KERBERIZE_CLUSTER",
+      "START_AND_TEST_SERVICES",
+    ],
+  },
+  2: {
+    label: "Configure Kerberos",
+    completed: false,
+    Component: <h1>Configure Kerberos</h1>,
+    canGoBack: true,
+    isNextEnabled: false,
+    name: "CONFIGURE_KERBEROS",
+    keysToRemove: [
+      "CONFIGURE_IDENTITIES",
+      "INSTALL_AND_TEST_KERBEROS_CLIENT",
+      "CONFIRM_CONFIGURATION",
+      "STOP_SERVICES",
+      "KERBERIZE_CLUSTER",
+      "START_AND_TEST_SERVICES",
+    ],
+  },
+  3: {
+    label: "Install and Test Kerberos Client",
+    completed: false,
+    Component: <h1>Install and Test kerberos client</h1>,
+    canGoBack: true,
+    isNextEnabled: false,
+    name: "INSTALL_AND_TEST_KERBEROS_CLIENT",
+    keysToRemove: [
+      "CONFIGURE_IDENTITIES",
+      "CONFIRM_CONFIGURATION",
+      "STOP_SERVICES",
+      "KERBERIZE_CLUSTER",
+      "START_AND_TEST_SERVICES",
+    ],
+  },
+  4: {
+    label: "Configure Identities",
+    completed: false,
+    Component: <h1>Configure Identities</h1>,
+    canGoBack: true,
+    isNextEnabled: true,
+    name: "CONFIGURE_IDENTITIES",
+    keysToRemove: [
+      "CONFIRM_CONFIGURATION",
+      "STOP_SERVICES",
+      "KERBERIZE_CLUSTER",
+      "START_AND_TEST_SERVICES",
+    ],
+  },
+  5: {
+    label: "Confirm Configuration",
+    completed: false,
+    Component: <h1>Confirm Configuration</h1>,
+    canGoBack: true,
+    isNextEnabled: true,
+    name: "CONFIRM_CONFIGURATION",
+    keysToRemove: [
+      "STOP_SERVICES",
+      "KERBERIZE_CLUSTER",
+      "START_AND_TEST_SERVICES",
+    ],
+  },
+  6: {
+    label: "Stop Services",
+    completed: false,
+    Component: <h1>Stop services</h1>,
+    canGoBack: true,
+    isNextEnabled: true,
+    name: "STOP_SERVICES",
+    keysToRemove: ["KERBERIZE_CLUSTER", "START_AND_TEST_SERVICES"],
+  },
+  7: {
+    label: "Kerberize cluster",
+    completed: false,
+    Component: <h1>Kerberize cluster</h1>,
+    canGoBack: true,
+    isNextEnabled: false,
+    name: "KERBERIZE_CLUSTER",
+    keysToRemove: ["START_AND_TEST_SERVICES"],
+  },
+  8: {
+    label: "Start and Test Services",
+    completed: false,
+    Component: <h1>Start and Test Services</h1>,
+    canGoBack: true,
+    isNextEnabled: false,
+    name: "START_AND_TEST_SERVICES",
+  },
+};


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to