@spinnaker/ecs 2026.2.4 → 2026.3.1

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 (209) hide show
  1. package/dist/ecs.module.d.ts +3 -1
  2. package/dist/ecsCluster/ecsCluster.read.service.d.ts +2 -3
  3. package/dist/iamRoles/iamRole.read.service.d.ts +1 -2
  4. package/dist/index.d.ts +5 -0
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/instance/details/EcsInstanceDetails.d.ts +50 -0
  8. package/dist/loadBalancer/loadBalancer.transformer.d.ts +1 -5
  9. package/dist/loadBalancer/targetGroup.states.d.ts +2 -1
  10. package/dist/metricAlarm/metricAlarm.read.service.d.ts +1 -2
  11. package/dist/pipeline/stages/cloneServerGroup/ecsCloneServerGroupStage.d.ts +1 -0
  12. package/dist/pipeline/stages/common/EcsServerGroupStepLabel.d.ts +7 -0
  13. package/dist/pipeline/stages/common/EcsStageConfigs.d.ts +11 -0
  14. package/dist/pipeline/stages/destroyAsg/ecsDestroyAsgStage.d.ts +1 -2
  15. package/dist/pipeline/stages/disableAsg/ecsDisableAsgStage.d.ts +1 -2
  16. package/dist/pipeline/stages/disableCluster/ecsDisableClusterStage.d.ts +1 -2
  17. package/dist/pipeline/stages/enableAsg/ecsEnableAsgStage.d.ts +1 -2
  18. package/dist/pipeline/stages/findImageFromTags/EcsFindImageFromTagsExecutionDetails.d.ts +5 -0
  19. package/dist/pipeline/stages/findImageFromTags/ecsFindImageFromTagStage.d.ts +1 -2
  20. package/dist/pipeline/stages/resizeAsg/ecsResizeAsgStage.d.ts +1 -2
  21. package/dist/pipeline/stages/scaleDownCluster/ecsScaleDownClusterStage.d.ts +1 -2
  22. package/dist/pipeline/stages/shrinkCluster/ecsShrinkClusterStage.d.ts +1 -2
  23. package/dist/placementStrategy/placementStrategy.service.d.ts +0 -1
  24. package/dist/secrets/secret.read.service.d.ts +1 -2
  25. package/dist/securityGroup/details/EcsSecurityGroupDetails.d.ts +45 -0
  26. package/dist/securityGroup/securityGroup.reader.d.ts +0 -1
  27. package/dist/securityGroup/securityGroup.transformer.d.ts +3 -2
  28. package/dist/serverGroup/configure/dockerImage.util.d.ts +3 -0
  29. package/dist/serverGroup/configure/serverGroupCommandBuilder.service.d.ts +111 -2
  30. package/dist/serverGroup/configure/serverGroupConfiguration.service.d.ts +13 -63
  31. package/dist/serverGroup/configure/wizard/EcsCloneServerGroupModal.d.ts +64 -0
  32. package/dist/serverGroup/configure/wizard/capacityProvider/CapacityProvider.d.ts +29 -4
  33. package/dist/serverGroup/configure/wizard/container/Container.d.ts +3 -3
  34. package/dist/serverGroup/configure/wizard/networking/Networking.d.ts +3 -3
  35. package/dist/serverGroup/configure/wizard/pages/AdvancedSettings.d.ts +3 -0
  36. package/dist/serverGroup/configure/wizard/pages/BasicSettings.d.ts +3 -0
  37. package/dist/serverGroup/configure/wizard/pages/ContainerSettings.d.ts +3 -0
  38. package/dist/serverGroup/configure/wizard/pages/HorizontalScalingSettings.d.ts +3 -0
  39. package/dist/serverGroup/configure/wizard/pages/LoggingSettings.d.ts +3 -0
  40. package/dist/serverGroup/configure/wizard/pages/NetworkingSettings.d.ts +3 -0
  41. package/dist/serverGroup/configure/wizard/pages/ServiceDiscoverySettings.d.ts +3 -0
  42. package/dist/serverGroup/configure/wizard/pages/TaskDefinitionSettings.d.ts +3 -0
  43. package/dist/serverGroup/configure/wizard/pages/common.d.ts +8 -0
  44. package/dist/serverGroup/configure/wizard/pages/validation.d.ts +22 -0
  45. package/dist/serverGroup/configure/wizard/serviceDiscovery/ServiceDiscovery.d.ts +5 -3
  46. package/dist/serverGroup/configure/wizard/taskDefinition/TaskDefinition.d.ts +3 -3
  47. package/dist/serverGroup/details/EcsServerGroupActions.d.ts +6 -0
  48. package/dist/serverGroup/details/ecsServerGroupDetailsGetter.d.ts +3 -0
  49. package/dist/serverGroup/details/resize/EcsResizeServerGroupModal.d.ts +43 -0
  50. package/dist/serverGroup/details/resize/index.d.ts +1 -0
  51. package/dist/serverGroup/details/rollback/EcsRollbackServerGroupModal.d.ts +46 -0
  52. package/dist/serverGroup/details/rollback/index.d.ts +1 -0
  53. package/dist/serverGroup/details/sections/EcsServerGroupDetailsSections.d.ts +9 -0
  54. package/dist/serverGroup/details/sections/EcsServerGroupEventsSection.d.ts +3 -0
  55. package/dist/serverGroup/details/sections/EcsServerGroupInformationSection.d.ts +3 -0
  56. package/dist/serverGroup/events/EcsServerGroupEventsModal.d.ts +22 -0
  57. package/dist/serverGroup/events/EventsLink.d.ts +2 -0
  58. package/dist/serverGroup/events/serverGroupEventsReader.service.d.ts +1 -1
  59. package/dist/serverGroup/serverGroup.transformer.d.ts +1 -2
  60. package/dist/serviceDiscovery/serviceDiscovery.read.service.d.ts +1 -1
  61. package/package.json +3 -9
  62. package/src/ecs.module.spec.ts +86 -0
  63. package/src/ecs.module.ts +68 -84
  64. package/src/ecsCluster/ecsCluster.read.service.ts +3 -9
  65. package/src/iamRoles/iamRole.read.service.ts +1 -7
  66. package/src/index.ts +6 -0
  67. package/src/instance/details/EcsInstanceDetails.spec.tsx +426 -0
  68. package/src/instance/details/EcsInstanceDetails.tsx +474 -0
  69. package/src/loadBalancer/details/loadBalancerDetails.tsx +1 -1
  70. package/src/loadBalancer/details/targetGroupDetails.tsx +1 -1
  71. package/src/loadBalancer/loadBalancer.transformer.ts +2 -7
  72. package/src/loadBalancer/targetGroup.states.ts +55 -53
  73. package/src/metricAlarm/metricAlarm.read.service.ts +1 -7
  74. package/src/pipeline/stages/cloneServerGroup/ecsCloneServerGroupStage.js +22 -94
  75. package/src/pipeline/stages/common/EcsServerGroupStepLabel.tsx +16 -0
  76. package/src/pipeline/stages/common/EcsStageConfigs.tsx +587 -0
  77. package/src/pipeline/stages/destroyAsg/ecsDestroyAsgStage.js +29 -65
  78. package/src/pipeline/stages/disableAsg/ecsDisableAsgStage.js +27 -70
  79. package/src/pipeline/stages/disableCluster/ecsDisableClusterStage.js +21 -84
  80. package/src/pipeline/stages/enableAsg/ecsEnableAsgStage.js +22 -73
  81. package/src/pipeline/stages/findImageFromTags/EcsFindImageFromTagsExecutionDetails.tsx +40 -0
  82. package/src/pipeline/stages/findImageFromTags/ecsFindImageFromTagStage.js +12 -24
  83. package/src/pipeline/stages/resizeAsg/ecsResizeAsgStage.js +30 -128
  84. package/src/pipeline/stages/scaleDownCluster/ecsScaleDownClusterStage.js +24 -78
  85. package/src/pipeline/stages/shrinkCluster/ecsShrinkClusterStage.js +19 -73
  86. package/src/placementStrategy/placementStrategy.service.ts +0 -6
  87. package/src/secrets/secret.read.service.ts +1 -7
  88. package/src/securityGroup/details/EcsSecurityGroupDetails.spec.tsx +245 -0
  89. package/src/securityGroup/details/EcsSecurityGroupDetails.tsx +285 -0
  90. package/src/securityGroup/securityGroup.reader.ts +0 -5
  91. package/src/securityGroup/securityGroup.transformer.js +5 -13
  92. package/src/serverGroup/configure/dockerImage.util.ts +29 -0
  93. package/src/serverGroup/configure/serverGroupCommandBuilder.service.js +215 -278
  94. package/src/serverGroup/configure/serverGroupCommandBuilder.service.spec.ts +83 -0
  95. package/src/serverGroup/configure/serverGroupConfiguration.service.ts +16 -633
  96. package/src/serverGroup/configure/wizard/EcsCloneServerGroupModal.spec.tsx +2078 -0
  97. package/src/serverGroup/configure/wizard/EcsCloneServerGroupModal.tsx +712 -0
  98. package/src/serverGroup/configure/wizard/capacityProvider/CapacityProvider.tsx +98 -49
  99. package/src/serverGroup/configure/wizard/container/Container.spec.tsx +20 -8
  100. package/src/serverGroup/configure/wizard/container/Container.tsx +53 -24
  101. package/src/serverGroup/configure/wizard/networking/Networking.tsx +60 -38
  102. package/src/serverGroup/configure/wizard/pages/AdvancedSettings.tsx +290 -0
  103. package/src/serverGroup/configure/wizard/pages/BasicSettings.tsx +101 -0
  104. package/src/serverGroup/configure/wizard/pages/ContainerSettings.tsx +10 -0
  105. package/src/serverGroup/configure/wizard/pages/HorizontalScalingSettings.tsx +137 -0
  106. package/src/serverGroup/configure/wizard/pages/LoggingSettings.tsx +60 -0
  107. package/src/serverGroup/configure/wizard/pages/NetworkingSettings.tsx +10 -0
  108. package/src/serverGroup/configure/wizard/pages/ServiceDiscoverySettings.tsx +10 -0
  109. package/src/serverGroup/configure/wizard/pages/TaskDefinitionSettings.tsx +59 -0
  110. package/src/serverGroup/configure/wizard/pages/common.ts +10 -0
  111. package/src/serverGroup/configure/wizard/pages/validation.tsx +190 -0
  112. package/src/serverGroup/configure/wizard/serviceDiscovery/ServiceDiscovery.tsx +83 -34
  113. package/src/serverGroup/configure/wizard/taskDefinition/TaskDefinition.spec.tsx +21 -8
  114. package/src/serverGroup/configure/wizard/taskDefinition/TaskDefinition.tsx +63 -33
  115. package/src/serverGroup/details/EcsServerGroupActions.spec.tsx +244 -0
  116. package/src/serverGroup/details/EcsServerGroupActions.tsx +152 -0
  117. package/src/serverGroup/details/ecsServerGroupDetailsGetter.spec.ts +110 -0
  118. package/src/serverGroup/details/ecsServerGroupDetailsGetter.ts +73 -0
  119. package/src/serverGroup/details/resize/EcsResizeServerGroupModal.spec.tsx +130 -0
  120. package/src/serverGroup/details/resize/EcsResizeServerGroupModal.tsx +263 -0
  121. package/src/serverGroup/details/resize/index.ts +1 -0
  122. package/src/serverGroup/details/rollback/EcsRollbackServerGroupModal.spec.tsx +173 -0
  123. package/src/serverGroup/details/rollback/EcsRollbackServerGroupModal.tsx +285 -0
  124. package/src/serverGroup/details/rollback/index.ts +1 -0
  125. package/src/serverGroup/details/sections/EcsServerGroupDetailsSections.spec.tsx +130 -0
  126. package/src/serverGroup/details/sections/EcsServerGroupDetailsSections.tsx +172 -0
  127. package/src/serverGroup/details/sections/EcsServerGroupEventsSection.tsx +14 -0
  128. package/src/serverGroup/details/sections/EcsServerGroupInformationSection.tsx +25 -0
  129. package/src/serverGroup/events/EcsServerGroupEventsModal.spec.tsx +109 -0
  130. package/src/serverGroup/events/EcsServerGroupEventsModal.tsx +112 -0
  131. package/src/serverGroup/events/EventsLink.tsx +18 -0
  132. package/src/serverGroup/events/serverGroupEventsReader.service.spec.ts +41 -0
  133. package/src/serverGroup/events/serverGroupEventsReader.service.ts +2 -8
  134. package/src/serverGroup/serverGroup.transformer.spec.ts +10 -24
  135. package/src/serverGroup/serverGroup.transformer.ts +1 -5
  136. package/src/serviceDiscovery/serviceDiscovery.read.service.ts +1 -1
  137. package/dist/common/common.module.d.ts +0 -1
  138. package/dist/common/footer.component.d.ts +0 -1
  139. package/dist/instance/details/instance.details.controller.d.ts +0 -2
  140. package/dist/securityGroup/details/securityGroupDetail.controller.d.ts +0 -2
  141. package/dist/securityGroup/securityGroup.module.d.ts +0 -1
  142. package/dist/serverGroup/configure/wizard/CloneServerGroup.ecs.controller.d.ts +0 -2
  143. package/dist/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.d.ts +0 -2
  144. package/dist/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.d.ts +0 -2
  145. package/dist/serverGroup/configure/wizard/location/ServerGroupBasicSettings.controller.d.ts +0 -2
  146. package/dist/serverGroup/configure/wizard/logging/logging.component.d.ts +0 -1
  147. package/dist/serverGroup/details/resize/resizeCapacity.component.d.ts +0 -1
  148. package/dist/serverGroup/details/resize/resizeServerGroup.controller.d.ts +0 -2
  149. package/dist/serverGroup/details/rollback/rollbackServerGroup.controller.d.ts +0 -2
  150. package/dist/serverGroup/details/serverGroupDetails.ecs.controller.d.ts +0 -2
  151. package/dist/serverGroup/details/serverGroupDetails.module.d.ts +0 -1
  152. package/dist/serverGroup/events/events.component.d.ts +0 -3
  153. package/dist/serverGroup/events/events.controller.d.ts +0 -19
  154. package/dist/serverGroup/serverGroup.module.d.ts +0 -1
  155. package/src/common/common.module.ts +0 -6
  156. package/src/common/footer.component.ts +0 -29
  157. package/src/instance/details/instance.details.controller.js +0 -356
  158. package/src/instance/details/instanceDetails.html +0 -204
  159. package/src/pipeline/stages/cloneServerGroup/cloneServerGroupStage.html +0 -101
  160. package/src/pipeline/stages/cloneServerGroup/cloneServerGroupStepLabel.html +0 -1
  161. package/src/pipeline/stages/destroyAsg/destroyAsgStage.html +0 -9
  162. package/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html +0 -1
  163. package/src/pipeline/stages/disableAsg/disableAsgStage.html +0 -11
  164. package/src/pipeline/stages/disableAsg/disableAsgStepLabel.html +0 -1
  165. package/src/pipeline/stages/disableCluster/disableClusterStage.html +0 -26
  166. package/src/pipeline/stages/enableAsg/enableAsgStage.html +0 -11
  167. package/src/pipeline/stages/enableAsg/enableAsgStepLabel.html +0 -1
  168. package/src/pipeline/stages/findImageFromTags/findImageFromTagsExecutionDetails.html +0 -36
  169. package/src/pipeline/stages/findImageFromTags/findImageFromTagsStage.html +0 -9
  170. package/src/pipeline/stages/resizeAsg/resizeAsgStage.html +0 -87
  171. package/src/pipeline/stages/resizeAsg/resizeAsgStepLabel.html +0 -1
  172. package/src/pipeline/stages/scaleDownCluster/scaleDownClusterStage.html +0 -35
  173. package/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html +0 -34
  174. package/src/securityGroup/details/securityGroupDetail.controller.js +0 -147
  175. package/src/securityGroup/details/securityGroupDetail.html +0 -104
  176. package/src/securityGroup/securityGroup.module.ts +0 -12
  177. package/src/serverGroup/configure/wizard/CloneServerGroup.ecs.controller.js +0 -259
  178. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.html +0 -194
  179. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.component.js +0 -17
  180. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.html +0 -10
  181. package/src/serverGroup/configure/wizard/capacityProvider/capacityProvider.html +0 -11
  182. package/src/serverGroup/configure/wizard/container/container.html +0 -9
  183. package/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.html +0 -118
  184. package/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.component.js +0 -20
  185. package/src/serverGroup/configure/wizard/horizontalScaling/horizontalScaling.html +0 -13
  186. package/src/serverGroup/configure/wizard/location/ServerGroupBasicSettings.controller.js +0 -41
  187. package/src/serverGroup/configure/wizard/location/basicSettings.html +0 -137
  188. package/src/serverGroup/configure/wizard/logging/logging.component.html +0 -29
  189. package/src/serverGroup/configure/wizard/logging/logging.component.ts +0 -12
  190. package/src/serverGroup/configure/wizard/logging/logging.html +0 -7
  191. package/src/serverGroup/configure/wizard/networking/networking.html +0 -9
  192. package/src/serverGroup/configure/wizard/serverGroupWizard.html +0 -55
  193. package/src/serverGroup/configure/wizard/serviceDiscovery/serviceDiscovery.html +0 -11
  194. package/src/serverGroup/configure/wizard/taskDefinition/taskDefinition.html +0 -51
  195. package/src/serverGroup/configure/wizard/templateSelection/templateSelection.html +0 -9
  196. package/src/serverGroup/configure/wizard/verticalScaling/verticalScaling.html +0 -10
  197. package/src/serverGroup/details/resize/resizeCapacity.component.html +0 -94
  198. package/src/serverGroup/details/resize/resizeCapacity.component.ts +0 -14
  199. package/src/serverGroup/details/resize/resizeServerGroup.controller.js +0 -85
  200. package/src/serverGroup/details/resize/resizeServerGroup.html +0 -28
  201. package/src/serverGroup/details/rollback/rollbackServerGroup.controller.js +0 -97
  202. package/src/serverGroup/details/rollback/rollbackServerGroup.html +0 -67
  203. package/src/serverGroup/details/serverGroupDetails.ecs.controller.js +0 -366
  204. package/src/serverGroup/details/serverGroupDetails.html +0 -216
  205. package/src/serverGroup/details/serverGroupDetails.module.ts +0 -5
  206. package/src/serverGroup/events/events.component.ts +0 -35
  207. package/src/serverGroup/events/events.controller.ts +0 -45
  208. package/src/serverGroup/events/events.html +0 -36
  209. package/src/serverGroup/serverGroup.module.ts +0 -6
