Skip to content

ACM-20968: Decouple InfraEnv Create Page#2826

Open
rawagner wants to merge 1 commit intoopenshift-assisted:masterfrom
rawagner:cim_dynamic
Open

ACM-20968: Decouple InfraEnv Create Page#2826
rawagner wants to merge 1 commit intoopenshift-assisted:masterfrom
rawagner:cim_dynamic

Conversation

@rawagner
Copy link
Member

@rawagner rawagner commented Mar 4, 2025

Even though it looks like a lot of new code, this is actually mostly a refactoring of existing InfraEnv form. I've moved things around to create a nicer structure.

The new code is CredentialsField.tsx , as that was previously done in ACM console, which we cannot do anymore.
Another new code is YamlEditor.tsx. It will need some more tweaking (ie makings sure it sizes properly). But that can be handled in a followup.

See also stolostron/console#4307

Summary by CodeRabbit

  • New Features

    • Added extensive new UI translations for infrastructure environment and host management workflows.
    • Introduced hooks and components for watching and managing Kubernetes resources related to infrastructure environments, agents, and hosts.
    • Added new modals for deleting and unbinding hosts with clear confirmation and error handling.
    • Implemented a new InfraEnv creation page and form with enhanced validation, credential selection, and YAML editing.
    • Added a YAML editor component supporting resource validation and submission.
    • Introduced a credentials selection field integrated with form state and navigation.
    • Enhanced agent and host tables with internalized state management and simplified callbacks.
    • Added new utility functions for patching and managing agent and cluster resources.
  • Improvements

    • Refactored multiple components to remove external callback props, centralizing logic and reducing complexity.
    • Updated navigation links to use consistent Kubernetes resource paths.
    • Improved error handling and loading states across components.
    • Enhanced translation coverage with additional prompts and messages.
    • Simplified form and modal submission flows by internalizing patch and create operations.
    • Updated UI text for clarity and consistency.
    • Added new CSS rules for better UI spacing and theming.
  • Bug Fixes

    • Fixed proxy configuration fields to be optional and handled missing values gracefully.
    • Corrected minor text in warnings to better reflect data sensitivity.
  • Style

    • Added and updated CSS files for YAML editor, InfraEnv hosts tab, and other components.
  • Documentation

    • Added helper popovers and links to documentation in forms.
    • Improved instructional messages guiding host addition and environment creation.
  • Chores

    • Removed deprecated props and callbacks from multiple components and types.
    • Upgraded dependency on dynamic plugin SDK.
    • Consolidated imports and exports for cleaner module structure.
    • Added new typed Kubernetes resource models and hooks for better type safety.

@rawagner rawagner requested a review from a team as a code owner March 4, 2025 12:17
@openshift-ci openshift-ci bot requested review from batzionb and jkilzi March 4, 2025 12:17
@openshift-ci
Copy link

openshift-ci bot commented Mar 4, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: rawagner

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Mar 4, 2025
@rawagner
Copy link
Member Author

/hold

@openshift-ci openshift-ci bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Mar 10, 2025
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 14, 2025
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label May 20, 2025
@coderabbitai
Copy link

coderabbitai bot commented May 20, 2025

Walkthrough

This update introduces a comprehensive refactor and feature expansion of the infrastructure environment (InfraEnv) and host management workflows. It adds new components for creating and managing InfraEnvs, centralizes resource creation and patching logic, internalizes modal and action handling, simplifies and unifies type definitions, and introduces new hooks for Kubernetes resource watching. Numerous translation keys, UI enhancements, and error handling improvements are also included.

Changes

File(s) / Group Change Summary
libs/locales/lib/en/translation.json Added new translation keys for InfraEnv and host management, UI prompts, error messages, and instructional text.
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/*, .../utils.ts, .../useInfraEnvResources.ts New form, page, validation, and resource aggregation logic for creating InfraEnvs; dynamic resource generation and validation.
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/*, .../AgentsTab.tsx, .../DetailsTab.tsx New details and tabbed views for InfraEnv, with data fetching, navigation, and host/agent display.
libs/ui-lib/lib/cim/components/InfraEnv/index.ts Removed legacy exports, added new exports for InfraEnvDetails and CreateInfraEnvPage.
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx, .../infra-env.css Deleted legacy InfraEnv form and associated CSS.
libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx, .../types.ts Refactored to use internal hooks for provisioning config; removed external action props.
libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx Refactored to use hooks for secret fetching; removed external submit handlers and fetchers.
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx Internalized modal and action management; removed external callbacks.
libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx, .../types.ts Centralized BMH creation logic; removed onCreateBMH prop.
libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx Refactored cluster/infraEnv link generation; changed onDeleteHost signature.
libs/ui-lib/lib/cim/components/ClusterDeployment/* Removed many callback props for host/agent actions; centralized deletion logic; improved loading/error handling.
libs/ui-lib/lib/cim/components/modals/* Removed many external callback props; internalized patching, deletion, and submission logic for host/agent modals; added DeleteHostModal and UnbindHostModal.
libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx New Formik-integrated credentials selector component.
libs/ui-lib/lib/cim/components/YamlEditor/* New YAML editor modal with Monaco integration, theme, and validation/submission utilities.
libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx Internalized ConfigMap fetching with new hooks; removed prop.
libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx, .../NoAgentsAlert.tsx Updated infraEnv link paths to new Kubernetes resource URLs.
libs/ui-lib/lib/cim/components/helpers/agents.ts Simplified hostname change logic; direct patching.
libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts Localized getConditionByType utility.
libs/ui-lib/lib/cim/components/modals/utils.ts Added deleteHost utility for agent/BMH/NMState deletion and provision adjustment.
libs/ui-lib/lib/cim/config/constants.ts Added DOC_VERSION constant.
libs/ui-lib/lib/cim/types/models.ts New module exporting Kubernetes resource models.
libs/ui-lib/lib/cim/types/k8s/* Added/updated types for InfraEnv, NMState, MCE, KlusterletAddonConfig, etc.
libs/ui-lib/lib/cim/hooks/* Added new hooks for watching K8s resources (Agents, BMHs, InfraEnv, NMState, AgentClusterInstall, etc.).
libs/ui-lib/lib/cim/utils.ts Replaced getConditionByType with patching, approval, and name utilities.
libs/ui-lib/lib/cim/index.ts Re-exported all from utils.
libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx Minor wording update in warning message.
libs/ui-lib/package.json Upgraded dynamic plugin SDK, added SVG copy script.
libs/ui-lib/lib/ocm/components/Routes.tsx Added explicit props type for UILibRoutes.
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx, .css Updated icon class and added CSS rule for margin.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI
    participant Formik
    participant K8sAPI
    participant Router

    User->>UI: Click "Create InfraEnv"
    UI->>Formik: Initialize form
    User->>Formik: Fill form fields and submit
    Formik->>UI: Validate and collect values
    UI->>K8sAPI: Dry-run create Secret, InfraEnv, (optional) Role
    K8sAPI-->>UI: Dry-run response
    UI->>K8sAPI: Create Secret, InfraEnv, (optional) Role
    K8sAPI-->>UI: Creation response
    UI->>Router: Navigate to InfraEnv details page
Loading
sequenceDiagram
    participant User
    participant UI
    participant Modal
    participant K8sAPI

    User->>UI: Click "Delete Host"
    UI->>Modal: Open DeleteHostModal
    User->>Modal: Confirm deletion
    Modal->>K8sAPI: Delete Agent/BMH/NMState, adjust provision requirements
    K8sAPI-->>Modal: Success/Error
    Modal->>UI: Close modal, refresh view
Loading

Possibly related PRs

Suggested labels

lgtm

Suggested reviewers

  • rawagner
  • ammont82
  • jgyselov

Poem

🐇✨
A garden of clusters, hosts abound,
With forms and tabs now neatly found.
Secrets watched, credentials picked,
YAML flows and errors fixed.
Rabbits hop—InfraEnv blooms anew,
In every patch, a future grew!
🌱🛠️

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "@openshift-assisted/eslint-config" to extend from. Please check that the name of the config is correct.

The config "@openshift-assisted/eslint-config" was referenced from the config file in "/libs/ui-lib/.eslintrc.cjs".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "@openshift-assisted/eslint-config" to extend from. Please check that the name of the config is correct.

The config "@openshift-assisted/eslint-config" was referenced from the config file in "/libs/ui-lib/.eslintrc.cjs".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "@openshift-assisted/eslint-config" to extend from. Please check that the name of the config is correct.

The config "@openshift-assisted/eslint-config" was referenced from the config file in "/libs/ui-lib/.eslintrc.cjs".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

  • 67 others
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 21

🔭 Outside diff range comments (1)
libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (1)

42-44: 💡 Verification agent

🧩 Analysis chain

Document why error handling is suppressed.

Error handling in the secret fetch operation is suppressed with a commented-out console.error. It would be helpful to add a comment explaining why this approach was chosen.


🏁 Script executed:

#!/bin/bash
# Check if this error handling pattern is consistent across the codebase

# Look for similar patterns of commented-out error logging
echo "Files with commented-out error logging:"
rg -A 2 "console\.error.*\(.*\);" --type=ts | grep -B 1 "\/\/"

# Count occurrences
echo "Count of commented-out console.error occurrences:"
rg "\/\/\s*console\.error" --type=ts | wc -l

Length of output: 2441


Document suppressed error handling in EditBMHModal

Please add a brief comment above the silent catch block to explain why console.error is disabled—e.g. that failures fetching the secret are non-critical and the UI will fall back gracefully. Without this note, future readers may not understand the intent.

Affected location:

  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (around lines 42–44)

Suggested snippet:

   } catch (err) {
-    // console.error(t('ai:Could not get secret'), err);
+    // Intentionally silencing fetch errors for the BMH secret.
+    // If the secret isn’t available we fall back to defaults without blocking the form.
+    // console.error(t('ai:Could not get secret'), err);
   }

Consider applying a similar comment to other instances of commented-out console.error for consistency.

🧹 Nitpick comments (32)
libs/ui-lib/lib/ocm/components/Routes.tsx (2)

17-22: Rename props type alias to avoid collision.

Extracting the inline props into a named alias is a great refactor for clarity and reuse. However, naming the alias UILibRoutes—the same as the component—can lead to confusion in IDEs and code navigation. Consider renaming the alias to something like UILibRoutesProps to clearly communicate its purpose and avoid shadowing the component name.


24-29: Review React.FC usage and children declaration.

Using React.FC<UILibRoutes> already provides an implicit children prop, so the explicit children?: React.ReactNode in your alias is redundant. You can either:

  1. Remove children from the UILibRoutes alias and keep the React.FC annotation, or
  2. Drop the React.FC generic and annotate the component directly:
    export const UILibRoutes = ({
      allEnabledFeatures,
      children,
      history,
      basename,
    }: UILibRoutesProps) => { ... }

Aligning on one pattern will simplify the types and reduce duplication.

libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1)

6-29: Consider handling edge cases for empty infraEnv name and namespace

The hook implementation looks solid and follows the custom hook pattern well. However, there are a couple of edge cases to consider:

  1. On line 17, if infraEnv.metadata?.namespace is undefined, this could cause issues with the watch.
  2. On line 21, using infraEnv?.metadata?.name || '' may match unintended resources if the name is empty.

Consider adding additional validation:

export const useInfraEnvBMHs = (
  infraEnv: InfraEnvK8sResource | undefined,
): WatchK8sResult<BareMetalHostK8sResource[]> => {
  const [bmhs, loaded, err] = useK8sWatchResource<BareMetalHostK8sResource[]>(
-    infraEnv
+    infraEnv && infraEnv.metadata?.name && infraEnv.metadata?.namespace
      ? {
          groupVersionKind: {
            kind: BMHModel.kind,
            version: BMHModel.apiVersion,
            group: BMHModel.apiGroup,
          },
          namespace: infraEnv.metadata?.namespace,
          isList: true,
          selector: {
            matchLabels: {
-              [INFRAENV_AGENTINSTALL_LABEL_KEY]: infraEnv?.metadata?.name || '',
+              [INFRAENV_AGENTINSTALL_LABEL_KEY]: infraEnv.metadata.name,
            },
          },
        }
      : null,
  );

  return [bmhs, loaded, err];
};
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (2)

11-17: Consider using an object return type for better readability and maintainability.

Currently, the hook returns a tuple with multiple heterogeneous values (arrays, boolean, unknown). While tuples are valid, an object with named properties would make the hook's API more self-documenting and less prone to usage errors.

-export const useInfraEnvResources = (): [
-  string[],
-  OsImage[],
-  SecretK8sResource[],
-  boolean,
-  unknown,
-] => {
+export const useInfraEnvResources = (): {
+  usedNames: string[];
+  osImages: OsImage[];
+  credentials: SecretK8sResource[];
+  isLoaded: boolean;
+  error: unknown;
+} => {

Then update the return statement accordingly:

-  return [
-    usedNames,
-    osImages,
-    credentials,
-    infraLoaded && agentLoaded && credsLoaded,
-    infraErr || agentErr || credsErr,
-  ];
+  return {
+    usedNames,
+    osImages,
+    credentials,
+    isLoaded: infraLoaded && agentLoaded && credsLoaded,
+    error: infraErr || agentErr || credsErr,
+  };

1-10: Add JSDoc documentation for better developer experience.

Since this hook provides key infrastructure environment resources that will be used by other components, adding documentation would improve usability and maintainability.

+/**
+ * A hook that watches and aggregates Kubernetes resources needed for Infrastructure Environment creation.
+ * 
+ * @returns An array containing:
+ * - List of existing InfraEnv names (to prevent duplicates)
+ * - Available OS images from AgentServiceConfig
+ * - Secret credentials filtered by cluster type
+ * - A boolean indicating if all resources are loaded
+ * - Any errors encountered during loading
+ */
export const useInfraEnvResources = (): [
libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (2)

54-54: Clean up unnecessary dependencies in useEffect.

The dependency array includes hasDHCP and t (translation function), which aren't used within the effect function.

-  }, [bmhName, bmhNamespace, bmhSecret, hasDHCP, t]);
+  }, [bmhName, bmhNamespace, bmhSecret]);

35-44: Consider using useK8sWatchResource for consistency.

You're using k8sGet to fetch the secret, but the project is also introducing a new useK8sWatchResource hook. For consistency across components, consider using the new hook.

-        try {
-          const secretResult = await k8sGet({
-            model: SecretModel,
-            name: bmhSecret,
-            ns: bmhNamespace,
-          });
-          setSecret(secretResult);
-        } catch (err) {
-          // console.error(t('ai:Could not get secret'), err);
-        }
+  // Move this outside the effect
+  const [secret, secretLoaded, secretError] = useK8sWatchResource<SecretK8sResource>({
+    groupVersionKind: {
+      kind: SecretModel.kind,
+      version: SecretModel.apiVersion,
+    },
+    name: bmhSecret,
+    namespace: bmhNamespace,
+  });
+
+  React.useEffect(() => {
+    setLoading(!secretLoaded);
+    if (secretLoaded && !secretError) {
+      setSecret(secret);
+    }
libs/ui-lib/lib/cim/components/helpers/agents.ts (1)

38-63: Add documentation to clarify function behavior.

This function has complex logic for hostname updates, but lacks documentation explaining its behavior and expected usage.

+/**
+ * Creates a function to update hostnames for agents or bare metal hosts.
+ * 
+ * @param agents - List of Agent resources to search
+ * @param bmhs - List of BareMetalHost resources to search
+ * @returns A function that takes a host and hostname and updates the appropriate resource
+ */
export const onAgentChangeHostname: OnAgentChangeHostname<
  AgentK8sResource,
  BareMetalHostK8sResource
> = (agents, bmhs) => (host, hostname) => {
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (2)

1-17: Add documentation explaining the purpose of this wrapper.

This hook appears to be a simple typed wrapper around the console SDK's hook, but it's not clear why this wrapper exists rather than using the original hook directly.

+/**
+ * A typed wrapper around the OpenShift Console's useK8sWatchResource hook.
+ * 
+ * This provides consistent typing for Kubernetes resource watching throughout
+ * the application and allows for potential future enhancements like error handling
+ * without requiring changes to component implementations.
+ * 
+ * @param initResource - The resource configuration to watch
+ * @returns A tuple containing the resource(s), loading state, and any error
+ */
export const useK8sWatchResource: UseK8sWatchResource = (props) => consoleWatch(props);

7-14: Consider enhancing type safety for errors.

The current type signature uses unknown for the error type. Consider defining a more specific error type to provide better type safety for error handling.

+// Define a more specific error type
+export interface K8sWatchError {
+  message: string;
+  code?: number;
+  [key: string]: any;
+}

export type WatchK8sResult<R extends K8sResourceCommon | K8sResourceCommon[]> = [
  R,
  boolean,
-  unknown,
+  K8sWatchError | null,
];
libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (2)

7-18: Guard‐clause before iterating can avoid an unnecessary full-array scan

When infraEnv is undefined or its matchLabels selector is empty, we still run Array.prototype.filter, only to immediately return an empty array inside the callback.
Adding an early return keeps intent clearer and avoids the superfluous loop.

 export const getInfraEnvNMStates = (
   nmStateConfigs: NMStateK8sResource[] = [],
   infraEnv?: InfraEnvK8sResource,
 ) =>
-  nmStateConfigs.filter((nmStateConfig) => {
+  !infraEnv ||
+  !Object.keys(infraEnv.spec?.nmStateConfigLabelSelector?.matchLabels ?? {}).length
+    ? []
+    : nmStateConfigs.filter((nmStateConfig) => {-  });
+    });

20-35: Pass undefined instead of null to optional hooks for stricter typings

useK8sWatchResource accepts null, but nearly every callsite within UI-lib passes undefined.
Using a single sentinel value helps TypeScript catch accidental truthy/falsy mistakes and avoids implicit any overloads.

-      : null,
+      : undefined,
libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (1)

217-221: Hard-coded router paths may drift from central route definitions

The literal /multicloud/infrastructure/clusters/details/... path duplicates logic that already lives in @console/dynamic-plugin-sdk route helpers.
If the console URL structure changes, these links will silently break.

Consider composing the URL with a helper such as getClusterDetailsLink(hcNamespace, hcName) or at least wrapping the string construction in one exported util so the path exists in a single place.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (3)

67-72: Avoid an unnecessary Fragment in bodyContent

<></> is wrapping only a single child – the translated string – so the fragment is superfluous and flagged by Biome.
Removing it trims two extra nodes from the tree without changing behaviour.

-              <PopoverIcon
-                noVerticalAlign
-                bodyContent={
-                  <>
-                    {t(
-                      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-                    )}
-                  </>
-                }
+              <PopoverIcon
+                noVerticalAlign
+                bodyContent={t(
+                  'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+                )}
               />
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


126-126: Guard against rendering the version dropdown when osImages is empty

!!osImages will be true for an empty array, which can surface a dropdown containing no items and confuse users.
Prefer an explicit length check:

-          {!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+          {osImages?.length > 0 && (
+            <InfraEnvOpenShiftVersionDropdown osImages={osImages} />
+          )}

141-148: Wrap atob calls with basic validation / try-catch

If a secret’s data value is not valid Base-64, atob throws a DOMException, breaking the whole form.
Adding a tiny helper keeps the UI resilient to malformed secrets:

-              setFieldValue(
-                'pullSecret',
-                cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-              );
+              const safeDecode = (val?: string) => {
+                try {
+                  return val ? atob(val) : '';
+                } catch {
+                  return '';
+                }
+              };
+              setFieldValue('pullSecret', safeDecode(cred.data?.['pullSecret']));

(Do the same for the SSH key.)

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1)

135-136: Memoise the onSave callback to avoid unnecessary re-renders

onAgentChangeHostname(agents, bareMetalHosts) is re-executed on every render, producing a brand-new function each time.
This forces EditAgentModal to re-receive a changed onSave prop and can trigger avoidable renders.

-  {editAgent && (
+  {editAgent && (
     <EditAgentModal
       onClose={() => setEditAgent(undefined)}
       usedHostnames={usedHostnames}
       agent={editAgent}
-      onSave={onAgentChangeHostname(agents, bareMetalHosts)}
+      onSave={React.useMemo(
+        () => onAgentChangeHostname(agents, bareMetalHosts),
+        [agents, bareMetalHosts],
+      )}
     />
   )}
libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (1)

49-56: Stabilise the useK8sWatchResource descriptor

Passing a new object literal on every render can cause the watch hook to resubscribe repeatedly (depending on its internal implementation).
Memoising the descriptor eliminates unnecessary watch churn:

-  const [provisioningConfig, provisioningConfigLoaded, provisioningConfigError] =
-    useK8sWatchResource<K8sResourceCommon>({
-      name: 'provisioning-configuration',
-      groupVersionKind: {
-        group: 'metal3.io',
-        version: 'v1alpha1',
-        kind: 'Provisioning',
-      },
-    });
+  const provisioningGvk = React.useMemo(
+    () => ({
+      name: 'provisioning-configuration',
+      groupVersionKind: { group: 'metal3.io', version: 'v1alpha1', kind: 'Provisioning' },
+    }),
+    [],
+  );
+  const [provisioningConfig, provisioningConfigLoaded, provisioningConfigError] =
+    useK8sWatchResource<K8sResourceCommon>(provisioningGvk);
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1)

42-50: Redundant useParams invocation

InfraEnvDetailsContent calls useParams() even though its parent (InfraEnvDetails) already obtained name and namespace. Passing these two values as props avoids the extra hook call and makes the component easier to unit-test.

-const { name, namespace } = useParams() as { name: string; namespace: string };
+// receive from parent
+const { name, namespace } = props;

This is a small clean-up but improves clarity and slightly reduces re-renders.

libs/ui-lib/lib/cim/components/modals/types.ts (1)

42-45: createSecret probably wants to be optional.

EditPullSecretFormikValues introduces a non-optional createSecret: boolean, but many existing forms invoke the modal in “edit-only” mode where no new secret is created.
Consider making it optional with a sensible default to preserve backwards compatibility.

-  createSecret: boolean;
+  createSecret?: boolean;   // defaults to false
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (2)

30-33: Unused name variable returned by useParams().

const { namespace } = useParams() as { name: string; namespace: string };

name is destructured but never used, which will trigger the eslint no-unused-vars rule.
Either remove the property or use it explicitly.


56-63: Aggregated error handling hides the actual failing resource.

if (nmError || amError || aciError) { return <ErrorState />; }

You lose the information about which watch failed and why.
Consider passing the first non-undefined error to ErrorState (or at least logging it) to ease troubleshooting.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (3)

68-85: Namespace existence check swallows unexpected errors.

Only a 404 should flip createNs = true; every other error is surfaced to the user, but the original stack trace is lost.
Forwarding the complete HttpError (or at least its .message) would make debugging cluster-side RBAC issues much easier.

-              setSubmitError(
-                t('ai:Failed to check if namespace {{namespace}} exists', {
-                  namespace: infraEnv.metadata?.name,
-                }),
-              );
+              setSubmitError(
+                `${t('ai:Failed to check if namespace {{namespace}} exists', {
+                  namespace: infraEnv.metadata?.name,
+                })}: ${getErrorMessage(e)}`
+              );

176-183: Accessibility: main banner icon lacks alt text.

SVGs rendered as <MainIcon /> are announced as “graphic” by screen readers.
Please wrap it with an aria-label or provide an alt attribute for better accessibility compliance.

-<MainIcon />
+<MainIcon aria-label={t('ai:Infrastructure environment illustration')} />

187-190: Navigation on cancel may surprise users.

navigate(-1) relies on browser history; hitting cancel after a hard refresh could throw the user to an unrelated page.
Prefer an explicit path (e.g., environments list) for deterministic UX.

libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (2)

32-55: Gracefully handle an empty credentials array

When credentials.length === 0, the Select opens with an empty list – this is confusing UX.
Consider adding a disabled placeholder option (or disabling the toggle) to inform the user there are no credentials to pick.

-{credentials.map((p) => (
-  <SelectOption key={p.metadata?.uid} value={p.metadata?.uid}>
-    {p.metadata?.name}
-  </SelectOption>
-))}
+{credentials.length > 0 ? (
+  credentials.map((p) => (
+    <SelectOption key={p.metadata?.uid} value={p.metadata?.uid}>
+      {p.metadata?.name}
+    </SelectOption>
+  ))
+) : (
+  <SelectOption isDisabled>{t('ai:No credentials found')}</SelectOption>
+)}

This avoids a blank dropdown and clarifies what the user should do next.


67-72: navigate callback loses form state

Navigating away immediately on click can discard any unsaved data the user already entered in the InfraEnv form.
Consider opening the create-credential flow in a new tab or adding a confirmation prompt.

-onClick={() => navigate('/multicloud/credentials/create?type=hostinventory')}
+onClick={(e) => {
+  e.preventDefault();
+  window.open(
+    '/multicloud/credentials/create?type=hostinventory',
+    '_blank',
+    'noopener,noreferrer',
+  );
+}}

This preserves the current form state and avoids accidental data loss.

libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (1)

213-218: Show error state for pull-secret loading

isWarning={!pullSecret} silently marks the item as “warning” even when the watch errored.
Consider distinguishing “not configured” vs. “failed to load” to aid troubleshooting.

- isWarning={!pullSecret}
+ isWarning={!!pullSecretError}
+ /* optionally add `isError` prop for dedicated styling */

At minimum, surface pullSecretError somewhere in the UI so users understand why the pull secret status is unknown.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (2)

162-166: Missing dependency: onApproveAgent is used inside useMemo but not declared

agentStatusColumn receives onApprove from onApproveAgent. Because the function is referenced inside useMemo, it should be added to the dependency array to avoid stale closures when the import is re-created during HMR or tests.

-      bmhStatuses,
-      agentMachines,
+      bmhStatuses,
+      agentMachines,
+      onApproveAgent,

258-274: Side effect in render: onAgentChangeHostname([editAgent], …)

onAgentChangeHostname is invoked on every render to create a new callback, which:

  1. Prevents EditAgentModal from receiving a stable prop (causing unnecessary re-renders).
  2. Executes eagerly if the helper contains internal side-effects.

Consider memoising the callback:

-          onSave={onAgentChangeHostname([editAgent], bareMetalHosts)}
+          onSave={React.useMemo(
+            () => onAgentChangeHostname([editAgent], bareMetalHosts),
+            [editAgent, bareMetalHosts],
+          )}
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (2)

129-136: Label parsing loses values containing =

values.labels.forEach((l) => { const label = l.split('='); … })

String.split('=') without a limit splits all occurrences, so a label like key=a=b becomes ['key', 'a', 'b'], breaking the intended k=v logic.

-const label = l.split('=');
+const [key, ...rest] = l.split('=');
+const value = rest.join('='); // preserves additional '='

Also guard against empty keys to satisfy Kubernetes label constraints.


160-166: additionalNTPSources should respect enableNtpSources flag

additionalNTPSources is set regardless of enableNtpSources.
Either honour the flag or remove it from the form to keep behaviour consistent.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between e596899 and 78fb3cd.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (55)
  • libs/locales/lib/en/translation.json (37 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
🧰 Additional context used
🧬 Code Graph Analysis (27)
libs/ui-lib/lib/ocm/components/Routes.tsx (1)
libs/ui-lib/lib/common/features/featureGate.tsx (1)
  • FeatureListType (6-8)
libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (4)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (2)
  • WatchK8sResult (7-11)
  • useK8sWatchResource (16-16)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentModel (67-76)
libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (2)
libs/ui-lib/lib/cim/components/modals/types.ts (1)
  • UploadActionModalProps (52-59)
libs/ui-lib/lib/cim/types/models.ts (1)
  • BMHModel (78-87)
libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (1)
libs/ui-lib/lib/cim/utils.ts (1)
  • onApproveAgent (30-41)
libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (4)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (2)
  • WatchK8sResult (7-11)
  • useK8sWatchResource (16-16)
libs/ui-lib/lib/cim/types/models.ts (1)
  • NMStateModel (89-98)
libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (20-28)
libs/ui-lib/lib/cim/types/models.ts (1)
  • InfraEnvModel (24-33)
libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (1)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (4)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentErrors.tsx (1)
  • EnvironmentErrors (16-56)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (4)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (2)
  • WatchK8sResult (7-11)
  • useK8sWatchResource (16-16)
libs/ui-lib/lib/cim/types/models.ts (1)
  • BMHModel (78-87)
libs/ui-lib/lib/cim/components/common/constants.ts (1)
  • INFRAENV_AGENTINSTALL_LABEL_KEY (10-10)
libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (1)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (2)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (20-28)
libs/ui-lib/lib/cim/types/models.ts (1)
  • InfraEnvModel (24-33)
libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1)
libs/ui-lib/lib/cim/components/helpers/agents.ts (1)
  • onAgentChangeHostname (43-63)
libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (1)
libs/ui-lib/lib/cim/utils.ts (1)
  • onDeleteHost (95-131)
libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (1)
libs/ui-lib/lib/cim/utils.ts (1)
  • onDeleteHost (95-131)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (15-34)
libs/ui-lib/lib/common/hooks/index.ts (1)
  • useTranslation (3-3)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1)
libs/ui-lib/lib/common/hooks/index.ts (1)
  • useTranslation (3-3)
libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (3)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (20-28)
libs/ui-lib/lib/cim/types/models.ts (1)
  • InfraEnvModel (24-33)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (10)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/common/hooks/index.ts (1)
  • useTranslation (3-3)
libs/ui-lib/lib/cim/components/ClusterDeployment/helpers.ts (1)
  • getAgentsHostsNames (196-210)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (1)
  • InfraEnvHostsTabAgentsWarning (13-16)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (16-16)
libs/ui-lib/lib/cim/types/models.ts (1)
  • InfraEnvModel (24-33)
libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1)
  • useInfraEnvAgents (6-33)
libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1)
  • useInfraEnvBMHs (6-29)
libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1)
libs/ui-lib/lib/cim/components/helpers/agents.ts (1)
  • onAgentChangeHostname (43-63)
libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (1)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (16-16)
libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/common/hooks/index.ts (1)
  • useTranslation (3-3)
libs/ui-lib/lib/cim/utils.ts (2)
  • onUnbindHost (140-169)
  • getAgentName (133-138)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (7)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)
  • ClusterDeploymentHostDiscoveryTableProps (176-184)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1)
  • useInfraEnvNMStates (20-43)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (16-16)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentClusterInstallModel (111-120)
