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

feat(deploy/blockDevices): Adds a Volume section in the Deploy wizard #8911

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
b9107e4
feat(deploy/blockDevices): Add a Volume section in the Deploy Wizzard…
jorgebee65 Feb 11, 2021
d566588
Merge branch 'master' of https://github.com/spinnaker/deck into block…
jorgebee65 Feb 11, 2021
9c209f6
feat(blockDevice/tags): add other volumeTypes
jorgebee65 Mar 2, 2021
bfce1d8
Merge branch 'master' into blockDeviceTags
jorgebee65 Mar 9, 2021
74f92ce
Merge branch 'master' into blockDeviceTags
jorgebee65 Mar 15, 2021
aedb62c
feat(blockDevice/tags): rename attribute to blockDeviceTags
jorgebee65 Mar 16, 2021
e111619
feat(blockDevice/tags): fix imports in AmazonCloneServerGroupModal.tsx
jorgebee65 Mar 16, 2021
f93f476
feat(blockDevice/tags): fix imports in AmazonCloneServerGroupModal.tsx
jorgebee65 Mar 16, 2021
8e47e4b
Merge branch 'master' into blockDeviceTags
jorgebee65 Mar 19, 2021
8527537
Merge branch 'master' into blockDeviceTags
jorgebee65 Mar 29, 2021
e8239c9
Merge branch 'master' into blockDeviceTags
rvazquezglez Mar 29, 2021
fa4b76e
Merge branch 'master' into blockDeviceTags
jorgebee65 Apr 6, 2021
63c2fe9
Merge branch 'master' into blockDeviceTags
zachsmith1 May 25, 2021
c68a2ee
Merge branch 'master' into blockDeviceTags
jorgebee65 Jun 1, 2021
232664f
Merge branch 'master' into blockDeviceTags
jorgebee65 Jun 1, 2021
7cecd63
Merge branch 'master' into blockDeviceTags
jorgebee65 Jun 1, 2021
709ccb5
Update app/scripts/modules/amazon/src/serverGroup/configure/serverGro…
jorgebee65 Jun 1, 2021
e6944aa
Merge branch 'master' into blockDeviceTags
zachsmith1 Jun 14, 2021
5d3b65b
Merge branch 'master' into blockDeviceTags
zachsmith1 Jun 21, 2021
2f05a95
refactor(amazon/volumes): Refactoring the code implementing FormikFor…
jorgebee65 Jul 13, 2021
b1d5ca3
refactor(amazon/volumes): Make some fields required and other optiona…
jorgebee65 Jul 13, 2021
41d5cc3
Merge branch 'master' into blockDeviceTags
jorgebee65 Jul 13, 2021
af52e1f
Merge branch 'master' into blockDeviceTags
jorgebee65 Jul 19, 2021
89ee718
Merge branch 'master' into blockDeviceTags
jorgebee65 Jul 21, 2021
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
1 change: 1 addition & 0 deletions app/scripts/modules/amazon/src/help/amazon.help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const helpContents: { [key: string]: string } = {
'aws.serverGroup.instanceMonitoring':
'(Optional) <b>Instance Monitoring</b> whether to enable detailed monitoring of instances. Group metrics must be disabled to update an ASG with Instance Monitoring set to false.',
'aws.serverGroup.tags': '(Optional) <b>Tags</b> are propagated to the instances in this cluster.',
'aws.serverGroup.blockDevice.tags': '(Optional) <b>Tags</b> apply to all the volumes in specified above.',
'aws.serverGroup.allImages': 'Search for an image that does not match the name of your application.',
'aws.serverGroup.filterImages': 'Select from a pre-filtered list of images matching the name of your application.',
'aws.serverGroup.spotPrice': 'The maximum price to pay per hour per instance',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ export interface IAmazonServerGroupCommandViewState extends IServerGroupCommandV
spelLoadBalancers: string[];
}

export interface IServerGroupCommandBlockDevice {
deleteOnTermination: boolean;
deviceName: string;
size: number;
volumeType: string;
virtualName: string;
iops: number;
snapshotId: string;
encrypted: boolean;
}

