export function ConnectToLocalKubernetesClusterWizard()

in packages/online-editor/src/accounts/kubernetes/ConnectToLocalKubernetesClusterWizard.tsx [113:488]


export function ConnectToLocalKubernetesClusterWizard(props: {
  kieSandboxKubernetesService?: KieSandboxKubernetesService;
  setMode: React.Dispatch<React.SetStateAction<KubernetesSettingsTabMode>>;
  connection: KubernetesConnection;
  setConnection: React.Dispatch<React.SetStateAction<KubernetesConnection>>;
  status: KubernetesInstanceStatus;
  setStatus: React.Dispatch<React.SetStateAction<KubernetesInstanceStatus>>;
  setNewAuthSession: React.Dispatch<React.SetStateAction<KubernetesAuthSession>>;
  isLoadingService: boolean;
}) {
  const { i18n } = useOnlineI18n();
  const routes = useRoutes();
  const [isConnectionValidated, setConnectionValidated] = useState(false);
  const [isConnecting, setConnecting] = useState(false);
  const [isConnectLoading, setConnectLoading] = useState(false);
  const authSessionsDispatch = useAuthSessionsDispatch();
  const [operatingSystem, setOperatingSystem] = useState(getOperatingSystem() ?? OperatingSystem.LINUX);
  const [kubernetesFlavor, setKubernetesFlavor] = useState<KubernetesFlavor>(KubernetesFlavor.KIND);
  const [previousConnection, setPreviousConnection] = useState<KubernetesConnection>();

  const onClearHost = useCallback(() => props.setConnection({ ...props.connection, host: "" }), [props]);
  const onClearNamespace = useCallback(() => props.setConnection({ ...props.connection, namespace: "" }), [props]);
  const onClearToken = useCallback(() => props.setConnection({ ...props.connection, token: "" }), [props]);

  const clusterConfigCommands: ClusterConfigCommands = useMemo(() => {
    if (kubernetesFlavor === KubernetesFlavor.KIND) {
      return {
        createCluster:
          operatingSystem === OperatingSystem.WINDOWS
            ? COMMANDS.kindCreateClusterWindows
            : COMMANDS.kindCreateClusterUnix,
        applyAndWaitIngress: () =>
          operatingSystem === OperatingSystem.WINDOWS
            ? `${COMMANDS.kindApplyIngress()}; ${COMMANDS.sleep()}; ${COMMANDS.waitForIngress()}`
            : `${COMMANDS.kindApplyIngress()} && ${COMMANDS.sleep()} && ${COMMANDS.waitForIngress()}`,
        applyDeploymentResources:
          operatingSystem === OperatingSystem.WINDOWS
            ? COMMANDS.applyDeploymentResourcesWindows
            : COMMANDS.applyDeploymentResourcesUnix,
        getSecret: operatingSystem === OperatingSystem.WINDOWS ? COMMANDS.getSecretWindows : COMMANDS.getSecretUnix,
      };
    } else {
      return {
        createCluster: COMMANDS.minikubeCreateCluster,
        applyAndWaitIngress: () =>
          operatingSystem === OperatingSystem.WINDOWS
            ? `${COMMANDS.minikubeApllyIngress()}; ${COMMANDS.sleep()}; ${COMMANDS.waitForIngress()}`
            : `${COMMANDS.minikubeApllyIngress()} && ${COMMANDS.sleep()} && ${COMMANDS.waitForIngress()}`,
        applyDeploymentResources:
          operatingSystem === OperatingSystem.WINDOWS
            ? COMMANDS.applyDeploymentResourcesWindows
            : COMMANDS.applyDeploymentResourcesUnix,
        getSecret: operatingSystem === OperatingSystem.WINDOWS ? COMMANDS.getSecretWindows : COMMANDS.getSecretUnix,
      };
    }
  }, [kubernetesFlavor, operatingSystem]);

  useEffect(() => {
    setPreviousConnection(props.connection);
    props.setConnection({
      namespace: DEFAULT_LOCAL_CLUSTER_NAMESPACE,
      host: DEFAULT_LOCAL_CLUSTER_HOST,
      token: "",
      insecurelyDisableTlsCertificateValidation: false,
    });
  }, []);

  const isNamespaceValidated = useMemo(() => {
    return isNamespaceValid(props.connection.namespace);
  }, [props.connection.namespace]);

  const isHostValidated = useMemo(() => {
    return isHostValid(props.connection.host);
  }, [props.connection.host]);

  const isTokenValidated = useMemo(() => {
    return isTokenValid(props.connection.token);
  }, [props.connection.token]);

  useEffect(() => {
    setConnectionValidated(isKubernetesConnectionValid(props.connection));
  }, [props.connection]);

  const onCancel = useCallback(() => {
    if (previousConnection) {
      props.setConnection(previousConnection);
    }
    props.setMode(KubernetesSettingsTabMode.SIMPLE);
  }, [props, previousConnection]);

  const onNamespaceInputChanged = useCallback(
    (event: React.FormEvent<HTMLInputElement>, newValue: string) => {
      props.setConnection((c) => ({ ...c, namespace: newValue }));
    },
    [props]
  );

  const onHostInputChanged = useCallback(
    (event: React.FormEvent<HTMLInputElement>, newValue: string) => {
      props.setConnection((c) => ({ ...c, host: newValue }));
    },
    [props]
  );

  const onTokenInputChanged = useCallback(
    (event: React.FormEvent<HTMLInputElement>, newValue: string) => {
      props.setConnection((c) => ({ ...c, token: newValue }));
    },
    [props]
  );

  /* 
  TODO: uncomment when enabling kubernetes deployment to use cors-proxy
  const onInsecurelyDisableTlsCertificateValidationChange = useCallback((checked: boolean) => {
    props.setConnection({ ...props.connection, insecurelyDisableTlsCertificateValidation: checked });
  }, [props]); */

  const onStepChanged = useCallback(
    async ({ id }) => {
      if (id === WizardStepIds.CONNECT) {
        setConnectLoading(true);
        setConnectionValidated(
          (props.kieSandboxKubernetesService && (await props.kieSandboxKubernetesService.isConnectionEstablished())) ===
            KubernetesConnectionStatus.CONNECTED
        );
        setConnectLoading(false);
      }
    },
    [props.kieSandboxKubernetesService]
  );

  const onSave = useCallback(async () => {
    if (isConnecting) {
      return;
    }

    if (!isKubernetesConnectionValid(props.connection)) {
      return;
    }

    setConnecting(true);
    const isConnectionEstablished =
      props.kieSandboxKubernetesService && (await props.kieSandboxKubernetesService.isConnectionEstablished());
    setConnecting(false);

    if (isConnectionEstablished === KubernetesConnectionStatus.CONNECTED && props.kieSandboxKubernetesService) {
      const newAuthSession: KubernetesAuthSession = {
        type: CloudAuthSessionType.Kubernetes,
        version: AUTH_SESSION_VERSION_NUMBER,
        id: uuid(),
        ...props.connection,
        authProviderId: "kubernetes",
        createdAtDateISO: new Date().toISOString(),
        k8sApiServerEndpointsByResourceKind: props.kieSandboxKubernetesService.args.k8sApiServerEndpointsByResourceKind,
      };
      setConnectionValidated(true);
      props.setStatus(KubernetesInstanceStatus.CONNECTED);
      authSessionsDispatch.add(newAuthSession);
      props.setNewAuthSession(newAuthSession);
    } else {
      setConnectionValidated(false);
      return;
    }
  }, [authSessionsDispatch, isConnecting, props]);

  const firstStepContent = useMemo(
    () => (
      <>
        <br />
        <List component={ListComponent.ol} type={OrderType.number} className="pf-v5-u-mt-md">
          <ListItem>
            <TextContent>
              <Text component={TextVariants.p}>
                <a href={FLAVOR_INSTALL_DOCS[kubernetesFlavor]} target={"_blank"} rel="noreferrer">
                  {i18n.devDeployments.kubernetesConfigWizard.steps.first.installFlavor(kubernetesFlavor)}
                  &nbsp;
                  <ExternalLinkAltIcon className="pf-v5-u-mx-sm" />
                </a>
              </Text>
            </TextContent>
          </ListItem>
          <ListItem>
            <TextContent>
              <Text component={TextVariants.p}>
                <a href={KUBECTL_INSTALL_DOCS[operatingSystem]} target={"_blank"} rel="noreferrer">
                  {i18n.devDeployments.kubernetesConfigWizard.steps.first.installKubectl}
                  &nbsp;
                  <ExternalLinkAltIcon className="pf-v5-u-mx-sm" />
                </a>
              </Text>
            </TextContent>
          </ListItem>
          <ListItem>
            <TextContent>
              <Text component={TextVariants.p}>
                {i18n.devDeployments.kubernetesConfigWizard.steps.first.runCommandsTerminal}
              </Text>
            </TextContent>
            <List component={ListComponent.ol} type={OrderType.lowercaseLetter}>
              <ListItem>
                <TextContent>
                  <Text component={TextVariants.p}>
                    {i18n.devDeployments.kubernetesConfigWizard.steps.first.createCluster}
                  </Text>
                </TextContent>
                <CommandCopyBlock
                  command={clusterConfigCommands.createCluster(
                    `${window.location.origin}${
                      window.location.pathname
                    }${routes.static.devDeployments.kubernetes.clusterConfig.kindClusterConfig.path({})}`
                  )}
                />
              </ListItem>
              <ListItem>
                <TextContent>
                  <Text component={TextVariants.p}>
                    {i18n.devDeployments.kubernetesConfigWizard.steps.first.installIngress}
                  </Text>
                </TextContent>
                <CommandCopyBlock command={clusterConfigCommands.applyAndWaitIngress()} />
              </ListItem>
              <ListItem>
                <TextContent>
                  <Text component={TextVariants.p}>
                    {i18n.devDeployments.kubernetesConfigWizard.steps.first.installKieSandboxYaml}
                  </Text>
                </TextContent>
                <CommandCopyBlock
                  command={clusterConfigCommands.applyDeploymentResources(
                    `${window.location.origin}${
                      window.location.pathname
                    }${routes.static.devDeployments.kubernetes.clusterConfig.kieSandboxDevDeploymentsResources.path(
                      {}
                    )}`
                  )}
                />
              </ListItem>
            </List>
          </ListItem>
        </List>
      </>
    ),
    [
      clusterConfigCommands,
      i18n.devDeployments.kubernetesConfigWizard.steps.first,
      kubernetesFlavor,
      operatingSystem,
      routes.static.devDeployments.kubernetes.clusterConfig,
    ]
  );

  const wizardSteps = useMemo(
    () => [
      {
        id: WizardStepIds.CREATE_CLUSTER,
        name: i18n.devDeployments.kubernetesConfigWizard.steps.first.name,
        component: (
          <div>
            <Text component={TextVariants.p}>
              {i18n.devDeployments.kubernetesConfigWizard.steps.first.introduction}
            </Text>
            <Tabs
              activeKey={kubernetesFlavor}
              onSelect={(_, flavor) => setKubernetesFlavor(flavor as KubernetesFlavor)}
              isVertical={false}
              isBox={false}
            >
              <Tab
                className="kie-tools--settings-tab"
                eventKey={KubernetesFlavor.KIND}
                title={<TabTitleText>Kind</TabTitleText>}
              >
                {firstStepContent}
              </Tab>
              <Tab
                className="kie-tools--settings-tab"
                eventKey={KubernetesFlavor.MINIKUBE}
                title={<TabTitleText>Minikube</TabTitleText>}
              >
                {firstStepContent}
              </Tab>
            </Tabs>
          </div>
        ),
      },
      {
        id: WizardStepIds.CONNECTION_INFO,
        name: i18n.devDeployments.kubernetesConfigWizard.steps.second.name,
        component: (
          <div>
            <Text component={TextVariants.p}>
              {i18n.devDeployments.kubernetesConfigWizard.steps.second.introduction}
            </Text>
            <Text component={TextVariants.small} style={{ color: "var(--pf-v5-global--palette--red-100)" }}>
              {i18n.devDeployments.kubernetesConfigWizard.steps.second.disclaimer}
            </Text>
            <br />
            <br />
            <Form className="pf-v5-u-mt-md" onSubmit={(e) => e.preventDefault()}>
              <FormGroup
                fieldId={"dev-deployments-config-namespace"}
                label={i18n.devDeployments.kubernetesConfigWizard.fields.namespace}
                isRequired={true}
              >
                <InputGroup>
                  <InputGroupItem isFill>
                    <TextInput
                      autoFocus={true}
                      autoComplete={"off"}
                      type="text"
                      id="namespace-field"
                      name="namespace-field"
                      aria-label="namespace field"
                      value={props.connection.namespace}
                      placeholder={i18n.devDeployments.kubernetesConfigWizard.steps.second.namespacePlaceholder}
                      onChange={onNamespaceInputChanged}
                    />
                  </InputGroupItem>
                  <InputGroupText>
                    <Button size="sm" variant="plain" aria-label="Clear namespace button" onClick={onClearNamespace}>
                      <TimesIcon />
                    </Button>
                  </InputGroupText>
                </InputGroup>
                <HelperText>
                  {isNamespaceValidated === true ? (
                    <HelperTextItem variant="error">{i18n.devDeployments.common.requiredField}</HelperTextItem>
                  ) : (
                    <HelperTextItem icon={ValidatedOptions.success}></HelperTextItem>
                  )}
                </HelperText>
              </FormGroup>
              <Text component={TextVariants.p}>
                {i18n.devDeployments.kubernetesConfigWizard.steps.second.namespaceInputReason}
              </Text>
              <FormGroup
                fieldId={"dev-deployments-config-host"}
                label={i18n.devDeployments.kubernetesConfigWizard.fields.kubernetesApiServerUrl}
                isRequired={true}
              >
                <InputGroup>
                  <InputGroupItem isFill>
                    <TextInput
                      autoFocus={true}
                      autoComplete={"off"}
                      isRequired
                      type="text"
                      id="host-field"
                      name="host-field"
                      aria-label="Host field"
                      value={props.connection.host}
                      placeholder={i18n.devDeployments.kubernetesConfigWizard.steps.second.hostPlaceholder}
                      onChange={onHostInputChanged}
                    />
                  </InputGroupItem>
                  <InputGroupText>
                    <Button size="sm" variant="plain" aria-label="Clear host button" onClick={onClearHost}>
                      <TimesIcon />
                    </Button>
                  </InputGroupText>
                </InputGroup>
                <HelperText>
                  {isHostValidated === true ? (
                    <HelperTextItem variant="error">{i18n.devDeployments.common.requiredField}</HelperTextItem>
                  ) : (
                    <HelperTextItem icon={ValidatedOptions.success}></HelperTextItem>
                  )}
                </HelperText>
              </FormGroup>
              <Text component={TextVariants.p}>
                {i18n.devDeployments.kubernetesConfigWizard.steps.second.hostInputReason}
              </Text>
            </Form>
          </div>
        ),
      },