@@ -1,19 +1,17 @@
1
- import { module } from 'angular';
2
- import { isEqual, uniqWith } from 'lodash';
1
+ import { isEqual, uniq, uniqWith } from 'lodash';
3
2
  import * as React from 'react';
4
3
  import { Alert } from 'react-bootstrap';
5
4
  import type { Option } from 'react-select';
6
- import { react2angular } from 'react2angular';
7
5
 
8
6
  import type { ISubnet } from '@spinnaker/core';
9
- import { HelpField, TetheredSelect, withErrorBoundary } from '@spinnaker/core';
7
+ import { HelpField, TetheredSelect } from '@spinnaker/core';
10
8
 
11
9
  import type { IEcsServerGroupCommand } from '../../serverGroupConfiguration.service';
12
10
 
13
11
  export interface IEcsNetworkingProps {
14
12
  command: IEcsServerGroupCommand;
15
- notifyAngular: (key: string, value: any) => void;
16
- configureCommand: (query: string) => PromiseLike<void>;
13
+ onFieldChange: (key: string, value: any) => void;
14
+ configureCommand: (query: string) => Promise<void>;
17
15
  }
18
16
 
19
17
  interface IEcsNetworkingState {
@@ -43,20 +41,22 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
43
41
 
44
42
  cmd.subnetTypes = uniqWith(defaultSubnetTypes, isEqual);
45
43
 
44
+ const availableSubnetTypes = cmd.backingData?.filtered?.subnetTypes || [];
45
+ const persistedSubnetTypes = cmd.subnetTypes
46
+ .filter((purpose) => !availableSubnetTypes.some((subnet) => subnet.purpose === purpose))
47
+ .map((purpose) => ({ purpose, vpcId: cmd.vpcId || 'unavailable' } as ISubnet));
48
+
46
49
  this.state = {
47
50
  associatePublicIpAddress: cmd.associatePublicIpAddress,
48
51
  networkMode: cmd.networkMode,
49
- networkModesAvailable: cmd.backingData && cmd.backingData.networkModes ? cmd.backingData.networkModes : [],
52
+ networkModesAvailable: uniq([...(cmd.backingData?.networkModes || []), cmd.networkMode]).filter(Boolean),
50
53
  securityGroupNames: cmd.securityGroupNames,
51
- securityGroupsAvailable:
52
- cmd.backingData && cmd.backingData.filtered && cmd.backingData.filtered.securityGroupNames
53
- ? cmd.backingData.filtered.securityGroupNames
54
- : [],
54
+ securityGroupsAvailable: uniq([
55
+ ...(cmd.backingData?.filtered?.securityGroupNames || []),
56
+ ...(cmd.securityGroupNames || []),
57
+ ]),
55
58
  subnetTypes: cmd.subnetTypes,
56
- subnetTypesAvailable:
57
- cmd.backingData && cmd.backingData.filtered && cmd.backingData.filtered.subnetTypes
58
- ? cmd.backingData.filtered.subnetTypes
59
- : [],
59
+ subnetTypesAvailable: [...availableSubnetTypes, ...persistedSubnetTypes],
60
60
  };
61
61
  }
