Skip to content

Commit

Permalink
refactor(aws/titus): Refactor instance status section to react (#8497)
Browse files Browse the repository at this point in the history
* refactor(aws/titus): Refactor instance status section to react

* refactor(aws/titus): Integrate new component and abstract custom url
  • Loading branch information
caseyhebebrand committed Sep 2, 2020
1 parent 7bea174 commit f358e5e
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 85 deletions.
2 changes: 2 additions & 0 deletions app/scripts/modules/amazon/src/aws.module.ts
Expand Up @@ -69,6 +69,7 @@ import { AMAZON_INSTANCE_AWSINSTANCETYPE_SERVICE } from './instance/awsInstanceT
import { AMAZON_INSTANCE_DETAILS_INSTANCE_DETAILS_CONTROLLER } from './instance/details/instance.details.controller';
import { AMAZON_SEARCH_SEARCHRESULTFORMATTER } from './search/searchResultFormatter';
import { AWS_EVALUATE_CLOUD_FORMATION_CHANGE_SET_EXECUTION_SERVICE } from './pipeline/stages/deployCloudFormation/evaluateCloudFormationChangeSetExecution.service';
import { INSTANCE_STATUS_COMPONENT } from './instance/details/instanceStatus.component';

// load all templates into the $templateCache
const templates = require.context('./', true, /\.html$/);
Expand Down Expand Up @@ -108,6 +109,7 @@ module(AMAZON_MODULE, [
CLOUDFORMATION_TEMPLATE_ENTRY,
CLOUD_FORMATION_CHANGE_SET_INFO,
AWS_EVALUATE_CLOUD_FORMATION_CHANGE_SET_EXECUTION_SERVICE,
INSTANCE_STATUS_COMPONENT,
]).config(() => {
CloudProviderRegistry.registerProvider('aws', {
name: 'Amazon',
Expand Down
90 changes: 90 additions & 0 deletions app/scripts/modules/amazon/src/instance/details/InstanceStatus.tsx
@@ -0,0 +1,90 @@
import React from 'react';

import { CollapsibleSection, InstanceLoadBalancerHealth, robotToHuman, Tooltip } from '@spinnaker/core';
import { IAmazonHealth } from '../../domain';

export type MetricTypes = 'LoadBalancer' | 'TargetGroup';

export interface CustomHealthLink {
type: string;
href: string;
text: string;
}

export interface IInstanceStatusProps {
healthMetrics: IAmazonHealth[];
healthState: string;
metricTypes: MetricTypes[];
customHealthUrl?: CustomHealthLink;
privateIpAddress?: string;
}

export const InstanceStatus = ({
healthMetrics,
healthState,
metricTypes,
customHealthUrl,
privateIpAddress,
}: IInstanceStatusProps) => {
const hasLoadBalancer = metricTypes.includes('LoadBalancer');
const hasTargetGroup = metricTypes.includes('TargetGroup');

return (
<CollapsibleSection heading="Status" defaultExpanded={true}>
{!healthMetrics.length && (
<p>{healthState === 'Starting' ? 'Starting' : 'No health metrics found for this instance'}</p>
)}
<dl className="horizontal-when-filters-collapsed">
{healthMetrics
.sort((a: IAmazonHealth, b: IAmazonHealth) => (a.type < b.type ? -1 : a.type > b.type ? 1 : 0))
.map((metric: IAmazonHealth) => (
<>
<dt>{robotToHuman(metric.type)}</dt>
<dd>
{!metricTypes.includes(metric.type as MetricTypes) && (
<div>
<Tooltip value={metric.state.toLowerCase() === 'down' ? metric.description : ''} placement="left">
<span>
<span className={`glyphicon glyphicon-${metric.state}-triangle`} />
<span>{robotToHuman(metric.state)}</span>
</span>
</Tooltip>
<span className="pad-left small">
{metric.healthCheckUrl && (
<a target="_blank" href={metric.healthCheckUrl}>
Health Check
</a>
)}
{metric.healthCheckUrl && metric.statusPageUrl && <span> | </span>}
{metric.statusPageUrl && (
<a target="_blank" href={metric.statusPageUrl}>
Status
</a>
)}
{customHealthUrl && metric.type === customHealthUrl.type && (
<span>
{' '}
|{' '}
<a target="_blank" href={customHealthUrl.href}>
{customHealthUrl.text}
</a>
</span>
)}
</span>
</div>
)}
{hasLoadBalancer &&
metric.type === 'LoadBalancer' &&
(metric.loadBalancers || []).map(lb => <InstanceLoadBalancerHealth loadBalancer={lb} />)}
{hasTargetGroup &&
metric.type === 'TargetGroup' &&
(metric.targetGroups || []).map(tg => (
<InstanceLoadBalancerHealth loadBalancer={tg} ipAddress={privateIpAddress} />
))}
</dd>
</>
))}
</dl>
</CollapsibleSection>
);
};
Expand Up @@ -136,49 +136,13 @@ <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>
<dd ng-if="instance.imageId">{{instance.imageId}}</dd>
</dl>
</collapsible-section>
<collapsible-section heading="Status" expanded="true">
<p ng-if="instance.healthState !== 'Starting' && !healthMetrics.length">
No health metrics found for this instance
</p>
<p ng-if="instance.healthState === 'Starting' && !healthMetrics.length">
<span class="glyphicon glyphicon-Starting-triangle"></span> <strong>Starting</strong>
</p>

<dl class="horizontal-when-filters-collapsed">
<dt ng-repeat-start="metric in healthMetrics | orderBy: 'type'">{{metric.type | robotToHuman}}</dt>
<dd ng-repeat-end>
<div ng-if="metric.type !== 'LoadBalancer' && metric.type !== 'TargetGroup'">
<span
uib-tooltip="{{metric.state.toLowerCase() === 'down' ? metric.description : ''}}"
tooltip-placement="left"
>
<span class="glyphicon glyphicon-{{metric.state}}-triangle"></span>
{{metric.state | robotToHuman}}
</span>
<span class="pad-left small">
<a ng-if="metric.healthCheckUrl" target="_blank" href="{{metric.healthCheckUrl}}">Health Check</a>
<span ng-if="metric.healthCheckUrl && metric.statusPageUrl"> | </span>
<a ng-if="metric.statusPageUrl" target="_blank" href="{{metric.statusPageUrl}}">Status</a>
</span>
</div>
<div
ng-if="metric.type === 'LoadBalancer' && metric.loadBalancers.length"
ng-repeat="loadBalancer in metric.loadBalancers"
>
<instance-load-balancer-health load-balancer="loadBalancer"></instance-load-balancer-health>
</div>
<div
ng-if="metric.type === 'TargetGroup' && metric.targetGroups.length"
ng-repeat="targetGroup in metric.targetGroups"
>
<instance-load-balancer-health
load-balancer="targetGroup"
ip-address="instance.privateIpAddress"
></instance-load-balancer-health>
</div>
</dd>
</dl>
</collapsible-section>
<instance-status
health-metrics="healthMetrics"
health-state="instance.healthState"
metric-types="['LoadBalancer', 'TargetGroup']"
private-ip-address="instance.privateIpAddress"
>
</instance-status>
<collapsible-section heading="DNS">
<dl class="horizontal-when-filters-collapsed">
<dt ng-if="instance.privateDnsName">Private DNS Name</dt>
Expand Down
@@ -0,0 +1,11 @@
import { module } from 'angular';
import { react2angular } from 'react2angular';

import { InstanceStatus } from './InstanceStatus';

export const INSTANCE_STATUS_COMPONENT = 'spinnaker.application.instanceStatus.component';

module(INSTANCE_STATUS_COMPONENT, []).component(
'instanceStatus',
react2angular(InstanceStatus, ['healthMetrics', 'healthState', 'metricTypes', 'customHealthUrl', 'privateIpAddress']),
);
7 changes: 5 additions & 2 deletions app/scripts/modules/core/src/domain/IHealth.ts
@@ -1,7 +1,10 @@
export interface IHealth {
type: string;
state: string;
description: string;
healthCheckUrl?: string;
loadBalancers: ILoadBalancerHealth[];
state: string;
statusPageUrl?: string;
type: string;
}

export interface ILoadBalancerHealth {
Expand Down
1 change: 1 addition & 0 deletions app/scripts/modules/core/src/instance/index.ts
Expand Up @@ -2,4 +2,5 @@ export * from './InstanceReader';
export * from './details';
export * from './instance.write.service';
export * from './instanceType.service';
export * from './loadBalancer/InstanceLoadBalancerHealth';
export * from './templates';
Expand Up @@ -112,46 +112,14 @@ <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>
</dd>
</dl>
</collapsible-section>
<collapsible-section heading="Status" expanded="true">
<p ng-if="instance.healthState !== 'Starting' && !healthMetrics.length">
No health metrics found for this instance
</p>
<p ng-if="instance.healthState === 'Starting' && !healthMetrics.length">
<span class="glyphicon glyphicon-Starting-triangle"></span> <strong>Starting</strong>
</p>
<dl class="horizontal-when-filters-collapsed">
<dt ng-repeat-start="metric in healthMetrics | orderBy: 'type'">{{metric.type | robotToHuman}}</dt>
<dd ng-repeat-end>
<div ng-if="metric.type !== 'TargetGroup'">
<span
uib-tooltip="{{metric.state.toLowerCase() === 'down' ? metric.description : ''}}"
tooltip-placement="left"
>
<span class="glyphicon glyphicon-{{metric.state}}-triangle"></span>
{{metric.state | robotToHuman}}
</span>
<span class="pad-left small">
<a ng-if="metric.healthCheckUrl" target="_blank" href="{{metric.healthCheckUrl}}">Health Check</a>
<span ng-if="metric.healthCheckUrl && metric.statusPageUrl"> | </span>
<a ng-if="metric.statusPageUrl" target="_blank" href="{{metric.statusPageUrl}}">Status</a>
<span ng-if="metric.type === 'Discovery'">
|
<a target="_blank" href="{{ctrl.discoveryInfoLink}}">Discovery Info</a>
</span>
</span>
</div>
<div
ng-if="metric.type === 'TargetGroup' && metric.targetGroups.length"
ng-repeat="targetGroup in metric.targetGroups"
>
<instance-load-balancer-health
load-balancer="targetGroup"
ip-address="metric.instanceId"
></instance-load-balancer-health>
</div>
</dd>
</dl>
</collapsible-section>
<instance-status
health-metrics="healthMetrics"
health-state="instance.healthState"
metric-types="['TargetGroup']"
private-ip-address="instance.privateIpAddress"
custom-health-url="{ type: 'Discovery', href: 'instance.discoveryInfoLink', text: 'Discovery Info'}"
>
</instance-status>
<collapsible-section heading="DNS">
<dl class="dl-horizontal dl-flex">
<dt ng-if="instance.placement.containerIp">Container IP</dt>
Expand Down

0 comments on commit f358e5e

Please sign in to comment.