libs/ui-lib/lib/cim/components/helpers/agents.ts (1)
  • onAgentChangeHostname (43-63)
libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (4)
libs/ui-lib/lib/common/components/clusterConfiguration/DiscoveryImageConfigForm.tsx (1)
  • DiscoveryImageFormValues (56-56)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (20-28)
libs/ui-lib/lib/cim/types/models.ts (1)
  • InfraEnvModel (24-33)
libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (3)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/modals/types.ts (1)
  • EditPullSecretFormikValues (42-45)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/components/modals/types.ts (1)
libs/ui-lib/lib/cim/components/Agent/types.ts (1)
  • BMCFormProps (18-27)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (3)
libs/ui-lib-tests/cypress/fixtures/infra-envs/openshift-versions.ts (2)
  • x86 (8-8)
  • s390x (10-10)
libs/ui-lib/lib/common/components/ui/formik/validationSchemas.ts (7)
  • richNameValidationSchema (456-489)
  • locationValidationSchema (654-679)
  • pullSecretValidationSchema (143-162)
  • sshPublicKeyValidationSchema (105-115)
  • httpProxyValidationSchema (534-573)
  • noProxyValidationSchema (587-602)
  • ntpSourceValidationSchema (604-627)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1)
  • useInfraEnvResources (11-69)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (7)
  • initialValues (69-85)
  • validationSchema (36-67)
  • EnvironmentStepFormValues (15-34)
  • getPullSecretSecret (87-100)
  • getInfraEnv (102-169)
  • getRole (171-187)
  • getNamespace (189-197)
libs/ui-lib/lib/cim/types/models.ts (4)
  • NamespaceModel (46-54)
  • RoleModel (13-22)
  • SecretModel (3-11)
  • InfraEnvModel (24-33)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: lint
  • GitHub Check: translation-files
  • GitHub Check: unit-tests
  • GitHub Check: tests
  • GitHub Check: circular-deps
  • GitHub Check: format
🔇 Additional comments (65)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1)

1-3: Approve CSS class addition
The new .cim-infra-env-hosts-tab-title__icon rule correctly applies the intended left margin using the PatternFly spacer token and aligns with the updated class usage in the component.

libs/ui-lib/lib/cim/config/constants.ts (1)

4-4: Verify documentation version constant
Introducing DOC_VERSION centralizes the documentation version and improves maintainability. Ensure this value is synchronized with any external documentation, automated docs generation, and relevant tests.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2)

11-11: Ensure CSS import is effective
The added import for InfraEnvHostsTabAgentsWarning.css brings in the new icon class. Confirm that global CSS loading in the build pipeline includes this file without conflicts.


58-58: Align component class with new CSS
Updated the className to cim-infra-env-hosts-tab-title__icon, matching the CSS file. This ensures the icon receives the correct styling.

libs/ui-lib/package.json (3)

5-5: Review major SDK upgrade
Bumping @openshift-console/dynamic-plugin-sdk from 0.x to 1.4.0 may introduce breaking changes. Verify that all dynamic-plugin-sdk APIs used (k8sCreate, k8sPatch, resource watches, etc.) remain compatible and that automated tests cover these interactions.


120-120: Include SVG assets in build
The updated build script now calls yarn copy:svg alongside copy:css, ensuring SVG assets are packaged for CJS output. This supports the new icon and image files used in the UI library.


125-125: Copy SVGs in build output
The copy:svg rsync invocation mirrors all SVG files from lib to build/cjs while preserving directory structure. Confirm that all required SVGs are covered and correctly referenced in the built module.

libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1)

1-7: Introduce MCEK8sResource type alias
The new type extends K8sResourceCommon and adds an optional spec.targetNamespace, aligning with the Multi-Cluster Engine model. It enhances type safety for resource interactions.

libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)

5-5: Improved type safety by using unknown instead of any.

This change enhances type safety by using unknown instead of any for the config property, requiring explicit type checking before usage. This is a good practice that aligns with modern TypeScript standards and helps prevent potential type-related bugs.

libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1)

28-28: Simplified component interface by internalizing resource creation.

Removing the onCreateBmcByYaml prop simplifies the component interface and follows better React patterns by keeping the resource creation logic inside the form component itself. This reduces prop drilling and improves maintainability.

libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)

20-22: Made proxy configuration fields optional for greater flexibility.

Making the proxy fields (httpProxy, httpsProxy, and noProxy) optional improves the type definition's accuracy and provides better flexibility when handling proxy configurations. This change supports cases where proxy information may not be provided and aligns with the refactored proxy handling components.

libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1)

2-3: Improved component organization with dedicated create and details pages.

The exports have been updated to reflect a more modular architecture, replacing the previous components with dedicated CreateInfraEnvPage and InfraEnvDetails components from their respective subdirectories. This reorganization follows better React practices and aligns with the PR's goal of creating a cleaner, more maintainable code structure.

libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2)

29-29: Import added for centralized deletion logic.

The code now imports the onDeleteHost utility function from ../../utils, aligning with the PR's goal of centralizing resource operations. This change simplifies the component by removing the need for external callback props.


165-165: Using centralized deletion utility instead of callback prop.

The component now directly uses the imported onDeleteHost utility function instead of relying on a callback prop. This implementation correctly passes the agent, BMH, and nmStates parameters, maintaining the same functionality while reducing prop drilling.

libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (2)

31-32: Imports for direct Kubernetes API interaction.

Added imports to support direct k8sCreate operations and K8s model definition, removing the need for external callback props. These additions align with the PR objective of decoupling components and centralizing resource operations.


34-34: Simplified component props by removing onCreateBmcByYaml callback.

The component signature has been simplified to only require the onClose prop, removing the dependency on an external callback for BMC host creation. This change is consistent with the PR's goal of reducing prop drilling and centralizing resource operations.

libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2)

24-24: Import added for centralized agent approval logic.

The code now imports the onApproveAgent utility function from ../../utils, aligning with the PR's goal of centralizing resource operations. This change simplifies the component by removing the need for external callback props.


115-115: Using centralized approval utility instead of callback prop.

The component now directly uses the imported onApproveAgent utility function instead of relying on a callback prop. The implementation maintains the same functionality while reducing prop drilling and centralizing the agent approval logic.

libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (4)

4-4: Updated SDK import for direct K8s resource interaction.

The import now includes k8sGet and K8sResourceCommon from the OpenShift dynamic plugin SDK, providing direct access to Kubernetes resources. This aligns with the PR's goal of centralizing resource operations.


10-10: Added import for SecretModel.

The code now imports the SecretModel from ../../types/models, which is needed for direct interaction with Kubernetes Secret resources. This replaces the need for an external secret fetching callback.


53-57: Direct K8s resource fetching replaces callback.

The hook now directly fetches the Secret resource using k8sGet with the appropriate model and parameters instead of relying on an external callback function. This implementation reduces prop drilling and centralizes Kubernetes resource management.


90-90: Updated useEffect dependencies.

The dependency array no longer includes fetchSecret as it's been replaced with direct k8sGet calls. The array correctly includes all dependencies used in the effect: cdNamespace, cdName, secretName, fetchManagedClusters, and fetchKlusterletAddonConfig.

libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1)

6-33: Well-implemented hook for watching InfraEnv agents

This new hook effectively watches Agent resources associated with an InfraEnv by constructing the appropriate label selector from the InfraEnv's status and using the Kubernetes watch resource API. The implementation correctly handles the case when infraEnv is undefined by passing null to useK8sWatchResource.

libs/ui-lib/lib/cim/components/InfraEnv/types.ts (2)

3-3: LGTM: Import change aligns with type simplification

The import change correctly aligns with the simplified props type, only importing what's needed after the callback props were removed.


7-12: Props interface simplification improves maintainability

Simplifying the AddHostDropdownProps type by removing callback props (onSaveISOParams, onCreateBMH, onCreateBmcByYaml, and provisioningConfigResult) aligns with the PR's goal of decoupling components and internalizing logic. This reduces prop drilling and makes the component API cleaner.

libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1)

182-182: Simplified onSave handler reduces prop drilling

The onSave prop no longer passes callbacks to onAgentChangeHostname, which is consistent with the pattern of internalizing logic rather than passing callbacks through props. This simplifies the component interface while maintaining the same functionality.

libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2)

26-28: LGTM: New imports support direct K8s resource patching

These imports enable the modal to directly interact with Kubernetes resources instead of relying on external callbacks, which aligns with the decoupling goals of the PR.


98-121: Improved implementation with direct K8s resource patching

The form submission now handles K8s resource patching internally rather than delegating to an external callback. This approach:

  1. Constructs proxy settings based on form values
  2. Creates patches only for changed values using appendPatch
  3. Applies patches directly using k8sPatch
  4. Includes an optimization to avoid API calls when no changes are made (patches.length check)

This implementation is more self-contained and aligns with the PR's goal of decoupling components.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1)

1-33: Clean, well-structured component implementation

The DetailsTab component is well-organized and follows good React patterns. It clearly separates error handling from details display and properly passes derived boolean indicators to child components.

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (2)

107-107: Simplified conditional logic improves readability

The conditional was simplified to only check isAIFlow (which is !!infraEnv), removing unnecessary checks. This is a good refactoring that makes the code clearer and aligns with the broader changes to internalize host management logic.


44-49: Removed fetchSecret from useYamlPreview hook

The useYamlPreview hook call no longer includes the fetchSecret parameter, matching the refactoring in other components to use direct Kubernetes resource watchers or SDK calls instead of passing down callbacks.

libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3)

21-23: Added necessary imports for direct K8s resource management

Good addition of the necessary imports to support direct Kubernetes resource patching instead of relying on external callbacks. This aligns with the broader refactoring goals.


52-52: Modal is now always open when rendered

The component now hardcodes isOpen={true}, making it the parent component's responsibility to mount/unmount the entire component to control visibility. This pattern simplifies the modal interface and reduces prop drilling.


64-78: Direct Kubernetes resource patching

Good implementation of direct Kubernetes resource patching using the SDK. The code:

  1. Creates a patch only if the SSH key has changed
  2. Uses the utility function appendPatch for consistent patch construction
  3. Only makes the API call if there are actual changes to apply

This approach centralizes resource management and reduces the need for external callback props.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1)

60-60:

Details

❓ Verification inconclusive

Potential issue with OS image extraction.

This assumes all required OS images are in the first AgentServiceConfig (agentServiceConfigs?.[0]). If there are multiple configs with different images, you'll only get images from the first one.


🏁 Script executed:

#!/bin/bash
# Check how many AgentServiceConfig resources typically exist and whether they contain different OS images

# First, count how many AgentServiceConfig resources typically exist
echo "Number of AgentServiceConfig resources:"
ast-grep --pattern 'kind: AgentServiceConfig' | wc -l

# Check if there are references to multiple AgentServiceConfig resources
echo "References to multiple AgentServiceConfigs:"
rg -A 2 'agentServiceConfigs' --type=ts

Length of output: 956


🏁 Script executed:

#!/bin/bash
# Find where AgentServiceConfigK8sResource is defined to understand the resource structure
rg -C3 "type AgentServiceConfigK8sResource" -g "*.ts"

Length of output: 676


🏁 Script executed:

#!/bin/bash
# Show full spec definition including osImages in AgentServiceConfigK8sResource
echo "=== AgentServiceConfigK8sResource spec definition ==="
rg -A10 "spec:" -g "libs/ui-lib/lib/cim/types/k8s/agent-service-config.ts"

# Show the parameters passed to useK8sWatchResource in useInfraEnvResources.ts
echo "=== useK8sWatchResource call context ==="
rg -C5 "useK8sWatchResource" -g "libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts"

Length of output: 5594


Review OS image aggregation logic
The current implementation only reads osImages from the first AgentServiceConfig in the list:

const osImages = agentServiceConfigs?.[0]?.spec.osImages || [];

If your cluster ever contains more than one AgentServiceConfig (for example, per‐region or per‐environment overrides), this will drop all but the first config’s images. Please verify whether:

  • You always provision exactly one AgentServiceConfig (in which case this is safe), or
  • You should instead aggregate across all configs, e.g.:
const osImages =
  agentServiceConfigs
    ?.flatMap(cfg => cfg.spec.osImages ?? [])
    .filter(Boolean) ?? [];

Adjust as needed to ensure no images are accidentally omitted.

libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (1)

59-59:

Details

✅ Verification successful

Verify the isOpen behavior.

The isOpen prop is now hardcoded to true, which means the modal will always be rendered in an open state. This shifts visibility control to the parent component, which must conditionally render this modal only when needed.


🏁 Script executed:

#!/bin/bash
# Check how this modal is rendered in parent components

# Find components that import EditBMHModal
echo "Components that import EditBMHModal:"
rg "import.*EditBMHModal" --type=ts

# Look for conditional rendering of EditBMHModal
echo "Conditional rendering of EditBMHModal:"
rg -A 2 -B 2 "<EditBMHModal" --type=tsx

Length of output: 520


🏁 Script executed:

#!/bin/bash
# Retry searching for EditBMHModal usage without relying on --type
echo "Searching for <EditBMHModal usage in TSX files:"
rg "<EditBMHModal" -A2 -B2 -g "*.tsx"

Length of output: 1526


isOpen is always true; visibility’s handled by parent rendering

Both InfraEnvAgentTable.tsx and ClusterDeploymentHostsDiscovery.tsx wrap the modal in a conditional based on editBMH, e.g.:

  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
    {editBMH && (
      <EditBMHModal
        infraEnv={infraEnv}
        bmh={editBMH}
          
    )}
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
    {editBMH && (
      <EditBMHModal
        infraEnv={infraEnv}
        bmh={editBMH}
          
    )}

Since the parent now controls whether the modal is rendered at all, hard-coding isOpen to true is appropriate and no further changes are needed.

libs/ui-lib/lib/cim/components/helpers/agents.ts (1)

5-5: LGTM: Improved code organization.

The explicit import of utility functions centralizes host/agent modification logic, which is a positive improvement that aligns with the broader refactoring effort.

libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1)

37-43: Memo dependency list is correct – good job!

infraEnvNMStates is re-computed only when either the source list or the selector changes, avoiding unnecessary re-renders.

libs/locales/lib/en/translation.json (1)

5-6: Consistency win – plural keys look tidy

Plural & singular keys were unified, preventing the dreaded i18next “missing translation” warnings.

Also applies to: 9-16

libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2)

33-38: Modal title translation key casing

ai:Edit Ntp sources dialog mixes “Ntp”/“NTP”. For translation-key hygiene, use the acronym form everywhere (Edit NTP sources dialog).
[ suggest_nitpick ]


50-56: ⚠️ Potential issue

remove patch may fail when the field is already absent

When additionalNTPSources is undefined, the remove op raises 422: path does not exist.
Guard before pushing:

-if (infraEnv.spec?.additionalNTPSources) {
-  patches.push({ op: 'remove', path: '/spec/additionalNTPSources' });
-}
+if (infraEnv.spec?.additionalNTPSources?.length) {
+  patches.push({ op: 'remove', path: '/spec/additionalNTPSources' });
+}

Likely an incorrect or invalid review comment.

libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (5)

1-12: Well-structured imports with appropriate dependencies.

The imports include all necessary components and utilities for implementing a host deletion modal, following a clean organization pattern with UI components, resources, utilities, and translation hooks properly grouped.


13-25: Good component props definition with appropriate typing.

The component accepts clearly typed optional Kubernetes resources (agent, bmh, agentClusterInstall, nmStates) and a required onClose callback. The type structure follows best practices by using inline typings for clarity.


30-41: Well-implemented delete handler with proper error management.

The onDelete function correctly handles the async deletion process, including:

  • Setting and clearing error state
  • Managing loading state via isDeleting
  • Using try/catch/finally for robust error handling
  • Properly calling the shared onDeleteHost utility

This follows best practices for asynchronous operations in React components.


44-64: Properly configured modal with user-friendly UX during deletion.

The modal implementation correctly:

  • Prevents closing during active deletion operation
  • Disables interaction with buttons during deletion
  • Shows loading state on the confirm button
  • Uses appropriate variants (danger for delete confirmation)
  • Uses translated text for all UI elements

This creates a good user experience with clear feedback during operations.


65-75: Clear confirmation message with proper error display.

The modal body shows the host name for clear identification and conditionally displays errors using the Alert component with appropriate styling. This provides users with clear information about what they're deleting and any issues that occur.

libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (6)

22-24: Required imports added for the refactored implementation.

The added imports support the removal of external callback dependencies by bringing in the necessary Kubernetes API functions from the OpenShift dynamic plugin SDK.


33-33: Broadened type for better error handling compatibility.

Changing pullSecretError type to unknown | undefined aligns with the generic error handling approach using getErrorMessage.


77-77: Standardized error handling with reusable utility.

Using getErrorMessage provides consistent error formatting across different error types, improving user experience.


122-122: Simplified component rendering pattern.

Changed from a conditional isOpen prop to a hardcoded isOpen={true}, meaning the component expects to be conditionally rendered by its parent rather than controlled via an isOpen prop. This simplifies the component's API and aligns with the pattern used in other modals.


130-131: Improved initial form state.

Setting the initial pullSecret value to an empty string provides a cleaner initial state. The actual value is properly set from the existing pull secret in the useEffect hook.


135-169: Internalized Kubernetes operations with robust error handling.

The form submission handler was refactored to:

  1. Directly handle Kubernetes resource operations rather than relying on an external callback
  2. Correctly choose between creating a new secret or patching an existing one
  3. Properly encode the pull secret data
  4. Handle errors consistently
  5. Close the modal on success

This change improves component independence and aligns with the refactoring goal of internalizing Kubernetes operations within components.

libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (3)

18-21: Required imports added for Kubernetes operations.

The added imports provide the necessary functionality for performing Kubernetes patch operations and working with the InfraEnv model.


22-69: Well-structured utility function for ISO parameter management.

The new onSaveISOParams function:

  1. Takes form values and an InfraEnv resource as parameters
  2. Constructs JSON patches for SSH key, proxy settings, and image type
  3. Handles all edge cases (add/replace/remove operations)
  4. Only executes patches when changes exist

This follows best practices by:

  • Using the appendPatch utility for consistent patch creation
  • Intelligently comparing existing and new values
  • Handling presence/absence of optional fields
  • Properly structuring the patch operations

Extracting this as an exported function also improves testability and reusability.


92-92: Simplified implementation by using the extracted utility function.

Changed from an external callback to the new utility function, reducing prop dependencies and centralizing Kubernetes operations.

libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (3)

7-11: Required imports added for resource watching.

The added imports support the refactored implementation that internalizes resource fetching.


33-48: Well-implemented resource watching hook.

The useAssistedServiceConfigMap hook correctly:

  1. Uses the namespace from the previous hook
  2. Conditionally watches the ConfigMap only when namespace is available
  3. Returns the result for use in the component

This follows best practices for Kubernetes resource watching in React components.


62-66: Proper early return when ConfigMap is not available.

The component correctly:

  1. Uses the new hook to get the ConfigMap
  2. Returns null if the ConfigMap isn't loaded yet
  3. No longer requires an external prop

This prevents rendering the component with incomplete data and simplifies the component's API.

libs/ui-lib/lib/cim/components/modals/types.ts (1)

25-30: Confirm that hasDHCP is intentionally dropped from AddBmcHostModalProps.

BMCFormProps still exposes the hasDHCP flag, but the new AddBmcHostModalProps drops it.
If the underlying modal logic still branches on DHCP support, the prop removal will surface as a runtime undefined or compilation error once you re-wire the component. Please double-check all callers of <AddBmcHostModal>.

libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (1)

98-112: Guard group field for core resources

SecretModel.apiGroup is undefined, so groupVersionKind.group becomes undefined.
Some helpers treat undefined and '' differently, leading to watch failures.
Explicitly pass an empty string for core resources:

-          group: SecretModel.apiGroup,
+          group: SecretModel.apiGroup ?? '',

This guarantees a valid watch key.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (1)

97-103: Potential ID mismatch between table rows and k8s resources

onSelect stores host.id while subsequent look-ups compare the stored IDs with metadata.uid.
If host.id !== metadata.uid for BMH rows (or for agents in edge-cases), the mass-action logic will silently skip the selected rows.

Please double-check that tableUtils always sets host.id = resource.metadata.uid.
If that guarantee does not hold, consider switching both the selection and the filters to metadata.uid to avoid hard-to-trace inconsistencies.

libs/ui-lib/lib/cim/utils.ts (1)

124-130: ⚠️ Potential issue

workerAgents count can become negative

When deleting the last worker, (current || 1) - 1 results in 0, which is fine, but if the field was already 0 or undefined the value becomes -1, violating the CRD schema.

-const workerCount = (agentClusterInstall.spec?.provisionRequirements.workerAgents || 1) - 1;
+const current = agentClusterInstall.spec?.provisionRequirements.workerAgents ?? 0;
+const workerCount = Math.max(current - 1, 0);

Likely an incorrect or invalid review comment.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)

69-85: CPU architecture enum value might be incorrect

initialValues.cpuArchitecture = CpuArchitecture.x86.

The common enum (see openshift-versions.ts) uses the literal 'x86_64'. Using an unsupported enum member will make the form silently submit an invalid value and the CR creation will fail server-side.

Verify the enum keys and default accordingly.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

167-174: Callbacks disappeared from InfraEnvAgentTableProps – confirm intent

The table props now only contain data and no row-level action handlers (approve, delete, etc.).
Please verify that:

  1. The table component was refactored to manage these actions internally, and
  2. No callers still attempt to pass the old callbacks.

Otherwise this change will surface as TypeScript errors.


176-184:

Details

❌ Incorrect review comment

onEditBMH still exported but appears deprecated

The PR description says onEditBMH was removed, yet ClusterDeploymentHostDiscoveryTableProps still re-exports it. Keeping an unused prop invites confusion.

If BMH editing is indeed deprecated, drop it from the pick list:

