@spinnaker/ecs 0.0.0-main-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/CHANGELOG.md +1186 -0
  2. package/LICENSE.txt +203 -0
  3. package/dist/common/common.module.d.ts +1 -0
  4. package/dist/common/footer.component.d.ts +1 -0
  5. package/dist/domain/IEcsLoadBalancer.d.ts +119 -0
  6. package/dist/ecs.help.d.ts +1 -0
  7. package/dist/ecs.module.d.ts +4 -0
  8. package/dist/ecs.settings.d.ts +9 -0
  9. package/dist/ecsCluster/IEcsCapacityProviderDetails.d.ts +10 -0
  10. package/dist/ecsCluster/IEcsCluster.d.ts +5 -0
  11. package/dist/ecsCluster/ecsCluster.read.service.d.ts +7 -0
  12. package/dist/iamRoles/IRole.d.ts +6 -0
  13. package/dist/iamRoles/iamRole.read.service.d.ts +5 -0
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +6010 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/instance/details/instance.details.controller.d.ts +2 -0
  18. package/dist/loadBalancer/EcsLoadBalancerClusterContainer.d.ts +6 -0
  19. package/dist/loadBalancer/TargetGroup.d.ts +11 -0
  20. package/dist/loadBalancer/details/loadBalancerDetails.d.ts +27 -0
  21. package/dist/loadBalancer/details/targetGroupDetails.d.ts +30 -0
  22. package/dist/loadBalancer/listener.d.ts +10 -0
  23. package/dist/loadBalancer/loadBalancer.transformer.d.ts +8 -0
  24. package/dist/loadBalancer/targetGroup.states.d.ts +1 -0
  25. package/dist/metricAlarm/MetricAlarm.d.ts +6 -0
  26. package/dist/metricAlarm/metricAlarm.read.service.d.ts +5 -0
  27. package/dist/pipeline/stages/destroyAsg/ecsDestroyAsgStage.d.ts +2 -0
  28. package/dist/pipeline/stages/disableAsg/ecsDisableAsgStage.d.ts +2 -0
  29. package/dist/pipeline/stages/disableCluster/ecsDisableClusterStage.d.ts +2 -0
  30. package/dist/pipeline/stages/enableAsg/ecsEnableAsgStage.d.ts +2 -0
  31. package/dist/pipeline/stages/findImageFromTags/ecsFindImageFromTagStage.d.ts +2 -0
  32. package/dist/pipeline/stages/resizeAsg/ecsResizeAsgStage.d.ts +2 -0
  33. package/dist/pipeline/stages/scaleDownCluster/ecsScaleDownClusterStage.d.ts +2 -0
  34. package/dist/pipeline/stages/shrinkCluster/ecsShrinkClusterStage.d.ts +2 -0
  35. package/dist/placementStrategy/IPlacementStrategy.d.ts +4 -0
  36. package/dist/placementStrategy/placementStrategy.service.d.ts +11 -0
  37. package/dist/secrets/ISecret.d.ts +5 -0
  38. package/dist/secrets/secret.read.service.d.ts +5 -0
  39. package/dist/securityGroup/details/securityGroupDetail.controller.d.ts +2 -0
  40. package/dist/securityGroup/securityGroup.module.d.ts +1 -0
  41. package/dist/securityGroup/securityGroup.reader.d.ts +5 -0
  42. package/dist/securityGroup/securityGroup.transformer.d.ts +2 -0
  43. package/dist/serverGroup/configure/serverGroupCommandBuilder.service.d.ts +2 -0
  44. package/dist/serverGroup/configure/serverGroupConfiguration.service.d.ts +165 -0
  45. package/dist/serverGroup/configure/wizard/CloneServerGroup.ecs.controller.d.ts +2 -0
  46. package/dist/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.d.ts +2 -0
  47. package/dist/serverGroup/configure/wizard/capacityProvider/CapacityProvider.d.ts +7 -0
  48. package/dist/serverGroup/configure/wizard/container/Container.d.ts +32 -0
  49. package/dist/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.d.ts +2 -0
  50. package/dist/serverGroup/configure/wizard/location/ServerGroupBasicSettings.controller.d.ts +2 -0
  51. package/dist/serverGroup/configure/wizard/logging/logging.component.d.ts +1 -0
  52. package/dist/serverGroup/configure/wizard/networking/Networking.d.ts +28 -0
  53. package/dist/serverGroup/configure/wizard/serviceDiscovery/ServiceDiscovery.d.ts +34 -0
  54. package/dist/serverGroup/configure/wizard/taskDefinition/TaskDefinition.d.ts +39 -0
  55. package/dist/serverGroup/details/resize/resizeCapacity.component.d.ts +1 -0
  56. package/dist/serverGroup/details/resize/resizeServerGroup.controller.d.ts +2 -0
  57. package/dist/serverGroup/details/rollback/rollbackServerGroup.controller.d.ts +2 -0
  58. package/dist/serverGroup/details/serverGroupDetails.ecs.controller.d.ts +2 -0
  59. package/dist/serverGroup/details/serverGroupDetails.module.d.ts +1 -0
  60. package/dist/serverGroup/events/EventsLink.d.ts +4 -0
  61. package/dist/serverGroup/events/events.component.d.ts +3 -0
  62. package/dist/serverGroup/events/events.controller.d.ts +19 -0
  63. package/dist/serverGroup/events/serverGroupEventsReader.service.d.ts +10 -0
  64. package/dist/serverGroup/serverGroup.module.d.ts +1 -0
  65. package/dist/serverGroup/serverGroup.transformer.d.ts +11 -0
  66. package/dist/serviceDiscovery/IServiceDiscovery.d.ts +12 -0
  67. package/dist/serviceDiscovery/serviceDiscovery.read.service.d.ts +4 -0
  68. package/package.json +47 -0
  69. package/src/common/common.module.ts +6 -0
  70. package/src/common/footer.component.ts +29 -0
  71. package/src/domain/IEcsLoadBalancer.ts +129 -0
  72. package/src/ecs.help.ts +91 -0
  73. package/src/ecs.module.ts +116 -0
  74. package/src/ecs.settings.ts +17 -0
  75. package/src/ecsCluster/IEcsCapacityProviderDetails.ts +11 -0
  76. package/src/ecsCluster/IEcsCluster.ts +5 -0
  77. package/src/ecsCluster/ecsCluster.read.service.ts +23 -0
  78. package/src/iamRoles/IRole.ts +6 -0
  79. package/src/iamRoles/iamRole.read.service.ts +14 -0
  80. package/src/index.ts +1 -0
  81. package/src/instance/details/instance.details.controller.js +356 -0
  82. package/src/instance/details/instanceDetails.html +204 -0
  83. package/src/loadBalancer/EcsLoadBalancerClusterContainer.tsx +48 -0
  84. package/src/loadBalancer/TargetGroup.tsx +74 -0
  85. package/src/loadBalancer/details/loadBalancerDetails.tsx +235 -0
  86. package/src/loadBalancer/details/targetGroupDetails.tsx +251 -0
  87. package/src/loadBalancer/listener.tsx +65 -0
  88. package/src/loadBalancer/loadBalancer.transformer.ts +21 -0
  89. package/src/loadBalancer/targetGroup.states.ts +59 -0
  90. package/src/logo/ecs.icon.svg +27 -0
  91. package/src/logo/ecs.logo.less +5 -0
  92. package/src/logo/ecs.logo.svg +27 -0
  93. package/src/metricAlarm/MetricAlarm.ts +6 -0
  94. package/src/metricAlarm/metricAlarm.read.service.ts +14 -0
  95. package/src/pipeline/stages/cloneServerGroup/cloneServerGroupStage.html +101 -0
  96. package/src/pipeline/stages/cloneServerGroup/cloneServerGroupStepLabel.html +1 -0
  97. package/src/pipeline/stages/cloneServerGroup/ecsCloneServerGroupStage.js +94 -0
  98. package/src/pipeline/stages/destroyAsg/destroyAsgStage.html +9 -0
  99. package/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html +1 -0
  100. package/src/pipeline/stages/destroyAsg/ecsDestroyAsgStage.js +65 -0
  101. package/src/pipeline/stages/disableAsg/disableAsgStage.html +11 -0
  102. package/src/pipeline/stages/disableAsg/disableAsgStepLabel.html +1 -0
  103. package/src/pipeline/stages/disableAsg/ecsDisableAsgStage.js +70 -0
  104. package/src/pipeline/stages/disableCluster/disableClusterStage.html +26 -0
  105. package/src/pipeline/stages/disableCluster/ecsDisableClusterStage.js +84 -0
  106. package/src/pipeline/stages/enableAsg/ecsEnableAsgStage.js +73 -0
  107. package/src/pipeline/stages/enableAsg/enableAsgStage.html +11 -0
  108. package/src/pipeline/stages/enableAsg/enableAsgStepLabel.html +1 -0
  109. package/src/pipeline/stages/findImageFromTags/ecsFindImageFromTagStage.js +26 -0
  110. package/src/pipeline/stages/findImageFromTags/findImageFromTagsExecutionDetails.html +36 -0
  111. package/src/pipeline/stages/findImageFromTags/findImageFromTagsStage.html +9 -0
  112. package/src/pipeline/stages/resizeAsg/ecsResizeAsgStage.js +128 -0
  113. package/src/pipeline/stages/resizeAsg/resizeAsgStage.html +87 -0
  114. package/src/pipeline/stages/resizeAsg/resizeAsgStepLabel.html +1 -0
  115. package/src/pipeline/stages/scaleDownCluster/ecsScaleDownClusterStage.js +78 -0
  116. package/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.html +35 -0
  117. package/src/pipeline/stages/shrinkCluster/ecsShrinkClusterStage.js +73 -0
  118. package/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html +34 -0
  119. package/src/placementStrategy/IPlacementStrategy.ts +4 -0
  120. package/src/placementStrategy/placementStrategy.service.ts +63 -0
  121. package/src/secrets/ISecret.ts +5 -0
  122. package/src/secrets/secret.read.service.ts +14 -0
  123. package/src/securityGroup/details/securityGroupDetail.controller.js +147 -0
  124. package/src/securityGroup/details/securityGroupDetail.html +104 -0
  125. package/src/securityGroup/securityGroup.module.ts +12 -0
  126. package/src/securityGroup/securityGroup.reader.ts +16 -0
  127. package/src/securityGroup/securityGroup.transformer.js +13 -0
  128. package/src/serverGroup/configure/serverGroupCommandBuilder.service.js +281 -0
  129. package/src/serverGroup/configure/serverGroupConfiguration.service.ts +747 -0
  130. package/src/serverGroup/configure/wizard/CloneServerGroup.ecs.controller.js +259 -0
  131. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.html +194 -0
  132. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.js +17 -0
  133. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.html +10 -0
  134. package/src/serverGroup/configure/wizard/capacityProvider/CapacityProvider.tsx +381 -0
  135. package/src/serverGroup/configure/wizard/capacityProvider/capacityProvider.html +11 -0
  136. package/src/serverGroup/configure/wizard/container/Container.tsx +347 -0
  137. package/src/serverGroup/configure/wizard/container/container.html +9 -0
  138. package/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.html +118 -0
  139. package/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.js +20 -0
  140. package/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.html +13 -0
  141. package/src/serverGroup/configure/wizard/location/ServerGroupBasicSettings.controller.js +41 -0
  142. package/src/serverGroup/configure/wizard/location/basicSettings.html +137 -0
  143. package/src/serverGroup/configure/wizard/logging/logging.component.html +29 -0
  144. package/src/serverGroup/configure/wizard/logging/logging.component.ts +12 -0
  145. package/src/serverGroup/configure/wizard/logging/logging.html +7 -0
  146. package/src/serverGroup/configure/wizard/networking/Networking.tsx +261 -0
  147. package/src/serverGroup/configure/wizard/networking/networking.html +9 -0
  148. package/src/serverGroup/configure/wizard/serverGroupWizard.html +55 -0
  149. package/src/serverGroup/configure/wizard/serviceDiscovery/ServiceDiscovery.tsx +250 -0
  150. package/src/serverGroup/configure/wizard/serviceDiscovery/serviceDiscovery.html +11 -0
  151. package/src/serverGroup/configure/wizard/taskDefinition/TaskDefinition.tsx +460 -0
  152. package/src/serverGroup/configure/wizard/taskDefinition/taskDefinition.html +51 -0
  153. package/src/serverGroup/configure/wizard/templateSelection/templateSelection.html +9 -0
  154. package/src/serverGroup/configure/wizard/verticalScaling/verticalScaling.html +10 -0
  155. package/src/serverGroup/details/resize/resizeCapacity.component.html +94 -0
  156. package/src/serverGroup/details/resize/resizeCapacity.component.ts +14 -0
  157. package/src/serverGroup/details/resize/resizeServerGroup.controller.js +85 -0
  158. package/src/serverGroup/details/resize/resizeServerGroup.html +28 -0
  159. package/src/serverGroup/details/rollback/rollbackServerGroup.controller.js +97 -0
  160. package/src/serverGroup/details/rollback/rollbackServerGroup.html +67 -0
  161. package/src/serverGroup/details/serverGroupDetails.ecs.controller.js +366 -0
  162. package/src/serverGroup/details/serverGroupDetails.html +216 -0
  163. package/src/serverGroup/details/serverGroupDetails.module.ts +5 -0
  164. package/src/serverGroup/events/EventsLink.tsx +5 -0
  165. package/src/serverGroup/events/events.component.ts +35 -0
  166. package/src/serverGroup/events/events.controller.ts +45 -0
  167. package/src/serverGroup/events/events.html +36 -0
  168. package/src/serverGroup/events/serverGroupEventsReader.service.ts +27 -0
  169. package/src/serverGroup/serverGroup.module.ts +6 -0
  170. package/src/serverGroup/serverGroup.transformer.spec.ts +184 -0
  171. package/src/serverGroup/serverGroup.transformer.ts +117 -0
  172. package/src/serviceDiscovery/IServiceDiscovery.ts +13 -0
  173. package/src/serviceDiscovery/serviceDiscovery.read.service.ts +8 -0
