Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions libs/locales/lib/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@
"ai:Available": "Available",
"ai:Back": "Back",
"ai:Bare metal": "Bare metal",
"ai:Bare metal host": "Bare metal host",
"ai:Bare metal host cannot be edited. Remove this host and add it again if a change is needed.": "Bare metal host cannot be edited. Remove this host and add it again if a change is needed.",
"ai:Bare metal host cannot be removed from cluster.": "Bare metal host cannot be removed from cluster.",
"ai:Bare metal host events": "Bare metal host events",
"ai:Bare metal host not found": "Bare metal host not found",
"ai:Bare Metal Host related": "Bare Metal Host related",
"ai:Base domain": "Base domain",
Expand Down Expand Up @@ -260,6 +262,7 @@
"ai:Define the quantity of worker nodes and nodepools to create for your cluster. Additional worker nodes and nodepools can be added after the cluster is created.": "Define the quantity of worker nodes and nodepools to create for your cluster. Additional worker nodes and nodepools can be added after the cluster is created.",
"ai:Defines how big the subnets for each individual node are out of the given CIDR. Must enter a whole number.": "Defines how big the subnets for each individual node are out of the given CIDR. Must enter a whole number.",
"ai:Deleted hosts": "Deleted hosts",
"ai:Deleting": "Deleting",
"ai:Deprovisioning": "Deprovisioning",
"ai:Details": "Details",
"ai:Developer Preview": "Developer Preview",
Expand Down Expand Up @@ -521,6 +524,7 @@
"ai:Labels": "Labels",
"ai:Labels matching hosts": "Labels matching hosts",
"ai:Last observed condition:": "Last observed condition:",
"ai:Last updated:": "Last updated:",
"ai:Launch OpenShift Console": "Launch OpenShift Console",
"ai:Learn more": "Learn more",
"ai:Learn more about configuration.": "Learn more about configuration.",
Expand Down Expand Up @@ -611,6 +615,7 @@
"ai:NIC_plural": "NICs",
"ai:NMState": "NMState",
"ai:No available hosts with {{cpuArchitecture}} architecture were found": "No available hosts with {{cpuArchitecture}} architecture were found",
"ai:No BMH events found.": "No BMH events found.",
"ai:No host is selected.": "No host is selected.",
"ai:No host matches provided labels/locations": "No host matches provided labels/locations",
"ai:No hosts found": "No hosts found",
Expand Down Expand Up @@ -922,6 +927,7 @@
"ai:try again": "try again",
"ai:Try logging into the machine directly through physical access, out-of-band management, or a virtual machine console. To generate a new bootable image file with password-based login enabled, download the full image file and patch it locally with a login password of your choice using": "Try logging into the machine directly through physical access, out-of-band management, or a virtual machine console. To generate a new bootable image file with password-based login enabled, download the full image file and patch it locally with a login password of your choice using",
"ai:Two nodes control plane OpenShift must include an additional arbiter node.": "Two nodes control plane OpenShift must include an additional arbiter node.",
"ai:Type": "Type",
"ai:Type or select location(s)": "Type or select location(s)",
"ai:Unable to SSH into your hosts through the network?": "Unable to SSH into your hosts through the network?",
"ai:Unique hostname": "Unique hostname",
Expand Down Expand Up @@ -958,6 +964,7 @@
"ai:Verify that you can access your host machine using SSH, or a console such as BMC or virtual machine console. In the CLI, enter the following command:": "Verify that you can access your host machine using SSH, or a console such as BMC or virtual machine console. In the CLI, enter the following command:",
"ai:View {{count}} affected host": "View {{count}} affected host",
"ai:View {{count}} affected host_plural": "View {{count}} affected hosts",
"ai:View BMH events": "View BMH events",
"ai:View cluster events": "View cluster events",
"ai:View documentation": "View documentation",
"ai:View host events": "View host events",
Expand Down
3 changes: 3 additions & 0 deletions libs/ui-lib/lib/cim/components/Agent/AgentStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export type AgentStatusProps = {
zIndex?: number;
wizardStepId?: ClusterDeploymentWizardStepsType;
isDay2?: boolean;
additionalBMHInfo?: React.ReactNode;
};