-export type ClusterDeploymentHostDiscoveryTableProps = Pick<
-  AgentTableActions,
-  'onEditRole' | 'onEditHost' | 'onEditBMH' | 'onSetInstallationDiskId'
+export type ClusterDeploymentHostDiscoveryTableProps = Pick<
+  AgentTableActions,
+  'onEditRole' | 'onEditHost' | 'onSetInstallationDiskId'
 >

Please double-check the implementation before merging.


🏁 Script executed:

#!/bin/bash
set -e
# Locate the definition of AgentTableActions and its properties
rg "export (type|interface) AgentTableActions" -A10

Length of output: 1415


🏁 Script executed:

#!/bin/bash
set -e
# Search for onEditBMH usage across the codebase
rg -n "onEditBMH"

Length of output: 1687


Ignore removal of onEditBMH – it’s still in active use
The onEditBMH callback remains defined in AgentTableActions and passed through several components. Removing it would break existing functionality.
Key usages:

  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (props deconstruction at line 97)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (onEditBMH={setEditBMH})
  • libs/ui-lib/lib/common/components/hosts/tableUtils.tsx and libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx

Please retain onEditBMH in ClusterDeploymentHostDiscoveryTableProps.

Likely an incorrect or invalid review comment.

Comment on lines +431 to 432
return onDeleteHost({ agent, bmh });
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Signature mismatch risk after refactor to object parameter

onDeleteHost({ agent, bmh }) assumes the callback now receives a single object.
libs/ui-lib/lib/cim/utils.ts (still) exports:

export const onDeleteHost = async (
  agent?: AgentK8sResource,
  bmh?: BareMetalHostK8sResource,
  
)

If that util hasn’t been migrated, this call will raise a TypeScript error or, worse, a runtime failure when invoked from JS. Please verify all implementations & imports were updated, or add an adapter here:

-return onDeleteHost({ agent, bmh });
+return onDeleteHost(agent, bmh);

🏁 Script executed:

#!/bin/bash
set -e

# Locate and display the definition of onDeleteHost in the utils.ts file
echo "=== onDeleteHost definition in libs/ui-lib/lib/cim/utils.ts ==="
rg -n "export (const|function) onDeleteHost" -A 5 libs/ui-lib/lib/cim/utils.ts || echo "No definition found in utils.ts"

# As a fallback, search the entire codebase for onDeleteHost signature
echo "=== onDeleteHost definitions across the codebase ==="
rg -n "onDeleteHost\s*\(" -A 3 .

Length of output: 2479


Correct the onDeleteHost call to use positional parameters

The utility onDeleteHost is still defined to accept positional arguments (agent, bmh, …), but here it’s being invoked with a single object:

• File: libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
• Lines: 431–432

Suggested fix:

- return onDeleteHost({ agent, bmh });
+ return onDeleteHost(agent, bmh);

This brings the call site in line with the exported signature and avoids TypeScript errors or runtime failures.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return onDeleteHost({ agent, bmh });
}
return onDeleteHost(agent, bmh);
}
🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx at lines 431-432, the
call to onDeleteHost incorrectly passes a single object with properties agent
and bmh, but the onDeleteHost function is defined to accept positional
parameters. Fix this by changing the call to pass agent and bmh as separate
arguments instead of an object, aligning with the function's expected signature.

Comment on lines 130 to 122
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Ensure all consumers removed onDeleteHost from hostActions

ClusterDeploymentWizardProps.hostActions no longer exposes onDeleteHost. Any stale usage will now break type-checking or crash at run-time.

Quick verification script:


🏁 Script executed:

rg -n "hostActions.*onDeleteHost"

Length of output: 35


To ensure there are no leftover references anywhere in the codebase, let’s broaden the search to any occurrence of onDeleteHost:


🏁 Script executed:

#!/bin/bash
# Search for any usage of onDeleteHost across the repo
rg -n "onDeleteHost"

Length of output: 2644


Remove stale onDeleteHost from hostActions consumers

The hostActions type in
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts
was updated to only include onEditHost | onEditRole | onSetInstallationDiskId. Any destructuring of onDeleteHost will now fail.

Please update the following components:

  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (≈ line 97)
    • Remove onDeleteHost: setDeleteHost from the hostActions destructuring.
    • Where you need deletion behavior, call the standalone onDeleteHost util imported from ../../utils.ts.

  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (≈ line 114)
    • Remove onDeleteHost: setDeleteHost from the hostActions destructuring.
    • Swap in the onDeleteHost util from ../../utils.ts for any delete-host UI actions.

🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts around lines
130-131, the hostActions type no longer includes onDeleteHost. Update all
consumers accordingly: in ClusterDeploymentHostDiscoveryTable.tsx near line 97
and InfraEnvAgentTable.tsx near line 114, remove onDeleteHost: setDeleteHost
from hostActions destructuring. Replace any usage of onDeleteHost with the
standalone onDeleteHost utility imported from ../../utils.ts to maintain
deletion functionality without type errors or runtime crashes.

Comment on lines +30 to 24
onDeleteHost: (host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }) => void;
onSetInstallationDiskId: (agent: AgentK8sResource, diskId: string) => Promise<AgentK8sResource>;
// eslint-disable-next-line
onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<any>;
onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
onApprove: (agent: AgentK8sResource) => Promise<AgentK8sResource>;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Unify delete APIs for a predictable caller experience

onDeleteHost now receives a single wrapper object, but onMassDeleteHost still takes two positional params. Two different calling conventions for the same conceptual action are error-prone and complicate refactors.

Proposed shape:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  // Accept an array of the same wrapper used by `onDeleteHost`
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

This keeps both callbacks symmetrical, makes “mass” semantics explicit, and prevents accidental param swap bugs.


I’d like to verify how these callbacks are used across the codebase to confirm the impact of unifying their signatures.


🏁 Script executed:

#!/bin/bash
set -e

echo "Definition in types.ts:"
rg -n 'onMassDeleteHost' libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts
rg -n 'onDeleteHost'    libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts

echo -e "\nUsages of onMassDeleteHost across the repo:"
rg -n 'onMassDeleteHost'

echo -e "\nUsages of onDeleteHost across the repo:"
rg -n 'onDeleteHost'

Length of output: 4270


Unify onMassDeleteHost signature for a consistent API

File: libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts
Lines: 30–33

The two callbacks for deleting hosts use different conventions—one takes a single wrapper object, the other two positional params—making callers prone to parameter-swap bugs. Let’s align them:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  // Accepts an array of the same wrapper used by `onDeleteHost`
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

Next, update all CIM callers to pass in a hosts array:

  • In ClusterDeploymentHostDiscoveryTable.tsx: replace onMassDeleteHost(agent, bmh) with onMassDeleteHost([{ agent, bmh }, …]).
  • In MassDeleteAgentModal.tsx: invoke the new onMassDeleteHost(hosts) directly instead of looping with positional args.

This change makes “mass” semantics explicit and prevents accidental param swaps.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
onDeleteHost: (host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }) => void;
onSetInstallationDiskId: (agent: AgentK8sResource, diskId: string) => Promise<AgentK8sResource>;
// eslint-disable-next-line
onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<any>;
onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
onApprove: (agent: AgentK8sResource) => Promise<AgentK8sResource>;
onDeleteHost: (host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }) => void;
onSetInstallationDiskId: (agent: AgentK8sResource, diskId: string) => Promise<AgentK8sResource>;
// Accepts an array of the same wrapper used by `onDeleteHost`
onMassDeleteHost: (
hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
) => Promise<unknown>;
onApprove: (agent: AgentK8sResource) => Promise<AgentK8sResource>;
🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts around lines 30 to
33, unify the onMassDeleteHost callback signature to accept a single array of
host objects, each with optional agent and bmh properties, matching the
onDeleteHost single wrapper object style. Update the type definition
accordingly, then refactor all CIM callers: in
ClusterDeploymentHostDiscoveryTable.tsx, change calls from
onMassDeleteHost(agent, bmh) to onMassDeleteHost([{ agent, bmh }, ...]), and in
MassDeleteAgentModal.tsx, modify the invocation to pass the hosts array directly
instead of looping with positional arguments. This ensures consistent API usage
and prevents parameter swap errors.

@rawagner rawagner force-pushed the cim_dynamic branch 3 times, most recently from 9cb23e9 to 8e0f20b Compare May 20, 2025 13:16
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

♻️ Duplicate comments (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (2)

18-34: 🛠️ Refactor suggestion

credentials field is still unused

The EnvironmentStepFormValues type keeps the credentials property (line 18) but:

  1. It is not part of validationSchema.
  2. It is never consumed when building Kubernetes manifests (getPullSecretSecret, getInfraEnv, …).

Keeping dead form state confuses maintainers and bloats the bundle.
Either remove the field completely or wire it into validation and manifest generation.


141-152: ⚠️ Potential issue

Empty proxy object still emitted when no URLs are provided

The prior review pointed out that creating infraEnv.spec.proxy = {} while all three URL fields are empty violates the CRD schema.
This edge case is still present: the code adds an empty object as soon as enableProxy === true.

-  if (values.enableProxy) {
-    infraEnv.spec.proxy = {};
+  if (
+    values.enableProxy &&
+    (values.httpProxy || values.httpsProxy || values.noProxy)
+  ) {
+    infraEnv.spec.proxy = {};

This guards against producing an invalid InfraEnv manifest.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

30-33: 🛠️ Refactor suggestion

onMassDeleteHost signature remains inconsistent

onDeleteHost now takes a single wrapper object, yet onMassDeleteHost still uses two positional params (agent?, bmh?).
For a predictable API and to avoid caller mishaps, please update the “mass” variant to accept the same wrapper array recommended earlier:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

All call sites (MassDeleteAgentModal, discovery tables, etc.) should then pass one array instead of looping or swapping params.

libs/ui-lib/lib/cim/utils.ts (2)

44-55: ⚠️ Potential issue

replace fails when BMH hostname annotation is missing

onChangeBMHHostname still uses a hard replace patch.
If the annotation does not exist, the API returns 422.
Reuse appendPatch (already defined) so the op switches automatically between add and replace.

-export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) =>
-  k8sPatch({
-    model: BMHModel,
-    resource: bmh,
-    data: [
-      {
-        op: 'replace',
-        path: `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`,
-        value: hostname,
-      },
-    ],
-  });
+export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) => {
+  const patches: Patch[] = [];
+  appendPatch(
+    patches,
+    `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`,
+    hostname,
+    bmh.metadata?.annotations?.[BMH_HOSTNAME_ANNOTATION],
+  );
+  return k8sPatch({ model: BMHModel, resource: bmh, data: patches });
+};

112-118: ⚠️ Potential issue

Guard against negative workerAgents counts

Both onDeleteHost and onUnbindHost decrement workerAgents with
(current || 1) - 1, which can underflow to –1.

-const workerCount = (agentClusterInstall.spec?.provisionRequirements.workerAgents || 1) - 1;
+const current = agentClusterInstall.spec?.provisionRequirements.workerAgents ?? 0;
+const workerCount = Math.max(current - 1, 0);

Apply the same fix in onUnbindHost.

🧹 Nitpick comments (5)
libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (2)

125-141: Implemented direct K8s resource creation

Replaced the external callback with direct K8s resource creation logic. The implementation:

  1. Iterates through all YAML documents
  2. Attempts to extract GroupVersionKind for each document
  3. Uses the appropriate model to create resources

Consider adding error messaging for documents where GVK extraction fails rather than silently continuing to the next document.

 if (yamlContent?.length) {
   for (const content of yamlContent) {
     let gvk: K8sGroupVersionKind | undefined = undefined;
     try {
       gvk = getGroupVersionKindForResource(content as K8sResourceCommon);
-    } catch (e) {
+    } catch (e) {
+      setError(`Failed to extract resource kind from document: ${getErrorMessage(e)}`);
       continue;
     }
     if (gvk)
       await k8sCreate({
         model: models[`${gvk.group || 'core'}~${gvk.kind}~${gvk.version}`],
         data: content as K8sResourceCommon,
       });
+    else {
+      setError('Could not determine resource type from YAML document. Please ensure the document includes kind, apiVersion, and metadata fields.');
+      return;
+    }
   }
 }

137-140: Model lookup implementation

The model lookup uses a specific string format ${gvk.group || 'core'}~${gvk.kind}~${gvk.version} to identify the correct K8s model. Consider adding a comment to explain this format for future maintainers.

 if (gvk)
   await k8sCreate({
+    // Models are keyed by "group~kind~version" in the models object provided by useK8sModels
     model: models[`${gvk.group || 'core'}~${gvk.kind}~${gvk.version}`],
     data: content as K8sResourceCommon,
   });
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment

The Fragment wrapping the translation text is redundant since it only contains a single child element.

-<>
  {t(
    'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
  )}
-</>
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (2)

29-32: Route constants could be externalized

Consider moving these route constants to a separate constants file to improve reusability across components and centralize route definitions.

-const infraEnvironmentHosts =
-  '/multicloud/infrastructure/environments/details/:namespace/:name/hosts';
-const infraEnvironmentOverview = '/multicloud/infrastructure/environments/details/:namespace/:name';

Create a new file libs/ui-lib/lib/cim/config/routes.ts:

export const ROUTES = {
  INFRA_ENV: {
    HOSTS: '/multicloud/infrastructure/environments/details/:namespace/:name/hosts',
    OVERVIEW: '/multicloud/infrastructure/environments/details/:namespace/:name',
    LIST: '/multicloud/infrastructure/environments'
  }
};

Then import and use these constants in this component.


89-96: Warning component nested in link

The navigation includes an InfraEnvHostsTabAgentsWarning component inside a Link, which is an unconventional but functional approach. Consider refactoring to separate the warning from the navigation item for cleaner semantics.

-<Link to={hostsPath}>
-  {
-    <>
-      <InfraEnvHostsTabAgentsWarning
-        infraAgents={infraAgents}
-        infraBMHs={infraBMHs}
-      />
-      {t('ai:Hosts')}
-    </>
-  }
-</Link>

+<Link to={hostsPath}>
+  <span>
+    <InfraEnvHostsTabAgentsWarning
+      infraAgents={infraAgents}
+      infraBMHs={infraBMHs}
+    />
+    {t('ai:Hosts')}
+  </span>
+</Link>
🛑 Comments failed to post (1)
libs/ui-lib/lib/cim/utils.ts (1)

22-30: 🛠️ Refactor suggestion

appendPatch cannot remove existing values

When newVal is undefined, the helper currently generates a replace op with value: undefined, which the API rejects.
Emit a remove operation instead:

-  patches.push({
-    op: existingVal ? 'replace' : 'add',
-    path,
-    value: newVal,
-  });
+  patches.push(
+    newVal === undefined
+      ? { op: 'remove', path }
+      : { op: existingVal ? 'replace' : 'add', path, value: newVal },
+  );

This makes appendPatch safe for clearing optional fields.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

export const appendPatch = <V>(patches: Patch[], path: string, newVal?: V, existingVal?: V) => {
  if (!isEqual(newVal, existingVal)) {
    patches.push(
      newVal === undefined
        ? { op: 'remove', path }
        : { op: existingVal ? 'replace' : 'add', path, value: newVal },
    );
  }
};
🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/utils.ts around lines 22 to 30, the appendPatch function
incorrectly generates a 'replace' operation with value undefined when newVal is
undefined, which the API rejects. Modify the function to emit a 'remove'
operation instead of 'replace' or 'add' when newVal is undefined and existingVal
is defined, ensuring it safely handles clearing optional fields.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
libs/ui-lib/lib/cim/utils.ts (2)

44-55: ⚠️ Potential issue

/metadata/annotations/... patch should tolerate new annotations

When a BMH has no hostname annotation, the replace op fails. Swap to appendPatch.

Apply this diff to fix the hostname annotation patch:

-export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) =>
-  k8sPatch({
-    model: BMHModel,
-    resource: bmh,
-    data: [
-      {
-        op: 'replace',
-        path: `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`,
-        value: hostname,
-      },
-    ],
-  });
+export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) => {
+  const patches: Patch[] = [];
+  const annotationPath = `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`;
+  const existingValue = bmh.metadata?.annotations?.[BMH_HOSTNAME_ANNOTATION];
+  appendPatch(patches, annotationPath, hostname, existingValue);
+  return k8sPatch({ model: BMHModel, resource: bmh, data: patches });
+};

127-155: ⚠️ Potential issue

Prevent negative worker count in onUnbindHost

Similar to onDeleteHost, this function decreases workerAgents without checking if the count goes below zero.

Apply this diff to ensure the worker count doesn't go negative:

-      const workerCount = (agentClusterInstall.spec?.provisionRequirements.workerAgents || 1) - 1;
+      const currentWorkers = agentClusterInstall.spec?.provisionRequirements.workerAgents || 1;
+      const workerCount = Math.max(0, currentWorkers - 1);
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

32-32: 🛠️ Refactor suggestion

Unify onMassDeleteHost signature for a consistent API

The two callbacks for deleting hosts use different conventions—one takes a single wrapper object, the other two positional params—making callers prone to parameter-swap bugs.

Align the signatures by updating onMassDeleteHost to accept an array of host objects:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  // Accepts an array of the same wrapper used by `onDeleteHost`
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;
🧹 Nitpick comments (3)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (3)

68-72: Simplify by removing unnecessary Fragment

The Fragment wrapper here is redundant since it contains only a single child element. You can simplify this code by removing the Fragment tags.

- <>
    {t(
      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
    )}
- </>
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


126-126: Consider checking if osImages has items

The current check !!osImages will render the dropdown even if the array is empty. Consider checking for array length to avoid rendering the dropdown with no options.