@@ -0,0 +1,460 @@
1
+ import { module } from 'angular';
2
+ import { isEqual, uniqWith } from 'lodash';
3
+ import React from 'react';
4
+ import { Alert } from 'react-bootstrap';
5
+ import type { Option } from 'react-select';
6
+ import { react2angular } from 'react2angular';
7
+
8
+ import type { IArtifact, IExpectedArtifact } from '@spinnaker/core';
9
+ import {
10
+ ArtifactTypePatterns,
11
+ CheckboxInput,
12
+ HelpField,
13
+ StageArtifactSelectorDelegate,
14
+ StageConfigField,
15
+ TetheredSelect,
16
+ withErrorBoundary,
17
+ } from '@spinnaker/core';
18
+
19
+ import type {
20
+ IEcsContainerMapping,
21
+ IEcsDockerImage,
22
+ IEcsServerGroupCommand,
23
+ IEcsTargetGroupMapping,
24
+ IEcsTaskDefinitionArtifact,
25
+ } from '../../serverGroupConfiguration.service';
26
+
27
+ export interface ITaskDefinitionProps {
28
+ command: IEcsServerGroupCommand;
29
+ notifyAngular: (key: string, value: any) => void;
30
+ configureCommand: (query: string) => PromiseLike<void>;
31
+ }
32
+
33
+ interface ITaskDefinitionState {
34
+ taskDefArtifact: IEcsTaskDefinitionArtifact;
35
+ taskDefArtifactAccount: string;
36
+ containerMappings: IEcsContainerMapping[];
37
+ targetGroupMappings: IEcsTargetGroupMapping[];
38
+ dockerImages: IEcsDockerImage[];
39
+ targetGroupsAvailable: string[];
40
+ loadBalancedContainer: string;
41
+ evaluateTaskDefinitionArtifactExpressions: boolean;
42
+ }
43
+
44
+ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskDefinitionState> {
45
+ constructor(props: ITaskDefinitionProps) {
46
+ super(props);
47
+ const cmd = this.props.command;
48
+ let defaultContainer = '';
49
+ if (cmd.containerMappings && cmd.containerMappings.length > 0) {
50
+ defaultContainer = cmd.containerMappings[0].containerName;
51
+ }
52
+
53
+ let defaultTargetGroup: IEcsTargetGroupMapping[] = [];
54
+ if (cmd.targetGroupMappings && cmd.targetGroupMappings.length > 0) {
55
+ defaultTargetGroup = cmd.targetGroupMappings;
56
+ }
57
+
58
+ if (cmd.targetGroup && cmd.targetGroup.length > 0) {
59
+ defaultTargetGroup.push({
60
+ containerName: cmd.loadBalancedContainer || defaultContainer,
61
+ targetGroup: cmd.targetGroup,
62
+ containerPort: cmd.containerPort,
63
+ });
64
+ cmd.targetGroup = '';
65
+ cmd.loadBalancedContainer = '';
66
+ }
67
+
68
+ cmd.targetGroupMappings = uniqWith(defaultTargetGroup, isEqual);
69
+
70
+ this.state = {
71
+ taskDefArtifact: cmd.taskDefinitionArtifact,
72
+ containerMappings: cmd.containerMappings ? cmd.containerMappings : [],
73
+ targetGroupMappings: cmd.targetGroupMappings,
74
+ targetGroupsAvailable: cmd.backingData && cmd.backingData.filtered ? cmd.backingData.filtered.targetGroups : [],
75
+ dockerImages: cmd.backingData && cmd.backingData.filtered ? cmd.backingData.filtered.images : [],
76
+ loadBalancedContainer: cmd.loadBalancedContainer || defaultContainer,
77
+ taskDefArtifactAccount: cmd.taskDefinitionArtifactAccount,
78
+ evaluateTaskDefinitionArtifactExpressions: cmd.evaluateTaskDefinitionArtifactExpressions,
79
+ };
80
+ }
81
+
82
+ // TODO: Separate docker image component used by both TaskDefinition and Container
83
+ public componentDidMount() {
84
+ this.props.configureCommand('1').then(() => {
85
+ this.setState({
86
+ dockerImages: this.props.command.backingData.filtered.images,
87
+ targetGroupsAvailable: this.props.command.backingData.filtered.targetGroups,
88
+ });
89
+ });
90
+ }
91
+
92
+ private getIdToImageMap = (): Map<string, IEcsDockerImage> => {
93
+ const imageIdToDescription = new Map<string, IEcsDockerImage>();
94
+ this.props.command.backingData.filtered.images.forEach((e) => {
95
+ imageIdToDescription.set(e.imageId, e);
96
+ });
97
+
98
+ return imageIdToDescription;
99
+ };
100
+
101
+ private getEmptyImageDescription = (): IEcsDockerImage => {
102
+ return {
103
+ imageId: '',
104
+ message: '',
105
+ fromTrigger: false,
106
+ fromContext: false,
107
+ stageId: '',
108
+ imageLabelOrSha: '',
109
+ account: '',
110
+ registry: '',
111
+ repository: '',
112
+ tag: '',
113
+ };
114
+ };
115
+
116
+ private excludedArtifactTypePatterns = [
117
+ ArtifactTypePatterns.KUBERNETES,
118
+ ArtifactTypePatterns.DOCKER_IMAGE,
119
+ ArtifactTypePatterns.FRONT50_PIPELINE_TEMPLATE,
120
+ ];
121
+
122
+ private onExpectedArtifactSelected = (expectedArtifactId: string): void => {
123
+ const selectedArtifact = { artifactId: expectedArtifactId };
124
+ this.props.notifyAngular('taskDefinitionArtifact', selectedArtifact);
125
+ this.setState({ taskDefArtifact: selectedArtifact });
126
+ };
127
+
128
+ private onArtifactEdited = (artifact: IArtifact): void => {
129
+ const newArtifact = { artifact: artifact };
130
+ this.props.notifyAngular('taskDefinitionArtifact', newArtifact);
131
+ this.setState({ taskDefArtifact: newArtifact });
132
+ };
133
+
134
+ private pushMapping = () => {
135
+ const conMaps = this.state.containerMappings;
136
+ conMaps.push({ containerName: '', imageDescription: this.getEmptyImageDescription() });
137
+ this.setState({ containerMappings: conMaps });
138
+ };
139
+
140
+ private pushTargetGroupMapping = () => {
141
+ const targetMaps = this.state.targetGroupMappings;
142
+ targetMaps.push({ containerName: '', targetGroup: '', containerPort: 80 });
143
+ this.setState({ targetGroupMappings: targetMaps });
144
+ };
145
+
146
+ private updateContainerMappingName = (index: number, newName: string) => {
147
+ const currentMappings = this.state.containerMappings;
148
+ const targetMapping = currentMappings[index];
149
+ targetMapping.containerName = newName;
150
+ this.props.notifyAngular('containerMappings', currentMappings);
151
+ this.setState({ containerMappings: currentMappings });
152
+ };
153
+
154
+ private updateContainerMappingImage = (index: number, newImage: Option<string>) => {
155
+ const imageMap = this.getIdToImageMap();
156
+ let newImageDescription = imageMap.get(newImage.value);
157
+
158
+ if (!newImageDescription) {
159
+ newImageDescription = this.getEmptyImageDescription();
160
+ }
161
+ const currentMappings = this.state.containerMappings;
162
+ const targetMapping = currentMappings[index];
163
+ targetMapping.imageDescription = newImageDescription;
164
+ this.props.notifyAngular('containerMappings', currentMappings);
165
+ this.setState({ containerMappings: currentMappings });
166
+ };
167
+
168
+ private updateTargetGroupMappingTargetGroup = (index: number, newTargetGroup: Option<string>) => {
169
+ const currentMappings = this.state.targetGroupMappings;
170
+ const targetMapping = currentMappings[index];
171
+ targetMapping.targetGroup = newTargetGroup.value;
172
+ this.props.notifyAngular('targetGroupMappings', currentMappings);
173
+ this.setState({ targetGroupMappings: currentMappings });
174
+ };
175
+
176
+ private updateTargetGroupMappingContainer = (index: number, targetContainer: string) => {
177
+ const currentMappings = this.state.targetGroupMappings;
178
+ const targetMapping = currentMappings[index];
179
+ targetMapping.containerName = targetContainer;
180
+ this.props.notifyAngular('targetGroupMappings', currentMappings);
181
+ this.setState({ targetGroupMappings: currentMappings });
182
+ };
183
+
184
+ private updateTargetGroupMappingPort = (index: number, targetPort: number) => {
185
+ const currentMappings = this.state.targetGroupMappings;
186
+ const targetMapping = currentMappings[index];
187
+ targetMapping.containerPort = targetPort;
188
+ this.props.notifyAngular('targetGroupMappings', currentMappings);
189
+ this.setState({ targetGroupMappings: currentMappings });
190
+ };
191
+
192
+ private removeMapping = (index: number) => {
193
+ const currentMappings = this.state.containerMappings;
194
+ currentMappings.splice(index, 1);
195
+ this.props.notifyAngular('containerMappings', currentMappings);
196
+ this.setState({ containerMappings: currentMappings });
197
+ };
198
+
199
+ private removeTargetGroupMapping = (index: number) => {
200
+ const currentMappings = this.state.targetGroupMappings;
201
+ currentMappings.splice(index, 1);
202
+ this.props.notifyAngular('targetGroupMappings', currentMappings);
203
+ this.setState({ targetGroupMappings: currentMappings });
204
+ };
205
+
206
+ private updateEvaluateTaskDefArtifactFlag = () => {
207
+ this.props.notifyAngular(
208
+ 'evaluateTaskDefinitionArtifactExpressions',
209
+ !this.props.command.evaluateTaskDefinitionArtifactExpressions,
210
+ );
211
+ this.setState({
212
+ evaluateTaskDefinitionArtifactExpressions: !this.props.command.evaluateTaskDefinitionArtifactExpressions,
213
+ });
214
+ };
215
+
216
+ public render(): React.ReactElement<TaskDefinition> {
217
+ const { command } = this.props;
218
+ const removeMapping = this.removeMapping;
219
+ const removeTargetGroupMapping = this.removeTargetGroupMapping;
220
+ const updateContainerMappingName = this.updateContainerMappingName;
221
+ const updateContainerMappingImage = this.updateContainerMappingImage;
222
+ const updateTargetGroupMappingContainer = this.updateTargetGroupMappingContainer;
223
+ const updateTargetGroupMappingTargetGroup = this.updateTargetGroupMappingTargetGroup;
224
+ const updateTargetGroupMappingPort = this.updateTargetGroupMappingPort;
225
+ const updateEvaluateTaskDefArtifactFlag = this.updateEvaluateTaskDefArtifactFlag;
226
+
227
+ const dockerImageOptions = this.state.dockerImages.map(function (image) {
228
+ let msg = '';
229
+ if (image.fromTrigger || image.fromContext) {
230
+ msg = image.fromTrigger ? '(TRIGGER) ' : '(FIND IMAGE RESULT) ';
231
+ }
232
+ return { label: `${msg} (${image.imageId})`, value: image.imageId };
233
+ });
234
+
235
+ const targetGroupsAvailable = this.state.targetGroupsAvailable.map(function (targetGroup) {
236
+ return { label: `${targetGroup}`, value: targetGroup };
237
+ });
238
+
239
+ const mappingInputs = this.state.containerMappings.map(function (mapping, index) {
240
+ return (
241
+ <tr key={index}>
242
+ <td>
243
+ <input
244
+ data-test-id="Artifacts.containerName"
245
+ className="form-control input-sm"
246
+ required={true}
247
+ placeholder="enter container name..."
248
+ value={mapping.containerName.toString()}
249
+ onChange={(e) => updateContainerMappingName(index, e.target.value)}
250
+ />
251
+ </td>
252
+ <td data-test-id="Artifacts.containerImage">
253
+ <TetheredSelect
254
+ placeholder="Select an image to use..."
255
+ options={dockerImageOptions}
256
+ value={mapping.imageDescription.imageId}
257
+ onChange={(e: Option) => {
258
+ updateContainerMappingImage(index, e as Option<string>);
259
+ }}
260
+ clearable={false}
261
+ />
262
+ </td>
263
+ <td>
264
+ <div className="form-control-static">
265
+ <a
266
+ className="btn-link sm-label"
267
+ data-test-id="Artifacts.containerRemove"
268
+ onClick={() => removeMapping(index)}
269
+ >
270
+ <span className="glyphicon glyphicon-trash" />
271
+ <span className="sr-only">Remove</span>
272
+ </a>
273
+ </div>
274
+ </td>
275
+ </tr>
276
+ );
277
+ });
278
+
279
+ const targetGroupInputs = this.state.targetGroupMappings.map(function (mapping, index) {
280
+ return (
281
+ <tr key={index}>
282
+ <td>
283
+ <input
284
+ data-test-id="Artifacts.targetGroupContainer"
285
+ className="form-control input-sm"
286
+ required={true}
287
+ placeholder="Enter a container name ..."
288
+ value={mapping.containerName.toString()}
289
+ onChange={(e) => updateTargetGroupMappingContainer(index, e.target.value)}
290
+ />
291
+ </td>
292
+ <td data-test-id="Artifacts.targetGroup">
293
+ <TetheredSelect
294
+ placeholder="Select a target group to use..."
295
+ options={targetGroupsAvailable}
296
+ value={mapping.targetGroup.toString()}
297
+ onChange={(e: Option) => updateTargetGroupMappingTargetGroup(index, e as Option<string>)}
298
+ clearable={false}
299
+ />
300
+ </td>
301
+ <td>
302
+ <input
303
+ data-test-id="Artifacts.targetGroupPort"
304
+ type="number"
305
+ className="form-control input-sm no-spel"
306
+ required={true}
307
+ value={mapping.containerPort.toString()}
308
+ onChange={(e) => updateTargetGroupMappingPort(index, e.target.valueAsNumber)}
309
+ />
310
+ </td>
311
+ <td>
312
+ <div className="form-control-static">
313
+ <a
314
+ className="btn-link sm-label"
315
+ data-test-id="Artifacts.targetGroupRemove"
316
+ onClick={() => removeTargetGroupMapping(index)}
317
+ >
318
+ <span className="glyphicon glyphicon-trash" />
319
+ <span className="sr-only">Remove</span>
320
+ </a>
321
+ </div>
322
+ </td>
323
+ </tr>
324
+ );
325
+ });
326
+
327
+ const newTargetGroupMapping = this.state.targetGroupsAvailable.length ? (
328
+ <button
329
+ className="btn btn-block btn-sm add-new"
330
+ data-test-id="Artifacts.targetGroupAdd"
331
+ onClick={this.pushTargetGroupMapping}
332
+ >
333
+ <span className="glyphicon glyphicon-plus-sign" />
334
+ Add New Target Group Mapping
335
+ </button>
336
+ ) : (
337
+ <div className="sm-label-left">
338
+ <Alert color="warning">No target groups found in the selected account/region/VPC</Alert>
339
+ </div>
340
+ );
341
+
342
+ return (
343
+ <div className="container-fluid form-horizontal">
344
+ <div className="form-group">
345
+ <div className="col-md-12">
346
+ <StageArtifactSelectorDelegate
347
+ artifact={this.state.taskDefArtifact.artifact}
348
+ excludedArtifactTypePatterns={this.excludedArtifactTypePatterns}
349
+ expectedArtifactId={this.state.taskDefArtifact.artifactId}
350
+ label="Artifact"
351
+ helpKey="ecs.taskDefinitionArtifact"
352
+ onExpectedArtifactSelected={(artifact: IExpectedArtifact) => this.onExpectedArtifactSelected(artifact.id)}
353
+ onArtifactEdited={this.onArtifactEdited}
354
+ pipeline={command.viewState.pipeline}
355
+ stage={command.viewState.currentStage}
356
+ />
357
+ </div>
358
+ </div>
359
+
360
+ <StageConfigField
361
+ groupClassName="form-group evaluateTaskDef"
362
+ label="Expression Evaluation"
363
+ helpKey="ecs.evaluateExpression"
364
+ labelColumns={5}
365
+ fieldColumns={7}
366
+ >
367
+ <CheckboxInput
368
+ checked={command.evaluateTaskDefinitionArtifactExpressions === true}
369
+ onChange={() => {
370
+ updateEvaluateTaskDefArtifactFlag();
371
+ }}
372
+ text="Evaluate SpEL expressions in artifact"
373
+ />
374
+ </StageConfigField>
375
+
376
+ <div className="form-group">
377
+ <div className="sm-label-left">
378
+ <b>Container Mappings</b>
379
+ <HelpField id="ecs.containerMappings" />
380
+ </div>
381
+ <form name="ecsTaskDefinitionContainerMappings">
382
+ <table className="table table-condensed packed tags">
383
+ <thead>
384
+ <tr key="header">
385
+ <th style={{ width: '30%' }}>
386
+ Container name
387
+ <HelpField id="ecs.containerMappingName" />
388
+ </th>
389
+ <th style={{ width: '70%' }}>
390
+ Container image
391
+ <HelpField id="ecs.containerMappingImage" />
392
+ </th>
393
+ <th />
394
+ </tr>
395
+ </thead>
396
+ <tbody>{mappingInputs}</tbody>
397
+ <tfoot>
398
+ <tr>
399
+ <td colSpan={3}>
400
+ <button
401
+ className="btn btn-block btn-sm add-new"
402
+ data-test-id="Artifacts.containerAdd"
403
+ onClick={this.pushMapping}
404
+ >
405
+ <span className="glyphicon glyphicon-plus-sign" />
406
+ Add New Container Mapping
407
+ </button>
408
+ </td>
409
+ </tr>
410
+ </tfoot>
411
+ </table>
412
+ </form>
413
+ </div>
414
+ <div className="form-group">
415
+ <div className="sm-label-left">
416
+ <b>Target Group Mappings</b>
417
+ <HelpField id="ecs.targetGroupMappings" />
418
+ </div>
419
+ <form name="ecsTaskDefinitionTargetGroupMappings">
420
+ <table className="table table-condensed packed tags">
421
+ <thead>
422
+ <tr key="header">
423
+ <th style={{ width: '30%' }}>
424
+ Container name
425
+ <HelpField id="ecs.loadBalancedContainer" />
426
+ </th>
427
+ <th style={{ width: '55%' }}>
428
+ Target group
429
+ <HelpField id="ecs.loadBalancer.targetGroup" />
430
+ </th>
431
+ <th style={{ width: '15%' }}>
432
+ Target port
433
+ <HelpField id="ecs.loadbalancing.targetPort" />
434
+ </th>
435
+ <th />
436
+ </tr>
437
+ </thead>
438
+ <tbody>{targetGroupInputs}</tbody>
439
+ <tfoot>
440
+ <tr>
441
+ <td colSpan={4}>{newTargetGroupMapping}</td>
442
+ </tr>
443
+ </tfoot>
444
+ </table>
445
+ </form>
446
+ </div>
447
+ </div>
448
+ );
449
+ }
450
+ }
451
+
452
+ export const TASK_DEFINITION_REACT = 'spinnaker.ecs.serverGroup.configure.wizard.taskDefinition.react';
453
+ module(TASK_DEFINITION_REACT, []).component(
454
+ 'taskDefinitionReact',
455
+ react2angular(withErrorBoundary(TaskDefinition, 'taskDefinitionReact'), [
456
+ 'command',
457
+ 'notifyAngular',
458
+ 'configureCommand',
459
+ ]),
460
+ );
@@ -0,0 +1,51 @@
1
+ <div class="clearfix">
2
+ <div class="row">
3
+ <div class="col-md-12">
4
+ <div class="container-fluid form-horizontal">
5
+ <div class="form-group">
6
+ <div class="col-md-4 sm-label-right">
7
+ <b>Task Definition source</b>
8
+ <help-field key="ecs.taskDefinition"></help-field>
9
+ </div>
10
+ <div class="col-md-2 radio">
11
+ <label>
12
+ <input
13
+ data-test-id="ServerGroup.useInputs"
14
+ type="radio"
15
+ ng-model="command.useTaskDefinitionArtifact"
16
+ ng-value="false"
17
+ id="taskDefinitionSourceInputs"
18
+ />
19
+ Inputs
20
+ </label>
21
+ </div>
22
+ <div class="col-md-1 radio">
23
+ <label>
24
+ <input
25
+ data-test-id="ServerGroup.useArtifacts"
26
+ type="radio"
27
+ ng-model="command.useTaskDefinitionArtifact"
28
+ ng-value="true"
29
+ ng-disabled="command.viewState.mode === 'create'"
30
+ id="taskDefinitionSourceArtifact"
31
+ />
32
+ Artifact
33
+ </label>
34
+ </div>
35
+ </div>
36
+ <div ng-if="command.viewState.mode === 'create'" class="color-text-caption">
37
+ <hr />
38
+ <span><em>Artifacts not supported outside of pipelines.</em></span>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ <div class="col-md-12" ng-if="command.useTaskDefinitionArtifact">
43
+ <hr />
44
+ <task-definition-react
45
+ command="command"
46
+ notify-angular="notifyAngular"
47
+ configure-command="configureCommand"
48
+ ></task-definition-react>
49
+ </div>
50
+ </div>
51
+ </div>
@@ -0,0 +1,9 @@
1
+ <deploy-initializer
2
+ cloud-provider="ecs"
3
+ command="command"
4
+ application="application"
5
+ parent-state="state"
6
+ dismiss="ctrl.cancel()"
7
+ template-selection-text="ctrl.templateSelectionText"
8
+ on-template-selected="ctrl.templateSelected()"
9
+ ></deploy-initializer>
@@ -0,0 +1,10 @@
1
+ <div class="clearfix">
2
+ <div class="row">
3
+ <div class="col-md-12">
4
+ <ecs-server-group-vertical-scaling
5
+ command="command"
6
+ application="application"
7
+ ></ecs-server-group-vertical-scaling>
8
+ </div>
9
+ </div>
10
+ </div>
@@ -0,0 +1,94 @@
1
+ <div ng-if="$ctrl.command.advancedMode">
2
+ <div class="form-group">
3
+ <div class="col-md-12">
4
+ <p>Sets up auto-scaling for this server group.</p>
5
+ <p>To disable auto-scaling, use the <a href ng-click="$ctrl.command.advancedMode = false">Simple Mode</a>.</p>
6
+ </div>
7
+ </div>
8
+ <div class="form-group">
9
+ <div class="col-md-2 col-md-offset-3"><b>Min</b></div>
10
+ <div class="col-md-2"><b>Max</b></div>
11
+ <div class="col-md-2"><b>Desired</b></div>
12
+ </div>
13
+ <div class="form-group">
14
+ <div class="col-md-3 sm-label-right">Current</div>
15
+ <div class="col-md-2">
16
+ <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.min" readonly />
17
+ </div>
18
+ <div class="col-md-2">
19
+ <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.max" readonly />
20
+ </div>
21
+ <div class="col-md-2">
22
+ <input type="number" class="form-control input-sm" ng-model="$ctrl.currentSize.desired" readonly />
23
+ </div>
24
+ </div>
25
+ <div class="form-group">
26
+ <div class="col-md-3 sm-label-right">Resize to</div>
27
+ <div class="col-md-2">
28
+ <input
29
+ type="number"
30
+ class="form-control input-sm"
31
+ ng-model="$ctrl.command.min"
32
+ min="0"
33
+ required
34
+ max="{{ $ctrl.command.max }}"
35
+ />
36
+ </div>
37
+ <div class="col-md-2">
38
+ <input
39
+ type="number"
40
+ class="form-control input-sm"
41
+ ng-model="$ctrl.command.max"
42
+ required
43
+ min="{{ $ctrl.command.min }}"
44
+ />
45
+ </div>
46
+ <div class="col-md-2">
47
+ <input
48
+ type="number"
49
+ class="form-control input-sm"
50
+ ng-model="$ctrl.command.desired"
51
+ required
52
+ min="{{ $ctrl.command.min }}"
53
+ max="{{ $ctrl.command.max }}"
54
+ />
55
+ </div>
56
+ </div>
57
+ </div>
58
+ <div ng-if="!$ctrl.command.advancedMode">
59
+ <div class="form-group">
60
+ <div class="col-md-12">
61
+ <p>
62
+ To modify min and max instance counts, use the
63
+ <a href ng-click="$ctrl.command.advancedMode = true">Advanced Mode</a>.
64
+ </p>
65
+ </div>
66
+ </div>
67
+ <div class="form-group form-inline">
68
+ <div class="col-md-3 sm-label-right">Current size</div>
69
+ <div class="col-md-6">
70
+ <input
71
+ type="number"
72
+ class="form-control input-sm"
73
+ ng-model="$ctrl.currentSize.desired"
74
+ style="width: 60px"
75
+ readonly
76
+ />
77
+ instance<span ng-if="$ctrl.currentSize.desired > 1">s</span>
78
+ </div>
79
+ </div>
80
+ <div class="form-group form-inline">
81
+ <div class="col-md-3 sm-label-right">Resize to</div>
82
+ <div class="col-md-6">
83
+ <input
84
+ type="number"
85
+ class="form-control input-sm highlight-pristine"
86
+ ng-model="$ctrl.command.newSize"
87
+ min="0"
88
+ required
89
+ style="width: 60px"
90
+ />
91
+ instances
92
+ </div>
93
+ </div>
94
+ </div>
@@ -0,0 +1,14 @@
1
+ import type { IComponentOptions } from 'angular';
2
+ import { module } from 'angular';
3
+
4
+ const resizeCapacityComponent: IComponentOptions = {
5
+ bindings: {
6
+ command: '=',
7
+ currentSize: '=',
8
+ },
9
+ templateUrl: require('./resizeCapacity.component.html'),
10
+ controller: () => {},
11
+ };
12
+
13
+ export const ECS_RESIZE_CAPACITY_COMPONENT = 'spinnaker.ecs.serverGroup.resize';
14
+ module(ECS_RESIZE_CAPACITY_COMPONENT, []).component('ecsResizeCapacity', resizeCapacityComponent);