62
62
 
@@ -65,23 +65,52 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
65
65
 
66
66
  this.props.configureCommand('1').then(() => {
67
67
  this.setState({
68
- networkModesAvailable: cmd.backingData && cmd.backingData.networkModes ? cmd.backingData.networkModes : [],
69
- securityGroupsAvailable:
70
- cmd.backingData && cmd.backingData.filtered && cmd.backingData.filtered.securityGroupNames
71
- ? cmd.backingData.filtered.securityGroupNames
72
- : [],
73
- subnetTypesAvailable:
74
- cmd.backingData && cmd.backingData.filtered && cmd.backingData.filtered.subnetTypes
75
- ? cmd.backingData.filtered.subnetTypes
76
- : [],
68
+ networkModesAvailable: uniq([...(cmd.backingData?.networkModes || []), cmd.networkMode]).filter(Boolean),
69
+ securityGroupsAvailable: uniq([
70
+ ...(cmd.backingData?.filtered?.securityGroupNames || []),
71
+ ...(cmd.securityGroupNames || []),
72
+ ]),
73
+ subnetTypesAvailable: [
74
+ ...(cmd.backingData?.filtered?.subnetTypes || []),
75
+ ...(cmd.subnetTypes || [])
76
+ .filter(
77
+ (purpose) => !(cmd.backingData?.filtered?.subnetTypes || []).some((subnet) => subnet.purpose === purpose),
78
+ )
79
+ .map((purpose) => ({ purpose, vpcId: cmd.vpcId || 'unavailable' } as ISubnet)),
80
+ ],
77
81
  });
78
82
  });