- {!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+ {osImages && osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}

100-114: Enhance security for external link

Add rel="noreferrer" to the window.open call for better security when opening external links.

onClick={() =>
  window.open(
    getOCPStaticIPDocLink(DOC_VERSION),
    '_blank',
-   'noopener',
+   'noopener noreferrer',
  )
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between d58c77f and 8e0f20b.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (56)
  • libs/locales/lib/en/translation.json (38 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (4 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (2)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/locales/lib/en/translation.json
🚧 Files skipped from review as they are similar to previous changes (47)
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
🧰 Additional context used
🧬 Code Graph Analysis (3)
libs/ui-lib/lib/cim/utils.ts (7)
libs/ui-lib/lib/cim/types/k8s/shared.ts (1)
  • StatusCondition (1-8)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/models.ts (4)
  • AgentModel (67-76)
  • BMHModel (78-87)
  • AgentClusterInstallModel (111-120)
  • NMStateModel (89-98)
libs/ui-lib/lib/cim/components/common/constants.ts (2)
  • BMH_HOSTNAME_ANNOTATION (20-20)
  • AGENT_BMH_NAME_LABEL_KEY (12-12)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (15-34)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: tests
🔇 Additional comments (10)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

45-181: Good component structure and user experience

The form is well-structured with appropriate helper texts, validation messages, and contextual information through popovers. The layout is clean and the use of conditional rendering for optional fields (like NTP sources) is effective.

🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/utils.ts (5)

22-30: Well-designed utility for conditional patching

The appendPatch utility is a clean approach that conditionally adds patches based on whether values exist and have changed, handling both 'add' and 'replace' operations appropriately. This will help prevent unnecessary updates and handle both new and existing fields consistently.


32-36: Good use of appendPatch for spec.approved

The implementation correctly uses appendPatch to handle both adding and replacing the approved field, preventing potential 422 errors when the field doesn't exist.


38-42: Good use of appendPatch for hostname patching

The implementation correctly uses appendPatch to handle both adding and replacing the hostname, preventing potential errors when the field doesn't exist.


157-169: Good utility for filtering NMState resources

This function efficiently filters NMState resources based on label matching with InfraEnv's NMState label selector, which is a clean approach for finding associated resources.


171-172: Helpful platform detection utility

The isBMPlatform function provides a simple way to check if an infrastructure's platform is one of the supported bare metal types, which will be useful for conditional logic throughout the application.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (4)

30-30: Improved onDeleteHost signature with clearer parameter structure

The updated signature using a single object parameter with optional properties improves clarity and flexibility.


130-130: Simplified hostActions interface aligns with refactored components

Removing onDeleteHost from hostActions reflects the wider refactoring where host deletion is now handled by the standalone onDeleteHost utility function rather than through props.


165-172: Simplified InfraEnvAgentTableProps reflects internal state management

The significant simplification of this type, removing many callback props, aligns with the broader refactoring approach where components now handle these actions internally using the centralized utility functions.


176-176: Simplified table props for better component encapsulation

Removing onDeleteHost from the picked actions reflects the refactoring approach where deletion functionality is now handled internally using the dedicated utility functions.

@rawagner rawagner force-pushed the cim_dynamic branch 3 times, most recently from f944c6f to 9167fcc Compare May 20, 2025 13:44
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: atob() may throw → wrap in try/catch or validate upfront

atob raises a DOMException on malformed base-64 strings (user may store arbitrary secrets).
The previous review already highlighted this – it is still unfixed.

-onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
-}}
+onSelect={(cred) => {
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (e) {
+    console.error('Failed to decode credential data', e);
+    setFieldValue('pullSecret', '');
+    setFieldValue('sshPublicKey', '');
+  }
+}}
libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (2)

206-213: Gate DeleteHostModal rendering on watch completion

Render the modal only when all required resources are loaded.

-{deleteHost && (
-  <DeleteHostModal
-    {...deleteHost}
-    onClose={() => setDeleteHost(undefined)}
-    nmStates={nmStates}
-    agentClusterInstall={agentClusterInstall}
-  />
-)}
+{deleteHost && nmStatesLoaded && aciLoaded && (
+  <DeleteHostModal
+    {...deleteHost}
+    onClose={() => setDeleteHost(undefined)}
+    nmStates={nmStates}
+    agentClusterInstall={agentClusterInstall}
+  />
+)}

67-78: 🛠️ Refactor suggestion

Ignore-loaded flags from watch hooks → modal can receive undefined data

Both hooks return [data, loaded, error], but only data is captured.
If the user clicks “delete” before the watch finishes, DeleteHostModal receives
undefined resources and may crash.

-const [nmStates] = useInfraEnvNMStates(infraEnv);
-const [agentClusterInstall] = useK8sWatchResource<AgentClusterInstallK8sResource>({
+const [nmStates, nmStatesLoaded] = useInfraEnvNMStates(infraEnv);
+const [agentClusterInstall, aciLoaded] =
+  useK8sWatchResource<AgentClusterInstallK8sResource>({
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

31-32: onMassDeleteHost signature still inconsistent with onDeleteHost

Previous review suggested accepting a single hosts array (same wrapper object
used by onDeleteHost) to avoid parameter-swap bugs and simplify callers.
Consider aligning the APIs for consistency.

libs/ui-lib/lib/cim/utils.ts (1)

44-55: ⚠️ Potential issue

Fix /metadata/annotations/... patch to handle new annotations

When a BMH has no hostname annotation, the replace operation will fail. Use appendPatch to ensure the patch succeeds whether or not the annotation is present.

Apply this diff to fix the issue:

-export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) =>
-  k8sPatch({
-    model: BMHModel,
-    resource: bmh,
-    data: [
-      {
-        op: 'replace',
-        path: `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`,
-        value: hostname,
-      },
-    ],
-  });
+export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) => {
+  const patches: Patch[] = [];
+  const annotationPath = `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`;
+  const currentValue = bmh.metadata?.annotations?.[BMH_HOSTNAME_ANNOTATION];
+  appendPatch(patches, annotationPath, hostname, currentValue);
+  return k8sPatch({
+    model: BMHModel,
+    resource: bmh,
+    data: patches,
+  });
+};
🧹 Nitpick comments (3)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-74: Remove redundant fragment to satisfy linter and reduce DOM depth

<> … </> contains a single child, therefore the wrapper is unnecessary and triggers noUselessFragments from Biome.
Keeping the text node directly is sufficient.

-<>
-  {t(
-    'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-  )}
-</>
+{t(
+  'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/utils.ts (2)

57-81: Consider using appendPatch for individual properties

Currently, the function replaces the entire provisionRequirements object, which could overwrite other properties that might be present but not explicitly managed here.

Consider refactoring to use appendPatch for individual properties:

 const setProvisionRequirements = (
   agentClusterInstall: AgentClusterInstallK8sResource,
   workerCount: number | undefined,
   masterCount: number | undefined,
 ) => {
-  const provisionRequirements = { ...(agentClusterInstall.spec?.provisionRequirements || {}) };
-  if (workerCount !== undefined) {
-    provisionRequirements.workerAgents = workerCount;
-  }
-  if (masterCount !== undefined) {
-    provisionRequirements.controlPlaneAgents = masterCount;
-  }
-
-  return k8sPatch({
-    model: AgentClusterInstallModel,
-    resource: agentClusterInstall,
-    data: [
-      {
-        op: agentClusterInstall.spec?.provisionRequirements ? 'replace' : 'add',
-        path: '/spec/provisionRequirements',
-        value: provisionRequirements,
-      },
-    ],
-  });
+  const patches: Patch[] = [];
+  
+  // Ensure provisionRequirements exists
+  if (!agentClusterInstall.spec?.provisionRequirements) {
+    patches.push({
+      op: 'add',
+      path: '/spec/provisionRequirements',
+      value: {},
+    });
+  }
+  
+  if (workerCount !== undefined) {
+    appendPatch(
+      patches,
+      '/spec/provisionRequirements/workerAgents',
+      workerCount,
+      agentClusterInstall.spec?.provisionRequirements?.workerAgents
+    );
+  }
+  
+  if (masterCount !== undefined) {
+    appendPatch(
+      patches,
+      '/spec/provisionRequirements/controlPlaneAgents',
+      masterCount,
+      agentClusterInstall.spec?.provisionRequirements?.controlPlaneAgents
+    );
+  }
+  
+  return k8sPatch({
+    model: AgentClusterInstallModel,
+    resource: agentClusterInstall,
+    data: patches,
+  });
 };

112-112: Consider clarifying or addressing the TODO comment

The TODO comment about handling mass delete lacks context and implementation plans.

Consider either:

  1. Adding more details about what mass delete should handle
  2. Creating a separate tracking issue/ticket for this TODO
  3. Implementing the mass delete functionality if it's needed
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 8e0f20b and 9167fcc.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (57)
  • libs/locales/lib/en/translation.json (38 hunks)
  • libs/ui-lib-tests/cypress/integration/storage/storage-step-disk-holders.cy.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (4 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (3)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts
  • libs/ui-lib-tests/cypress/integration/storage/storage-step-disk-holders.cy.ts
🚧 Files skipped from review as they are similar to previous changes (45)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/locales/lib/en/translation.json
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
🧰 Additional context used
🧬 Code Graph Analysis (3)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (3)
libs/ui-lib-tests/cypress/fixtures/infra-envs/openshift-versions.ts (2)
  • x86 (8-8)
  • s390x (10-10)
libs/ui-lib/lib/common/components/ui/formik/validationSchemas.ts (7)
  • richNameValidationSchema (456-489)
  • locationValidationSchema (654-679)
  • pullSecretValidationSchema (143-162)
  • sshPublicKeyValidationSchema (105-115)
  • httpProxyValidationSchema (534-573)
  • noProxyValidationSchema (587-602)
  • ntpSourceValidationSchema (604-627)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (15-34)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: tests
  • GitHub Check: lint
🔇 Additional comments (1)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)

110-117: location string is used as a Kubernetes label value – verify it meets the label RFC

metadata.labels['agentclusterinstalls.extensions.hive.openshift.io/location'] = values.location

Kubernetes label values must match
[a-z0-9A-Z]([-a-z0-9A-Z_.]*[a-z0-9A-Z])? and ≤ 63 chars.
If locationValidationSchema allows spaces or uppercase characters, resource
creation will fail.

Please ensure the schema enforces the label value constraints or transform the
value (e.g. slugify / lowercase / replace spaces).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🔭 Outside diff range comments (1)
libs/ui-lib/lib/cim/utils.ts (1)

1-177: ⚠️ Potential issue

Missing onMassDeleteHost implementation

The onMassDeleteHost function is defined in the types file but missing from this utility file. This could lead to runtime errors.

Add an implementation of onMassDeleteHost that accepts an array of host objects:

export const onMassDeleteHost = async (
  hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
  agentClusterInstall?: AgentClusterInstallK8sResource,
  nmStates: NMStateK8sResource[] = [],
) => {
  for (const host of hosts) {
    await onDeleteHost(host.agent, host.bmh, agentClusterInstall, nmStates);
  }
};

Ensure you also update all calling code to use the new signature.

♻️ Duplicate comments (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: ⚠️ Potential issue

Add error handling for base64 decoding.

The atob() function can throw exceptions if the input isn't properly base64-encoded. Add try-catch blocks to handle potential decoding errors.

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    // Consider showing a user-friendly error message here
+  }
}}
libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (1)

211-218: ⚠️ Potential issue

Conditional rendering of DeleteHostModal needs loading check.

The DeleteHostModal should only be rendered when both resources are fully loaded to avoid passing undefined values to the modal.

-  {deleteHost && (
+  {deleteHost && nmLoaded && aciLoaded && (
     <DeleteHostModal
       {...deleteHost}
       onClose={() => setDeleteHost(undefined)}
       nmStates={nmStates}
       agentClusterInstall={agentClusterInstall}
     />
   )}
libs/ui-lib/lib/cim/utils.ts (2)

44-55: 🛠️ Refactor suggestion

Use appendPatch for BMH hostname annotation

The current implementation uses a direct 'replace' operation which will fail if the annotation doesn't exist. Use appendPatch for consistency and to avoid potential errors.

export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) =>
  k8sPatch({
    model: BMHModel,
    resource: bmh,
-    data: [
-      {
-        op: 'replace',
-        path: `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`,
-        value: hostname,
-      },
-    ],
+    data: (() => {
+      const patches: Patch[] = [];
+      const annotationPath = `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`;
+      const currentValue = bmh.metadata?.annotations?.[BMH_HOSTNAME_ANNOTATION];
+      appendPatch(patches, annotationPath, hostname, currentValue);
+      return patches;
+    })(),
  });

127-159: 🛠️ Refactor suggestion

Refactor onUnbindHost to use appendPatch

The current implementation uses direct 'replace' operations which could fail if properties don't exist. Use appendPatch for consistency and to avoid potential errors.

export const onUnbindHost = async (
  agent: AgentK8sResource,
  agentClusterInstall?: AgentClusterInstallK8sResource,
) => {
  if (agent.spec?.clusterDeploymentName?.name) {
    if (agentClusterInstall) {
      const masterCount = undefined; /* Only workers can be removed */
      const workerCount = agentClusterInstall.spec?.provisionRequirements.workerAgents || 1;
      await setProvisionRequirements(
        agentClusterInstall,
        Math.max(0, workerCount - 1),
        masterCount,
      );
    }

-    await k8sPatch({
-      model: AgentModel,
-      resource: agent,
-      data: [
-        {
-          op: 'replace',
-          path: '/spec/clusterDeploymentName',
-          value: null,
-        },
-        {
-          op: 'replace',
-          path: '/spec/role',
-          value: '',
-        },
-      ],
-    });
+    const patches: Patch[] = [];
+    appendPatch(patches, '/spec/clusterDeploymentName', null, agent.spec.clusterDeploymentName);
+    appendPatch(patches, '/spec/role', '', agent.spec.role);
+    
+    await k8sPatch({
+      model: AgentModel,
+      resource: agent,
+      data: patches,
+    });
  }
};
🧹 Nitpick comments (8)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (6)

13-19: The hook changes the loading behavior when errors occur.

The implementation overrides the loaded state to true when an error is present. This means consumers cannot distinguish between "successfully loaded" and "errored" states by checking the loaded value alone - they must also check the error value.

Consider whether this behavior is intentional and well-documented for consumers of this hook.

export const useK8sWatchResource = <R extends K8sResourceCommon | K8sResourceCommon[]>(
  props: WatchK8sResource | null,
): WatchK8sResult<R> => {
  // eslint-disable-next-line
  const [data, loaded, error] = consoleWatch<R>(props);
-  return [data, !!error ? true : loaded, error as unknown];
+  return [data, loaded, error as unknown];
  
  // Or if the override is intentional, consider adding a comment explaining why:
  // return [data, !!error ? true : loaded, error as unknown]; // Force loaded=true when error exists to prevent loading indicators when we can show error state
};
🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)


16-17: Remove or clarify the ESLint disable comment.

The ESLint disable comment doesn't specify which rule is being disabled. For better maintainability, either specify the exact rule being disabled or add a comment explaining why the disable is necessary.

- // eslint-disable-next-line
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const [data, loaded, error] = consoleWatch<R>(props);

18-18: Simplify boolean conversion.

The double negation (!!error) is redundant in the ternary expression as the expression will coerce to a boolean anyway.

- return [data, !!error ? true : loaded, error as unknown];
+ return [data, error ? true : loaded, error as unknown];
🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)


1-19: Consider adding documentation.

This hook performs a specialized function with some behavioral nuances (like changing loading state when errors occur). Adding JSDoc comments would help users understand its purpose and behavior clearly.

+/**
+ * A typed wrapper around the OpenShift Console SDK's useK8sWatchResource hook.
+ * @param props - The resource configuration to watch, or null
+ * @returns A tuple containing:
+ *   - The watched resource data
+ *   - A boolean indicating if data is loaded (true if error is present)
+ *   - Any error that occurred during the watch
+ */
export const useK8sWatchResource = <R extends K8sResourceCommon | K8sResourceCommon[]>(
  props: WatchK8sResource | null,
): WatchK8sResult<R> => {
🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)


7-11: Add JSDoc to the exported type.

Since this type is exported, adding documentation would improve its usability for other developers.

+/**
+ * Represents the result of watching a Kubernetes resource.
+ * @template R - The type of resource being watched
+ */
export type WatchK8sResult<R extends K8sResourceCommon | K8sResourceCommon[]> = [
  R,
  boolean,
  unknown,
];

3-5: Consider re-exporting the imported types.

Since these types are used in the hook's signature, consider re-exporting them to make them available to consumers of this module without requiring them to import from the OpenShift SDK directly.

import {
  useK8sWatchResource as consoleWatch,
  K8sResourceCommon,
  WatchK8sResource,
} from '@openshift-console/dynamic-plugin-sdk';

+export { K8sResourceCommon, WatchK8sResource };
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment.

This Fragment is redundant as it contains only one child element and can be removed.

-                  <>
                     {t(
                       'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
                     )}
-                  </>
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/utils.ts (1)

112-112: Remove stale TODO comment

The TODO comment about handling mass delete is now addressed by implementing the onMassDeleteHost function.

-  // TODO handle mass delete
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 9167fcc and b76f604.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (57)
  • libs/locales/lib/en/translation.json (38 hunks)
  • libs/ui-lib-tests/cypress/integration/storage/storage-step-disk-holders.cy.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (4 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (3)
  • libs/ui-lib-tests/cypress/integration/storage/storage-step-disk-holders.cy.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/locales/lib/en/translation.json
🚧 Files skipped from review as they are similar to previous changes (43)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
🧰 Additional context used
🧬 Code Graph Analysis (2)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (15-34)
libs/ui-lib/lib/common/hooks/index.ts (1)
  • useTranslation (3-3)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: tests
  • GitHub Check: lint
  • GitHub Check: format
🔇 Additional comments (26)
libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (4)

23-29: Good job refactoring to use the OpenShift Console SDK directly.

The imports from the dynamic plugin SDK are appropriate for the new internal resource creation approach, providing a more direct implementation.


39-39: Props interface simplified appropriately.

Removing the onCreateBmcByYaml callback prop simplifies the component interface, aligning with the PR objective to decouple components and centralize resource creation logic.


44-44: Type change ensures correct handling of multiple YAML documents.

Good adjustment of the yamlContent state type to explicitly handle an array of parsed YAML documents.


120-140:

Details

✅ Verification successful

Resource creation implementation handles multiple document types efficiently.

The direct resource creation approach with group-version-kind detection is an improvement over the previous callback approach. This implementation correctly:

  1. Extracts the GVK information from each document
  2. Uses the appropriate model from the models collection
  3. Handles potential errors gracefully for each document

🏁 Script executed:

#!/bin/bash
# Verify error handling across similar resource creation workflows in the codebase

# Look for similar k8sCreate patterns in the codebase to ensure consistent approach
rg "k8sCreate\s*\(\s*\{" --type=tsx --type=ts -C 2 libs/ui-lib

Length of output: 92


🏁 Script executed:

#!/bin/bash
# Re-run search for k8sCreate usage without type restrictions to ensure we catch tsx files too
rg "k8sCreate\s*\(\s*\{" -n libs/ui-lib

Length of output: 888


🏁 Script executed:

#!/bin/bash
# Inspect k8sCreate usage and surrounding error handling in BMCForm.tsx
rg -n -C 5 "await k8sCreate" libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx

# Inspect k8sCreate usage and surrounding error handling in CreateInfraEnvPage.tsx
rg -n -C 5 "await k8sCreate" libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx

Length of output: 1343


🏁 Script executed:

#!/bin/bash
# Inspect handleSubmit and error handling in BMCForm.tsx
rg -n -C 10 "handleSubmit" libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx

# Search for try/catch blocks wrapping k8sCreate in BMCForm.tsx
rg -n -C 10 "try" libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx

Length of output: 2131


🏁 Script executed:

#!/bin/bash
# Inspect the handleSubmit implementation and error handling in AddBmcHostYamlForm.tsx
rg -n -C 10 "const handleSubmit" libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx

# Look for catch blocks to confirm error handling strategy
rg -n -C 5 "catch" libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx

Length of output: 2529


Approve multi-document resource creation flow
The AddBmcHostYamlForm implementation aligns with existing k8sCreate patterns in the codebase—extracting GVK per document, selecting the correct model, and wrapping operations in a global try/catch (with a fine-grained getGroupVersionKindForResource guard). This matches error-handling in BMCForm.tsx and CreateInfraEnvPage.tsx, so no further changes are needed.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (2)

36-40: Type definition for component props is well structured.

The props interface clearly defines the required data for the form component, making it easy to understand what inputs are needed.


107-115: Good documentation link handling with version from constants.

Using the DOC_VERSION constant from config ensures consistent documentation references across the application. This approach makes it easier to update documentation links when new versions are released.

libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (4)

13-25: Well-defined props interface for the modal.

The component defines a clear interface with optional and required props, properly typed for type safety. Using optional types for agent and bmh accommodates different deletion scenarios.


30-41: Properly implemented deletion workflow with error handling.

The deletion process includes:

  1. Setting initial state (clearing errors and setting deleting status)
  2. Try-catch block for error handling
  3. Proper cleanup in the finally block

This ensures robust error handling and consistent UI state management.


43-63: Modal actions are disabled during deletion.

Good UX implementation by disabling both confirm and cancel buttons during deletion, preventing multiple submissions. Using isLoading on the confirm button provides visual feedback during the operation.


67-67: Use the agent or bmh name for deletion confirmation.

The modal correctly displays the name of the resource being deleted by using the getAgentName utility function, which handles both agent and BMH resources.

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (5)

38-48: Appropriate imports for resource handling and routing.

The added imports support the component's new responsibility for fetching and managing resources directly rather than relying on callbacks.


60-63: Well-typed state for host deletion.

The deletion state properly captures either an agent or BMH resource to be deleted, supporting both host types.


68-78: Directly fetches required resources using hooks.

Good use of hooks to fetch NMStates and AgentClusterInstall resources. The component correctly extracts loaded states from the hooks for use in rendering conditions.


98-98: Simplified table hook configuration with internal deletion handler.

Good refactoring of the useAgentsTable hook configuration to use the internal state setter for deletion instead of an external callback.


199-199: Simplified hostname change handling.

Direct use of the onAgentChangeHostname utility function eliminates unnecessary callback prop passing, aligning with the overall component decoupling objective.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (4)

129-129: LGTM: Reduced prop surface simplifies component integration

The hostActions property now only includes essential editing actions, which simplifies the component interface. This is consistent with moving host deletion functionality to the centralized utility functions.


164-171: LGTM: Simplified InfraEnvAgentTableProps with direct property listing

Removing the Pick<AgentTableActions> inheritance in favor of directly listing required properties makes the component's dependencies more explicit and easier to understand.


173-176: LGTM: Narrowed table props to essential actions

Removing deletion-related actions from the table props aligns with the centralization of deletion logic in utility functions.


29-31:

Details

❓ Verification inconclusive

Inconsistent parameter patterns between related functions

The onDeleteHost function now accepts a wrapper object { agent?, bmh? } while onMassDeleteHost still uses separate parameters. This inconsistency makes the API less predictable and could lead to parameter-swap errors.

  onDeleteHost: (host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }) => void;
  onSetInstallationDiskId: (agent: AgentK8sResource, diskId: string) => Promise<AgentK8sResource>;
- onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+ onMassDeleteHost: (hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[]) => Promise<unknown>;

🏁 Script executed:

#!/bin/bash
# Verify how onMassDeleteHost is called in the codebase
rg -n "onMassDeleteHost\(" --type ts

Length of output: 38


Inconsistent parameter patterns between onDeleteHost and onMassDeleteHost
We’ve updated onDeleteHost to accept a single object { agent?, bmh? }, but onMassDeleteHost still takes two separate parameters—this asymmetry can lead to swapped-argument bugs. To keep the API predictable, align both signatures:

  onDeleteHost: (host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }) => void;
  onSetInstallationDiskId: (agent: AgentK8sResource, diskId: string) => Promise<AgentK8sResource>;
- onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+ onMassDeleteHost: (hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[]) => Promise<unknown>;

Please verify and update all call sites of onMassDeleteHost to match this new signature and ensure no regressions.

libs/ui-lib/lib/cim/utils.ts (7)

1-14: LGTM: Well-organized imports with clear separation

The imports are well organized with clear separation between SDK imports, local type imports, and external utilities.


22-30: LGTM: Useful utility for conditional patching

The appendPatch function intelligently chooses between 'add' and 'replace' operations based on whether the value already exists, preventing common K8s API errors.


32-36: LGTM: Robust agent approval implementation

Using appendPatch ensures the function works correctly regardless of whether spec.approved already exists in the agent resource.


38-42: LGTM: Hostname change function with proper patching

Using appendPatch ensures the function works correctly regardless of whether spec.hostname already exists in the agent resource.


83-118: LGTM: Comprehensive host deletion with safeguards

The onDeleteHost function properly handles:

  1. Agent resource deletion
  2. BareMetalHost resource deletion
  3. Associated NMState resources cleanup
  4. Worker count adjustment with protection against negative values

This centralized utility simplifies component implementations.


161-173: LGTM: Well-implemented NMState filtering utility

The getInfraEnvNMStates function correctly handles null cases and uses isMatch for proper label selector matching.


175-176: LGTM: Simple platform detection utility

The isBMPlatform function provides a clean way to check for bare metal-related platforms.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: ⚠️ Potential issue

Add error handling for base64 decoding

The atob() function can throw exceptions if the input isn't properly base64-encoded. Consider adding try/catch blocks to handle potential decoding errors.

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    // Consider showing a user-friendly error message here
+  }
}}
libs/ui-lib/lib/cim/utils.ts (2)

44-55: ⚠️ Potential issue

/metadata/annotations/... patch should tolerate new annotations

When a BMH has no hostname annotation, the replace op fails. Swap to appendPatch.

Apply this pattern to ensure the patch works whether or not the annotation exists:

-export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) =>
-  k8sPatch({
-    model: BMHModel,
-    resource: bmh,
-    data: [
-      {
-        op: 'replace',
-        path: `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`,
-        value: hostname,
-      },
-    ],
-  });
+export const onChangeBMHHostname = (bmh: BareMetalHostK8sResource, hostname: string) => {
+  const patches: Patch[] = [];
+  const annotationPath = `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`;
+  const hasAnnotation = bmh.metadata?.annotations && BMH_HOSTNAME_ANNOTATION in bmh.metadata.annotations;
+  
+  patches.push({
+    op: hasAnnotation ? 'replace' : 'add',
+    path: annotationPath,
+    value: hostname,
+  });
+  
+  return k8sPatch({
+    model: BMHModel,
+    resource: bmh,
+    data: patches,
+  });
+};

127-159: 🛠️ Refactor suggestion

Refactor onUnbindHost to use appendPatch

The current implementation uses direct 'replace' operations which could fail if properties don't exist. Also, the two patches could be combined into a single array.

Apply this diff to improve the function:

 export const onUnbindHost = async (
   agent: AgentK8sResource,
   agentClusterInstall?: AgentClusterInstallK8sResource,
 ) => {
   if (agent.spec?.clusterDeploymentName?.name) {
     if (agentClusterInstall) {
       const masterCount = undefined; /* Only workers can be removed */
       const workerCount = agentClusterInstall.spec?.provisionRequirements.workerAgents || 1;
       await setProvisionRequirements(
         agentClusterInstall,
         Math.max(0, workerCount - 1),
         masterCount,
       );
     }

-    await k8sPatch({
-      model: AgentModel,
-      resource: agent,
-      data: [
-        {
-          op: 'replace',
-          path: '/spec/clusterDeploymentName',
-          value: null,
-        },
-        {
-          op: 'replace',
-          path: '/spec/role',
-          value: '',
-        },
-      ],
-    });
+    const patches: Patch[] = [];
+    appendPatch(patches, '/spec/clusterDeploymentName', null, agent.spec.clusterDeploymentName);
+    appendPatch(patches, '/spec/role', '', agent.spec.role);
+    
+    await k8sPatch({
+      model: AgentModel,
+      resource: agent,
+      data: patches,
+    });
   }
 };
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

129-129: Simplified hostActions interface

The hostActions property in ClusterDeploymentWizardProps has been correctly narrowed to only include the necessary actions. This is a good simplification that reduces the API surface.


31-31: 🛠️ Refactor suggestion

Unify API signatures between onDeleteHost and onMassDeleteHost

While onDeleteHost now accepts a single wrapper object, onMassDeleteHost still uses two positional parameters. These inconsistent signatures for similar operations could lead to confusion and errors.

Consider aligning these signatures by changing onMassDeleteHost to accept an array of the same wrapper objects:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[]
+  ) => Promise<unknown>;

This matches the previous review comment and makes the API more consistent and robust.

🧹 Nitpick comments (3)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)

18-18: Simplify the boolean expression

The double negation !!error is redundant in a boolean context.

- return [data, !!error ? true : loaded, error as unknown];
+ return [data, error ? true : loaded, error as unknown];
🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (2)

68-72: Remove unnecessary Fragment

The Fragment is redundant as it contains only one child element.

-                  <>
                     {t(
                       'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
                     )}
-                  </>
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


106-111: Apply a consistent pattern for the ternary structure

The structure of the ternary conditional for determining whether to watch a resource could be more readable with consistent formatting.

- infraEnv.spec?.pullSecretRef?.name
-   ? {
-       groupVersionKind: {
-         kind: SecretModel.kind,
-         version: SecretModel.apiVersion,
-         group: SecretModel.apiGroup,
-       },
-       name: infraEnv.spec?.pullSecretRef?.name,
-       namespace: infraEnv.metadata?.namespace,
-       isList: false,
-     }
-   : null,
+ infraEnv.spec?.pullSecretRef?.name ? {
+   groupVersionKind: {
+     kind: SecretModel.kind,
+     version: SecretModel.apiVersion,
+     group: SecretModel.apiGroup,
+   },
+   name: infraEnv.spec?.pullSecretRef?.name,
+   namespace: infraEnv.metadata?.namespace,
+   isList: false,
+ } : null,
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between b76f604 and b292b7b.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (57)
  • libs/locales/lib/en/translation.json (11 hunks)
  • libs/ui-lib-tests/cypress/integration/storage/storage-step-disk-holders.cy.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (4 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (3)
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib-tests/cypress/integration/storage/storage-step-disk-holders.cy.ts
  • libs/locales/lib/en/translation.json
🚧 Files skipped from review as they are similar to previous changes (45)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/types/models.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (15-34)
libs/ui-lib/lib/common/hooks/index.ts (1)
  • useTranslation (3-3)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: translation-files
  • GitHub Check: format
  • GitHub Check: unit-tests
  • GitHub Check: circular-deps
  • GitHub Check: tests
  • GitHub Check: lint
🔇 Additional comments (6)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (2)

13-19: Nice implementation of the typed wrapper hook

The hook provides a type-safe wrapper around the console's watch resource functionality, with a well-defined return type signature.

🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)


17-18: Consider the loaded=true when error exists behavior

Setting loaded=true when an error occurs might mask loading states during errors. Consumers might incorrectly assume the data is ready when it's actually errored. Consider whether this is the intended behavior or if it would be better to preserve the original loading state.

🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (2)

98-111: Good use of the new useK8sWatchResource hook

The refactoring to use the useK8sWatchResource hook improves code consistency and follows React's patterns better than manual fetching with useEffect.


230-240: Well-structured modal rendering pattern

The conditionally rendered modals with internal state management is a clean pattern that reduces prop drilling and simplifies the component interface.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

29-29: Improved onDeleteHost parameter typing

The signature change to use a single object parameter with optional properties is a good improvement. This makes the API more flexible and less prone to parameter order mistakes.


175-175:

Details

✅ Verification successful

Ensure removal of onDeleteHost is consistent

The ClusterDeploymentHostDiscoveryTableProps no longer includes onDeleteHost from AgentTableActions, which is consistent with the changes in other parts of the file. Make sure all consumers of this type have been updated accordingly.


🏁 Script executed:

#!/bin/bash
# Check if there are any remaining references to onDeleteHost in associated components
echo "Checking for onDeleteHost usage in ClusterDeploymentHostDiscoveryTable.tsx:"
rg -n "onDeleteHost.*ClusterDeploymentHostDiscoveryTable" -A 5 -B 5

echo -e "\nChecking if any consumer is destructuring onDeleteHost from hostActions:"
rg -n "hostActions.*onDeleteHost" -A 3 -B 3

Length of output: 437


Removal of onDeleteHost is Consistent

I’ve verified there are no remaining references to onDeleteHost in:

  • ClusterDeploymentHostDiscoveryTable.tsx
  • Any destructuring of hostActions

Approving these changes.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (3)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: Add error handling for base64 decoding

The atob() function can throw exceptions if the input isn't properly base64-encoded. Consider adding try/catch blocks to handle potential decoding errors.

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    // Consider showing a user-friendly error message here
+  }
}}
libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (1)

211-218: ⚠️ Potential issue

Guard modal rendering on loading state.

The DeleteHostModal is rendered when deleteHost is set, but it should also check that the required resources are loaded to avoid potential runtime errors from undefined data.

