Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show tls automation status #999

Merged
merged 2 commits into from
Apr 10, 2024
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
64 changes: 55 additions & 9 deletions src/components/external-dns-list/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,33 @@ import {

import * as PropTypes from 'prop-types';
import { Icon, Table, Typography } from '@equinor/eds-core-react';
import { ExternalDns, Tls } from '../../store/radix-api';
import { ExternalDns, Tls, TlsAutomation } from '../../store/radix-api';
import { ExternalDNSStatusBadge } from '../status-badges';
import { check, chevron_down, chevron_up } from '@equinor/eds-icons';
import { chevron_down, chevron_up } from '@equinor/eds-icons';
import clsx from 'clsx';
import { TLSCertificateList } from '../tls-certificate-list';
import { dataSorter, sortCompareString } from '../../utils/sort-utils';
import { pluraliser } from '../../utils/string';
import { differenceInDays } from 'date-fns';
import { Alert, AlertProps } from '../alert';
import { TLSAutomationStatusBadge } from '../status-badges/tls-automation-status-badge';

const AlertTemplates = {
type TlsStatus = Tls['status'];

const StatusMessageAlertTemplate = {
Pending: { type: 'info' },
Consistent: { type: 'info' },
Invalid: { type: 'danger' },
} satisfies Record<Tls['status'], AlertProps>;
} satisfies Record<TlsStatus, AlertProps>;

type StatusMessagesProps = {
status: Tls['status'];
status: TlsStatus;
messages: Array<string>;
};

function StatusMessages({ status, messages }: StatusMessagesProps) {
return (
<Alert {...AlertTemplates[status]}>
<Alert {...StatusMessageAlertTemplate[status]}>
<div className="grid grid--gap-medium">
{messages.map((msg, i) => (
<Typography key={i}>{msg}</Typography>
Expand All @@ -41,6 +44,33 @@ function StatusMessages({ status, messages }: StatusMessagesProps) {
);
}

type AutomationStatus = TlsAutomation['status'] | 'Unknown';

const TlsAutomationMessageAlertTemplate = {
Pending: { type: 'warning' },
Success: { type: 'info' },
Failed: { type: 'danger' },
Unknown: { type: 'warning' },
} satisfies Record<AutomationStatus, AlertProps>;

type TlsAutomationMessageProps = {
status: AutomationStatus;
message: string;
};

function TlsAutomationStatusMessage({
status,
message,
}: TlsAutomationMessageProps) {
return (
<Alert {...TlsAutomationMessageAlertTemplate[status]}>
<div className="grid grid--gap-medium">
<Typography>{message}</Typography>
</div>
</Alert>
);
}

const dayPluraliser = pluraliser('day', 'days');

export const ExternalDNSList: FunctionComponent<{
Expand All @@ -67,7 +97,7 @@ export const ExternalDNSList: FunctionComponent<{
<Table.Cell width={40} />
<Table.Cell>Alias</Table.Cell>
<Table.Cell width={150}>Expires</Table.Cell>
<Table.Cell width={150}>Status</Table.Cell>
<Table.Cell width={150}>Certificate</Table.Cell>
<Table.Cell width={190} style={{ textAlign: 'center' }}>
Certificate Automation
</Table.Cell>
Expand All @@ -83,6 +113,7 @@ export const ExternalDNSList: FunctionComponent<{
? v.tls.certificates[0].notAfter
: null,
hasMessages: v.tls.statusMessages?.length > 0,
hasAutomationMessage: v.tls.automation?.message?.length > 0,
expanded: !!expandedRows[v.fqdn],
}))
.map(
Expand All @@ -91,6 +122,7 @@ export const ExternalDNSList: FunctionComponent<{
hasCertificates,
certificateExpiry,
hasMessages,
hasAutomationMessage,
expanded,
}) => (
<Fragment key={externalDns.fqdn}>
Expand All @@ -100,7 +132,9 @@ export const ExternalDNSList: FunctionComponent<{
})}
>
<Table.Cell className="fitwidth padding-right-0">
{(hasCertificates || hasMessages) && (
{(hasCertificates ||
hasMessages ||
hasAutomationMessage) && (
<Typography
link
as="span"
Expand Down Expand Up @@ -141,7 +175,11 @@ export const ExternalDNSList: FunctionComponent<{
<Table.Cell style={{ textAlign: 'center' }}>
{externalDns.tls.useAutomation && (
<Typography as="span" color="primary">
<Icon data={check} />
<TLSAutomationStatusBadge
status={
externalDns.tls.automation?.status || 'Unknown'
}
/>
</Typography>
)}
</Table.Cell>
Expand All @@ -154,6 +192,14 @@ export const ExternalDNSList: FunctionComponent<{
className="grid grid--gap-medium"
style={{ margin: '16px 0' }}
>
{hasAutomationMessage && (
<TlsAutomationStatusMessage
status={
externalDns.tls.automation?.status || 'Unknown'
}
message={externalDns.tls.automation?.message}
/>
)}
{hasMessages && (
<StatusMessages
status={externalDns.tls.status}
Expand Down
10 changes: 5 additions & 5 deletions src/components/status-badges/external-dns-status-badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@ type Status = Tls['status'];

const BadgeTemplates: Record<
Status,
Readonly<Pick<StatusBadgeTemplateProps, 'icon' | 'type'>>
Readonly<Pick<StatusBadgeTemplateProps, 'icon' | 'type'> & { text?: string }>
> = {
Pending: { type: 'warning', icon: <Icon data={time} /> },
Consistent: { icon: <Icon data={check} /> },
Pending: { type: 'warning', icon: <Icon data={time} />, text: 'Missing' },
Consistent: { icon: <Icon data={check} />, text: 'Valid' },
Invalid: { type: 'danger', icon: <Icon data={error_outlined} /> },
};

type Props = {
status: Status;
};
export function ExternalDNSStatusBadge({ status }: Props) {
const { type, icon } = BadgeTemplates[status];
const { type, icon, text } = BadgeTemplates[status];

return (
<StatusBadgeTemplate type={type} icon={icon}>
{status}
{text || status}
</StatusBadgeTemplate>
);
}
Expand Down
51 changes: 51 additions & 0 deletions src/components/status-badges/tls-automation-status-badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Icon } from '@equinor/eds-core-react';
import { check, error_outlined, time } from '@equinor/eds-icons';
import * as PropTypes from 'prop-types';

import {
StatusBadgeTemplate,
StatusBadgeTemplateProps,
} from './status-badge-template';

import { TlsAutomation } from '../../store/radix-api';

type Status = TlsAutomation['status'] | 'Unknown';

const BadgeTemplates: Record<
Status,
Readonly<Pick<StatusBadgeTemplateProps, 'icon' | 'type'> & { text?: string }>
> = {
Pending: {
type: 'warning',
icon: <Icon data={time} />,
text: 'Order In Progress',
},
Success: { icon: <Icon data={check} />, text: 'Order Successful' },
Failed: {
type: 'danger',
icon: <Icon data={error_outlined} />,
text: 'Order Failed',
},
Unknown: {
type: 'warning',
icon: <Icon data={time} />,
text: 'Order Status Unknown',
},
};

type Props = {
status: Status;
};
export function TLSAutomationStatusBadge({ status }: Props) {
const { type, icon, text } = BadgeTemplates[status];

return (
<StatusBadgeTemplate type={type} icon={icon}>
{text || status}
</StatusBadgeTemplate>
);
}

TLSAutomationStatusBadge.propTypes = {
status: PropTypes.string.isRequired as PropTypes.Validator<Status>,
};
10 changes: 10 additions & 0 deletions src/store/radix-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2134,6 +2134,15 @@ export type StopApplicationApiArg = {
/** Works only with custom setup of cluster. Allow impersonation of a comma-seperated list of test groups (Required if Impersonate-User is set) */
'Impersonate-Group'?: string;
};
export type TlsAutomation = {
/** Message is a human readable description of the reason for the status */
message?: string;
/** Status of certificate automation request
Pending TLSAutomationPending Certificate automation request pending
Success TLSAutomationSuccess Certificate automation request succeeded
Failed TLSAutomationFailed Certificate automation request failed */
status: 'Pending' | 'Success' | 'Failed';
};
export type X509Certificate = {
/** DNSNames defines list of Subject Alternate Names in the certificate */
dnsNames?: string[];
Expand All @@ -2147,6 +2156,7 @@ export type X509Certificate = {
subject: string;
};
export type Tls = {
automation?: TlsAutomation;
/** Certificates holds the X509 certificate chain
The first certificate in the list should be the host certificate and the rest should be intermediate certificates */
certificates?: X509Certificate[];
Expand Down