Skip to content

Commit

Permalink
refactor(titus): Adding load balancer incompatibility (#7386)
Browse files Browse the repository at this point in the history
  • Loading branch information
alanmquach authored Sep 12, 2019
1 parent a3f3695 commit 7d65ea9
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
import * as React from 'react';
import { Button, Modal } from 'react-bootstrap';

import { ILoadBalancerModalProps, ModalClose, ReactModal, noop } from '@spinnaker/core';
import {
ILoadBalancerIncompatibility,
ILoadBalancerModalProps,
ModalClose,
ReactModal,
noop,
CloudProviderRegistry,
} from '@spinnaker/core';

import { IAmazonLoadBalancerConfig, LoadBalancerTypes } from './LoadBalancerTypes';

export interface IAmazonLoadBalancerChoiceModalProps extends ILoadBalancerModalProps {
choices?: IAmazonLoadBalancerConfig[];
}

export interface IAmazonLoadBalancerChoiceModalState {
choices: IAmazonLoadBalancerConfig[];
selectedChoice: IAmazonLoadBalancerConfig;
}

export class AmazonLoadBalancerChoiceModal extends React.Component<
IAmazonLoadBalancerChoiceModalProps,
ILoadBalancerModalProps,
IAmazonLoadBalancerChoiceModalState
> {
public static defaultProps: Partial<IAmazonLoadBalancerChoiceModalProps> = {
public static defaultProps: Partial<ILoadBalancerModalProps> = {
closeModal: noop,
dismissModal: noop,
choices: LoadBalancerTypes,
};

public static show(props: IAmazonLoadBalancerChoiceModalProps): Promise<void> {
public static show(props: ILoadBalancerModalProps): Promise<void> {
return ReactModal.show(
AmazonLoadBalancerChoiceModal,
{
Expand All @@ -34,10 +37,11 @@ export class AmazonLoadBalancerChoiceModal extends React.Component<
);
}

constructor(props: IAmazonLoadBalancerChoiceModalProps) {
constructor(props: ILoadBalancerModalProps) {
super(props);
this.state = {
selectedChoice: props.choices[0],
choices: LoadBalancerTypes,
selectedChoice: LoadBalancerTypes[0],
};
}

Expand All @@ -60,9 +64,43 @@ export class AmazonLoadBalancerChoiceModal extends React.Component<
this.props.dismissModal(reason);
};

private getIncompatibility(choice: IAmazonLoadBalancerConfig, cloudProvider: string): ILoadBalancerIncompatibility {
const { loadBalancer } = CloudProviderRegistry.getProvider(cloudProvider);
const {
incompatibleLoadBalancerTypes = [],
}: { incompatibleLoadBalancerTypes: ILoadBalancerIncompatibility[] } = loadBalancer;

return incompatibleLoadBalancerTypes.find(lb => lb.type === choice.type);
}

private isIncompatibleWithAllProviders(choice: IAmazonLoadBalancerConfig) {
const {
app: { attributes },
} = this.props;
const { cloudProviders = [] }: { cloudProviders: string[] } = attributes;

if (cloudProviders.length > 0) {
return cloudProviders.every((cloudProvider: string) => !!this.getIncompatibility(choice, cloudProvider));
}

// If the list of cloud providers is empty, assume it is compatible by default
return true;
}

public render() {
const { choices } = this.props;
const { selectedChoice } = this.state;
const {
app: { attributes },
} = this.props;
const { cloudProviders = [] }: { cloudProviders: string[] } = attributes;
const { choices, selectedChoice } = this.state;

// Remove any choices that are not compatible with all configured cloud providers
const filteredChoices = choices.filter(choice => !this.isIncompatibleWithAllProviders(choice));

// Compute incompatibilities with the current selected choice so we can display a warning
const incompatibilities: ILoadBalancerIncompatibility[] = cloudProviders
.map(cloudProvider => this.getIncompatibility(selectedChoice, cloudProvider))
.filter((x: ILoadBalancerIncompatibility) => x);

return (
<>
Expand All @@ -73,7 +111,7 @@ export class AmazonLoadBalancerChoiceModal extends React.Component<
<Modal.Body>
<div className="modal-body">
<div className="card-choices">
{choices.map(choice => (
{filteredChoices.map(choice => (
<div
key={choice.type}
className={`card ${selectedChoice === choice ? 'active' : ''}`}
Expand All @@ -85,6 +123,16 @@ export class AmazonLoadBalancerChoiceModal extends React.Component<
</div>
))}
</div>
<>
{incompatibilities.length > 0 &&
incompatibilities.map(incompatibility => (
<div className="alert alert-warning">
<p>
<i className="fa fa-exclamation-triangle" /> {incompatibility.reason}
</p>
</div>
))}
</>
<div className="load-balancer-description" />
</div>
</Modal.Body>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface ILoadBalancerIncompatibility {
type: string;
reason: string;
}
1 change: 1 addition & 0 deletions app/scripts/modules/core/src/domain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export * from './IJenkinsInfo';
export * from '../widgets/Keys';

export * from './ILoadBalancer';
export * from './ILoadBalancerIncompatibility';

export * from './IManifest';

Expand Down

This file was deleted.

19 changes: 11 additions & 8 deletions app/scripts/modules/titus/src/titus.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { module } from 'angular';

import { CloudProviderRegistry, DeploymentStrategyRegistry } from '@spinnaker/core';
import { AmazonLoadBalancersTag } from '@spinnaker/amazon';

import { TITUS_MIGRATION_CONFIG_COMPONENT } from './migration/titusMigrationConfig.component';
import { TITUS_SERVERGROUP_DETAILS_CAPACITYDETAILSSECTION } from './serverGroup/details/capacityDetailsSection.component';
Expand All @@ -12,8 +13,6 @@ import './pipeline/stages/runJob/titusRunJobStage';
import { TitusCloneServerGroupModal } from './serverGroup/configure/wizard/TitusCloneServerGroupModal';

import './logo/titus.logo.less';
import { defaultsDeep } from 'lodash';
import { TitusLoadBalancerChoiceModal } from './loadBalancers/TitusLoadBalancerChoiceModal';

// load all templates into the $templateCache
const templates = require.context('./', true, /\.html$/);
Expand Down Expand Up @@ -61,12 +60,16 @@ module(TITUS_MODULE, [
reader: 'titusSecurityGroupReader',
useProvider: 'aws',
},
loadBalancer: defaultsDeep(
{
CreateLoadBalancerModal: TitusLoadBalancerChoiceModal,
},
CloudProviderRegistry.getProvider('aws').loadBalancer,
),
loadBalancer: {
LoadBalancersTag: AmazonLoadBalancersTag,
incompatibleLoadBalancerTypes: [
{
type: 'classic',
reason: 'Classic Load Balancers cannot be used with Titus as they do not have IP based target groups.',
},
],
useProvider: 'aws',
},
instance: {
detailsTemplateUrl: require('./instance/details/instanceDetails.html'),
detailsController: 'titusInstanceDetailsCtrl',
Expand Down

0 comments on commit 7d65ea9

Please sign in to comment.