-{deleteHost && (
+{deleteHost && nmLoaded && aciLoaded && (
  <DeleteHostModal
    {...deleteHost}
    onClose={() => setDeleteHost(undefined)}
    nmStates={nmStates}
    agentClusterInstall={agentClusterInstall}
  />
)}
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

31-31: 🛠️ Refactor suggestion

Unify onMassDeleteHost signature for consistency

The onMassDeleteHost signature is still using separate parameters while onDeleteHost now uses a wrapper object pattern. This inconsistency makes the API harder to use correctly.

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[]
+  ) => Promise<unknown>;

This keeps both deletion callbacks symmetrical, makes "mass" semantics explicit, and prevents accidental parameter swap bugs.

🧹 Nitpick comments (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (3)

68-72: Remove unnecessary Fragment

The Fragment wrapper is redundant since it contains only a single child element. React doesn't require fragments when there's only one child element.

- <>
    {t(
      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
    )}
- </>
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


126-126: Consider simplifying conditional check

Since osImages is a required prop (based on InfraEnvFormProps), the !!osImages check may be redundant. The component should always receive this prop.

- {!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+ <InfraEnvOpenShiftVersionDropdown osImages={osImages} />

If there's a concern that osImages might be empty, consider checking for array length instead:

- {!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+ {osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}

105-111: Add rel="noreferrer" for security when opening external links

When using window.open() with _blank, it's recommended to include rel="noreferrer" (along with the existing noopener) to prevent potential security issues where the opened page could access your window.opener object.

onClick={() =>
  window.open(
    getOCPStaticIPDocLink(DOC_VERSION),
    '_blank',
-   'noopener',
+   'noopener noreferrer',
  )
}
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)

18-18: Consider simplifying the double negation.

The double negation (!!error) can be simplified since you're already coercing to a boolean with the ternary operator.

-  return [data, !!error ? true : loaded, error as unknown];
+  return [data, error ? true : loaded, error as unknown];
🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

libs/ui-lib/lib/cim/utils.ts (1)

111-111: Address the TODO for mass delete

There's a TODO comment to handle mass deletion, but the implementation is not provided. This should be implemented to support the onMassDeleteHost function.

-  // TODO handle mass delete
+  // Implement mass delete by accepting an array of hosts and calling onDeleteHost for each one
+  // This would support the onMassDeleteHost function defined in the AgentTableActions type

Would you like me to propose an implementation for the mass delete functionality?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between b292b7b and 4f42bce.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (57)
  • libs/locales/lib/en/translation.json (11 hunks)
  • libs/ui-lib-tests/cypress/integration/storage/storage-step-disk-holders.cy.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (4 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (2)
  • libs/ui-lib-tests/cypress/integration/storage/storage-step-disk-holders.cy.ts
  • libs/ui-lib/lib/cim/config/constants.ts
🚧 Files skipped from review as they are similar to previous changes (44)
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/locales/lib/en/translation.json
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
🧰 Additional context used
🧬 Code Graph Analysis (3)
libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (3)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/modals/types.ts (1)
  • EditPullSecretFormikValues (41-44)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/utils.ts (7)
libs/ui-lib/lib/cim/types/k8s/shared.ts (1)
  • StatusCondition (1-8)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/models.ts (4)
  • AgentModel (67-76)
  • BMHModel (78-87)
  • AgentClusterInstallModel (111-120)
  • NMStateModel (89-98)
libs/ui-lib/lib/cim/components/common/constants.ts (2)
  • BMH_HOSTNAME_ANNOTATION (20-20)
  • AGENT_BMH_NAME_LABEL_KEY (12-12)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: format
  • GitHub Check: lint
  • GitHub Check: translation-files
  • GitHub Check: tests
  • GitHub Check: unit-tests
  • GitHub Check: circular-deps
🔇 Additional comments (17)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)

1-19: LGTM! A well-designed wrapper hook for Kubernetes resource watching.

This is a clean, typed wrapper around the OpenShift console's watch resource hook that provides type safety for consumers. The loading boolean override to return true when an error exists is a good UX decision that simplifies error state handling for consumers.

🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (3)

111-181: LGTM! Good refactoring to internalize resource operations.

The modal now handles its own resource operations using the OpenShift dynamic plugin SDK's k8sCreate and k8sPatch functions, which is a cleaner approach than delegating to external callbacks. The error handling is robust, utilizing the getErrorMessage utility to normalize different error types.


122-122: Modal isOpen prop hardcoded to true.

The isOpen prop is hardcoded to true, which indicates this component is meant to be conditionally rendered by its parent rather than controlled via props. This is consistent with the pattern used across other modals in this PR.


135-168: Solid implementation of resource creation/patching.

The conditional logic to either create a new secret or patch an existing one is well-structured. The code correctly handles base64 encoding of the pull secret and properly constructs the patch operation when updating an existing secret.

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (2)

152-154: Fixed loading state condition.

The loading condition has been corrected to show loading state when either NMStates or AgentClusterInstall resources are not loaded, which addresses a previous issue where it was showing loading when AgentClusterInstall was loaded.


59-78: LGTM! Good refactoring to use resource watching hooks.

The component now properly uses hooks for watching Kubernetes resources, which is a cleaner approach than passing resources through props. The destructuring of both the resource and loading state from the hooks is well implemented.

libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (2)

98-111: LGTM! Good refactoring to use K8s resource watching.

The component now uses useK8sWatchResource to reactively watch the pull secret, which is a cleaner approach than manual fetching. The conditional watch based on whether pullSecretRef.name exists is a good pattern.


230-252: Clean modal rendering pattern.

The modals are now conditionally rendered based on local state flags instead of being controlled via isOpen props, which is a more concise pattern and aligns with the broader refactoring in this PR.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

164-171: InfraEnvAgentTableProps now decoupled from actions

This is a good refactoring that separates data from actions, making the component more reusable. Instead of receiving callbacks through props, the component can now import utility functions directly from utils.ts.


173-176: ClusterDeploymentHostDiscoveryTableProps no longer includes onDeleteHost

Removing onDeleteHost from the picked properties is consistent with the changes in hostActions and the pattern of using utility functions directly from utils.ts.

libs/ui-lib/lib/cim/utils.ts (7)

22-30: Good implementation of appendPatch utility

The appendPatch function is a helpful utility that simplifies patch operations by handling both 'add' and 'replace' operations based on whether the target path already exists.


32-36: Robust implementation of onApproveAgent

Using the appendPatch helper ensures the patch operation will work correctly whether spec.approved already exists or not.


38-42: Well-implemented hostname change utilities

Both onChangeHostname and onChangeBMHHostname use the appendPatch helper to handle patching correctly. The BMH implementation properly escapes the annotation path with replace('/', '~1').

Also applies to: 44-54


119-124: Helpful utility for agent name

The getAgentName function provides a consistent way to extract names from different resource types, with appropriate fallbacks.


126-150: Well-implemented onUnbindHost function

The onUnbindHost function correctly uses the appendPatch helper to ensure patches work whether the properties exist or not, and prevents negative worker counts with Math.max(0, workerCount - 1).


152-164: Useful utility for filtering NMStates by InfraEnv

The getInfraEnvNMStates function provides a clean way to filter NMState resources based on the label selector in an InfraEnv resource.


166-167: Clear platform type helper

The isBMPlatform function provides a simple way to check if the infrastructure is one of the bare metal compatible platforms.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify consumers no longer use onDeleteHost from hostActions

The hostActions type no longer includes onDeleteHost, which means components using this prop need to be updated to use the standalone utility function.

Let's verify there are no stale usages:


🏁 Script executed:

#!/bin/bash
# Search for any usage of hostActions.onDeleteHost in the codebase
rg -n "hostActions.*onDeleteHost"

# Check components that previously used this pattern
grep -n "onDeleteHost" libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
grep -n "onDeleteHost" libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx

Length of output: 473


Update onDeleteHost References to Use the Standalone Utility

The hostActions type no longer includes onDeleteHost, so all consumers must be updated to import and call the new standalone delete-host utility instead of pulling onDeleteHost out of hostActions.

Please update the following locations:

  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
    • Remove onDeleteHost: setDeleteHost from the hostActions destructure (around line 98).
    • Import the standalone delete-host handler and invoke it where you currently call setDeleteHost.

  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
    • Remove onDeleteHost: setDeleteHost from the props destructure (line 114).
    • Replace the <DeleteHostAction … onDeleteHost={() => setMassDeleteOpen(…)} /> usage (around line 211) to call the standalone delete-host utility directly.

This ensures no lingering references to hostActions.onDeleteHost and aligns with the updated hostActions type.

🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts at line 129, the
hostActions type no longer includes onDeleteHost. Update all consumers by
removing onDeleteHost from hostActions destructuring in
ClusterDeploymentHostDiscoveryTable.tsx around line 98 and
InfraEnvAgentTable.tsx around line 114. Import the standalone delete-host
utility function in these files and replace all calls to
hostActions.onDeleteHost or setDeleteHost with calls to this standalone
function, including the DeleteHostAction usage near line 211 in
InfraEnvAgentTable.tsx.

Comment on lines 82 to 116
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

onDeleteHost signature doesn't match its type definition

The implementation of onDeleteHost takes separate parameters instead of the single wrapper object defined in the AgentTableActions type. This mismatch will cause type errors.

-export const onDeleteHost = async (
-  agent?: AgentK8sResource,
-  bmh?: BareMetalHostK8sResource,
-  agentClusterInstall?: AgentClusterInstallK8sResource,
-  nmStates: NMStateK8sResource[] = [],
-) => {
+export const onDeleteHost = async (
+  host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource },
+  agentClusterInstall?: AgentClusterInstallK8sResource,
+  nmStates: NMStateK8sResource[] = [],
+) => {
-  if (agent) {
+  if (host.agent) {
     await k8sDelete({
       model: AgentModel,
-      resource: agent,
+      resource: host.agent,
     });
   }
-  if (bmh) {
+  if (host.bmh) {
     await k8sDelete({
       model: BMHModel,
-      resource: bmh,
+      resource: host.bmh,
     });

     const bmhNMStates = (nmStates || []).filter(
-      (nm) => nm.metadata?.labels?.[AGENT_BMH_NAME_LABEL_KEY] === bmh.metadata?.name,
+      (nm) => nm.metadata?.labels?.[AGENT_BMH_NAME_LABEL_KEY] === host.bmh.metadata?.name,
     );

This change ensures the implementation matches the type definition in AgentTableActions.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const onDeleteHost = async (
agent?: AgentK8sResource,
bmh?: BareMetalHostK8sResource,
agentClusterInstall?: AgentClusterInstallK8sResource,
nmStates: NMStateK8sResource[] = [],
) => {
if (agent) {
await k8sDelete({
model: AgentModel,
resource: agent,
});
}
if (bmh) {
await k8sDelete({
model: BMHModel,
resource: bmh,
});
const bmhNMStates = (nmStates || []).filter(
(nm) => nm.metadata?.labels?.[AGENT_BMH_NAME_LABEL_KEY] === bmh.metadata?.name,
);
for (const nmState of bmhNMStates) {
await k8sDelete({
model: NMStateModel,
resource: nmState,
});
}
}
// TODO handle mass delete
if (agentClusterInstall) {
const masterCount = undefined; /* Only workers can be removed */
const workerCount = agentClusterInstall.spec?.provisionRequirements.workerAgents || 1;
await setProvisionRequirements(agentClusterInstall, Math.max(0, workerCount - 1), masterCount);
}
};
export const onDeleteHost = async (
host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource },
agentClusterInstall?: AgentClusterInstallK8sResource,
nmStates: NMStateK8sResource[] = [],
) => {
if (host.agent) {
await k8sDelete({
model: AgentModel,
resource: host.agent,
});
}
if (host.bmh) {
await k8sDelete({
model: BMHModel,
resource: host.bmh,
});
const bmhNMStates = (nmStates || []).filter(
(nm) =>
nm.metadata?.labels?.[AGENT_BMH_NAME_LABEL_KEY] ===
host.bmh!.metadata?.name,
);
for (const nmState of bmhNMStates) {
await k8sDelete({
model: NMStateModel,
resource: nmState,
});
}
}
// TODO handle mass delete
if (agentClusterInstall) {
const masterCount = undefined; /* Only workers can be removed */
const workerCount =
agentClusterInstall.spec?.provisionRequirements.workerAgents || 1;
await setProvisionRequirements(
agentClusterInstall,
Math.max(0, workerCount - 1),
masterCount,
);
}
};
🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/utils.ts around lines 82 to 117, the onDeleteHost
function currently takes multiple separate parameters, but its type definition
in AgentTableActions expects a single object parameter. To fix this, refactor
onDeleteHost to accept one object argument containing the properties agent, bmh,
agentClusterInstall, and nmStates, then destructure these inside the function.
This will align the function signature with its type definition and prevent type
errors.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: Add error handling for base64 decoding

The atob() function can throw exceptions if the input isn't properly base64-encoded. Consider adding try/catch blocks to handle potential decoding errors.

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    // Consider showing a user-friendly error message here
+  }
}}
libs/ui-lib/lib/cim/utils.ts (1)

82-117: ⚠️ Potential issue

Parameter signature inconsistency with type definition

The onDeleteHost implementation accepts separate parameters, but its type definition in ClusterDeployment/types.ts expects a single wrapper object. This mismatch will cause type errors when using the utility function.

-export const onDeleteHost = async (
-  agent?: AgentK8sResource,
-  bmh?: BareMetalHostK8sResource,
-  agentClusterInstall?: AgentClusterInstallK8sResource,
-  nmStates: NMStateK8sResource[] = [],
-) => {
+export const onDeleteHost = async (
+  host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource },
+  agentClusterInstall?: AgentClusterInstallK8sResource,
+  nmStates: NMStateK8sResource[] = [],
+) => {
-  if (agent) {
+  if (host.agent) {
     await k8sDelete({
       model: AgentModel,
-      resource: agent,
+      resource: host.agent,
     });
   }
-  if (bmh) {
+  if (host.bmh) {
     await k8sDelete({
       model: BMHModel,
-      resource: bmh,
+      resource: host.bmh,
     });

     const bmhNMStates = (nmStates || []).filter(
-      (nm) => nm.metadata?.labels?.[AGENT_BMH_NAME_LABEL_KEY] === bmh.metadata?.name,
+      (nm) => nm.metadata?.labels?.[AGENT_BMH_NAME_LABEL_KEY] === host.bmh.metadata?.name,
     );
libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (1)

239-330: ⚠️ Potential issue

Missing BMH creation during Add Host flow

The onCreateBMH function does not create a new BareMetalHost when bmh is undefined (during "Add host" flow). It currently only creates/patches Secrets and NMState resources, leaving orphaned credentials & NMState objects and producing a silent failure.

  if (bmh) {
    const patches: Patch[] = [];
    appendPatch(
      patches,
      `/metadata/annotations/${BMH_HOSTNAME_ANNOTATION.replace('/', '~1')}`,
      values.hostname,
      bmh.metadata?.annotations?.[BMH_HOSTNAME_ANNOTATION],
    );
    appendPatch(patches, '/spec/bmc/address', values.bmcAddress, bmh.spec?.bmc?.address);
    appendPatch(
      patches,
      '/spec/bmc/disableCertificateVerification',
      values.disableCertificateVerification,
      bmh.spec?.bmc?.disableCertificateVerification,
    );
    appendPatch(patches, '/spec/bootMACAddress', values.bootMACAddress, bmh.spec?.bootMACAddress);
    appendPatch(patches, '/spec/online', values.online, bmh.spec?.online);

    if (newSecret) {
      appendPatch(
        patches,
        '/spec/bmc/credentialsName',
        newSecret.metadata?.name,
        bmh.spec?.bmc?.credentialsName,
      );
    }
    if (patches.length) {
      await k8sPatch({
        model: BMHModel,
        resource: bmh,
        data: patches,
      });
    }
+  } else {
+    // Create new BMH
+    const newBmh: BareMetalHostK8sResource = {
+      apiVersion: 'metal3.io/v1alpha1',
+      kind: 'BareMetalHost',
+      metadata: {
+        name: values.name,
+        namespace: infraEnv.metadata?.namespace,
+        labels: {
+          [INFRAENV_AGENTINSTALL_LABEL_KEY]: infraEnv.metadata?.name || '',
+        },
+        annotations: {
+          [BMH_HOSTNAME_ANNOTATION]: values.hostname,
+        },
+      },
+      spec: {
+        bmc: {
+          address: values.bmcAddress,
+          credentialsName: (newSecret ?? secret)?.metadata?.name ?? '',
+          disableCertificateVerification: values.disableCertificateVerification,
+        },
+        bootMACAddress: values.bootMACAddress,
+        online: values.online,
+      },
+    };
+
+    await k8sCreate<BareMetalHostK8sResource>({
+      model: BMHModel,
+      data: newBmh,
+    });
   }
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

30-31: 🛠️ Refactor suggestion

Inconsistent deletion API patterns

While onDeleteHost now uses a wrapper object, onMassDeleteHost still uses separate parameters. This inconsistency makes the API less predictable and more error-prone.

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;
🧹 Nitpick comments (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (3)

68-72: Simplify unnecessary Fragment

Remove the unnecessary Fragment wrapper since it contains only one child element. This simplification will reduce DOM nesting and improve code readability.

- <>
-   {t(
-     'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-   )}
- </>
+ {t(
+   'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+ )}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)


126-126: Improve conditional rendering for better readability

The OpenShift version dropdown conditional rendering could be more explicit. While !!osImages works correctly, it might be clearer to check for array length.

- {!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+ {osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}

41-182: Consider extracting form sections into smaller components

The form is fairly large and contains multiple logical sections (basic info, network settings, credentials, proxy settings, NTP settings). Consider extracting these into smaller, focused components to improve maintainability and readability.

// Example of how this could look:
const CreateInfraEnvForm: React.FC<InfraEnvFormProps> = ({ credentials, osImages }) => {
  const { values } = useFormikContext<EnvironmentStepFormValues>();
  const { t } = useTranslation();

  return (
    <Stack hasGutter>
      <StackItem>{t('ai:Infrastructure environments are used...')}</StackItem>
      <StackItem>
        <Form>
          <BasicInfoSection />
          <NetworkConfigSection />
          <CredentialsSection credentials={credentials} />
          <ProxyConfigSection />
          <NTPConfigSection />
        </Form>
      </StackItem>
    </Stack>
  );
};
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)

17-18: Simplify boolean coercion

The double negation (!!error) is redundant when the value will already be coerced to a boolean in this context.

- return [data, !!error ? true : loaded, error as unknown];
+ return [data, error ? true : loaded, error as unknown];
🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 4f42bce and 8903447.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (57)
  • libs/locales/lib/en/translation.json (11 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (4 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (2)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/config/constants.ts
🚧 Files skipped from review as they are similar to previous changes (46)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/hooks/useInfraEnvAgents.ts
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvNMStates.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvBMHs.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/locales/lib/en/translation.json
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: circular-deps
  • GitHub Check: unit-tests
  • GitHub Check: tests
  • GitHub Check: translation-files
  • GitHub Check: format
  • GitHub Check: lint
🔇 Additional comments (12)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (3)

127-136: Location field implementation looks great

The location field is well-implemented with appropriate validation messages, required flag, and helpful descriptive text that explains the purpose of the field to users.


77-123: Well-structured network type selection

The network type selection is well-implemented with appropriate radio buttons, spacing, and helpful documentation popovers. The link to external documentation for static IP configuration is particularly helpful for users.


155-177: Well-implemented conditional rendering for NTP sources

The NTP sources configuration uses effective conditional rendering based on the checkbox state. The implementation properly wraps the additional fields in a Grid container when enabled, providing good structure and layout.

libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)

13-19: Well-structured resource watching hook with improved loading state handling

This hook provides a strongly typed wrapper around the console's resource watching hook with a useful improvement to the loading state logic. By marking loading as true when an error is present, it prevents components from attempting to render data during error states.

🧰 Tools
🪛 Biome (1.9.4)

[error] 18-18: Avoid redundant double-negation.

It is not necessary to use double-negation when a value will already be coerced to a boolean.
Unsafe fix: Remove redundant double-negation

(lint/complexity/noExtraBooleanCast)

libs/ui-lib/lib/cim/utils.ts (4)

22-30: Clean appendPatch helper to avoid redundant API calls

The appendPatch utility is well-designed. It only adds patches when there's an actual difference between values and correctly selects between 'add' and 'replace' operations based on the existence of the target path.


32-36: Robust agent approval implementation

Using appendPatch for approving agents ensures the operation works correctly regardless of whether the agent already has an approval status set, preventing potential 422 errors from the API server.


152-164: Well-designed filter function with proper type handling

The getInfraEnvNMStates function effectively filters NMState configs based on label matching and handles potential missing label selectors gracefully.


166-167: Platform detection handles all bare metal scenarios

The isBMPlatform function covers all relevant platform types that might represent bare metal infrastructure, making it robust for different deployment scenarios.

libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (1)

344-354: Form submission now uses the centralized creation utility

The form submission handler has been refactored to use the exported onCreateBMH function, removing the need for a callback prop and centralizing the resource creation logic. This is a good pattern for maintainability.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3)

129-129: Simplified hostActions interface reduces prop drilling

The hostActions type now only includes core editing capabilities, removing deletion operations that are now handled by standalone utilities. This aligns with the internal refactoring to reduce prop drilling and centralize resource operations.


164-171: Streamlined InfraEnvAgentTableProps removes callback dependencies

The revised InfraEnvAgentTableProps focuses solely on data resources, eliminating callbacks entirely. This is a clean approach that allows the component to manage its own state and actions internally.


173-176: Reduced ClusterDeploymentHostDiscoveryTableProps dependencies

The properties picked from AgentTableActions now exclude deletion operations, which aligns with the broader refactoring to use centralized utilities for these operations instead of passing callbacks.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: ⚠️ Potential issue

Address the unresolved base64 decoding safety issue.

Despite being marked as addressed in previous commits, the atob() calls are still not wrapped in try/catch blocks. This can cause runtime exceptions if the credential data contains invalid base64.

Apply this fix to safely handle base64 decoding:

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    setFieldValue('pullSecret', '');
+    setFieldValue('sshPublicKey', '');
+  }
}}
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (2)

113-118: Handler signature mismatch persists - async actions expected but setters provided

The useAgentsTable hook is receiving state setters (setDeleteHost, setEditBMH, setEditAgent, setUnbindHost) where it may expect async callback functions. If the hook internally awaits these handlers or expects them to return promises, passing state setters could cause the table to remain in a loading state.

Verify that useAgentsTable accepts these setter functions. If async functions are required, wrap the setters:

-onDeleteHost: setDeleteHost,
-onEditBMH: setEditBMH,
-onEditHost: setEditAgent,
-onUnbindHost: setUnbindHost,
+onDeleteHost: (params) => setDeleteHost(params),
+onEditBMH: (bmh) => setEditBMH(bmh),
+onEditHost: (agent) => setEditAgent(agent),
+onUnbindHost: (agent) => setUnbindHost(agent),

215-215: Missing bareMetalHosts in hostname calculation

The getAgentsHostsNames utility function accepts both agents and BMHs to extract all hostnames, but only agents are being passed. This could result in hostname conflicts with bare metal hosts.

-  const usedHostnames = React.useMemo(() => getAgentsHostsNames(agents), [agents]);
+  const usedHostnames = React.useMemo(() => getAgentsHostsNames(agents, bareMetalHosts), [agents, bareMetalHosts]);
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1)

95-106: Fix unnecessary curly braces in JSX fragment

The JSX structure has unnecessary curly braces around the React fragment, which could cause rendering issues.

 <NavItem isActive={location.pathname === hostsPath}>
   <Link to={hostsPath}>
-    {
-      <>
-        <InfraEnvHostsTabAgentsWarning
-          infraAgents={infraAgents}
-          infraBMHs={infraBMHs}
-        />
-        {t('ai:Hosts')}
-      </>
-    }
+    <>
+      <InfraEnvHostsTabAgentsWarning
+        infraAgents={infraAgents}
+        infraBMHs={infraBMHs}
+      />
+      {t('ai:Hosts')}
+    </>
   </Link>
 </NavItem>
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

29-32: Inconsistent parameter styles between delete operations

The onDeleteHost callback uses a wrapper object while onMassDeleteHost still uses positional parameters. This inconsistency makes the API error-prone and harder to maintain.

-  onDeleteHost: (host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }) => void;
-  onSetInstallationDiskId: (agent: AgentK8sResource, diskId: string) => Promise<AgentK8sResource>;
-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onDeleteHost: (host: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }) => void;
+  onSetInstallationDiskId: (agent: AgentK8sResource, diskId: string) => Promise<AgentK8sResource>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;
🧹 Nitpick comments (2)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment wrapper.

The Fragment is redundant since it contains only one child element.

bodyContent={
-  <>
-    {t(
-      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-    )}
-  </>
+  t(
+    'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+  )
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1)

176-178: Enhance error handling with specific error context

The current error handling shows a generic error state without indicating which resource failed to load (InfraEnv, Agents, or BMHs).

 if (error) {
-  return <ErrorState title={getErrorMessage(error)} />;
+  const errorMessage = infraErr 
+    ? t('ai:Failed to load infrastructure environment')
+    : agentsErr 
+    ? t('ai:Failed to load agents') 
+    : t('ai:Failed to load bare metal hosts');
+  
+  return <ErrorState 
+    title={errorMessage}
+    content={t('ai:Please try refreshing the page or contact support if the issue persists.')}
+  />;
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a0e6716 and 899ba5a.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (74)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (5 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
✅ Files skipped from review due to trivial changes (5)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/hooks/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
🚧 Files skipped from review as they are similar to previous changes (50)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/utils.ts
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/locales/lib/en/translation.json
🧰 Additional context used
🧬 Code Graph Analysis (12)
libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1)
libs/ui-lib/lib/cim/types/k8s/shared.ts (1)
  • StatusCondition (1-8)
libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (4)
libs/ui-lib/lib/cim/hooks/types.ts (1)
  • K8sWatchHookListProps (3-3)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentMachineModel (100-109)
libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/hooks/useSecret.ts (2)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/hooks/useBMHs.ts (3)
libs/ui-lib/lib/cim/hooks/types.ts (1)
  • K8sWatchHookListProps (3-3)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/types/models.ts (1)
  • BMHModel (78-87)
libs/ui-lib/lib/cim/hooks/useAgents.ts (4)
libs/ui-lib/lib/cim/hooks/types.ts (1)
  • K8sWatchHookListProps (3-3)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentModel (67-76)
libs/ui-lib/lib/cim/hooks/useNMStates.ts (4)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (2)
  • WatchK8sResult (7-11)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/models.ts (1)
  • NMStateModel (89-98)
libs/ui-lib/lib/cim/hooks/useConfigMap.ts (2)
libs/ui-lib/lib/cim/hooks/types.ts (1)
  • K8sWatchHookProps (4-4)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (4)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/utils.ts (1)
  • onApproveAgent (20-24)
libs/ui-lib/lib/cim/components/ClusterDeployment/helpers.ts (1)
  • getAgentsHostsNames (196-210)
libs/ui-lib/lib/cim/components/helpers/agents.ts (1)
  • onAgentChangeHostname (49-84)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (10)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/ClusterDeployment/helpers.ts (1)
  • getAgentsHostsNames (196-210)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (1)
  • InfraEnvHostsTabAgentsWarning (13-16)
libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1)
  • useInfraEnv (6-14)
libs/ui-lib/lib/cim/hooks/useAgents.ts (1)
  • useAgents (6-19)
libs/ui-lib/lib/cim/hooks/useBMHs.ts (1)
  • useBMHs (6-19)
libs/ui-lib/lib/cim/components/common/constants.ts (1)
  • INFRAENV_AGENTINSTALL_LABEL_KEY (10-10)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (15-34)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (20)
libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1)

1-16: LGTM! Well-implemented resource watch hook.

This hook follows excellent practices:

  • Defensive programming: The conditional logic prevents unnecessary API calls when required parameters are missing
  • Correct resource specification: ConfigMap is properly defined as a core v1 resource (no group field needed)
  • Type safety: Properly typed with ConfigMapK8sResource and K8sWatchHookProps
  • Consistent pattern: Follows the established pattern used by other resource watch hooks in this refactor

The implementation correctly handles edge cases where name or namespace might be undefined, null, or empty strings by returning null to disable the watch.

libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (2)

3-7: LGTM: Import changes are appropriate.

The addition of StatusCondition to the imports is necessary for the new local function definition and follows the existing import patterns.


12-18:

Details

✅ Verification successful

Function implementation is correct, but verify for code duplication.

The getConditionByType function is well-implemented with proper generics and type safety. However, since this was moved from a shared utility module, ensure no other modules have duplicated this functionality.


🏁 Script executed:

#!/bin/bash
# Description: Check for potential duplicate implementations of getConditionByType function
# Expected: Should find minimal occurrences, ideally only in this file and potentially the original shared module

echo "Searching for getConditionByType function definitions..."
ast-grep --pattern 'export const getConditionByType = $$$'

echo -e "\nSearching for any getConditionByType references..."
rg -A 3 'getConditionByType.*=' --type ts --type tsx

echo -e "\nSearching for imports of getConditionByType from other modules..."
rg 'import.*getConditionByType' --type ts --type tsx

Length of output: 1241


🏁 Script executed:

#!/bin/bash
# Comprehensive search for all occurrences of getConditionByType in the repository
echo "Searching for all instances of getConditionByType..."
rg -n 'getConditionByType' .

Length of output: 1113


No duplicate implementation found – approving changes.

Search across the repo shows only one getConditionByType definition (in utils.ts) and its expected imports/references, with no other copies elsewhere. Feel free to proceed with this implementation.

libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1)

15-15:

Details

✅ Verification successful

Verify that the function move doesn't introduce code duplication.

The import consolidation looks good for code organization. However, please verify that moving getConditionByType from the shared utils (../../../utils) to local utils (./utils) doesn't create code duplication if other components were using this function.


🏁 Script executed:

#!/bin/bash
# Description: Check if getConditionByType is used elsewhere in the codebase
# Expected: Should only find usage in the current file and the new local utils file

echo "Searching for getConditionByType usage across the codebase..."
rg -A 2 "getConditionByType" --type ts --type tsx

echo -e "\nSearching for imports from the old shared utils location..."
rg "from ['\"].*?/utils['\"]" --type ts --type tsx -A 1 -B 1

Length of output: 440


🏁 Script executed:

#!/bin/bash
# Retry searching without relying on rg’s built-in --type flags

echo "🔍 Searching for getConditionByType usage across .ts/.tsx files..."
rg -A2 "getConditionByType" -g '*.ts' -g '*.tsx' || true

echo -e "\n🔍 Searching for imports from the old shared utils location..."
rg -A2 "from ['\"][^'\"]*/utils['\"]" -g '*.ts' -g '*.tsx' || true

Length of output: 61659


Consolidation Safe: No Duplication Detected

Search results confirm that getConditionByType is defined only in

  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
    and imported only by
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx.

There are no remaining imports of getConditionByType from any shared “../../../utils” location. Consolidating it locally does not introduce duplication or break other components—this change is safe to approve.

libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1)

4-12: LGTM! Clean implementation following established patterns.

The hook correctly configures the watch for the metal3.io Provisioning resource and follows the same pattern as other resource-specific hooks in the codebase.

libs/ui-lib/lib/cim/hooks/useSecret.ts (1)

5-19: Well-structured conditional logic and parameter handling.

The hook properly handles the optional parameters and conditionally enables/disables the watch based on whether a name is provided. The parameter structure and typing are correct for watching individual Secret resources.

libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1)

6-15: LGTM! Consistent implementation following established patterns.

The hook correctly configures list watching for AgentMachine resources, properly uses the spread operator to merge props while ensuring isList: true, and follows the same pattern as other list-watching hooks in the codebase.

libs/ui-lib/lib/cim/hooks/useBMHs.ts (1)

6-19: LGTM! Proper implementation with correct conditional logic.

The hook follows the established pattern for optional list watching, correctly uses the BMHModel configuration, and properly handles the conditional watch enabling/disabling based on the props parameter.

libs/ui-lib/lib/cim/hooks/useAgents.ts (1)

6-19: LGTM! Clean implementation of typed Agent resource watcher.

The hook follows the established pattern and correctly configures the watch with AgentModel metadata. The conditional watching and proper typing make this a solid addition to the resource watching utilities.

libs/ui-lib/lib/cim/hooks/useNMStates.ts (1)

7-39: LGTM! Well-designed hook with proper filtering and memoization.

The hook correctly watches NMState resources and filters them based on the InfraEnv's label selector. The use of React.useMemo with appropriate dependencies ensures efficient re-filtering, and the lodash isMatch function provides robust label matching.

libs/ui-lib/lib/cim/components/modals/utils.ts (1)

98-132: LGTM! Comprehensive host deletion orchestration.

The function properly handles the complete deletion workflow including agent, BMH, associated NMState resources, and provision requirement updates. The bounds checking for worker count and the filtering logic for NMState resources are well-implemented.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

41-181: Well-structured form component with comprehensive UI elements.

The form implementation is well-organized with proper Formik integration, PatternFly components, and comprehensive field coverage for infrastructure environment creation. The conditional rendering and validation setup demonstrate good practices.

🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (2)

34-50: Clean imports organization

The new modal imports and utilities are well-organized and support the internalization refactor effectively.


258-288: Well-structured modal state management

The conditional rendering of modals based on internal state is clean and follows React best practices. Each modal receives the appropriate data and close handlers.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (3)

21-45: Well-designed custom hook for resource aggregation

The useAgentTabResources hook effectively combines multiple resource watchers and provides unified loading/error states. The hook correctly handles the namespace parameter and returns a clean interface.


47-77: Proper async state handling

The AgentsTab component correctly handles loading and error states before rendering content, following React best practices for async data fetching.


79-124: Clean UI structure with PatternFly components

The AgentsTabContent component is well-structured using PatternFly layout components and properly passes all required data to the InfraEnvAgentTable.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1)

120-167: Excellent resource management with label selectors

The useInfraEnvResources hook demonstrates proper Kubernetes resource watching with appropriate label selectors for filtering agents and BMHs. The logic correctly builds selectors from the InfraEnv status.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

164-171: Excellent simplification of component props

The InfraEnvAgentTableProps type has been significantly simplified by removing external callback dependencies. This supports the refactoring goal of internalizing host and agent management logic.


129-129:

Details

❓ Verification inconclusive

Verify all hostActions consumers are updated

The hostActions type has been reduced to only include specific actions. Ensure all components using this type have been updated to handle the removed callbacks internally.


🏁 Script executed:

#!/bin/bash
# Description: Verify no components are still destructuring removed hostActions properties

# Search for any remaining references to removed hostActions properties
rg -n "hostActions.*onDeleteHost|hostActions.*onApprove|hostActions.*onChangeHostname"

# Check for destructuring patterns that might include removed properties
rg -n "onDeleteHost.*hostActions|onApprove.*hostActions|onChangeHostname.*hostActions"

Length of output: 177


Verify removal of deprecated hostActions callbacks

No matches were found for the removed callbacks (onDeleteHost, onApprove, onChangeHostname) when searching the codebase. Please manually review any components or destructuring patterns that consume hostActions to confirm they no longer expect these callbacks and correctly handle only the remaining actions (onEditHost, onEditRole, onSetInstallationDiskId).

Comment on lines 9 to 28
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify the apiGroup reference for core Kubernetes resources.

The SecretModel in the relevant snippets doesn't include an apiGroup field. For core Kubernetes resources like Secrets, the API group is typically empty. Referencing SecretModel.apiGroup (line 12) will result in group: undefined, which may work but could be problematic.


🏁 Script executed:

#!/bin/bash
# Check if SecretModel includes apiGroup field
ast-grep --pattern $'export const SecretModel: K8sModel = {
  $$$
}'

Length of output: 592


Handle undefined apiGroup for core Secret resources

The SecretModel in libs/ui-lib/lib/cim/types/models.ts doesn’t define an apiGroup, so SecretModel.apiGroup is undefined. This leads to:

// libs/ui-lib/lib/cim/hooks/useSecret.ts:12
group: SecretModel.apiGroup,  // → undefined

Kubernetes core resources must use an empty string for the group. You’ll need to choose one of the following fixes:

• In models.ts, add an explicit empty apiGroup property:

export const SecretModel: K8sModel = {
  apiGroup: '',
  apiVersion: 'v1',};

• Or in useSecret.ts, provide a fallback when building groupVersionKind:

-group: SecretModel.apiGroup,
+group: SecretModel.apiGroup ?? '',

Either change will ensure group is correctly set to '' instead of undefined.

🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/hooks/useSecret.ts around lines 9 to 13, the group field
is set to SecretModel.apiGroup, which is undefined for core Kubernetes resources
like Secrets. To fix this, update the code to provide a fallback empty string
for the group field when SecretModel.apiGroup is undefined, ensuring group is
set to '' instead of undefined. Alternatively, add an explicit apiGroup: ''
property to SecretModel in libs/ui-lib/lib/cim/types/models.ts.

@rawagner rawagner force-pushed the cim_dynamic branch 2 times, most recently from ff846eb to b9e36d2 Compare June 9, 2025 14:58
@openshift-ci-robot
Copy link

openshift-ci-robot commented Jun 9, 2025

@rawagner: This pull request references ACM-20968 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.20.0" version, but no target version was set.

Details

In response to this:

Even though it looks like a lot of new code, this is actually mostly a refactoring of existing InfraEnv form. I've moved things around to create a nicer structure.

The new code is CredentialsField.tsx , as that was previously done in ACM console, which we cannot do anymore.
Another new code is YamlEditor.tsx. It will need some more tweaking (ie makings sure it sizes properly). But that can be handled in a followup.

See also stolostron/console#4307

Summary by CodeRabbit

  • New Features

  • Added extensive new UI translations for infrastructure environment and host management workflows.

  • Introduced hooks and components for watching and managing Kubernetes resources related to infrastructure environments, agents, and hosts.

  • Added new modals for deleting and unbinding hosts with clear confirmation and error handling.

  • Implemented a new InfraEnv creation page and form with enhanced validation, credential selection, and YAML editing.

  • Added a YAML editor component supporting resource validation and submission.

  • Introduced a credentials selection field integrated with form state and navigation.

  • Enhanced agent and host tables with internalized state management and simplified callbacks.

  • Added new utility functions for patching and managing agent and cluster resources.

  • Improvements

  • Refactored multiple components to remove external callback props, centralizing logic and reducing complexity.

  • Updated navigation links to use consistent Kubernetes resource paths.

  • Improved error handling and loading states across components.

  • Enhanced translation coverage with additional prompts and messages.

  • Simplified form and modal submission flows by internalizing patch and create operations.

  • Updated UI text for clarity and consistency.

  • Added new CSS rules for better UI spacing and theming.

  • Bug Fixes

  • Fixed proxy configuration fields to be optional and handled missing values gracefully.

  • Corrected minor text in warnings to better reflect data sensitivity.

  • Style

  • Added and updated CSS files for YAML editor, InfraEnv hosts tab, and other components.

  • Documentation

  • Added helper popovers and links to documentation in forms.

  • Improved instructional messages guiding host addition and environment creation.

  • Chores

  • Removed deprecated props and callbacks from multiple components and types.

  • Upgraded dependency on dynamic plugin SDK.

  • Consolidated imports and exports for cleaner module structure.

  • Added new typed Kubernetes resource models and hooks for better type safety.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (5)
libs/ui-lib/lib/cim/hooks/useSecret.ts (2)

20-24: Handle undefined apiGroup for core Secret resources.

The SecretModel doesn't define an apiGroup, so SecretModel.apiGroup is undefined. For core Kubernetes resources like Secrets, the group should be an empty string.

Apply this fix:

 groupVersionKind: {
   kind: SecretModel.kind,
   version: SecretModel.apiVersion,
-  group: SecretModel.apiGroup,
+  group: SecretModel.apiGroup ?? '',
 },

6-14: 🛠️ Refactor suggestion

Inconsistent group handling between hooks.

The useSecrets hook doesn't specify a group field, while useSecret does. For consistency and correctness with core Kubernetes resources, both should handle the group field the same way.

Apply this diff to make the hooks consistent:

 export const useSecrets = (props: K8sWatchHookListProps) =>
   useK8sWatchResource<SecretK8sResource[]>({
     groupVersionKind: {
       kind: SecretModel.kind,
       version: SecretModel.apiVersion,
+      group: SecretModel.apiGroup ?? '',
     },
     ...props,
     isList: true,
   });
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: ⚠️ Potential issue

Add error handling for base64 decoding.

The atob() function can throw exceptions if the input isn't properly base64-encoded. Despite being marked as addressed in previous reviews, this issue still exists.

Apply this diff to add proper error handling:

 onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    setFieldValue('pullSecret', '');
+    setFieldValue('sshPublicKey', '');
+  }
 }}
libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (1)

151-151: ⚠️ Potential issue

Add error handling for base64 encoding

The btoa() function can throw exceptions when input contains non-ASCII characters. Consider adding try/catch blocks to handle potential encoding errors.

Apply this fix at both locations (lines 151 and 164):

- '.dockerconfigjson': btoa(values.pullSecret),
+ '.dockerconfigjson': (() => {
+   try {
+     return btoa(values.pullSecret);
+   } catch (error) {
+     console.error('Failed to encode pull secret:', error);
+     throw new Error('Pull secret contains invalid characters that cannot be encoded');
+   }
+ })(),

Also applies to: 164-164

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

29-31: 🛠️ Refactor suggestion

Fix inconsistent parameter signatures between delete functions

The onDeleteHost function uses a single wrapper object parameter, while onMassDeleteHost still uses two separate parameters. This inconsistency makes the API error-prone and was flagged in previous reviews.

Apply this fix to unify the API:

- onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+ onMassDeleteHost: (
+   hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+ ) => Promise<unknown>;

This change will:

  • Make "mass" semantics explicit with an array parameter
  • Prevent parameter swap bugs
  • Provide consistent calling conventions
🧹 Nitpick comments (1)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment wrapper.

The Fragment is redundant since it only contains a single child element.

Apply this diff:

-                <>
                   {t(
                     'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
                   )}
-                </>
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 899ba5a and b9e36d2.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (75)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (5 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (2)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
🚧 Files skipped from review as they are similar to previous changes (61)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/components/modals/utils.ts
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/hooks/types.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/locales/lib/en/translation.json
🧰 Additional context used
🧬 Code Graph Analysis (5)
libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (4)
libs/ui-lib/lib/cim/hooks/types.ts (2)
  • K8sWatchHookListProps (3-3)
  • K8sWatchHookProps (4-4)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/models.ts (1)
  • InfraEnvModel (24-33)
libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (4)
libs/ui-lib/lib/cim/hooks/types.ts (1)
  • K8sWatchHookListProps (3-3)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/types/k8s/agent-service-config.ts (1)
  • AgentServiceConfigK8sResource (23-33)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentServiceConfigModel (35-44)
libs/ui-lib/lib/cim/hooks/useSecret.ts (3)
libs/ui-lib/lib/cim/hooks/types.ts (2)
  • K8sWatchHookListProps (3-3)
  • K8sWatchHookProps (4-4)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)
  • useK8sWatchResource (13-19)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (3)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/modals/types.ts (1)
  • EditPullSecretFormikValues (41-44)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (8)
libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1)

6-15: LGTM! Clean and consistent hook implementation.

The hook follows the established pattern for Kubernetes resource watching hooks and correctly configures the AgentServiceConfig resource type with proper typing.

libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (2)

6-15: LGTM! Well-structured list hook implementation.

The useInfraEnvs hook correctly implements the list pattern with proper typing and configuration.


17-25: LGTM! Clean single resource hook implementation.

The useInfraEnv hook follows the correct pattern for watching single Kubernetes resources.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

36-184: Well-structured form component with comprehensive features.

The component provides a good user experience with proper validation, internationalization, helpful popovers, and logical field organization. The integration with Formik and PatternFly components is well-executed.

🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/utils.ts (1)

1-58: Well-structured utility functions for K8s resource management

The refactored utilities provide a clean foundation for Kubernetes resource operations. The appendPatch function correctly handles the undefined vs falsy value distinction, and the specialized functions (onApproveAgent, setProvisionRequirements, getAgentName) follow consistent patterns for their respective use cases.

libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (2)

238-335: Excellent centralization of resource management logic

The new onCreateBMH function effectively consolidates the creation and patching of BMH, Secret, and NMState resources. The implementation correctly uses the appendPatch utility for safe patching operations and handles both create and update scenarios appropriately.


455-455: Good practice using void to suppress async lint warnings

The arrow function wrapper with void properly handles the async submitForm() call and suppresses linting warnings about unhandled promises.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

164-192: Type simplifications align well with architectural improvements

The removal of numerous callback properties from these type definitions successfully reduces prop drilling and external dependencies. This aligns perfectly with the broader refactoring effort to internalize host and agent management operations within components.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: The atob() decoding issue still exists.

The previous review comment about adding error handling for base64 decoding was marked as addressed, but the code still contains unprotected atob() calls that can throw exceptions with invalid input.

libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (1)

151-151: Add error handling for base64 encoding.

The btoa() function can throw exceptions when input contains non-ASCII characters. Consider adding try/catch blocks to handle potential encoding errors.

- '.dockerconfigjson': btoa(values.pullSecret),
+ '.dockerconfigjson': (() => {
+   try {
+     return btoa(values.pullSecret);
+   } catch (error) {
+     console.error('Failed to encode pull secret:', error);
+     throw new Error('Pull secret contains invalid characters that cannot be encoded');
+   }
+ })(),

Also applies to: 164-164

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

29-31: Inconsistent delete API signatures create developer confusion.

While onDeleteHost was updated to use a wrapper object parameter, onMassDeleteHost still uses two positional parameters. This inconsistency makes the API error-prone and complicates refactoring.

- onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+ onMassDeleteHost: (
+   hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+ ) => Promise<unknown>;

This would unify the API style, make "mass" semantics explicit, and prevent parameter swap bugs.

🧹 Nitpick comments (1)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment.

The Fragment is redundant since it only contains a single child element.