79
83
  }
80
84
 
85
+ public componentDidUpdate() {
86
+ const cmd = this.props.command;
87
+ const availableSubnetTypes = cmd.backingData?.filtered?.subnetTypes || [];
88
+ const nextState: IEcsNetworkingState = {
89
+ associatePublicIpAddress: cmd.associatePublicIpAddress,
90
+ networkMode: cmd.networkMode,
91
+ networkModesAvailable: uniq([...(cmd.backingData?.networkModes || []), cmd.networkMode]).filter(Boolean),
92
+ securityGroupNames: cmd.securityGroupNames || [],
93
+ securityGroupsAvailable: uniq([
94
+ ...(cmd.backingData?.filtered?.securityGroupNames || []),
95
+ ...(cmd.securityGroupNames || []),
96
+ ]),
97
+ subnetTypes: cmd.subnetTypes || [],
98
+ subnetTypesAvailable: [
99
+ ...availableSubnetTypes,
100
+ ...(cmd.subnetTypes || [])
101
+ .filter((purpose) => !availableSubnetTypes.some((subnet) => subnet.purpose === purpose))
102
+ .map((purpose) => ({ purpose, vpcId: cmd.vpcId || 'unavailable' } as ISubnet)),
103
+ ],
104
+ };
105
+ if (!isEqual(this.state, nextState)) {
106
+ this.setState(nextState);
107
+ }
108
+ }
109
+
81
110
  private updateNetworkMode = (newNetworkMode: Option<string>) => {
82
111
  const updatedNetworkMode = newNetworkMode.value;
83
112
  const cmd = this.props.command;
84
- this.props.notifyAngular('networkMode', updatedNetworkMode);
113
+ this.props.onFieldChange('networkMode', updatedNetworkMode);
85
114
  this.setState({
86
115
  networkMode: updatedNetworkMode,
87
116
  subnetTypesAvailable:
@@ -95,7 +124,7 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
95
124
  const updatedSecurityGroups = Array.isArray(newSecurityGroups)
96
125
  ? newSecurityGroups.map((securityGroups) => securityGroups.value)
97
126
  : [];
98
- this.props.notifyAngular('securityGroupNames', updatedSecurityGroups);
127
+ this.props.onFieldChange('securityGroupNames', updatedSecurityGroups);
99
128
  this.setState({ securityGroupNames: updatedSecurityGroups });
100
129
  };
101
130
 
@@ -104,7 +133,7 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
104
133
  const updatedSubnetTypes = Array.isArray(newSubnetTypes)
105
134
  ? newSubnetTypes.map((subnetType) => subnetType.value)
106
135
  : [];
107
- this.props.notifyAngular('subnetTypes', updatedSubnetTypes);
136
+ this.props.onFieldChange('subnetTypes', updatedSubnetTypes);
108
137
  cmd.subnetTypeChanged(cmd);
109
138
  this.setState({
110
139
  subnetTypes: updatedSubnetTypes,
@@ -116,7 +145,7 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
116
145
  };
117
146
 
118
147
  private updateAssociatePublicIpAddress = (usePublicIp: boolean) => {
119
- this.props.notifyAngular('associatePublicIpAddress', usePublicIp);
148
+ this.props.onFieldChange('associatePublicIpAddress', usePublicIp);
120
149
  this.setState({ associatePublicIpAddress: usePublicIp });
121
150
  };
122
151
 
@@ -140,6 +169,7 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
140
169
 
141
170
  const subnetTypeOptions = this.state.subnetTypesAvailable.length ? (
142
171
  <TetheredSelect
172
+ inputProps={{ 'aria-label': 'VPC subnet' }}
143
173
  multi={true}
144
174
  options={subnetTypesAvailable}
145
175
  value={this.state.subnetTypes}
@@ -153,6 +183,7 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
153
183
 
154
184
  const securityGroupsOptions = this.state.securityGroupsAvailable.length ? (
155
185
  <TetheredSelect
186
+ inputProps={{ 'aria-label': 'Security groups' }}
156
187
  multi={true}
157
188
  options={securityGroupsAvailable}
158
189
  value={this.state.securityGroupNames}
@@ -234,6 +265,7 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
234
265
  </div>
235
266
  <div className="col-md-9" data-test-id="Networking.networkMode">
236
267
  <TetheredSelect
268
+ inputProps={{ 'aria-label': 'Network mode' }}
237
269
  placeholder="Select a network mode to use ..."
238
270
  options={networkModesAvailable}
239
271
  value={this.state.networkMode}
@@ -249,13 +281,3 @@ export class EcsNetworking extends React.Component<IEcsNetworkingProps, IEcsNetw
249
281
  );
250
282
  }
251
283
  }
252
-
253
- export const ECS_NETWORKING_REACT = 'spinnaker.ecs.serverGroup.configure.wizard.networking.react';
254
- module(ECS_NETWORKING_REACT, []).component(
255
- 'ecsNetworkingReact',
256
- react2angular(withErrorBoundary(EcsNetworking, 'ecsNetworkingReact'), [
257
- 'command',
258
- 'notifyAngular',
259
- 'configureCommand',
260
- ]),
261
- );
@@ -0,0 +1,290 @@
1
+ import React from 'react';
2
+
3
+ import { HelpField, MapEditor } from '@spinnaker/core';
4
+
5
+ import type { IEcsWizardPageProps } from './common';
6
+
7
+ const placementStrategies = [
8
+ 'AZ Balanced Spread',
9
+ 'AZ Balanced BinPack CPU',
10
+ 'AZ Balanced BinPack Memory',
11
+ 'BinPack CPU',
12
+ 'BinPack Memory',
13
+ 'One Task Per Host',
14
+ 'None',
15
+ ];
16
+
17
+ export const AdvancedSettings = ({ command, onFieldChange }: IEcsWizardPageProps) => {
18
+ const placementConstraints = command.placementConstraints || [];
19
+ const iamRoles = Array.from(new Set([...(command.backingData.filtered.iamRoles || []), command.iamRole])).filter(
20
+ Boolean,
21
+ );
22
+ const secrets = Array.from(
23
+ new Set([...(command.backingData.filtered.secrets || []), command.dockerImageCredentialsSecret]),
24
+ ).filter(Boolean);
25
+ const updateConstraint = (index: number, field: string, value: string) => {
26
+ const constraints = placementConstraints.map((constraint: any, constraintIndex: number) =>
27
+ constraintIndex === index ? { ...constraint, [field]: value } : constraint,
28
+ );
29
+ onFieldChange('placementConstraints', constraints);
30
+ };
31
+
32
+ return (
33
+ <div className="container-fluid form-horizontal" data-test-id="EcsServerGroupWizard.advancedSettings">
34
+ <div className="form-group">
35
+ <div className="col-md-5 sm-label-right">
36
+ Health Check Grace Period <HelpField id="ecs.healthgraceperiod" />
37
+ </div>
38
+ <div className="col-md-2">
39
+ <input
40
+ aria-label="Health check grace period"
41
+ className="form-control input-sm no-spel"
42
+ data-test-id="Advanced.healthCheckGracePeriodSeconds"
43
+ onChange={(event) =>
44
+ onFieldChange(
45
+ 'healthCheckGracePeriodSeconds',
46
+ event.target.value === '' ? '' : Number(event.target.value),
47
+ )
48
+ }
49
+ type="number"
50
+ value={command.healthCheckGracePeriodSeconds ?? ''}
51
+ />
52
+ </div>
53
+ </div>
54
+
55
+ <div className="form-group">
56
+ <div className="col-md-5 sm-label-right">
57
+ <b>ECS IAM Instance Profile</b> <HelpField id="ecs.iamrole" />
58
+ </div>
59
+ <div className="col-md-7">
60
+ {iamRoles.length ? (
61
+ <select
62
+ aria-label="ECS IAM instance profile"
63
+ className="form-control input-sm"
64
+ data-test-id="Advanced.iamRole"
65
+ onChange={(event) => onFieldChange('iamRole', event.target.value)}
66
+ value={command.iamRole || ''}
67
+ >
68
+ {iamRoles.map((iamRole) => (
69
+ <option key={iamRole} value={iamRole}>
70
+ {iamRole}
71
+ </option>
72
+ ))}
73
+ </select>
74
+ ) : (
75
+ 'No account was selected, or no IAM roles are available for ECS tasks in this account.'
76
+ )}
77
+ </div>
78
+ </div>
79
+
80
+ {!command.useTaskDefinitionArtifact && (
81
+ <div className="form-group">
82
+ <div className="col-md-5 sm-label-right">
83
+ <b>Docker Image Credentials</b> <HelpField id="ecs.dockerimagecredentials" />
84
+ </div>
85
+ <div className="col-md-7">
86
+ {secrets.length ? (
87
+ <select
88
+ aria-label="Docker image credentials"
89
+ className="form-control input-sm"
90
+ data-test-id="Advanced.dockerImageCredentialsSecret"
91
+ onChange={(event) => onFieldChange('dockerImageCredentialsSecret', event.target.value)}
92
+ value={command.dockerImageCredentialsSecret || ''}
93
+ >
94
+ {secrets.map((secret) => (
95
+ <option key={secret} value={secret}>
96
+ {secret}
97
+ </option>
98
+ ))}
99
+ </select>
100
+ ) : (
101
+ 'No account or region was selected, or no AWS Secrets Manager secrets are available in this account and region.'
102
+ )}
103
+ </div>
104
+ </div>
105
+ )}
106
+
107
+ <div className="form-group">
108
+ <div className="col-md-5 sm-label-right">
109
+ Fargate platform version <HelpField id="ecs.platformVersion" />
110
+ </div>
111
+ <div className="col-md-3">
112
+ <input
113
+ aria-label="Fargate platform version"
114
+ className="form-control input-sm"
115
+ data-test-id="Advanced.platformVersion"
116
+ onChange={(event) => onFieldChange('platformVersion', event.target.value)}
117
+ type="text"
118
+ value={command.platformVersion || ''}
119
+ />
120
+ </div>
121
+ </div>
122
+
123
+ <div className="form-group">
124
+ <div className="col-md-5 sm-label-right">
125
+ Enable Deployment Circuit Breaker <HelpField id="ecs.enableDeploymentCircuitBreaker" />
126
+ </div>
127
+ <div className="col-md-3">
128
+ <input
129
+ aria-label="Enable deployment circuit breaker"
130
+ checked={!!command.enableDeploymentCircuitBreaker}
131
+ data-test-id="Advanced.enableDeploymentCircuitBreaker"
132
+ onChange={(event) => onFieldChange('enableDeploymentCircuitBreaker', event.target.checked)}
133
+ type="checkbox"
134
+ />
135
+ </div>
136
+ </div>
137
+
138
+ <div className="form-group">
139
+ <div className="col-md-5 sm-label-right">
140
+ <b>Placement Strategy</b> <HelpField id="ecs.placementStrategy" />
141
+ </div>
142
+ <div className="col-md-7">
143
+ <select
144
+ aria-label="Placement strategy"
145
+ className="form-control input-sm"
146
+ data-test-id="Advanced.placementStrategyName"
147
+ onChange={(event) => onFieldChange('placementStrategyName', event.target.value)}
148
+ value={command.placementStrategyName || ''}
149
+ >
150
+ <option value="">Select...</option>
151
+ {placementStrategies.map((strategy) => (
152
+ <option key={strategy} value={strategy}>
153
+ {strategy}
154
+ </option>
155
+ ))}
156
+ </select>
157
+ </div>
158
+ </div>
159
+
160
+ <div className="form-group">
161
+ <div className="sm-label-left">
162
+ <b>Placement Constraints</b> <HelpField id="ecs.placementConstraints" />
163
+ </div>
164
+ <table className="table table-condensed packed tags">
165
+ <thead>
166
+ <tr>
167
+ <th style={{ width: '25%' }}>Type</th>
168
+ <th style={{ width: '68%' }}>Expression</th>
169
+ <th />
170
+ </tr>
171
+ </thead>
172
+ <tbody>
173
+ {placementConstraints.map((constraint: any, index: number) => (
174
+ <tr key={index}>
175
+ <td>
176
+ <select
177
+ aria-label={`Placement constraint type ${index + 1}`}
178
+ className="form-control input-sm"
179
+ data-test-id={`Advanced.placementConstraint.type.${index}`}
180
+ onChange={(event) => updateConstraint(index, 'type', event.target.value)}
181
+ value={constraint.type || ''}
182
+ >
183
+ <option value="">Select...</option>
184
+ <option value="distinctInstance">distinctInstance</option>
185
+ <option value="memberOf">memberOf</option>
186
+ </select>
187
+ </td>
188
+ <td>
189
+ <input
190
+ aria-label={`Placement constraint expression ${index + 1}`}
191
+ className="form-control input-sm no-spel"
192
+ data-test-id={`Advanced.placementConstraint.expression.${index}`}
193
+ onChange={(event) => updateConstraint(index, 'expression', event.target.value)}
194
+ type="text"
195
+ value={constraint.expression || ''}
196
+ />
197
+ </td>
198
+ <td>
199
+ <button
200
+ aria-label={`Remove placement constraint ${index + 1}`}
201
+ className="btn btn-link sm-label"
202
+ onClick={() =>
203
+ onFieldChange(
204
+ 'placementConstraints',
205
+ placementConstraints.filter(
206
+ (_constraint: any, constraintIndex: number) => constraintIndex !== index,
207
+ ),
208
+ )
209
+ }
210
+ type="button"
211
+ >
212
+ <span className="glyphicon glyphicon-trash" /> <span className="sr-only">Remove</span>
213
+ </button>
214
+ </td>
215
+ </tr>
216
+ ))}
217
+ </tbody>
218
+ <tfoot>
219
+ <tr>
220
+ <td colSpan={3}>
221
+ <button
222
+ className="btn btn-block btn-sm add-new"
223
+ onClick={() => onFieldChange('placementConstraints', [...placementConstraints, {}])}
224
+ type="button"
225
+ >
226
+ <span className="glyphicon glyphicon-plus-sign" /> Add New Placement Constraint
227
+ </button>
228
+ </td>
229
+ </tr>
230
+ </tfoot>
231
+ </table>
232
+ </div>
233
+
234
+ {!command.useTaskDefinitionArtifact && (
235
+ <>
236
+ <div className="form-group" data-test-id="Advanced.dockerLabels">
237
+ <div className="sm-label-left">
238
+ <b>Docker labels (optional)</b> <HelpField id="ecs.dockerLabels" />
239
+ </div>
240
+ <MapEditor
241
+ allowEmpty={true}
242
+ keyLabel="Docker label name"
243
+ model={command.dockerLabels || {}}
244
+ onChange={(dockerLabels) => onFieldChange('dockerLabels', dockerLabels)}
245
+ valueLabel="Docker label value"
246
+ />
247
+ </div>
248
+ <div className="form-group" data-test-id="Advanced.environmentVariables">
249
+ <div className="sm-label-left">
250
+ <b>Environment Variables (optional)</b> <HelpField id="ecs.environmentVariables" />
251
+ </div>
252
+ <MapEditor
253
+ allowEmpty={true}
254
+ keyLabel="Environment variable name"
255
+ model={command.environmentVariables || {}}
256
+ onChange={(environmentVariables) => onFieldChange('environmentVariables', environmentVariables)}
257
+ valueLabel="Environment variable value"
258
+ />
259
+ </div>
260
+ </>
261
+ )}
262
+
263
+ <div className="form-group" data-test-id="Advanced.tags">
264
+ <div className="sm-label-left">
265
+ <b>Tags (optional)</b> <HelpField id="ecs.tags" />
266
+ </div>
267
+ <MapEditor
268
+ allowEmpty={true}
269
+ keyLabel="Tag name"
270
+ model={command.tags || {}}
271
+ onChange={(tags) => onFieldChange('tags', tags)}
272
+ valueLabel="Tag value"
273
+ />
274
+ </div>
275
+
276
+ {command.useTaskDefinitionArtifact && (
277
+ <div style={{ color: '#666' }}>
278
+ <hr />
279
+ <p>
280
+ <em>
281
+ <strong>Docker Image Credentials, Docker labels</strong>, and <strong>Environment Variables</strong>{' '}
282
+ cannot be individually set when using a Task Definition artifact. Please include them in their respective
283
+ container definition in that file.
284
+ </em>
285
+ </p>
286
+ </div>
287
+ )}
288
+ </div>
289
+ );
290
+ };
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+
3
+ import { AccountSelectInput, DeploymentStrategySelector, NameUtils, RegionSelectInput } from '@spinnaker/core';
4
+
5
+ import type { IEcsWizardPageProps } from './common';
6
+
7
+ const fieldValue = (value: any) => value?.target?.value ?? value;
8
+
9
+ export const BasicSettings = ({ application, command, onFieldChange }: IEcsWizardPageProps) => {
10
+ const accounts = command.backingData.accounts || Object.keys(command.backingData.credentialsKeyedByAccount || {});
11
+ const regions = command.backingData.filtered.regions || [];
12
+ const clusters = command.backingData.filtered.ecsClusters || [];
13
+
14
+ return (
15
+ <div className="container-fluid form-horizontal" data-test-id="EcsServerGroupWizard.basicSettings">
16
+ <div className="form-group">
17
+ <div className="col-md-3 sm-label-right">Account</div>
18
+ <div className="col-md-7">
19
+ <AccountSelectInput
20
+ aria-label="Account"
21
+ accounts={accounts}
22
+ onChange={(value) => onFieldChange('credentials', fieldValue(value))}
23
+ provider="ecs"
24
+ readOnly={command.viewState.readOnlyFields?.credentials}
25
+ value={command.credentials || ''}
26
+ />
27
+ </div>
28
+ </div>
29
+ <div className="form-group">
30
+ <div className="col-md-3 sm-label-right">Region</div>
31
+ <div className="col-md-7">
32
+ <RegionSelectInput
33
+ aria-label="Region"
34
+ account={command.credentials}
35
+ onChange={(value) => onFieldChange('region', fieldValue(value))}
36
+ readOnly={command.viewState.readOnlyFields?.region}
37
+ regions={regions}
38
+ value={command.region || ''}
39
+ />
40
+ </div>
41
+ </div>
42
+ <div className="form-group">
43
+ <div className="col-md-3 sm-label-right">ECS Cluster name</div>
44
+ <div className="col-md-7">
45
+ <select
46
+ aria-label="ECS Cluster name"
47
+ className="form-control input-sm"
48
+ data-test-id="ServerGroup.clusterName"
49
+ onChange={(event) => onFieldChange('ecsClusterName', event.target.value)}
50
+ required
51
+ value={command.ecsClusterName || ''}
52
+ >
53
+ <option value="">Select...</option>
54
+ {clusters.map((cluster) => (
55
+ <option key={cluster} value={cluster}>
56
+ {cluster}
57
+ </option>
58
+ ))}
59
+ </select>
60
+ </div>
61
+ </div>
62
+ <div className="form-group">
63
+ <div className="col-md-3 sm-label-right">Stack</div>
64
+ <div className="col-md-7">
65
+ <input
66
+ aria-label="Stack"
67
+ className="form-control input-sm no-spel"
68
+ data-test-id="ServerGroup.stack"
69
+ onChange={(event) => onFieldChange('stack', event.target.value)}
70
+ value={command.stack || ''}
71
+ />
72
+ </div>
73
+ </div>
74
+ <div className="form-group">
75
+ <div className="col-md-3 sm-label-right">Detail</div>
76
+ <div className="col-md-7">
77
+ <input
78
+ aria-label="Detail"
79
+ className="form-control input-sm no-spel"
80
+ data-test-id="ServerGroup.details"
81
+ onChange={(event) => onFieldChange('freeFormDetails', event.target.value)}
82
+ value={command.freeFormDetails || ''}
83
+ />
84
+ </div>
85
+ </div>
86
+ {!command.viewState.disableStrategySelection && command.selectedProvider && (
87
+ <DeploymentStrategySelector
88
+ command={command as any}
89
+ onFieldChange={onFieldChange}
90
+ onStrategyChange={(_updatedCommand, strategy) => onFieldChange('strategy', strategy.key)}
91
+ />
92
+ )}
93
+ {!command.viewState.hideClusterNamePreview && (
94
+ <div className="well-compact well text-center">
95
+ Your server group will be in the cluster:{' '}
96
+ <strong>{NameUtils.getClusterName(application.name, command.stack, command.freeFormDetails)}</strong>
97
+ </div>
98
+ )}
99
+ </div>
100
+ );
101
+ };
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+
3
+ import type { IEcsWizardPageProps } from './common';
4
+ import { Container } from '../container/Container';
5
+
6
+ export const ContainerSettings = ({ command, configureCommand, onFieldChange }: IEcsWizardPageProps) => (
7
+ <div data-test-id="EcsServerGroupWizard.container">
8
+ <Container command={command} configureCommand={configureCommand} onFieldChange={onFieldChange} />
9
+ </div>
10
+ );