export interface IAmazonServerGroupCommand extends IServerGroupCommand {
associateIPv6Address?: boolean;
associatePublicIpAddress: boolean;
Expand All @@ -101,6 +112,8 @@ export interface IAmazonServerGroupCommand extends IServerGroupCommand {
setLaunchTemplate?: boolean;
unlimitedCpuCredits?: boolean;
viewState: IAmazonServerGroupCommandViewState;
blockDevices: IServerGroupCommandBlockDevice[];
blockDeviceTags: string[];

getBlockDeviceMappingsSource: (command: IServerGroupCommand) => IBlockDeviceMappingSource;
selectBlockDeviceMappingsSource: (command: IServerGroupCommand, selection: string) => void;
Expand All @@ -120,6 +133,7 @@ export class AwsServerGroupConfigurationService {
'GroupTotalInstances',
];
private healthCheckTypes = ['EC2', 'ELB'];
private volumeTypes = ['gp2', 'st1', 'io1', 'sc1'];
jorgebee65 marked this conversation as resolved.
Show resolved Hide resolved
private terminationPolicies = [
'OldestInstance',
'NewestInstance',
Expand Down Expand Up @@ -147,6 +161,7 @@ export class AwsServerGroupConfigurationService {
command.backingData = {
enabledMetrics: clone(this.enabledMetrics),
healthCheckTypes: clone(this.healthCheckTypes),
volumeTypes: clone(this.volumeTypes),
terminationPolicies: clone(this.terminationPolicies),
} as IAmazonServerGroupCommandBackingData;
}
Expand Down Expand Up @@ -220,6 +235,7 @@ export class AwsServerGroupConfigurationService {
this.awsInstanceTypeService.getAllTypesByRegion(),
$q.when(clone(this.enabledMetrics)),
$q.when(clone(this.healthCheckTypes)),
$q.when(clone(this.volumeTypes)),
$q.when(clone(this.terminationPolicies)),
])
.then(
Expand All @@ -232,6 +248,7 @@ export class AwsServerGroupConfigurationService {
instanceTypes,
enabledMetrics,
healthCheckTypes,
volumeTypes,
terminationPolicies,
]) => {
const backingData: Partial<IAmazonServerGroupCommandBackingData> = {
Expand All @@ -243,6 +260,7 @@ export class AwsServerGroupConfigurationService {
instanceTypes,
enabledMetrics,
healthCheckTypes,
volumeTypes,
terminationPolicies,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
ServerGroupInstanceType,
ServerGroupLoadBalancers,
ServerGroupSecurityGroups,
ServerGroupVolumes,
ServerGroupZones,
} from './pages';
import { IAmazonServerGroupCommand } from '../serverGroupConfiguration.service';
Expand Down Expand Up @@ -245,6 +246,13 @@ export class AmazonCloneServerGroupModal extends React.Component<
<ServerGroupAdvancedSettings ref={innerRef} formik={formik} app={application} />
)}
/>

<WizardPage
label="Volumes"
wizard={wizard}
order={nextIdx()}
render={({ innerRef }) => <ServerGroupVolumes ref={innerRef} formik={formik} app={application} />}
/>
</>
)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './ServerGroupLoadBalancers';
export * from './ServerGroupSecurityGroups';
export * from './advancedSettings/ServerGroupAdvancedSettings';
export * from './advancedSettings/ServerGroupAdvancedSettingsCommon';
export * from './volumes/ServerGroupVolumes';
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';
import { FormikProps } from 'formik';
import { IServerGroupCommandBlockDevice } from '../../../serverGroupConfiguration.service';
import { VolumeEditor } from './VolumeEditor';

import { Application, IServerGroup, IWizardPageComponent, MapEditor, HelpField } from '@spinnaker/core';

import { IAmazonServerGroupCommand } from '../../../serverGroupConfiguration.service';
import { isNil } from 'lodash';

export interface IServerGroupVolumesProps {
app: Application;
formik: FormikProps<IAmazonServerGroupCommand>;
}

export interface IServerGroupVolumesState {
namePreview: string;
createsNewCluster: boolean;
latestServerGroup: IServerGroup;
}

export class ServerGroupVolumes
extends React.Component<IServerGroupVolumesProps, IServerGroupVolumesState>
implements IWizardPageComponent<IAmazonServerGroupCommand> {
private duplicateKeys = false;

public validate() {
const errors = {} as any;

if (this.duplicateKeys) {
errors.tags = 'Tags have duplicate keys.';
}

return errors;
}

private blockChange = (volumes: IServerGroupCommandBlockDevice[]) => {
this.props.formik.setFieldValue('blockDevices', volumes);
};

private tagsChanged = (tags: { [key: string]: string }, duplicateKeys: boolean) => {
this.duplicateKeys = duplicateKeys;
this.props.formik.setFieldValue('blockDeviceTags', tags);
};

constructor(props: IServerGroupVolumesProps) {
super(props);
}

public render() {
const { values } = this.props.formik;
const blockTags = isNil(values.blockDeviceTags) ? [] : values.blockDeviceTags;

return (
<div className="container-fluid form-horizontal">
<div className="form-group">
<div className="sm-label-left">
<b>Volumes (optional)</b>
</div>
<VolumeEditor
volumeTypes={values.backingData.volumeTypes}
model={values.blockDevices}
onChange={this.blockChange}
/>
</div>
<div className="form-group">
<div className="sm-label-left">
<b>Tags (optional)</b>
<HelpField id="aws.serverGroup.blockDevice.tags" />
</div>
<MapEditor model={blockTags as any} allowEmpty={true} onChange={this.tagsChanged} />
</div>
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import React from 'react';
import { IServerGroupCommandBlockDevice } from '../../../serverGroupConfiguration.service';
import Select, { Option } from 'react-select';

export const VolumeData = (props: {
blockDevice: IServerGroupCommandBlockDevice;
volumeTypes: string[];
onChange: (value: any, field: string) => void;
onDelete: () => void;
}) => {
const { blockDevice, onChange, onDelete, volumeTypes } = props;

return (
<>
<div className="form-group">
<div className="col-md-5 sm-label-right">
<b>Delete on Termination</b>
</div>
<div className="col-md-5 checkbox">
<label>
<input
type="checkbox"
checked={blockDevice.deleteOnTermination}
onChange={(e) => onChange(e.target.checked, 'deleteOnTermination')}
/>{' '}
Delete on Termination
</label>
</div>
<div className="col-md-2">
<a className="clickable" onClick={onDelete}>
<span className="glyphicon glyphicon-trash" />
<span className="sr-only">Remove field</span>
</a>
</div>
</div>
<div className="form-group">
<div className="col-md-5 sm-label-right">
<b>Encrypted</b>
</div>
<div className="col-md-5 checkbox">
<label>
<input
type="checkbox"
checked={blockDevice.encrypted}
onChange={(e) => onChange(e.target.checked, 'encrypted')}
/>{' '}
Encrypted
</label>
</div>
</div>
<div className="form-group">
<div className="col-md-5 sm-label-right">
<b>Volume Type</b>
</div>
<div className="col-md-6">
<Select
value={blockDevice.volumeType}
clearable={false}
placeholder="Select..."
options={volumeTypes.map((t) => ({ label: t, value: t }))}
onChange={(option: Option) => onChange(option.value, 'volumeType')}
/>
</div>
</div>
<div className="form-group">
<div className="col-md-5 sm-label-right">
<b>Device Name</b>
</div>
<div className="col-md-5 checkbox">
<input
className="form-control input input-sm"
type="text"
value={blockDevice.deviceName}
onChange={(e) => onChange(e.target.value, 'deviceName')}
/>
</div>
</div>

<div className="form-group">
<div className="col-md-5 sm-label-right">
<b>Size</b>
</div>
<div className="col-md-5 checkbox">
<input
className="form-control input input-sm"
type="text"
value={blockDevice.size}
onChange={(e) => onChange(e.target.value, 'size')}
/>
</div>
</div>

<div className="form-group">
<div className="col-md-5 sm-label-right">
<b>Snapshot Id</b>
</div>
<div className="col-md-5 checkbox">
<input
className="form-control input input-sm"
type="text"
value={blockDevice.snapshotId}
onChange={(e) => onChange(e.target.value, 'snapshotId')}
/>
</div>
</div>

<div className="form-group">
<div className="col-md-5 sm-label-right">
<b>Virtual Name</b>
</div>
<div className="col-md-5 checkbox">
<input
className="form-control input input-sm"
type="text"
value={blockDevice.virtualName}
onChange={(e) => onChange(e.target.value, 'virtualName')}
/>
</div>
</div>

<div className="form-group">
<div className="col-md-5 sm-label-right">
<b>Iops</b>
</div>
<div className="col-md-5 checkbox">
<input
className="form-control input input-sm"
type="text"
value={blockDevice.iops}
onChange={(e) => onChange(e.target.value, 'iops')}
/>
</div>
</div>
</>
);
};
Loading