Skip to content

Commit

Permalink
feat(ecs): migrate networking server group wizard to react
Browse files Browse the repository at this point in the history
  • Loading branch information
piradeepk authored and mergify[bot] committed Nov 3, 2020
1 parent ade00f7 commit 5283f9f
Show file tree
Hide file tree
Showing 7 changed files with 257 additions and 155 deletions.
4 changes: 2 additions & 2 deletions app/scripts/modules/ecs/src/ecs.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { module } from 'angular';
import { CloudProviderRegistry, DeploymentStrategyRegistry } from '@spinnaker/core';

import { ECS_SERVER_GROUP_TRANSFORMER } from './serverGroup/serverGroup.transformer';
import { ECS_NETWORKING_SECTION } from './serverGroup/configure/wizard/networking/networkingSelector.component';
import { SERVER_GROUP_DETAILS_MODULE } from './serverGroup/details/serverGroupDetails.module';
import { IAM_ROLE_READ_SERVICE } from './iamRoles/iamRole.read.service';
import { ECS_CLUSTER_READ_SERVICE } from './ecsCluster/ecsCluster.read.service';
Expand All @@ -17,6 +16,7 @@ import { COMMON_MODULE } from './common/common.module';
import { ECS_SERVERGROUP_MODULE } from './serverGroup/serverGroup.module';
import { ECS_SERVER_GROUP_LOGGING } from './serverGroup/configure/wizard/logging/logging.component';
import { CONTAINER_REACT } from './serverGroup/configure/wizard/container/Container';
import { NETWORKING_REACT } from './serverGroup/configure/wizard/networking/Networking';
import { SERVICE_DISCOVERY_REACT } from './serverGroup/configure/wizard/serviceDiscovery/ServiceDiscovery';
import { TASK_DEFINITION_REACT } from './serverGroup/configure/wizard/taskDefinition/TaskDefinition';
import { ECS_SECURITY_GROUP_MODULE } from './securityGroup/securityGroup.module';
Expand Down Expand Up @@ -64,9 +64,9 @@ module(ECS_MODULE, [
ECS_SERVERGROUP_CONFIGURE_WIZARD_HORIZONTALSCALING_HORIZONTALSCALING_COMPONENT,
TASK_DEFINITION_REACT,
CONTAINER_REACT,
NETWORKING_REACT,
SERVICE_DISCOVERY_REACT,
ECS_SERVER_GROUP_LOGGING,
ECS_NETWORKING_SECTION,
ECS_CLUSTER_READ_SERVICE,
ECS_SECRET_READ_SERVICE,
METRIC_ALARM_READ_SERVICE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ export interface IEcsServerGroupCommandBackingData extends IServerGroupCommandBa
iamRoles: IRoleDescriptor[];
metricAlarms: IMetricAlarmDescriptor[];
launchTypes: string[];
// subnetTypes: string;
// securityGroups: string[]
networkModes: string[];
secrets: ISecretDescriptor[];
serviceDiscoveryRegistries: IServiceDiscoveryRegistryDescriptor[];
images: IEcsDockerImage[];
Expand Down Expand Up @@ -115,6 +114,7 @@ export interface IEcsServiceDiscoveryRegistryAssociation {
}

export interface IEcsServerGroupCommand extends IServerGroupCommand {
associatePublicIpAddress: boolean;
backingData: IEcsServerGroupCommandBackingData;
computeUnits: number;
reservedMemory: number;
Expand All @@ -124,6 +124,9 @@ export interface IEcsServerGroupCommand extends IServerGroupCommand {
placementStrategyName: string;
placementStrategySequence: IPlacementStrategy[];
imageDescription: IEcsDockerImage;
networkMode: string;
subnetType: string;
securityGroups: string[];
viewState: IEcsServerGroupCommandViewState;
taskDefinitionArtifact: IEcsTaskDefinitionArtifact;
taskDefinitionArtifactAccount: string;
Expand All @@ -135,7 +138,6 @@ export interface IEcsServerGroupCommand extends IServerGroupCommand {

subnetTypeChanged: (command: IEcsServerGroupCommand) => IServerGroupCommandResult;
placementStrategyNameChanged: (command: IEcsServerGroupCommand) => IServerGroupCommandResult;
// subnetTypeChanged: (command: IEcsServerGroupCommand) => IServerGroupCommandResult;
regionIsDeprecated: (command: IEcsServerGroupCommand) => boolean;

clusterChanged: (command: IServerGroupCommand) => void;
Expand All @@ -146,6 +148,7 @@ export class EcsServerGroupConfigurationService {
// private healthCheckTypes = ['EC2', 'ELB'];
// private terminationPolicies = ['OldestInstance', 'NewestInstance', 'OldestLaunchConfiguration', 'ClosestToNextInstanceHour', 'Default'];
private launchTypes = ['EC2', 'FARGATE'];
private networkModes = ['bridge', 'host', 'awsvpc', 'none', 'default'];

public static $inject = [
'$q',
Expand Down Expand Up @@ -174,6 +177,7 @@ export class EcsServerGroupConfigurationService {
command.backingData = {
// terminationPolicies: clone(this.terminationPolicies)
launchTypes: clone(this.launchTypes),
networkModes: clone(this.networkModes),
} as IEcsServerGroupCommandBackingData;
}

Expand Down Expand Up @@ -240,6 +244,7 @@ export class EcsServerGroupConfigurationService {
metricAlarms: this.metricAlarmReader.listMetricAlarms(),
securityGroups: this.securityGroupReader.getAllSecurityGroups(),
launchTypes: this.$q.when(clone(this.launchTypes)),
networkModes: this.$q.when(clone(this.networkModes)),
secrets: this.secretReader.listSecrets(),
serviceDiscoveryRegistries: ServiceDiscoveryReader.listServiceDiscoveryRegistries(),
images: imagesPromise,
Expand Down Expand Up @@ -360,7 +365,10 @@ export class EcsServerGroupConfigurationService {
.compact()
.uniqBy('purpose')
.map('purpose')
.value();
.value()
.filter(function(e: string) {
return e && e.length > 0;
});
}

public configureAvailableEcsClusters(command: IEcsServerGroupCommand): void {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
import * as React from 'react';
import { module } from 'angular';
import { react2angular } from 'react2angular';
import { IEcsServerGroupCommand } from '../../serverGroupConfiguration.service';
import { HelpField, TetheredSelect, withErrorBoundary } from '@spinnaker/core';
import { Alert } from 'react-bootstrap';
import { Option } from 'react-select';

export interface INetworkingProps {
command: IEcsServerGroupCommand;
notifyAngular: (key: string, value: any) => void;
configureCommand: (query: string) => PromiseLike<void>;
}

interface INetworkingState {
associatePublicIpAddress: boolean;
networkMode: string;
networkModesAvailable: string[];
securityGroups: string[];
securityGroupsAvailable: string[];
subnetType: string;
subnetTypesAvailable: string[];
}

export class Networking extends React.Component<INetworkingProps, INetworkingState> {
constructor(props: INetworkingProps) {
super(props);
const cmd = this.props.command;

this.state = {
associatePublicIpAddress: cmd.associatePublicIpAddress,
networkMode: cmd.networkMode,
networkModesAvailable: cmd.backingData && cmd.backingData.networkModes ? cmd.backingData.networkModes : [],
securityGroups: cmd.securityGroups,
securityGroupsAvailable:
cmd.backingData && cmd.backingData.filtered && cmd.backingData.filtered.securityGroupNames
? cmd.backingData.filtered.securityGroupNames
: [],
subnetType: cmd.subnetType,
subnetTypesAvailable:
cmd.backingData && cmd.backingData.filtered && cmd.backingData.filtered.subnetTypes
? cmd.backingData.filtered.subnetTypes
: [],
};
}

public componentDidMount() {
const cmd = this.props.command;

this.props.configureCommand('1').then(() => {
this.setState({
networkModesAvailable: cmd.backingData && cmd.backingData.networkModes ? cmd.backingData.networkModes : [],
securityGroupsAvailable:
cmd.backingData && cmd.backingData.filtered && cmd.backingData.filtered.securityGroupNames
? cmd.backingData.filtered.securityGroupNames
: [],
subnetTypesAvailable:
cmd.backingData && cmd.backingData.filtered && cmd.backingData.filtered.subnetTypes
? cmd.backingData.filtered.subnetTypes
: [],
});
});
}

private updateNetworkMode = (newNetworkMode: Option<string>) => {
const updatedNetworkMode = newNetworkMode.value;
this.props.notifyAngular('networkMode', updatedNetworkMode);
this.setState({ networkMode: updatedNetworkMode });
};

private updateSecurityGroups = (newSecurityGroups: Option<string>) => {
const updatedSecurityGroups = Array.isArray(newSecurityGroups)
? newSecurityGroups.map(securityGroups => securityGroups.value)
: [];
this.props.notifyAngular('securityGroups', updatedSecurityGroups);
this.setState({ securityGroups: updatedSecurityGroups });
};

private updateSubnetType = (newSubnetType: Option<string>) => {
const updatedSubnetType = newSubnetType.value;
this.props.notifyAngular('subnetType', updatedSubnetType);
this.setState({ subnetType: updatedSubnetType });
};

private updateAssociatePublicIpAddress = (usePublicIp: boolean) => {
this.props.notifyAngular('associatePublicIpAddress', usePublicIp);
this.setState({ associatePublicIpAddress: usePublicIp });
};

public render(): React.ReactElement<Networking> {
const updateAssociatePublicIpAddress = this.updateAssociatePublicIpAddress;
const updateNetworkMode = this.updateNetworkMode;
const updateSecurityGroups = this.updateSecurityGroups;
const updateSubnetType = this.updateSubnetType;

const networkModesAvailable = this.state.networkModesAvailable.map(function(networkMode) {
return { label: `${networkMode}`, value: networkMode };
});

const securityGroupsAvailable = this.state.securityGroupsAvailable.map(function(securityGroup) {
return { label: `${securityGroup}`, value: securityGroup };
});

const subnetTypesAvailable = this.state.subnetTypesAvailable.map(function(subnetType) {
return { label: `${subnetType}`, value: subnetType };
});

const subnetTypeOptions = this.state.subnetTypesAvailable.length ? (
<TetheredSelect
options={subnetTypesAvailable}
value={this.state.subnetType}
onChange={(e: Option) => {
updateSubnetType(e as Option<string>);
}}
/>
) : (
<Alert color="warning">No account was selected, or no subnet types are available for this account</Alert>
);

const securityGroupsOptions = this.state.securityGroupsAvailable.length ? (
<TetheredSelect
multi={true}
options={securityGroupsAvailable}
value={this.state.securityGroups}
onChange={(e: Option) => {
updateSecurityGroups(e as Option<string>);
}}
/>
) : (
<Alert color="warning">No security groups found in the selected account/region</Alert>
);

const awsVpcOptions =
this.state.networkMode === 'awsvpc' ? (
<div className="form-group">
<div className="form-group">
<div className="col-md-3 sm-label-right">
<b>VPC Subnet</b>
<HelpField key="ecs.subnet" />
</div>
<div className="col-md-9" data-test-id="Networking.subnetType">
{subnetTypeOptions}
</div>
</div>

<div className="form-group">
<div className="col-md-3 sm-label-right">
<b>Security Groups</b>
<HelpField key="ecs.securityGroups" />
</div>
<div className="col-md-9" data-test-id="Networking.securityGroups">
{securityGroupsOptions}
</div>
</div>

<div className="form-group">
<div className="col-md-3 sm-label-right">
<b>Associate Public IP Address</b>
<HelpField key="ecs.publicip" />
</div>
<div className="col-md-1 radio">
<label>
<input
data-test-id="Networking.associatePublicIpAddressTrue"
type="radio"
value="true"
id="associatePublicIpAddressTrue"
checked={this.state.associatePublicIpAddress === true}
onChange={() => updateAssociatePublicIpAddress(true)}
/>
Yes
</label>
</div>
<div className="col-md-1 radio">
<label>
<input
data-test-id="Networking.associatePublicIpAddressFalse"
type="radio"
value="false"
id="associatePublicIpAddressFalse"
checked={this.state.associatePublicIpAddress === false}
onChange={() => updateAssociatePublicIpAddress(false)}
/>
No
</label>
</div>
</div>
</div>
) : (
<div className="col-md-3 sm-label-right"></div>
);

return (
<div className="networking-fluid form-horizontal">
<div className="form-group">
<div className="form-group">
<div className="col-md-3 sm-label-right">
<b>Network Mode</b>
<HelpField id="ecs.networkMode" />
</div>
<div className="col-md-9" data-test-id="Networking.networkMode">
<TetheredSelect
placeholder="Select a network mode to use ..."
options={networkModesAvailable}
value={this.state.networkMode}
onChange={(e: Option) => {
updateNetworkMode(e as Option<string>);
}}
/>
</div>
</div>
</div>
{awsVpcOptions}
</div>
);
}
}

export const NETWORKING_REACT = 'spinnaker.ecs.serverGroup.configure.wizard.networking.react';
module(NETWORKING_REACT, []).component(
'networkingReact',
react2angular(withErrorBoundary(Networking, 'networkingReact'), ['command', 'notifyAngular', 'configureCommand']),
);
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<div>
<ecs-server-group-load-balancer-selector command="command"></ecs-server-group-load-balancer-selector>
<div class="clearfix">
<div class="col-md-12">
<networking-react
command="command"
notify-angular="notifyAngular"
configure-command="configureCommand"
></networking-react>
</div>
</div>
Loading

0 comments on commit 5283f9f

Please sign in to comment.