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
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from 'react';
import * as classNames from 'classnames';
import { LoadingInline } from '@console/internal/components/utils/status-box';

const DetailItem: React.FC<DetailItemProps> = React.memo(
({ title, isLoading = false, children, error = false }) => {
export const DetailItem: React.FC<DetailItemProps> = React.memo(
({ title, isLoading = false, children, error = false, valueClassName }) => {
let status: React.ReactNode;
if (error) {
status = <span className="text-secondary">Not available</span>;
Expand All @@ -14,7 +15,7 @@ const DetailItem: React.FC<DetailItemProps> = React.memo(
return (
<>
<dt className="co-details-card__item-title">{title}</dt>
<dd className="co-details-card__item-value">{status}</dd>
<dd className={classNames('co-details-card__item-value', valueClassName)}>{status}</dd>
</>
);
},
Expand All @@ -24,7 +25,8 @@ export default DetailItem;

type DetailItemProps = {
title: string;
children: React.ReactNode;
isLoading?: boolean;
error?: boolean;
children: React.ReactNode;
valueClassName?: string;
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as _ from 'lodash';
import { K8sResourceKind } from '@console/internal/module/k8s';

export const getInfrastructurePlatform = (infrastructure: K8sResourceKind): string =>
_.get(infrastructure, 'status.platform');
infrastructure && infrastructure.status ? infrastructure.status.platform : undefined;
export const getInfrastructureAPIURL = (infrastructure: K8sResourceKind): string =>
infrastructure && infrastructure.status ? infrastructure.status.apiServerURL : undefined;
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const VMDetailsCard: React.FC<VMDetailsCardProps> = () => {
</DashboardCardHeader>
<DashboardCardBody isLoading={false}>
<DetailsBody>
<DetailItem title="Name" error={false} isLoading={!vm}>
<DetailItem title="Name" error={false} isLoading={!vm} valueClassName="co-select-to-copy">
{name}
</DetailItem>
<DetailItem title="Namespace" error={false} isLoading={!vm}>
Expand All @@ -64,7 +64,12 @@ export const VMDetailsCard: React.FC<VMDetailsCardProps> = () => {
>
{launcherPod && <NodeLink name={getNodeName(launcherPod)} />}
</DetailItem>
<DetailItem title="IP Address" error={!ipAddrs} isLoading={!vm}>
<DetailItem
title="IP Address"
error={!ipAddrs}
isLoading={!vm}
valueClassName="co-select-to-copy"
>
{ipAddrs}
</DetailItem>
</DetailsBody>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import * as React from 'react';
import * as _ from 'lodash-es';
import { connect } from 'react-redux';
import { getInfrastructurePlatform } from '@console/shared';
import { Button } from '@patternfly/react-core';
import { ArrowCircleUpIcon, InProgressIcon } from '@patternfly/react-icons';
import { getInfrastructureAPIURL, getInfrastructurePlatform } from '@console/shared';
import DashboardCard from '@console/shared/src/components/dashboard/dashboard-card/DashboardCard';
import DashboardCardBody from '@console/shared/src/components/dashboard/dashboard-card/DashboardCardBody';
import DashboardCardHeader from '@console/shared/src/components/dashboard/dashboard-card/DashboardCardHeader';
import DashboardCardTitle from '@console/shared/src/components/dashboard/dashboard-card/DashboardCardTitle';
import DetailsBody from '@console/shared/src/components/dashboard/details-card/DetailsBody';
import DetailItem from '@console/shared/src/components/dashboard/details-card/DetailItem';
import DashboardCardLink from '@console/shared/src/components/dashboard/dashboard-card/DashboardCardLink';
import { DashboardItemProps, withDashboardResources } from '../../with-dashboard-resources';
import { InfrastructureModel, ClusterVersionModel } from '../../../../models';
import {
Expand All @@ -17,11 +20,63 @@ import {
getK8sGitVersion,
ClusterVersionKind,
getClusterID,
getDesiredClusterVersion,
getLastCompletedUpdate,
getClusterUpdateStatus,
getClusterVersionChannel,
ClusterUpdateStatus,
getOCMLink,
} from '../../../../module/k8s';
import { FLAGS } from '../../../../const';
import { flagPending, featureReducerName } from '../../../../reducers/features';
import { FirehoseResource } from '../../../utils';
import { FirehoseResource, ExternalLink } from '../../../utils';
import { RootState } from '../../../../redux';
import { clusterUpdateModal } from '../../../modals';
import { Link } from 'react-router-dom';

const ClusterVersion: React.FC<ClusterVersionProps> = ({ cv }) => {
const desiredVersion = getDesiredClusterVersion(cv);
const lastVersion = getLastCompletedUpdate(cv);
const status = getClusterUpdateStatus(cv);

switch (status) {
case ClusterUpdateStatus.Updating:
return (
<>
<span className="co-select-to-copy">{desiredVersion}</span>
<div>
<Link to="/settings/cluster/">
<InProgressIcon className="co-icon-and-text__icon" />
Updating
</Link>
</div>
</>
);
case ClusterUpdateStatus.UpdatesAvailable:
return (
<>
<span className="co-select-to-copy">{desiredVersion}</span>
<div>
<Button
variant="link"
className="btn-link--no-btn-default-values"
onClick={() => clusterUpdateModal({ cv })}
icon={<ArrowCircleUpIcon />}
isInline
>
Update
</Button>
</div>
</>
);
default:
return lastVersion ? (
<span className="co-select-to-copy">{lastVersion}</span>
) : (
<span className="text-secondary">Not available</span>
);
}
};

const clusterVersionResource: FirehoseResource = {
kind: referenceForModel(ClusterVersionModel),
Expand Down Expand Up @@ -76,11 +131,13 @@ export const DetailsCard_ = connect(mapStateToProps)(
const clusterVersionData = _.get(resources.cv, 'data') as ClusterVersionKind;
const clusterId = getClusterID(clusterVersionData);
const openShiftVersion = getOpenShiftVersion(clusterVersionData);
const cvChannel = getClusterVersionChannel(clusterVersionData);

const infrastructureLoaded = _.get(resources.infrastructure, 'loaded', false);
const infrastructureError = _.get(resources.infrastructure, 'loadError');
const infrastructureData = _.get(resources.infrastructure, 'data') as K8sResourceKind;
const infrastructurePlatform = getInfrastructurePlatform(infrastructureData);
const infrastuctureApiUrl = getInfrastructureAPIURL(infrastructureData);

const kubernetesVersionData = urlResults.getIn(['version', 'data']);
const kubernetesVersionError = urlResults.getIn(['version', 'loadError']);
Expand All @@ -90,34 +147,50 @@ export const DetailsCard_ = connect(mapStateToProps)(
<DashboardCard>
<DashboardCardHeader>
<DashboardCardTitle>Details</DashboardCardTitle>
<DashboardCardLink to="/settings/cluster/">View settings</DashboardCardLink>
</DashboardCardHeader>
<DashboardCardBody isLoading={flagPending(openshiftFlag)}>
<DetailsBody>
{openshiftFlag ? (
<>
<DetailItem
key="clusterid"
title="Cluster API address"
isLoading={!infrastructureLoaded && !infrastructureError}
error={!!infrastructureError || !infrastuctureApiUrl}
valueClassName="co-select-to-copy"
>
{infrastuctureApiUrl}
</DetailItem>
<DetailItem
title="Cluster ID"
error={!!clusterVersionError || (clusterVersionLoaded && !clusterId)}
isLoading={!clusterVersionLoaded}
>
{clusterId}
<div className="co-select-to-copy">{clusterId}</div>
<ExternalLink text="OpenShift Cluster Manager" href={getOCMLink(clusterId)} />
</DetailItem>
<DetailItem
key="provider"
title="Provider"
error={!!infrastructureError || (infrastructureLoaded && !infrastructurePlatform)}
isLoading={!infrastructureLoaded}
valueClassName="co-select-to-copy"
>
{infrastructurePlatform}
</DetailItem>
<DetailItem
key="openshift"
title="OpenShift version"
error={!!clusterVersionError || (clusterVersionLoaded && !openShiftVersion)}
isLoading={!clusterVersionLoaded}
>
{openShiftVersion}
<ClusterVersion cv={clusterVersionData} />
</DetailItem>
<DetailItem
title="Update channel"
isLoading={!clusterVersionLoaded && !clusterVersionError}
error={!!clusterVersionError || !cvChannel}
valueClassName="co-select-to-copy"
>
{cvChannel}
</DetailItem>
</>
) : (
Expand All @@ -126,6 +199,7 @@ export const DetailsCard_ = connect(mapStateToProps)(
title="Kubernetes version"
error={!!kubernetesVersionError || (kubernetesVersionData && !k8sGitVersion)}
isLoading={!kubernetesVersionData}
valueClassName="co-select-to-copy"
>
{k8sGitVersion}
</DetailItem>
Expand All @@ -142,3 +216,7 @@ export const DetailsCard = withDashboardResources(DetailsCard_);
type DetailsCardProps = DashboardItemProps & {
openshiftFlag: boolean;
};

type ClusterVersionProps = {
cv: ClusterVersionKind;
};
3 changes: 3 additions & 0 deletions frontend/public/module/k8s/cluster-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export const getDesiredClusterVersion = (cv: ClusterVersionKind): string => {
return _.get(cv, 'status.desired.version');
};

export const getClusterVersionChannel = (cv: ClusterVersionKind): string =>
cv && cv.spec ? cv.spec.channel : undefined;

export const getLastCompletedUpdate = (cv: ClusterVersionKind): string => {
const history: UpdateHistory[] = _.get(cv, 'status.history', []);
const lastCompleted: UpdateHistory = history.find((update) => update.state === 'Completed');
Expand Down