-bodyContent={
-  <>
-    {t(
-      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-    )}
-  </>
-}
+bodyContent={t(
+  'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b9e36d2 and b3c9917.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (75)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (5 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (7 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (4)
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
✅ Files skipped from review due to trivial changes (4)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/types.ts
🚧 Files skipped from review as they are similar to previous changes (62)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
  • libs/ui-lib/lib/cim/hooks/useSecret.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/locales/lib/en/translation.json
🧰 Additional context used
🧬 Code Graph Analysis (5)
libs/ui-lib/lib/cim/utils.ts (2)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentModel (67-76)
libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (3)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/modals/types.ts (1)
  • EditPullSecretFormikValues (41-44)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/components/modals/utils.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/types/models.ts (4)
  • AgentClusterInstallModel (111-120)
  • AgentModel (67-76)
  • BMHModel (78-87)
  • NMStateModel (89-98)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/components/common/constants.ts (1)
  • AGENT_BMH_NAME_LABEL_KEY (12-12)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (4)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (15-34)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (6)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

45-181: Well-structured form component.

The component follows React best practices with proper use of Formik context, PatternFly components, and accessibility considerations. The form layout is logical and user-friendly with appropriate validation, helper text, and conditional rendering.

🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/utils.ts (1)

1-20: Well-implemented patching utilities with proper error handling.

The appendPatch and onApproveAgent functions correctly address the issues raised in previous reviews. The conditional logic existingVal === undefined ? 'add' : 'replace' properly distinguishes between adding new paths and replacing existing ones, preventing 422 errors. The deep equality check with isEqual ensures patches are only applied when necessary.

libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (1)

134-174: Good refactoring to internalize modal logic.

The modal now properly manages its own submission state and resource operations, eliminating the need for external callbacks. The conditional creation vs patching logic is sound, and error handling is appropriately managed through the local error state.

libs/ui-lib/lib/cim/components/modals/utils.ts (2)

97-121: Well-structured provision requirements patching.

The setProvisionRequirements function properly handles both worker and master count updates with appropriate conditional logic for the add vs replace patch operation.


159-164: Clean utility for extracting agent names.

The getAgentName function provides a reliable fallback hierarchy for extracting meaningful names from resources, handling both Agent and BMH types appropriately.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

129-129: Good simplification of component interfaces.

The reduction of callback properties in hostActions and ClusterDeploymentHostDiscoveryTableProps appropriately reflects the internalization of host management logic, reducing prop drilling and improving component cohesion.

Also applies to: 175-175

Comment on lines +154 to +155
const workerCount = agentClusterInstall.spec?.provisionRequirements.workerAgents || 1;
await setProvisionRequirements(agentClusterInstall, Math.max(0, workerCount - 1), masterCount);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix worker count defaulting logic.

Defaulting workerAgents to 1 when undefined may cause incorrect counts. If the actual initial value should have been 0, this logic subtracts an extra unit and can yield incorrect worker counts.

- const workerCount = agentClusterInstall.spec?.provisionRequirements.workerAgents || 1;
+ const workerCount = agentClusterInstall.spec?.provisionRequirements.workerAgents ?? 0;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const workerCount = agentClusterInstall.spec?.provisionRequirements.workerAgents || 1;
await setProvisionRequirements(agentClusterInstall, Math.max(0, workerCount - 1), masterCount);
const workerCount = agentClusterInstall.spec?.provisionRequirements.workerAgents ?? 0;
await setProvisionRequirements(agentClusterInstall, Math.max(0, workerCount - 1), masterCount);
🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/components/modals/utils.ts around lines 154 to 155, the
workerAgents count defaults to 1 if undefined, which can cause incorrect worker
counts when subtracting one. Change the default value from 1 to 0 to correctly
reflect the initial worker count and avoid subtracting an extra unit, ensuring
accurate worker count calculations.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (2)

95-106: Fix incorrect JSX structure in NavItem

The JSX fragment structure looks incorrect. The Link component's children should be properly formatted:

 <NavItem isActive={location.pathname === hostsPath}>
   <Link to={hostsPath}>
-    {
-      <>
-        <InfraEnvHostsTabAgentsWarning
-          infraAgents={infraAgents}
-          infraBMHs={infraBMHs}
-        />
-        {t('ai:Hosts')}
-      </>
-    }
+    <>
+      <InfraEnvHostsTabAgentsWarning
+        infraAgents={infraAgents}
+        infraBMHs={infraBMHs}
+      />
+      {t('ai:Hosts')}
+    </>
   </Link>
 </NavItem>

The extra curly braces around the fragment are unnecessary and could cause rendering issues.


176-178: Enhance error handling with specific error messages

The current error handling shows a generic error state without distinguishing between different error sources:

 if (error) {
-  return <ErrorState title={getErrorMessage(error)} />;
+  const errorMessage = infraErr 
+    ? t('ai:Failed to load infrastructure environment')
+    : agentsErr 
+    ? t('ai:Failed to load agents') 
+    : bmhsErr
+    ? t('ai:Failed to load bare metal hosts')
+    : t('ai:An unexpected error occurred');
+  
+  return <ErrorState 
+    title={errorMessage}
+    content={t('ai:Please try refreshing the page or contact support if the issue persists.')}
+  />;
 }

This provides users with more context about what failed and potential next steps.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

21-23: Inconsistent parameter style for onMassDeleteHost

While onDeleteHost was updated to use a wrapper object, onMassDeleteHost still uses two positional parameters which is inconsistent and error-prone.

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

This would unify the API style, make "mass" semantics explicit, and prevent parameter swap bugs.


121-121: Update onDeleteHost References to Use the Standalone Utility

The hostActions type no longer includes onDeleteHost, so all consumers must be updated to import and call the new standalone delete-host utility instead of pulling onDeleteHost out of hostActions.

Please update the following locations:

  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
    • Remove onDeleteHost: setDeleteHost from the hostActions destructure (around line 98).
    • Import the standalone delete-host handler and invoke it where you currently call setDeleteHost.

  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
    • Remove onDeleteHost: setDeleteHost from the props destructure (line 114).
    • Replace the <DeleteHostAction … onDeleteHost={() => setMassDeleteOpen(…)} /> usage (around line 211) to call the standalone delete-host utility directly.

This ensures no lingering references to hostActions.onDeleteHost and aligns with the updated hostActions type.

🧹 Nitpick comments (2)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment wrapper.

The Fragment wrapper around the single translation call is redundant and can be removed for cleaner code.

bodyContent={
-  <>
-    {t(
-      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-    )}
-  </>
+  t(
+    'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+  )
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/components/modals/types.ts (1)

34-34: Consider using a more descriptive type for pullSecret

The pullSecret field uses a generic string type. Consider using a more specific type or adding validation constraints if this represents structured data like JSON.

-  pullSecret: string;
+  pullSecret: string; // Consider: JsonString or add validation constraints
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b3c9917 and aec4881.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (77)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (5)
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (5)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
🚧 Files skipped from review as they are similar to previous changes (60)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/hooks/useSecret.ts
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/modals/utils.ts
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/locales/lib/en/translation.json
🧰 Additional context used
🧬 Code Graph Analysis (3)
libs/ui-lib/lib/cim/utils.ts (2)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentModel (67-76)
libs/ui-lib/lib/cim/components/modals/types.ts (1)
libs/ui-lib/lib/cim/components/Agent/types.ts (1)
  • BMCFormProps (18-27)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (16-35)
libs/ui-lib/lib/common/hooks/index.ts (1)
  • useTranslation (3-3)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (13)
libs/ui-lib/lib/cim/utils.ts (2)

6-14: LGTM! Well-designed utility for conditional patching.

The appendPatch function demonstrates excellent practices:

  • Uses deep equality comparison with isEqual to avoid unnecessary patches
  • Correctly handles undefined values by choosing appropriate JSON Patch operations
  • Generic typing provides good type safety

16-20: Clean implementation of agent approval logic.

The onApproveAgent function properly uses the appendPatch utility and follows the established pattern for Kubernetes resource updates. Good encapsulation of the approval workflow.

libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx (2)

8-13: Excellent refactoring to explicit prop types.

Defining explicit props instead of using spread operators improves type safety and makes the component's interface clearer. Good architectural improvement.


15-18: Good internalization of hostname change logic.

Computing usedHostnames internally and obtaining the onSave function from the helper reduces external dependencies and makes the component more self-contained. This aligns well with the broader refactoring effort.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (2)

100-114: Well-implemented documentation link integration.

The external documentation link for static IP configuration is well-implemented with proper security attributes (noopener) and good UX with the external link icon.


140-149: Good credential integration with form state.

The credentials selection properly updates form fields by decoding base64 data. The implementation handles the credential data structure correctly.

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (4)

50-60: Well-designed resource loading hook.

The useTableResources hook properly abstracts the loading of related Kubernetes resources and combines their loading states. Good encapsulation of the async resource fetching logic.


72-75: Good internalization of deletion state.

Moving the deletion state management inside the component reduces external dependencies and simplifies the component's interface. The explicit typing for the deleteHost state provides good type safety.


154-156: Proper loading state guard.

The loading guard ensures the table doesn't render with undefined resources, preventing potential runtime errors. Good defensive programming practice.


213-220: Safe conditional rendering of DeleteHostModal.

The modal is only rendered when deleteHost is set and the resources are loaded, ensuring the modal receives properly initialized data. This prevents the runtime errors that were flagged in previous reviews.

libs/ui-lib/lib/cim/components/modals/types.ts (1)

24-27: LGTM: Clean type composition using Pick utility

The use of Pick to select specific properties from BMCFormProps is a good pattern for type composition and aligns with the refactoring to remove external callbacks.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1)

120-167: Well-structured custom hook for resource aggregation

The useInfraEnvResources hook effectively aggregates related resources with proper selector mapping and loading state management. The hook correctly derives selectors from the InfraEnv status and handles the loading states appropriately.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

156-163: Clean type simplification aligns with refactoring goals

The simplified InfraEnvAgentTableProps removes external callback dependencies, which aligns well with the broader refactoring to internalize component logic and reduce prop drilling.

@rawagner rawagner force-pushed the cim_dynamic branch 3 times, most recently from 896fb00 to f70636a Compare June 9, 2025 17:50
@openshift-merge-robot openshift-merge-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jun 9, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (1)

113-118: Verify handler signatures match useAgentsTable expectations.

The handlers passed to useAgentsTable are state setters rather than async callback functions. If useAgentsTable expects async functions that return promises, this could cause the table to remain in a loading state.

#!/bin/bash
# Search for useAgentsTable implementation to verify expected handler signatures
ast-grep --pattern 'function useAgentsTable($$$) {
  $$$
}'

# Also search for the hook definition
rg -A 10 "export.*useAgentsTable" -t ts
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

121-121: Verify all consumers updated for removed onDeleteHost from hostActions

The hostActions type no longer includes onDeleteHost, which is a breaking change. Components that previously destructured onDeleteHost from hostActions will now fail at compile time or runtime.

Based on past reviews, the following components need updates:

  • ClusterDeploymentHostDiscoveryTable.tsx (remove onDeleteHost: setDeleteHost from destructuring)
  • InfraEnvAgentTable.tsx (remove onDeleteHost: setDeleteHost from destructuring)

These components should import and use the standalone delete-host utility instead.


23-23: 🛠️ Refactor suggestion

Unify the API signature for consistency

The onMassDeleteHost function still uses two positional parameters while onDeleteHost was updated to use a single wrapper object. This inconsistency makes the API error-prone and harder to maintain.

Consider updating to match the onDeleteHost pattern:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

This change would make the "mass" semantics explicit and prevent parameter order confusion.

🧹 Nitpick comments (1)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment.

The Fragment wrapper is redundant here since it only contains a single text element.

-                  <>
-                    {t(
-                      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-                    )}
-                  </>
+                  {t(
+                    'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+                  )}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aec4881 and f70636a.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (77)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (5)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (4)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/hooks/types.ts
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
🚧 Files skipped from review as they are similar to previous changes (63)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/hooks/useSecret.ts
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/modals/utils.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/locales/lib/en/translation.json
🧰 Additional context used
🧬 Code Graph Analysis (4)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/modals/utils.ts (1)
  • deleteHost (123-157)
libs/ui-lib/lib/cim/utils.ts (1)
  • onApproveAgent (16-20)
libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (1)
  • clusterColumn (188-230)
libs/ui-lib/lib/cim/components/helpers/agents.ts (1)
  • onAgentChangeHostname (49-84)
libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (7)
libs/ui-lib/lib/cim/components/Agent/types.ts (1)
  • AddBmcValues (5-16)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (6-14)
libs/ui-lib/lib/cim/types/models.ts (3)
  • SecretModel (3-11)
  • NMStateModel (89-98)
  • BMHModel (78-87)
libs/ui-lib/lib/cim/components/modals/utils.ts (2)
  • getBareMetalHostCredentialsSecret (18-37)
  • getBareMetalHost (39-77)
libs/ui-lib/lib/cim/components/common/constants.ts (1)
  • BMH_HOSTNAME_ANNOTATION (20-20)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (16-35)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: format
  • GitHub Check: unit-tests
  • GitHub Check: circular-deps
  • GitHub Check: translation-files
  • GitHub Check: lint
  • GitHub Check: tests
🔇 Additional comments (7)
libs/ui-lib/lib/cim/utils.ts (2)

6-14: LGTM! Clean utility function for conditional patching.

The appendPatch function correctly handles the undefined check and uses deep equality comparison to avoid unnecessary patches. This addresses the previous issues with falsely-valued but defined properties.


16-20: Excellent pattern for agent approval.

The onApproveAgent function properly uses the appendPatch utility to avoid redundant operations and returns a promise for the patch operation. This centralizes agent approval logic effectively.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: Base64 decoding is properly handled.

The credential selection logic correctly decodes base64 data from the selected credentials. The error handling concerns from previous reviews have been addressed.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (1)

256-287: Well-structured modal rendering.

The conditional modal rendering is clean and properly manages the state through the onClose handlers. Each modal receives the appropriate props and data.

libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (3)

238-335: Excellent centralized resource management.

The onCreateBMH function properly handles all three resource types (Secret, NMState, BareMetalHost) with appropriate create/patch logic. The function correctly creates a new BMH when one doesn't exist, addressing the previous review concern.


353-359: Clean function integration.

The form submission now properly calls the internal onCreateBMH function with all required parameters, removing the dependency on external callbacks.


455-455: Good practice for void return.

Using void with submitForm() properly suppresses the lint warning about unused promise return values.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (3)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

23-23: Unify API signature for consistency

The onMassDeleteHost function still uses positional parameters while onDeleteHost now uses a wrapper object. This inconsistency makes the API error-prone and harder to maintain.

Consider updating to use an array of the same wrapper objects:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

This would make the "mass" semantics explicit and prevent parameter swap bugs.


121-121: Verify consumers handle reduced hostActions interface

The hostActions type now only includes 'onEditRole' | 'onSetInstallationDiskId', removing several callback properties including onDeleteHost. This simplification aligns with the refactoring goals but requires verification that all consumers have been updated.

Based on past reviews, ensure the following components have been updated to use standalone utilities instead of extracting callbacks from hostActions:

  • ClusterDeploymentHostDiscoveryTable.tsx
  • InfraEnvAgentTable.tsx
#!/bin/bash
# Verify no stale references to removed hostActions properties
rg -n "hostActions\.(onDeleteHost|onApproveAgent|onEditBMH|onUnbindHost)" --type ts --type tsx
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

140-148: The base64 decoding error handling issue remains unaddressed.

This matches the previous review feedback about adding try/catch blocks around atob() calls. The current implementation can still throw exceptions if the credential data isn't properly base64-encoded.

🧹 Nitpick comments (1)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment wrapper.

The Fragment is redundant since it only contains a single child element.

 bodyContent={
-  <>
-    {t(
-      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-    )}
-  </>
+  t(
+    'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+  )
 }
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f70636a and 964329d.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (77)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (5)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (2)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/hooks/types.ts
🚧 Files skipped from review as they are similar to previous changes (64)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/utils.ts
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/modals/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/hooks/useSecret.ts
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/locales/lib/en/translation.json
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
🧰 Additional context used
🧬 Code Graph Analysis (3)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/modals/utils.ts (1)
  • deleteHost (123-157)
libs/ui-lib/lib/cim/utils.ts (1)
  • onApproveAgent (16-20)
libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (1)
  • clusterColumn (188-230)
libs/ui-lib/lib/cim/components/helpers/agents.ts (1)
  • onAgentChangeHostname (49-84)
libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (7)
libs/ui-lib/lib/cim/components/Agent/types.ts (1)
  • AddBmcValues (5-16)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (6-14)
libs/ui-lib/lib/cim/types/models.ts (3)
  • SecretModel (3-11)
  • NMStateModel (89-98)
  • BMHModel (78-87)
libs/ui-lib/lib/cim/components/modals/utils.ts (2)
  • getBareMetalHostCredentialsSecret (18-37)
  • getBareMetalHost (39-77)
libs/ui-lib/lib/cim/components/common/constants.ts (1)
  • BMH_HOSTNAME_ANNOTATION (20-20)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (16-35)
libs/ui-lib/lib/common/hooks/index.ts (1)
  • useTranslation (3-3)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: format
  • GitHub Check: unit-tests
  • GitHub Check: circular-deps
  • GitHub Check: tests
  • GitHub Check: translation-files
  • GitHub Check: lint
🔇 Additional comments (11)
libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (2)

50-60: Well-implemented resource loading hook

The useTableResources hook properly encapsulates the loading logic for both NMStates and AgentClusterInstall, returning a combined loaded state. This ensures the component waits for all required data before rendering.


72-76: Good internalization of delete modal state

The component now manages delete operations internally through the deleteHost state, eliminating the need for external callbacks. The modal is properly rendered when deleteHost is set, and the close handler correctly resets the state.

Also applies to: 213-220

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (2)

79-93: Successful internalization of modal state management

The component now manages all host/agent editing operations through internal state (editBMH, editAgent, deleteHost, unbindHost) instead of external callbacks. This significantly simplifies the component interface and centralizes state management.

Also applies to: 113-118


256-287: Clean modal rendering with internal state

All modals are now conditionally rendered based on internal state with proper cleanup handlers. The modals receive necessary data directly without requiring external callbacks.

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1)

42-42: Good adoption of internal modal state pattern

The component successfully adopts the same pattern as other components in this refactor - managing modal state internally with editAgent and conditionally rendering EditAgentModal. The direct passing of setEditAgent to child components is consistent with the broader refactoring approach.

Also applies to: 130-130, 161-168

libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (2)

238-335: Excellent centralization of BMH resource management

The onCreateBMH function provides a comprehensive solution for handling both creation and updates of BMH-related resources. It correctly:

  • Handles Secret creation/patching with base64-encoded credentials
  • Manages NMState resource lifecycle based on form data
  • Creates new BMH when in "add" mode or patches existing BMH in "edit" mode
  • Uses the appendPatch utility for conditional patching, avoiding unnecessary API calls

This centralized approach eliminates the need for external callbacks and provides consistent resource management across the application.


353-359: Clean integration of centralized resource management

The form submission handler cleanly integrates with the new onCreateBMH function, passing all necessary parameters. This removes the dependency on external callbacks and simplifies the component interface.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3)

21-21: Good: Wrapper object signature improves API consistency

The change to use a wrapper object with optional agent and bmh properties is more maintainable than positional parameters and reduces the risk of parameter order mistakes.


155-162: Clean type definition for InfraEnv components

The InfraEnvAgentTableProps type definition includes all necessary resources for agent table functionality. The inclusion of nmStates directly in props is appropriate for this component's scope.


164-172: Appropriate action subset for host discovery

The ClusterDeploymentHostDiscoveryTableProps correctly picks only the essential actions from AgentTableActions, maintaining a focused interface for the host discovery table component.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

41-184: Well-structured component with good practices.

The component follows React best practices with proper:

  • TypeScript typing for props and form values
  • Internationalization using translation hooks
  • Accessibility with proper form labels and field IDs
  • PatternFly component usage for consistent UI
  • Form validation and helper text
  • Security considerations (noopener for external links)
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

</Flex>
</FormGroup>
<CpuArchitectureDropdown />
{!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve osImages array validation.

The current check !!osImages will pass for empty arrays, which might not be the intended behavior. Consider checking if the array has content.

-{!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+{osImages && osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
{osImages && osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx
at line 126, the condition rendering InfraEnvOpenShiftVersionDropdown uses
`!!osImages`, which evaluates true even for empty arrays. Update the condition
to check that osImages is not only defined but also has a length greater than
zero, ensuring the dropdown only renders when the array contains elements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (3)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (2)

126-126: osImages array validation issue remains unaddressed.

The condition !!osImages will evaluate to true for empty arrays, which may not be the intended behavior. The dropdown should only render when there are actual OS images to display.

-{!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+{osImages && osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}

140-148: Base64 decoding error handling is still missing.

Despite the past review comment being marked as addressed, the atob() function calls still lack error handling. These functions can throw exceptions if the input isn't properly base64-encoded, potentially causing runtime crashes.

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    setFieldValue('pullSecret', '');
+    setFieldValue('sshPublicKey', '');
+  }
}}
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

23-23: 🛠️ Refactor suggestion

Consider unifying onMassDeleteHost signature for consistency.

While onDeleteHost was updated to use a wrapper object, onMassDeleteHost still uses two positional parameters. This inconsistency could lead to confusion and parameter swap errors.

Consider updating to match the pattern:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[]
+  ) => Promise<unknown>;

This would make the "mass" semantics explicit and maintain API consistency.

🧹 Nitpick comments (1)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment wrapper.

The Fragment wrapper around the single translation text is redundant and can be simplified.

-bodyContent={
-  <>
-    {t(
-      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-    )}
-  </>
-}
+bodyContent={t(
+  'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 964329d and dbc074a.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (77)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (5)
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (4)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
🚧 Files skipped from review as they are similar to previous changes (63)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/utils.ts
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/hooks/types.ts
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/modals/utils.ts
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/hooks/useSecret.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/locales/lib/en/translation.json
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
🧰 Additional context used
🧬 Code Graph Analysis (3)
libs/ui-lib/lib/cim/components/helpers/agents.ts (3)
libs/ui-lib/lib/cim/components/common/constants.ts (2)
  • AGENT_BMH_NAME_LABEL_KEY (12-12)
  • BMH_HOSTNAME_ANNOTATION (20-20)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (6-14)
libs/ui-lib/lib/cim/types/models.ts (2)
  • AgentModel (67-76)
  • BMHModel (78-87)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/modals/utils.ts (1)
  • deleteHost (123-157)
libs/ui-lib/lib/cim/utils.ts (1)
  • onApproveAgent (16-20)
libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (1)
  • clusterColumn (188-230)
libs/ui-lib/lib/cim/components/helpers/agents.ts (1)
  • onAgentChangeHostname (49-84)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (16-35)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: tests
  • GitHub Check: circular-deps
  • GitHub Check: unit-tests
  • GitHub Check: translation-files
  • GitHub Check: format
  • GitHub Check: lint
🔇 Additional comments (10)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

41-182: Well-structured form component with comprehensive functionality.

The component effectively implements a complex infrastructure environment creation form with proper validation, internationalization, and user experience considerations. The integration with Formik provides good state management, and the use of PatternFly components ensures consistent UI patterns.

🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (3)

50-60: Well-designed resource loading hook.

The useTableResources hook properly encapsulates the loading logic for both NMStates and AgentClusterInstall resources, returning a combined loading state. This ensures dependent components only render when all required data is available.


154-156: Proper loading state management.

The loading check prevents rendering the table until all resources are loaded, which addresses the previous issues with modals receiving partially-initialized data.


213-220: Safe modal rendering with complete data.

The DeleteHostModal is only rendered when deleteHost is set and the loading state ensures all resources (nmStates, agentClusterInstall) are fully loaded before rendering, preventing runtime errors.

libs/ui-lib/lib/cim/components/helpers/agents.ts (1)

49-84: Excellent centralization of hostname update logic.

The refactored onAgentChangeHostname function properly:

  • Handles both Agent and BareMetalHost hostname updates
  • Uses correct JSON Patch path escaping for BMH annotations (line 79)
  • Centralizes Kubernetes patch operations instead of relying on external callbacks
  • Returns proper Promise types for async operations

This change significantly improves maintainability and reduces coupling.

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (3)

113-118: Well-implemented internalization of action handlers.

The refactored approach using internal state setters (setDeleteHost, setEditBMH, etc.) for the useAgentsTable handlers is clean and reduces external coupling. The handlers now manage modal state internally rather than requiring external callbacks.


256-287: Comprehensive modal state management.

The conditional rendering of modals based on internal state (editBMH, editAgent, deleteHost, unbindHost) is well-organized and provides all necessary data to each modal component. This approach eliminates the need for external modal management.


299-299: Proper usage of refactored hostname change function.

The call to onAgentChangeHostname(agents, bareMetalHosts) correctly provides both agents and BMHs to the hostname change handler, ensuring all hostname updates are handled properly.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

21-21: Good refactoring of onDeleteHost signature.

The wrapper object approach { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource } is much cleaner than separate parameters and reduces the chance of parameter order errors.


121-121: Excellent simplification of hostActions interface.

Reducing hostActions to only the essential actions (onEditRole, onSetInstallationDiskId) makes the interface much cleaner and reduces coupling. The removal of deletion and hostname change callbacks aligns well with the internal state management approach.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (2)

126-126: Improve osImages array validation.

The condition !!osImages evaluates to true even for empty arrays. The dropdown should only render when the array contains elements.

-{!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+{osImages && osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}

140-148: Add error handling for base64 decoding.

The atob() function can throw exceptions if the input isn't properly base64-encoded. This issue from previous reviews still needs to be addressed.

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    // Consider showing a user-friendly error message here
+  }
}}
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

21-23: API inconsistency between delete operations remains unaddressed

The onDeleteHost signature was updated to use a wrapper object, but onMassDeleteHost still uses two positional parameters, creating an inconsistent API that increases the risk of parameter swap bugs.

Consider unifying the signatures:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

This would make the "mass" semantics explicit and prevent accidental parameter ordering errors.


121-121: Verify all consumers updated for reduced hostActions interface

The hostActions type now only includes 'onEditRole' | 'onSetInstallationDiskId', removing 'onEditHost' and 'onDeleteHost'. Based on past review comments, this appears to have been addressed, but ensure all consuming components have been updated to handle these operations through alternative means.

🧹 Nitpick comments (3)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment wrapper.

The Fragment is redundant since it contains only one child element.

-bodyContent={
-  <>
-    {t(
-      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-    )}
-  </>
-}
+bodyContent={
+  t(
+    'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+  )
+}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (2)

161-163: Add conditional check for cpuArchitecture assignment.

The current code assigns cpuArchitecture even when it might be undefined or empty, which could create unnecessary spec fields.

-if (values.cpuArchitecture) {
+if (values.cpuArchitecture && values.cpuArchitecture !== '') {
  infraEnv.spec.cpuArchitecture = values.cpuArchitecture;
}

175-191: Consider parameterizing the role name.

The hardcoded role name 'capi-provider-role' might conflict if multiple InfraEnvs are created in the same namespace. Consider making it unique per InfraEnv.

-export const getRole = (namespace: string) => {
+export const getRole = (namespace: string, infraEnvName?: string) => {
   return {
     kind: RoleModel.kind,
     apiVersion: `${RoleModel.apiGroup || ''}/${RoleModel.apiVersion}`,
     metadata: {
-      name: 'capi-provider-role',
+      name: infraEnvName ? `capi-provider-role-${infraEnvName}` : 'capi-provider-role',
       namespace,
     },
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dbc074a and 28ec45c.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (77)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (5)
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
✅ Files skipped from review due to trivial changes (3)
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/hooks/types.ts
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
🚧 Files skipped from review as they are similar to previous changes (62)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/modals/utils.ts
  • libs/ui-lib/lib/cim/hooks/useSecret.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/locales/lib/en/translation.json
🧰 Additional context used
🧬 Code Graph Analysis (4)
libs/ui-lib/lib/cim/utils.ts (2)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentModel (67-76)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (4)
libs/ui-lib-tests/cypress/fixtures/infra-envs/openshift-versions.ts (2)
  • x86 (8-8)
  • s390x (10-10)
libs/ui-lib/lib/common/components/ui/formik/validationSchemas.ts (7)
  • richNameValidationSchema (456-489)
  • locationValidationSchema (654-679)
  • pullSecretValidationSchema (143-162)
  • sshPublicKeyValidationSchema (105-115)
  • httpProxyValidationSchema (534-573)
  • noProxyValidationSchema (587-602)
  • ntpSourceValidationSchema (604-627)
libs/ui-lib/lib/cim/types/models.ts (3)
  • SecretModel (3-11)
  • InfraEnvModel (24-33)
  • RoleModel (13-22)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)
  • EnvironmentStepFormValues (16-35)
libs/ui-lib/lib/common/config/docs_links.ts (1)
  • getOCPStaticIPDocLink (62-63)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/common/components/ui/formik/LabelField.tsx (1)
  • LabelField (34-100)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: unit-tests
  • GitHub Check: translation-files
  • GitHub Check: tests
  • GitHub Check: circular-deps
  • GitHub Check: lint
  • GitHub Check: format
🔇 Additional comments (7)
libs/ui-lib/lib/cim/utils.ts (1)

6-20: Well-implemented utility functions.

The appendPatch helper correctly handles the add/replace logic with proper undefined checks, and onApproveAgent provides a clean abstraction for agent approval. These utilities effectively centralize patch creation logic.

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (2)

50-60: Clean resource loading abstraction.

The useTableResources hook provides a clean abstraction for loading the required resources and properly combines the loading states. This prevents rendering with partially loaded data.


213-220: Proper conditional rendering of DeleteHostModal.

The modal is only rendered when deleteHost is set, and it receives all necessary props including the loaded nmStates and agentClusterInstall. This avoids the runtime errors that could occur with undefined data.

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (1)

42-42: Good internalization of modal state management.

The editAgent state and conditional EditAgentModal rendering properly internalizes the agent editing workflow, eliminating the need for external callbacks.

Also applies to: 161-168

libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (1)

353-359: Good internalization of BMH creation logic.

The direct call to onCreateBMH with all necessary parameters properly internalizes the resource creation logic, eliminating the need for external callbacks.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

155-162: New InfraEnvAgentTableProps type looks well-structured

The type definition properly includes all necessary Kubernetes resource types for agent table functionality and follows consistent naming conventions with other prop types in the file.


166-166: Consistent property selection from AgentTableActions

The ClusterDeploymentHostDiscoveryTableProps correctly picks only the required actions from AgentTableActions, maintaining a clean interface that excludes mass deletion and approval operations which aren't needed for this component.

Comment on lines +134 to +139
values.labels.forEach((l) => {
const label = l.split('=');
if (label.length && infraEnv.metadata?.labels) {
infraEnv.metadata.labels[label[0]] = label.length === 2 ? label[1] : '';
}
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Fix potential issue with empty label keys.

The current logic could create labels with empty keys when label.length is 1 but still processes the label.

values.labels.forEach((l) => {
  const label = l.split('=');
-  if (label.length && infraEnv.metadata?.labels) {
-    infraEnv.metadata.labels[label[0]] = label.length === 2 ? label[1] : '';
+  if (label.length >= 2 && label[0].trim() && infraEnv.metadata?.labels) {
+    infraEnv.metadata.labels[label[0].trim()] = label.slice(1).join('=').trim();
  }
});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
values.labels.forEach((l) => {
const label = l.split('=');
if (label.length && infraEnv.metadata?.labels) {
infraEnv.metadata.labels[label[0]] = label.length === 2 ? label[1] : '';
}
});
values.labels.forEach((l) => {
const label = l.split('=');
if (label.length >= 2 && label[0].trim() && infraEnv.metadata?.labels) {
infraEnv.metadata.labels[label[0].trim()] = label.slice(1).join('=').trim();
}
});
🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts around lines
134 to 139, the code processes labels without checking if the label key is
empty, which can lead to creating labels with empty keys. Update the condition
to ensure that the label array has a non-empty first element before assigning it
as a key in infraEnv.metadata.labels. This prevents adding labels with empty
keys by verifying label[0] is not an empty string.

Comment on lines +55 to +65
labels: Yup.array()
.of(Yup.string())
.test(
'label-equals-validation',
'Label selector needs to be in a `key=value` form',
(values) =>
(values as string[]).every((value) => {
const parts = value.split('=');
return parts.length === 2;
}),
),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Improve label validation logic.

The current validation has several issues:

  1. It doesn't prevent empty keys or values (e.g., "=value" or "key=" would pass)
  2. The error message refers to "Label selector" but this validates metadata labels
  3. Labels with multiple = characters are rejected but could be valid in some cases
labels: Yup.array()
  .of(Yup.string())
  .test(
-    'label-equals-validation',
-    'Label selector needs to be in a `key=value` form',
+    'label-format-validation',
+    'Labels must be in a `key=value` format with non-empty key and value',
    (values) =>
      (values as string[]).every((value) => {
        const parts = value.split('=');
-        return parts.length === 2;
+        return parts.length >= 2 && parts[0].trim() !== '' && parts.slice(1).join('=').trim() !== '';
      }),
  ),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
labels: Yup.array()
.of(Yup.string())
.test(
'label-equals-validation',
'Label selector needs to be in a `key=value` form',
(values) =>
(values as string[]).every((value) => {
const parts = value.split('=');
return parts.length === 2;
}),
),
labels: Yup.array()
.of(Yup.string())
.test(
'label-format-validation',
'Labels must be in a `key=value` format with non-empty key and value',
(values) =>
(values as string[]).every((value) => {
const parts = value.split('=');
return parts.length >= 2 && parts[0].trim() !== '' && parts.slice(1).join('=').trim() !== '';
}),
),
🤖 Prompt for AI Agents
In libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts around lines
55 to 65, improve the Yup validation for labels by ensuring keys and values are
not empty (reject strings like "=value" or "key="), update the error message to
refer to "metadata labels" instead of "Label selector," and adjust the logic to
allow multiple '=' characters in values by only splitting on the first '=' and
validating that both key and value parts are non-empty.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (5)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (2)

140-148: ⚠️ Potential issue

Add error handling for base64 decoding

The atob() calls can throw exceptions if the credential data isn't properly base64-encoded. This issue was flagged in previous reviews but hasn't been addressed.

Wrap the decoding operations in try-catch blocks:

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    setFieldValue('pullSecret', '');
+    setFieldValue('sshPublicKey', '');
+  }
}}

126-126: 🛠️ Refactor suggestion

Improve osImages array validation

The current check !!osImages evaluates to true even for empty arrays, which might not be the intended behavior.

-{!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+{osImages && osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (2)

95-105: Fix incorrect JSX structure in NavItem

The JSX fragment structure has unnecessary curly braces around the fragment that could cause rendering issues.

Apply this fix:

 <NavItem isActive={location.pathname === hostsPath}>
   <Link to={hostsPath}>
-    {
-      <>
-        <InfraEnvHostsTabAgentsWarning
-          infraAgents={infraAgents}
-          infraBMHs={infraBMHs}
-        />
-        {t('ai:Hosts')}
-      </>
-    }
+    <>
+      <InfraEnvHostsTabAgentsWarning
+        infraAgents={infraAgents}
+        infraBMHs={infraBMHs}
+      />
+      {t('ai:Hosts')}
+    </>
   </Link>
 </NavItem>

176-177: Enhance error handling with specific error messages

The current error handling shows a generic error state without distinguishing between different error sources (InfraEnv, agents, or BMHs).

Consider implementing more specific error handling:

 if (error) {
-  return <ErrorState title={getErrorMessage(error)} />;
+  const errorMessage = infraErr 
+    ? t('ai:Failed to load infrastructure environment')
+    : agentsErr 
+    ? t('ai:Failed to load agents') 
+    : t('ai:Failed to load bare metal hosts');
+  
+  return <ErrorState 
+    title={errorMessage}
+    content={t('ai:Please try refreshing the page or contact support if the issue persists.')}
+  />;
 }
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

21-23: Inconsistent parameter style between delete methods

The onDeleteHost method now uses a wrapper object, but onMassDeleteHost still uses two positional parameters, creating API inconsistency.

Consider unifying the parameter style:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

This would make the "mass" semantics explicit and prevent parameter swap bugs.

🧹 Nitpick comments (1)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment

The Fragment wrapper is redundant when it contains only static content.

-                bodyContent={
-                  <>
-                    {t(
-                      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-                    )}
-                  </>
-                }
+                bodyContent={t(
+                  'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+                )}
🧰 Tools
🪛 Biome (1.9.4)

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 28ec45c and 9f1dc4c.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (77)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (5)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (5)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/types.ts
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
🚧 Files skipped from review as they are similar to previous changes (60)
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/hooks/useSecret.ts
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
  • libs/ui-lib/lib/cim/components/modals/utils.ts
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/locales/lib/en/translation.json
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts
🧰 Additional context used
🧬 Code Graph Analysis (4)
libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (3)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (6-14)
libs/ui-lib/lib/cim/types/models.ts (1)
  • InfraEnvModel (24-33)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (10)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/ClusterDeployment/helpers.ts (1)
  • getAgentsHostsNames (196-210)
libs/ui-lib/lib/cim/config/constants.ts (1)
  • DOC_VERSION (4-4)
libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (1)
  • InfraEnvHostsTabAgentsWarning (13-16)
libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1)
  • useInfraEnv (21-33)
libs/ui-lib/lib/cim/hooks/useAgents.ts (1)
  • useAgents (6-19)
libs/ui-lib/lib/cim/hooks/useBMHs.ts (1)
  • useBMHs (6-19)
libs/ui-lib/lib/cim/components/common/constants.ts (1)
  • INFRAENV_AGENTINSTALL_LABEL_KEY (10-10)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/helpers/agents.ts (3)
libs/ui-lib/lib/cim/components/common/constants.ts (2)
  • AGENT_BMH_NAME_LABEL_KEY (12-12)
  • BMH_HOSTNAME_ANNOTATION (20-20)
libs/ui-lib/lib/cim/utils.ts (1)
  • appendPatch (6-14)
libs/ui-lib/lib/cim/types/models.ts (2)
  • AgentModel (67-76)
  • BMHModel (78-87)
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (5)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/components/Hypershift/types.ts (1)
  • AgentMachineK8sResource (186-193)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1)
  • NMStateK8sResource (3-11)
libs/ui-lib/lib/cim/types/k8s/agent-cluster-install.ts (1)
  • AgentClusterInstallK8sResource (17-80)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: tests
  • GitHub Check: unit-tests
  • GitHub Check: translation-files
  • GitHub Check: circular-deps
  • GitHub Check: lint
  • GitHub Check: format
🔇 Additional comments (8)
libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (1)

20-22: LGTM: Well-implemented modal refactoring with proper K8s patching

The refactoring successfully internalizes the submission logic and removes external dependencies. The K8s patch implementation correctly handles both removal of NTP sources (auto mode) and addition/update with properly filtered entries (filtering out empty strings as previously addressed).

Also applies to: 29-29, 36-36, 47-80

libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (1)

27-27: LGTM: Excellent refactoring with proper resource loading and state management

The refactoring successfully:

  • Internalizes host deletion logic with proper state management
  • Introduces proper loading state handling via useTableResources hook
  • Ensures modals are only rendered with fully loaded resources
  • Addresses previous concerns about rendering modals with undefined data

The loading state logic and modal rendering are now correctly implemented.

Also applies to: 38-48, 50-60, 72-80, 154-156, 213-220

libs/ui-lib/lib/cim/components/helpers/agents.ts (1)

4-11: LGTM: Excellent consolidation of hostname update logic

The refactoring successfully:

  • Removes external callback dependencies as mentioned in previous concerns
  • Implements direct K8s patch operations for both Agent and BMH resources
  • Correctly handles JSON Patch path escaping for BMH annotations (BMH_HOSTNAME_ANNOTATION.replace('/', '~1'))
  • Provides clean separation between Agent-backed and BMH-backed hostname updates

The implementation is robust and follows K8s patch best practices.

Also applies to: 52-84

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (1)

34-49: LGTM: Well-executed internalization of modal and action management

The refactoring successfully:

  • Internalizes host and agent management via React state hooks
  • Removes external callback dependencies and simplifies component interface
  • Properly sets up modal rendering with appropriate props and state management
  • Uses direct utility functions (onApproveAgent) instead of external callbacks

The state setter approach for handlers passed to useAgentsTable is appropriate and maintains the expected function signature.

Also applies to: 78-92, 112-117, 255-286, 298-298

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (2)

130-136: Good implementation of selector construction

The selector construction logic properly handles both matchLabels and matchExpressions from the InfraEnv status, ensuring comprehensive agent filtering.


147-158:

Details

✅ Verification successful

Verify BMH selector label key constant

The BMH selector uses INFRAENV_AGENTINSTALL_LABEL_KEY constant. Ensure this label key correctly matches the labels applied to BMHs in the system.


🏁 Script executed:

#!/bin/bash
# Verify the BMH label key constant usage
echo "=== Checking INFRAENV_AGENTINSTALL_LABEL_KEY usage ==="
rg -n "INFRAENV_AGENTINSTALL_LABEL_KEY" --type ts

echo -e "\n=== Checking for BMH labeling patterns ==="
rg -n "infraenvs\.agent-install\.openshift\.io" --type ts -A 2 -B 2

Length of output: 4982


INFRAENV_AGENTINSTALL_LABEL_KEY matches BMH labels

Verified that the constant INFRAENV_AGENTINSTALL_LABEL_KEY is defined as 'infraenvs.agent-install.openshift.io' and is used consistently across BMH selectors and labeling patterns. No changes required.

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (2)

121-121: Streamlined hostActions interface reduces prop drilling

The simplified hostActions type that only includes onEditRole and onSetInstallationDiskId aligns well with the broader refactoring to internalize action handling within components.

This change reduces the API surface and moves toward better encapsulation by having components manage their own delete, approve, and other actions internally.


155-162: Simplified InfraEnvAgentTableProps improves component interface

The InfraEnvAgentTableProps type now focuses on data dependencies rather than callback props, which aligns with the pattern of internalizing action handling within components.

This design reduces coupling and makes the component more self-contained.

@rawagner rawagner force-pushed the cim_dynamic branch 2 times, most recently from 4de56e5 to 2c5e978 Compare June 10, 2025 07:01
@openshift-merge-robot openshift-merge-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 5, 2025
@openshift-merge-robot
Copy link

PR needs rebase.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (8)
libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1)

1-163: LGTM! Well-structured YAML editor component.

The component demonstrates good practices:

  • Proper use of useStateSafely for state management
  • Clean separation of concerns with submitYamls handling validation
  • Appropriate error handling and user feedback
  • Good accessibility with proper ARIA labels

Note: File upload functionality referenced in the UI text is still not implemented, but this appears to be a known limitation for future enhancement.

libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (2)

151-151: Add error handling for base64 encoding.

The btoa() function can throw exceptions when input contains non-ASCII characters, which could crash the application.

Apply this diff to handle encoding errors:

-                    '.dockerconfigjson': btoa(values.pullSecret),
+                    '.dockerconfigjson': (() => {
+                      try {
+                        return btoa(values.pullSecret);
+                      } catch (error) {
+                        throw new Error('Pull secret contains invalid characters that cannot be encoded');
+                      }
+                    })(),

164-164: Same base64 encoding issue in patch operation.

Apply the same error handling pattern here as well.

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (2)

126-126: Improve osImages array validation.

The current check !!osImages will pass for empty arrays, which might not be the intended behavior.

Apply this diff:

-{!!osImages && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}
+{osImages && osImages.length > 0 && <InfraEnvOpenShiftVersionDropdown osImages={osImages} />}

141-148: Add error handling for base64 decoding.

The atob() function can throw exceptions if the input isn't properly base64-encoded.

Apply this diff to handle decoding errors:

onSelect={(cred) => {
-  setFieldValue(
-    'pullSecret',
-    cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
-  );
-  setFieldValue(
-    'sshPublicKey',
-    cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
-  );
+  try {
+    setFieldValue(
+      'pullSecret',
+      cred.data?.['pullSecret'] ? atob(cred.data['pullSecret']) : '',
+    );
+    setFieldValue(
+      'sshPublicKey',
+      cred.data?.['ssh-publickey'] ? atob(cred.data['ssh-publickey']) : '',
+    );
+  } catch (error) {
+    console.error('Failed to decode credential data:', error);
+    setFieldValue('pullSecret', '');
+    setFieldValue('sshPublicKey', '');
+  }
}}
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (2)

55-65: Consider improving label validation robustness

The current label validation has some edge cases that could be improved:

  1. Empty keys/values are allowed (e.g., "=value" or "key=" would pass)
  2. Labels with multiple = characters are rejected but could be valid

Consider this improvement to handle edge cases:

labels: Yup.array()
  .of(Yup.string())
  .test(
-    'label-equals-validation',
-    'Label selector needs to be in a `key=value` form',
+    'label-format-validation', 
+    'Labels must be in a `key=value` format with non-empty key and value',
    (values) =>
      (values as string[]).every((value) => {
        const parts = value.split('=');
-        return parts.length === 2;
+        return parts.length >= 2 && parts[0].trim() !== '' && parts.slice(1).join('=').trim() !== '';
      }),
  ),

134-139: Fix potential issue with empty label keys

The current logic could create labels with empty keys when processing malformed label strings.

Apply this fix to prevent empty label keys:

values.labels.forEach((l) => {
  const label = l.split('=');
-  if (label.length && infraEnv.metadata?.labels) {
-    infraEnv.metadata.labels[label[0]] = label.length === 2 ? label[1] : '';
+  if (label.length >= 2 && label[0].trim() && infraEnv.metadata?.labels) {
+    infraEnv.metadata.labels[label[0].trim()] = label.slice(1).join('=').trim();
  }
});
libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

21-23: Consider unifying callback signatures for consistency

While onDeleteHost now uses a wrapper object (good!), onMassDeleteHost still uses positional parameters, creating inconsistent APIs.

Consider aligning the signatures:

-  onMassDeleteHost: (agent?: AgentK8sResource, bmh?: BareMetalHostK8sResource) => Promise<unknown>;
+  onMassDeleteHost: (
+    hosts: { agent?: AgentK8sResource; bmh?: BareMetalHostK8sResource }[],
+  ) => Promise<unknown>;

This would make the "mass" operation semantics explicit and prevent parameter swap errors.

🧹 Nitpick comments (1)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1)

68-72: Remove unnecessary Fragment wrapper.

The Fragment contains only one child element and is redundant.

Apply this diff:

-                bodyContent={
-                  <>
-                    {t(
-                      'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
-                    )}
-                  </>
-                }
+                bodyContent={t(
+                  'ai:This will determine for the infrastructure environment which kind of hosts would be able to be added. If the hosts that you want to add are using DHCP server, select this option, else, select the static IP.',
+                )}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f1dc4c and 3b53e4d.

⛔ Files ignored due to path filters (2)
  • libs/ui-lib/lib/cim/logos/OnPremiseBannerIcon.svg is excluded by !**/*.svg
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (77)
  • libs/locales/lib/en/translation.json (21 hunks)
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/Agent/types.ts (0 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (6 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css (0 hunks)
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts (5 hunks)
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/helpers/agents.ts (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (4 hunks)
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx (3 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx (0 hunks)
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx (1 hunks)
  • libs/ui-lib/lib/cim/components/modals/types.ts (2 hunks)
  • libs/ui-lib/lib/cim/components/modals/utils.ts (2 hunks)
  • libs/ui-lib/lib/cim/config/constants.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/types.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useAgents.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts (1 hunks)
  • libs/ui-lib/lib/cim/hooks/useSecret.ts (1 hunks)
  • libs/ui-lib/lib/cim/index.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts (1 hunks)
  • libs/ui-lib/lib/cim/types/models.ts (1 hunks)
  • libs/ui-lib/lib/cim/utils.ts (1 hunks)
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx (1 hunks)
  • libs/ui-lib/lib/ocm/components/Routes.tsx (1 hunks)
  • libs/ui-lib/package.json (2 hunks)
💤 Files with no reviewable changes (5)
  • libs/ui-lib/lib/cim/components/InfraEnv/infra-env.css
  • libs/ui-lib/lib/cim/components/Agent/types.ts
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/ProvisioningConfigErrorAlert.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvFormPage.tsx
✅ Files skipped from review due to trivial changes (1)
  • libs/ui-lib/lib/cim/hooks/useAgentServiceConfig.ts
🚧 Files skipped from review as they are similar to previous changes (62)
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.css
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/CimConfigProgressAlert.tsx
  • libs/ui-lib/lib/cim/config/constants.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvHostsTabAgentsWarning.tsx
  • libs/ui-lib/lib/common/components/clusterConfiguration/FormatDiskWarning.tsx
  • libs/ui-lib/lib/cim/types/k8s/multi-cluster-engine.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.css
  • libs/ui-lib/lib/cim/hooks/useProvisioningConfig.ts
  • libs/ui-lib/lib/cim/types/k8s/klusterlet.ts
  • libs/ui-lib/lib/cim/components/Agent/NoAgentsAlert.tsx
  • libs/ui-lib/lib/cim/hooks/useConfigMap.ts
  • libs/ui-lib/lib/cim/components/modals/MassApproveAgentModal.tsx
  • libs/ui-lib/lib/ocm/components/Routes.tsx
  • libs/ui-lib/lib/cim/types/k8s/nm-state.ts
  • libs/ui-lib/lib/cim/hooks/useBMHs.ts
  • libs/ui-lib/lib/cim/hooks/useAgentMachines.ts
  • libs/ui-lib/lib/cim/components/modals/CimConfiguration/utils.ts
  • libs/ui-lib/package.json
  • libs/ui-lib/lib/cim/hooks/useAgents.ts
  • libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/index.ts
  • libs/ui-lib/lib/cim/components/modals/MassDeleteAgentModal.tsx
  • libs/ui-lib/lib/cim/hooks/useNMStates.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/types.ts
  • libs/ui-lib/lib/cim/components/YamlEditor/Theme.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/DetailsTab.tsx
  • libs/ui-lib/lib/cim/index.ts
  • libs/ui-lib/lib/cim/components/modals/EditProxyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/ScaleUpModal.tsx
  • libs/ui-lib/lib/cim/hooks/types.ts
  • libs/ui-lib/lib/cim/components/Hypershift/DetailsPage/NodePoolsTable.tsx
  • libs/ui-lib/lib/cim/hooks/useInfraEnvs.ts
  • libs/ui-lib/lib/cim/components/modals/EditSSHKeyModal.tsx
  • libs/ui-lib/lib/cim/components/modals/AddHostModal.tsx
  • libs/ui-lib/lib/cim/components/modals/EditBMHModal.tsx
  • libs/ui-lib/lib/cim/hooks/useSecret.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/AddHostDropdown.tsx
  • libs/ui-lib/lib/cim/components/YamlPreview/useYAMLPreview.ts
  • libs/ui-lib/lib/cim/components/modals/EditNtpSourcesModal.tsx
  • libs/ui-lib/lib/cim/components/formik/CredentialsField.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlModal.tsx
  • libs/ui-lib/lib/cim/components/modals/DeleteHostModal.tsx
  • libs/ui-lib/lib/cim/components/YamlEditor/utils.ts
  • libs/ui-lib/lib/cim/components/Agent/tableUtils.tsx
  • libs/ui-lib/lib/cim/components/modals/AddBmcHostYamlForm.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/useInfraEnvResources.ts
  • libs/ui-lib/lib/cim/hooks/useAgentClusterInstall.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvPage.tsx
  • libs/ui-lib/lib/cim/components/modals/EditAgentModal.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostsDiscovery.tsx
  • libs/ui-lib/lib/cim/components/helpers/agents.ts
  • libs/ui-lib/lib/cim/components/common/InfoAndTroubleshootingNotification.tsx
  • libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentWizard.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/AgentsTab.tsx
  • libs/ui-lib/lib/cim/components/modals/utils.ts
  • libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvDetails/InfraEnvDetails.tsx
  • libs/ui-lib/lib/cim/components/Agent/BMCForm.tsx
  • libs/ui-lib/lib/cim/components/modals/UnbindHostModal.tsx
  • libs/ui-lib/lib/cim/components/InfraEnv/EnvironmentDetails.tsx
  • libs/ui-lib/lib/cim/types/models.ts
  • libs/ui-lib/lib/cim/components/modals/types.ts
  • libs/locales/lib/en/translation.json
🧰 Additional context used
🧠 Learnings (3)
libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx (3)
Learnt from: rawagner
PR: openshift-assisted/assisted-installer-ui#2826
File: libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx:50-61
Timestamp: 2025-05-22T07:31:16.062Z
Learning: The YamlEditor component in libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx already handles YAML validation through the submitYamls function in utils.ts, which validates YAML syntax and throws user-friendly error messages if parsing fails.
Learnt from: rawagner
PR: openshift-assisted/assisted-installer-ui#2826
File: libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx:50-61
Timestamp: 2025-05-22T07:31:16.062Z
Learning: The `submitYamls` function in the YamlEditor component (libs/ui-lib/lib/cim/components/YamlEditor/utils.ts) already handles YAML validation with yaml.loadAll() and provides user-friendly error messages. Additional validation in the submit function would be redundant.
Learnt from: rawagner
PR: openshift-assisted/assisted-installer-ui#2899
File: libs/ui-lib/lib/ocm/components/clusterWizard/OperatorsSelect.tsx:32-55
Timestamp: 2025-04-14T09:11:08.834Z
Learning: In React components with asynchronous operations, `useStateSafely` custom hook should be used instead of `React.useState` to prevent state updates on unmounted components and avoid memory leaks.
libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (2)
Learnt from: rawagner
PR: openshift-assisted/assisted-installer-ui#2826
File: libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx:50-61
Timestamp: 2025-05-22T07:31:16.062Z
Learning: The `submitYamls` function in the YamlEditor component (libs/ui-lib/lib/cim/components/YamlEditor/utils.ts) already handles YAML validation with yaml.loadAll() and provides user-friendly error messages. Additional validation in the submit function would be redundant.
Learnt from: rawagner
PR: openshift-assisted/assisted-installer-ui#2826
File: libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx:50-61
Timestamp: 2025-05-22T07:31:16.062Z
Learning: The YamlEditor component in libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx already handles YAML validation through the submitYamls function in utils.ts, which validates YAML syntax and throws user-friendly error messages if parsing fails.
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (2)
Learnt from: rawagner
PR: openshift-assisted/assisted-installer-ui#2826
File: libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx:50-61
Timestamp: 2025-05-22T07:31:16.062Z
Learning: The YamlEditor component in libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx already handles YAML validation through the submitYamls function in utils.ts, which validates YAML syntax and throws user-friendly error messages if parsing fails.
Learnt from: rawagner
PR: openshift-assisted/assisted-installer-ui#2826
File: libs/ui-lib/lib/cim/components/YamlEditor/YamlEditor.tsx:50-61
Timestamp: 2025-05-22T07:31:16.062Z
Learning: The `submitYamls` function in the YamlEditor component (libs/ui-lib/lib/cim/components/YamlEditor/utils.ts) already handles YAML validation with yaml.loadAll() and provides user-friendly error messages. Additional validation in the submit function would be redundant.
🧬 Code Graph Analysis (3)
libs/ui-lib/lib/cim/utils.ts (2)
libs/ui-lib/lib/cim/types/k8s/agent.ts (1)
  • AgentK8sResource (32-74)
libs/ui-lib/lib/cim/types/models.ts (1)
  • AgentModel (67-76)
libs/ui-lib/lib/cim/components/modals/EditPullSecretModal.tsx (3)
libs/ui-lib/lib/common/utils.ts (1)
  • getErrorMessage (13-21)
libs/ui-lib/lib/cim/components/modals/types.ts (1)
  • EditPullSecretFormikValues (29-32)
libs/ui-lib/lib/cim/types/models.ts (1)
  • SecretModel (3-11)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (4)
libs/ui-lib-tests/cypress/fixtures/infra-envs/openshift-versions.ts (2)
  • x86 (8-8)
  • s390x (10-10)
libs/ui-lib/lib/common/components/ui/formik/validationSchemas.ts (7)
  • richNameValidationSchema (456-489)
  • locationValidationSchema (654-679)
  • pullSecretValidationSchema (143-162)
  • sshPublicKeyValidationSchema (105-115)
  • httpProxyValidationSchema (534-573)
  • noProxyValidationSchema (587-602)
  • ntpSourceValidationSchema (604-627)
libs/ui-lib/lib/cim/types/models.ts (3)
  • SecretModel (3-11)
  • InfraEnvModel (24-33)
  • RoleModel (13-22)
libs/ui-lib/lib/cim/types/k8s/infra-env-k8s-resource.ts (1)
  • InfraEnvK8sResource (8-42)
🪛 Biome (1.9.4)
libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/CreateInfraEnvForm.tsx

[error] 68-72: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (6)
libs/ui-lib/lib/cim/hooks/useK8sWatchResource.ts (1)

1-27: LGTM! Solid typed wrapper implementation.

The hook provides excellent type safety while maintaining the original behavior of the console's useK8sWatchResource. The error handling logic correctly prioritizes error state over loading state.

libs/ui-lib/lib/cim/utils.ts (1)

1-20: LGTM! Clean utility functions after thorough refinement.

The implementation correctly handles:

  • Proper distinction between undefined and falsy values in appendPatch
  • Safe patching operations that work regardless of existing field state
  • Clean separation of concerns with reusable patch logic
libs/ui-lib/lib/cim/components/ClusterDeployment/ClusterDeploymentHostDiscoveryTable.tsx (1)

51-61: LGTM: Clean refactoring that internalizes state management

The refactoring successfully removes external callback dependencies by:

  • Adding internal deleteHost state management
  • Using useTableResources hook for resource watching with proper loading/error handling
  • Conditionally rendering DeleteHostModal based on internal state

This aligns well with the broader PR objective of decoupling components and centralizing resource management.

Also applies to: 73-82, 218-225

libs/ui-lib/lib/cim/components/InfraEnv/InfraEnvAgentTable.tsx (1)

78-92: LGTM: Consistent state internalization pattern

The component successfully follows the same refactoring pattern as other components in this PR:

  • Internal state hooks for editBMH, editAgent, deleteHost, and unbindHost
  • Updated useAgentsTable to use state setters instead of external callbacks
  • Conditional modal rendering based on internal state

This maintains consistency across the codebase while simplifying the component interface.

Also applies to: 112-117, 255-286

libs/ui-lib/lib/cim/components/InfraEnv/CreateInfraEnv/utils.ts (1)

88-104: LGTM: Well-structured resource generation functions

The resource generation functions are well-implemented:

  • getPullSecretSecret: Correctly creates Kubernetes Secret with proper naming
  • getInfraEnv: Comprehensively builds InfraEnv resource with all optional fields handled appropriately
  • getRole: Creates necessary RBAC Role for agent management

The conditional field inclusion and resource structure align with Kubernetes best practices.

Also applies to: 106-173, 175-191

libs/ui-lib/lib/cim/components/ClusterDeployment/types.ts (1)

121-121: LGTM: Simplified type definitions align with refactoring goals

The type simplification successfully reflects the internalization of callback management:

  • hostActions reduced to core actions only
  • InfraEnvAgentTableProps no longer requires external callbacks
  • Component interfaces are cleaner and more focused

This aligns well with the PR's objective to decouple components and reduce external dependencies.

Also applies to: 155-162, 166-166

@openshift-ci
Copy link

openshift-ci bot commented Dec 18, 2025

@rawagner: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/okd-scos-images 3b53e4d link true /test okd-scos-images

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Comments