const AgentStatus: React.FC<AgentStatusProps> = ({
Expand All @@ -29,6 +30,7 @@ const AgentStatus: React.FC<AgentStatusProps> = ({
zIndex,
wizardStepId,
isDay2,
additionalBMHInfo,
}) => {
const { t } = useTranslation();
const [host] = getAIHosts([agent]);
Expand Down Expand Up @@ -65,6 +67,7 @@ const AgentStatus: React.FC<AgentStatusProps> = ({
</StackItem>
) : undefined
}
additionalBMHInfo={additionalBMHInfo}
{...status}
>
{pendingApproval && onApprove && (
Expand Down
5 changes: 3 additions & 2 deletions libs/ui-lib/lib/cim/components/Agent/AgentTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import { AgentClusterInstallK8sResource, AgentK8sResource } from '../../types';
import { AgentTableActions } from '../ClusterDeployment/types';
import DefaultEmptyState from '../../../common/components/ui/uiState/EmptyState';
import { ConnectedIcon } from '@patternfly/react-icons/dist/js/icons/connected-icon';
import { infraEnvColumn, agentStatusColumn, useAgentsTable } from './tableUtils';
import { useAgentsTable } from './tableUtils';
import { infraEnvColumn, agentStatusColumn } from './tableColumns';
import {
cpuArchitectureColumn,
cpuCoresColumn,
disksColumn,
hostnameColumn,
memoryColumn,
roleColumn,
} from '../../../common/components/hosts/tableUtils';
} from '../../../common';
import HostsTable, { DefaultExpandComponent } from '../../../common/components/hosts/HostsTable';
import { usePagination } from '../../../common/components/hosts/usePagination';
import { useTranslation } from '../../../common/hooks/use-translation-wrapper';
Expand Down
15 changes: 3 additions & 12 deletions libs/ui-lib/lib/cim/components/Agent/AgentsSelectionTable.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
import React from 'react';
import { useField } from 'formik';
import HostsTable, { DefaultExpandComponent } from '../../../common/components/hosts/HostsTable';
import {
cpuCoresColumn,
disksColumn,
memoryColumn,
roleColumn,
} from '../../../common/components/hosts/tableUtils';
import { cpuCoresColumn, disksColumn, memoryColumn, roleColumn } from '../../../common';
import { agentHostnameColumn, infraEnvColumn, agentStatusColumn } from './tableColumns';
import { AgentK8sResource } from '../../types/k8s/agent';
import {
ClusterDeploymentHostsSelectionValues,
AgentTableActions,
} from '../ClusterDeployment/types';
import {
infraEnvColumn,
agentStatusColumn,
useAgentsTable,
agentHostnameColumn,
} from './tableUtils';
import { useAgentsTable } from './tableUtils';
import DefaultEmptyState from '../../../common/components/ui/uiState/EmptyState';
import { usePagination } from '../../../common/components/hosts/usePagination';
import { useFormikHelpers } from '../../../common/hooks/useFormikHelpers';
Expand Down
87 changes: 87 additions & 0 deletions libs/ui-lib/lib/cim/components/Agent/BMHEventsModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React from 'react';
import {
Modal,
ModalVariant,
ModalHeader,
ModalBody,
Content,
ContentVariants,
} from '@patternfly/react-core';
import { Table, Thead, Tr, Th, Tbody, Td, InnerScrollContainer } from '@patternfly/react-table';
import { getHumanizedDateTime, LoadingState, useTranslation } from '../../../common';
import { useEvents } from '../../hooks';

export const BMHEventsModal = ({
isOpen,
onClose,
namespace,
bmhName,
}: {
isOpen: boolean;
onClose: () => void;
namespace: string;
bmhName: string;
}) => {
const { t } = useTranslation();
const [events, loaded, error] = useEvents({
namespace: namespace,
isList: true,
fieldSelector: `involvedObject.name=${bmhName}`,
});

let modalBody: React.ReactNode;
if (!loaded) {
modalBody = <LoadingState />;
} else if (error) {
modalBody = <Content component={ContentVariants.p}>{error as string}</Content>;
Comment thread
jgyselov marked this conversation as resolved.
} else if (!events.length) {
modalBody = <Content component={ContentVariants.p}>{t('ai:No BMH events found.')}</Content>;
} else {
modalBody = (
<div style={{ height: '400px' }}>
<InnerScrollContainer>
<Table
variant="compact"
borders={false}
className="pf-v6-u-mb-sm"
gridBreakPoint=""
isStickyHeader
>
<Thead>
<Tr>
<Th width={25}>{t('ai:Time')}</Th>
<Th>{t('ai:Type')}</Th>
<Th>{t('ai:Message')}</Th>
</Tr>
</Thead>
<Tbody>
{events
.sort(
Comment thread
jgyselov marked this conversation as resolved.
(a, b) =>
b.metadata?.creationTimestamp?.localeCompare(
a.metadata?.creationTimestamp || '',
) || 0,
)
.map((e, i) => (
<Tr key={`bmc-event-${i}`}>
<Td className="pf-v6-u-font-weight-bold">
{getHumanizedDateTime(e.metadata?.creationTimestamp)}
</Td>
<Td>{e.type}</Td>
<Td>{e.message}</Td>
</Tr>
))}
Comment thread
jgyselov marked this conversation as resolved.
</Tbody>
</Table>
</InnerScrollContainer>
</div>
);
}

return (
<Modal isOpen={isOpen} onClose={onClose} variant={ModalVariant.medium}>
<ModalHeader title={t('ai:Bare metal host events')} />
<ModalBody>{modalBody}</ModalBody>
</Modal>
);
};
34 changes: 17 additions & 17 deletions libs/ui-lib/lib/cim/components/Agent/BMHStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
import { Button, Popover } from '@patternfly/react-core';
import * as React from 'react';
import { getBMHStatus } from '../helpers/status';
import { BareMetalHostK8sResource } from '../../types';
import { BMHStatusInfo } from './BMHStatusInfo';

type BMHStatusProps = {
bmhStatus: ReturnType<typeof getBMHStatus>;
bmh: BareMetalHostK8sResource;
};

const BMHStatus: React.FC<BMHStatusProps> = ({ bmhStatus }) =>
bmhStatus.errorMessage ? (
<Popover
headerContent="Error"
bodyContent={bmhStatus.errorMessage}
minWidth="30rem"
maxWidth="50rem"
hideOnOutsideClick
zIndex={300}
>
<Button variant="link" isInline>
{bmhStatus.state.title}
</Button>
</Popover>
) : (
<>{bmhStatus.state.title}</>
);
const BMHStatus: React.FC<BMHStatusProps> = ({ bmhStatus, bmh }) => (
<Popover
aria-label="Bare metal host status details"
bodyContent={<BMHStatusInfo bmhStatus={bmhStatus} bmh={bmh} />}
minWidth="30rem"
maxWidth="50rem"
hideOnOutsideClick
zIndex={300}
Comment thread
jgyselov marked this conversation as resolved.
>
<Button variant="link" isInline>
{bmhStatus.state.title}
</Button>
</Popover>
);
Comment thread
coderabbitai[bot] marked this conversation as resolved.

export default BMHStatus;
94 changes: 94 additions & 0 deletions libs/ui-lib/lib/cim/components/Agent/BMHStatusInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react';
import {
Level,
LevelItem,
Alert,
AlertVariant,
Content,
ContentVariants,
Button,
ButtonVariant,
} from '@patternfly/react-core';
import { CheckCircleIcon } from '@patternfly/react-icons/dist/js/icons/check-circle-icon';
import { PendingIcon } from '@patternfly/react-icons/dist/js/icons/pending-icon';
import { ExclamationTriangleIcon } from '@patternfly/react-icons/dist/js/icons/exclamation-triangle-icon';
import { t_global_color_status_success_default as okColor } from '@patternfly/react-tokens/dist/js/t_global_color_status_success_default';
import { t_global_icon_color_status_warning_default as warningColor } from '@patternfly/react-tokens/dist/js/t_global_icon_color_status_warning_default';

import { getHumanizedDateTime, useTranslation } from '../../../common';
import { BareMetalHostK8sResource } from '../../types';
import { getBMHStatus } from '../helpers';
import { BMHEventsModal } from './BMHEventsModal';

export const BMHStatusInfo = ({
bmhStatus,
bmh,
}: {
bmhStatus: ReturnType<typeof getBMHStatus>;
bmh: BareMetalHostK8sResource;
}) => {
const { t } = useTranslation();
const [isModalOpen, setModalOpen] = React.useState(false);

let alertVariant = AlertVariant.warning;
if (!!bmh.status?.errorMessage) {
alertVariant = AlertVariant.danger;
} else if (
bmh.status?.provisioning?.state === 'provisioned' ||
bmh.status?.provisioning?.state === 'externally provisioned'
) {
alertVariant = AlertVariant.success;
}

let icon: React.ReactNode;
switch (bmh.status?.operationalStatus) {
case 'OK':
case 'discovered':
icon = <CheckCircleIcon color={okColor.value} />;
break;
case 'error':
icon = <ExclamationTriangleIcon color={warningColor.value} />;
break;
default:
icon = <PendingIcon />;
break;
}

return (
<>
<Level>
<LevelItem className="pf-v6-u-font-weight-bold">{t('ai:Bare metal host')}</LevelItem>
<LevelItem>
{bmh.status?.operationalStatus} {icon}
</LevelItem>
</Level>
Comment thread
jgyselov marked this conversation as resolved.
<Alert title={bmhStatus.state.title} variant={alertVariant} isInline>
{!!bmh.status?.errorMessage && (
<Content component={ContentVariants.p}>{bmh.status?.errorMessage}</Content>
)}

<Level hasGutter>
<LevelItem>
<Button variant={ButtonVariant.link} isInline onClick={() => setModalOpen(true)}>
{t('ai:View BMH events')}
</Button>
</LevelItem>
<LevelItem>
<Content component={ContentVariants.small}>
{t('ai:Last updated:')} {getHumanizedDateTime(bmh.status?.lastUpdated)}
</Content>
</LevelItem>
</Level>
</Alert>

{isModalOpen && (
<BMHEventsModal
isOpen={isModalOpen}
onClose={() => setModalOpen(false)}
namespace={bmh.metadata?.namespace || ''}
bmhName={bmh.metadata?.name || ''}
/>
)}
Comment thread
jgyselov marked this conversation as resolved.
</>
);
};
2 changes: 2 additions & 0 deletions libs/ui-lib/lib/cim/components/Agent/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export { default as AgentTable } from './AgentTable';
export { default as BMCForm } from './BMCForm';
export * from './types';
export * from './tableColumns';
export * from './tableUtils';
Loading
Loading