@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,10 +1,9 @@
1
- import { module } from 'angular';
1
+ import { isEqual } from 'lodash';
2
2
  import React from 'react';
3
3
  import { Alert } from 'react-bootstrap';
4
4
  import type { Option } from 'react-select';
5
- import { react2angular } from 'react2angular';
6
5
 
7
- import { HelpField, TetheredSelect, withErrorBoundary } from '@spinnaker/core';
6
+ import { HelpField, TetheredSelect } from '@spinnaker/core';
8
7
 
9
8
  import type {
10
9
  IEcsServerGroupCommand,
@@ -13,8 +12,8 @@ import type {
13
12
 
14
13
  export interface IServiceDiscoveryProps {
15
14
  command: IEcsServerGroupCommand;
16
- notifyAngular: (key: string, value: any) => void;
17
- configureCommand: (query: string) => PromiseLike<void>;
15
+ onFieldChange: (key: string, value: any) => void;
16
+ configureCommand: (query: string) => Promise<void>;
18
17
  }
19
18
 
20
19
  export interface IEcsServiceDiscoveryRegistry {
@@ -37,37 +36,87 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
37
36
  super(props);
38
37
  const cmd = this.props.command;
39
38
 
39
+ const serviceDiscoveryAssociations = this.normalizeContainerNames(
40
+ cmd.serviceDiscoveryAssociations || [],
41
+ cmd.useTaskDefinitionArtifact,
42
+ );
43
+ cmd.serviceDiscoveryAssociations = serviceDiscoveryAssociations;
40
44
  this.state = {
41
- serviceDiscoveryAssociations: cmd.serviceDiscoveryAssociations,
42
- serviceDiscoveryRegistriesAvailable:
43
- cmd.backingData && cmd.backingData.filtered ? cmd.backingData.filtered.serviceDiscoveryRegistries : [],
45
+ serviceDiscoveryAssociations,
46
+ serviceDiscoveryRegistriesAvailable: this.mergeRegistries(
47
+ cmd.backingData?.filtered?.serviceDiscoveryRegistries || [],
48
+ serviceDiscoveryAssociations,
49
+ ),
44
50
  useTaskDefinitionArtifact: cmd.useTaskDefinitionArtifact,
45
51
  };
46
-
47
- if (!this.state.useTaskDefinitionArtifact) {
48
- this.state.serviceDiscoveryAssociations.forEach((serviceDiscoveryRegistryAssociation) => {
49
- serviceDiscoveryRegistryAssociation.containerName = null;
50
- });
51
- }
52
52
  }
53
53
 
54
54
  public componentDidMount() {
55
55
  this.props.configureCommand('1').then(() => {
56
56
  this.setState({
57
- serviceDiscoveryRegistriesAvailable: this.props.command.backingData.filtered.serviceDiscoveryRegistries,
57
+ serviceDiscoveryRegistriesAvailable: this.mergeRegistries(
58
+ this.props.command.backingData.filtered.serviceDiscoveryRegistries || [],
59
+ this.state.serviceDiscoveryAssociations,
60
+ ),
58
61
  });
59
62
  });
60
63
  }
61
64
 
65
+ public componentDidUpdate() {
66
+ const cmd = this.props.command;
67
+ const currentAssociations = cmd.serviceDiscoveryAssociations || [];
68
+ const serviceDiscoveryAssociations = this.normalizeContainerNames(
69
+ currentAssociations,
70
+ cmd.useTaskDefinitionArtifact,
71
+ );
72
+ if (!isEqual(currentAssociations, serviceDiscoveryAssociations)) {
73
+ cmd.serviceDiscoveryAssociations = serviceDiscoveryAssociations;
74
+ this.props.onFieldChange('serviceDiscoveryAssociations', serviceDiscoveryAssociations);
75
+ }
76
+ const nextState: IServiceDiscoveryState = {
77
+ serviceDiscoveryAssociations,
78
+ serviceDiscoveryRegistriesAvailable: this.mergeRegistries(
79
+ cmd.backingData?.filtered?.serviceDiscoveryRegistries || [],
80
+ serviceDiscoveryAssociations,
81
+ ),
82
+ useTaskDefinitionArtifact: cmd.useTaskDefinitionArtifact,
83
+ };
84
+ if (!isEqual(this.state, nextState)) {
85
+ this.setState(nextState);
86
+ }
87
+ }
88
+
89
+ private normalizeContainerNames = (
90
+ associations: IEcsServiceDiscoveryRegistryAssociation[],
91
+ useTaskDefinitionArtifact: boolean,
92
+ ): IEcsServiceDiscoveryRegistryAssociation[] => {
93
+ const normalized = associations.map((association) => ({
94
+ ...association,
95
+ containerName: useTaskDefinitionArtifact ? association.containerName || '' : null,
96
+ }));
97
+ return isEqual(associations, normalized) ? associations : normalized;
98
+ };
99
+
62
100
  private getNameToRegistryMap = (): Map<string, IEcsServiceDiscoveryRegistry> => {
63
101
  const displayNameToRegistry = new Map<string, IEcsServiceDiscoveryRegistry>();
64
- this.props.command.backingData.filtered.serviceDiscoveryRegistries.forEach((e) => {
102
+ this.state.serviceDiscoveryRegistriesAvailable.forEach((e) => {
65
103
  displayNameToRegistry.set(e.displayName, e);
66
104
  });
67
105
 
68
106
  return displayNameToRegistry;
69
107
  };
70
108
 
109
+ private mergeRegistries = (
110
+ available: IEcsServiceDiscoveryRegistry[],
111
+ associations: IEcsServiceDiscoveryRegistryAssociation[],
112
+ ): IEcsServiceDiscoveryRegistry[] => {
113
+ const registries = new Map<string, IEcsServiceDiscoveryRegistry>();
114
+ [...available, ...associations.map((association) => association.registry)].filter(Boolean).forEach((registry) => {
115
+ registries.set(registry.displayName, registry as IEcsServiceDiscoveryRegistry);
116
+ });
117
+ return Array.from(registries.values());
118
+ };
119
+
71
120
  private getEmptyRegistry = (): IEcsServiceDiscoveryRegistry => {
72
121
  return {
73
122
  account: '',
@@ -90,7 +139,7 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
90
139
  const currentAssociations = this.state.serviceDiscoveryAssociations;
91
140
  const targetAssociation = currentAssociations[index];
92
141
  targetAssociation.registry = newServiceDiscoveryRegistry;
93
- this.props.notifyAngular('serviceDiscoveryAssociations', currentAssociations);
142
+ this.props.onFieldChange('serviceDiscoveryAssociations', currentAssociations);
94
143
  this.setState({ serviceDiscoveryAssociations: currentAssociations });
95
144
  };
96
145
 
@@ -98,7 +147,7 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
98
147
  const currentAssociations = this.state.serviceDiscoveryAssociations;
99
148
  const targetAssociations = currentAssociations[index];
100
149
  targetAssociations.containerPort = targetPort;
101
- this.props.notifyAngular('serviceDiscoveryAssociations', currentAssociations);
150
+ this.props.onFieldChange('serviceDiscoveryAssociations', currentAssociations);
102
151
  this.setState({ serviceDiscoveryAssociations: currentAssociations });
103
152
  };
104
153
 
@@ -106,7 +155,7 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
106
155
  const currentAssociations = this.state.serviceDiscoveryAssociations;
107
156
  const targetAssociations = currentAssociations[index];
108
157
  targetAssociations.containerName = targetContainerName;
109
- this.props.notifyAngular('serviceDiscoveryAssociations', currentAssociations);
158
+ this.props.onFieldChange('serviceDiscoveryAssociations', currentAssociations);
110
159
  this.setState({ serviceDiscoveryAssociations: currentAssociations });
111
160
  };
112
161
 
@@ -119,7 +168,7 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
119
168
  private removeServiceDiscoveryAssociations = (index: number) => {
120
169
  const currentAssociations = this.state.serviceDiscoveryAssociations;
121
170
  currentAssociations.splice(index, 1);
122
- this.props.notifyAngular('serviceDiscoveryAssociations', currentAssociations);
171
+ this.props.onFieldChange('serviceDiscoveryAssociations', currentAssociations);
123
172
  this.setState({ serviceDiscoveryAssociations: currentAssociations });
124
173
  };
125
174
 
@@ -140,7 +189,9 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
140
189
  {useTaskDefinitionArtifact && (
141
190
  <td>
142
191
  <input
192
+ aria-label={`Container name ${index + 1}`}
143
193
  className="form-control input-sm"
194
+ data-test-id="ServiceDiscovery.containerName"
144
195
  placeholder="Enter a container name ..."
145
196
  required={true}
146
197
  value={mapping.containerName}
@@ -148,8 +199,9 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
148
199
  />
149
200
  </td>
150
201
  )}
151
- <td>
202
+ <td data-test-id="ServiceDiscovery.registry">
152
203
  <TetheredSelect
204
+ inputProps={{ 'aria-label': `Service registry ${index + 1}` }}
153
205
  placeholder="Select a registry..."
154
206
  options={registriesAvailable}
155
207
  value={mapping.registry.displayName.toString()}
@@ -160,6 +212,8 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
160
212
  </td>
161
213
  <td>
162
214
  <input
215
+ aria-label={`Container port ${index + 1}`}
216
+ data-test-id="ServiceDiscovery.containerPort"
163
217
  type="number"
164
218
  className="form-control input-sm no-spel"
165
219
  required={true}
@@ -169,10 +223,15 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
169
223
  </td>
170
224
  <td>
171
225
  <div className="form-control-static">
172
- <a className="btn-link sm-label" onClick={() => removeServiceDiscoveryAssociation(index)}>
226
+ <button
227
+ aria-label={`Remove service registry ${index + 1}`}
228
+ className="btn-link sm-label"
229
+ onClick={() => removeServiceDiscoveryAssociation(index)}
230
+ type="button"
231
+ >
173
232
  <span className="glyphicon glyphicon-trash" />
174
233
  <span className="sr-only">Remove</span>
175
- </a>
234
+ </button>
176
235
  </div>
177
236
  </td>
178
237
  </tr>
@@ -180,7 +239,7 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
180
239
  });
181
240
 
182
241
  const newServiceDiscoveryAssociation = this.state.serviceDiscoveryRegistriesAvailable.length ? (
183
- <button className="btn btn-block btn-sm add-new" onClick={this.pushServiceDiscoveryAssociation}>
242
+ <button className="btn btn-block btn-sm add-new" onClick={this.pushServiceDiscoveryAssociation} type="button">
184
243
  <span className="glyphicon glyphicon-plus-sign" />
185
244
  Add New Service Registry
186
245
  </button>
@@ -238,13 +297,3 @@ export class ServiceDiscovery extends React.Component<IServiceDiscoveryProps, IS
238
297
  );
239
298
  }
240
299
  }
241
-
242
- export const SERVICE_DISCOVERY_REACT = 'spinnaker.ecs.serverGroup.configure.wizard.serviceDiscovery.react';
243
- module(SERVICE_DISCOVERY_REACT, []).component(
244
- 'serviceDiscoveryReact',
245
- react2angular(withErrorBoundary(ServiceDiscovery, 'serviceDiscoveryReact'), [
246
- 'command',
247
- 'notifyAngular',
248
- 'configureCommand',
249
- ]),
250
- );
@@ -15,7 +15,7 @@ describe('TaskDefinition', () => {
15
15
  let command: IEcsServerGroupCommand;
16
16
 
17
17
  const configureCommand = (_query: string) => Promise.resolve() as PromiseLike<void>;
18
- const notifyAngular = (_key: string, _value: any) => {};
18
+ const onFieldChange = (_key: string, _value: any) => {};
19
19
 
20
20
  const dockerAccounts: IAccountDetails[] = [
21
21
  {
@@ -48,13 +48,14 @@ describe('TaskDefinition', () => {
48
48
  } as any) as IEcsServerGroupCommand;
49
49
 
50
50
  spyOn(AccountService, 'listAccounts').and.returnValue(Promise.resolve(dockerAccounts));
51
+ spyOn(AccountService, 'getArtifactAccounts').and.returnValue(Promise.resolve([]));
51
52
  spyOn(DockerImageReader, 'findImages').and.returnValue(Promise.resolve(dockerImages));
52
53
  });
53
54
 
54
55
  describe('updateDockerRegistryAccount', () => {
55
56
  it('calls DockerImageReader.findImages with the selected account', async () => {
56
57
  const wrapper = mount(
57
- <TaskDefinition command={command} notifyAngular={notifyAngular} configureCommand={configureCommand} />,
58
+ <TaskDefinition command={command} onFieldChange={onFieldChange} configureCommand={configureCommand} />,
58
59
  );
59
60
 
60
61
  await flushPromises();
@@ -70,21 +71,33 @@ describe('TaskDefinition', () => {
70
71
 
71
72
  it('updates component state and backingData with images returned for the account', async () => {
72
73
  const wrapper = mount(
73
- <TaskDefinition command={command} notifyAngular={notifyAngular} configureCommand={configureCommand} />,
74
+ <TaskDefinition command={command} onFieldChange={onFieldChange} configureCommand={configureCommand} />,
74
75
  );
75
76
 
76
77
  (wrapper.instance() as any).updateDockerRegistryAccount({ value: 'my-docker-account' });
77
78
  await flushPromises();
78
79
  wrapper.update();
79
80
 
80
- expect((wrapper.instance() as TaskDefinition).state.dockerImages).toEqual(dockerImages as IEcsDockerImage[]);
81
- expect(command.backingData.filtered.images).toEqual(dockerImages as IEcsDockerImage[]);
81
+ const expectedImages = [
82
+ {
83
+ ...dockerImages[0],
84
+ imageId: 'my-registry/my-repo:latest',
85
+ message: '',
86
+ fromTrigger: false,
87
+ fromContext: false,
88
+ stageId: '',
89
+ imageLabelOrSha: '',
90
+ },
91
+ ];
92
+
93
+ expect((wrapper.instance() as TaskDefinition).state.dockerImages).toEqual(expectedImages as IEcsDockerImage[]);
94
+ expect(command.backingData.filtered.images).toEqual(expectedImages as IEcsDockerImage[]);
82
95
  });
83
96
 
84
97
  it('clears existing images immediately when account changes', () => {
85
98
  command.backingData.filtered.images = dockerImages as IEcsDockerImage[];
86
99
  const wrapper = mount(
87
- <TaskDefinition command={command} notifyAngular={notifyAngular} configureCommand={configureCommand} />,
100
+ <TaskDefinition command={command} onFieldChange={onFieldChange} configureCommand={configureCommand} />,
88
101
  );
89
102
 
90
103
  (wrapper.instance() as any).updateDockerRegistryAccount({ value: 'my-docker-account' });
@@ -107,7 +120,7 @@ describe('TaskDefinition', () => {
107
120
  } as IEcsDockerImage;
108
121
 
109
122
  const wrapper = mount(
110
- <TaskDefinition command={command} notifyAngular={notifyAngular} configureCommand={configureCommand} />,
123
+ <TaskDefinition command={command} onFieldChange={onFieldChange} configureCommand={configureCommand} />,
111
124
  );
112
125
 
113
126
  expect((wrapper.instance() as TaskDefinition).state.selectedDockerAccount).toBe('my-docker-account');
@@ -115,7 +128,7 @@ describe('TaskDefinition', () => {
115
128
 
116
129
  it('starts with no account selected when imageDescription has no account', () => {
117
130
  const wrapper = mount(
118
- <TaskDefinition command={command} notifyAngular={notifyAngular} configureCommand={configureCommand} />,
131
+ <TaskDefinition command={command} onFieldChange={onFieldChange} configureCommand={configureCommand} />,
119
132
  );
120
133
 
121
134
  expect((wrapper.instance() as TaskDefinition).state.selectedDockerAccount).toBe('');
@@ -1,9 +1,7 @@
1
- import { module } from 'angular';
2
- import { isEqual, uniqWith } from 'lodash';
1
+ import { isEqual, uniq, uniqWith } from 'lodash';
3
2
  import 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 { IAccountDetails, IArtifact, IExpectedArtifact } from '@spinnaker/core';
9
7
  import {
@@ -14,10 +12,10 @@ import {
14
12
  StageArtifactSelectorDelegate,
15
13
  StageConfigField,
16
14
  TetheredSelect,
17
- withErrorBoundary,
18
15
  } from '@spinnaker/core';
19
16
  import { DockerImageReader } from '@spinnaker/docker';
20
17
 
18
+ import { normalizeEcsDockerImage } from '../../dockerImage.util';
21
19
  import type {
22
20
  IEcsContainerMapping,
23
21
  IEcsDockerImage,
@@ -28,8 +26,8 @@ import type {
28
26
 
29
27
  export interface ITaskDefinitionProps {
30
28
  command: IEcsServerGroupCommand;
31
- notifyAngular: (key: string, value: any) => void;
32
- configureCommand: (query: string) => PromiseLike<void>;
29
+ onFieldChange: (key: string, value: any) => void;
30
+ configureCommand: (query: string) => Promise<void>;
33
31
  }
34
32
 
35
33
  interface ITaskDefinitionState {
@@ -75,7 +73,10 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
75
73
  taskDefArtifact: cmd.taskDefinitionArtifact,
76
74
  containerMappings: cmd.containerMappings ? cmd.containerMappings : [],
77
75
  targetGroupMappings: cmd.targetGroupMappings,
78
- targetGroupsAvailable: cmd.backingData && cmd.backingData.filtered ? cmd.backingData.filtered.targetGroups : [],
76
+ targetGroupsAvailable: uniq([
77
+ ...(cmd.backingData?.filtered?.targetGroups || []),
78
+ ...cmd.targetGroupMappings.map((mapping) => mapping.targetGroup).filter(Boolean),
79
+ ]),
79
80
  dockerImages: cmd.backingData && cmd.backingData.filtered ? cmd.backingData.filtered.images : [],
80
81
  dockerRegistryAccounts: [],
81
82
  selectedDockerAccount: cmd.imageDescription?.account ?? '',
@@ -94,21 +95,49 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
94
95
  this.props.configureCommand('1').then(() => {
95
96
  this.setState({
96
97
  dockerImages: this.props.command.backingData.filtered.images,
97
- targetGroupsAvailable: this.props.command.backingData.filtered.targetGroups,
98
+ targetGroupsAvailable: uniq([
99
+ ...(this.props.command.backingData.filtered.targetGroups || []),
100
+ ...this.state.targetGroupMappings.map((mapping) => mapping.targetGroup).filter(Boolean),
101
+ ]),
98
102
  });
99
103
  });
100
104
  }
101
105
 
102
106
  private updateDockerRegistryAccount = (newAccount: Option<string>) => {
103
107
  const account = newAccount.value;
108
+ this.props.command.backingData.filtered.images = [];
104
109
  this.setState({ selectedDockerAccount: account, dockerImages: [] });
105
110
  DockerImageReader.findImages({ provider: 'dockerRegistry', account, count: 50 }).then((images) => {
106
- const ecsImages = images as IEcsDockerImage[];
111
+ const ecsImages = images.map((image) => normalizeEcsDockerImage(image));
107
112
  this.props.command.backingData.filtered.images = ecsImages;
108
113
  this.setState({ dockerImages: ecsImages });
109
114
  });
110
115
  };
111
116
 
117
+ public componentDidUpdate() {
118
+ const cmd = this.props.command;
119
+ const containerMappings = cmd.containerMappings || [];
120
+ const targetGroupMappings = cmd.targetGroupMappings || [];
121
+ const nextState: ITaskDefinitionState = {
122
+ taskDefArtifact: cmd.taskDefinitionArtifact,
123
+ taskDefArtifactAccount: cmd.taskDefinitionArtifactAccount,
124
+ containerMappings,
125
+ targetGroupMappings,
126
+ dockerImages: cmd.backingData?.filtered?.images || [],
127
+ targetGroupsAvailable: uniq([
128
+ ...(cmd.backingData?.filtered?.targetGroups || []),
129
+ ...targetGroupMappings.map((mapping) => mapping.targetGroup).filter(Boolean),
130
+ ]),
131
+ loadBalancedContainer: cmd.loadBalancedContainer || containerMappings[0]?.containerName || '',
132
+ evaluateTaskDefinitionArtifactExpressions: cmd.evaluateTaskDefinitionArtifactExpressions,
133
+ dockerRegistryAccounts: this.state.dockerRegistryAccounts,
134
+ selectedDockerAccount: this.state.selectedDockerAccount,
135
+ };
136
+ if (!isEqual(this.state, nextState)) {
137
+ this.setState(nextState);
138
+ }
139
+ }
140
+
112
141
  private getIdToImageMap = (): Map<string, IEcsDockerImage> => {
113
142
  const imageIdToDescription = new Map<string, IEcsDockerImage>();
114
143
  this.props.command.backingData.filtered.images.forEach((e) => {
@@ -141,13 +170,13 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
141
170
 
142
171
  private onExpectedArtifactSelected = (expectedArtifactId: string): void => {
143
172
  const selectedArtifact = { artifactId: expectedArtifactId };
144
- this.props.notifyAngular('taskDefinitionArtifact', selectedArtifact);
173
+ this.props.onFieldChange('taskDefinitionArtifact', selectedArtifact);
145
174
  this.setState({ taskDefArtifact: selectedArtifact });
146
175
  };
147
176
 
148
177
  private onArtifactEdited = (artifact: IArtifact): void => {
149
178
  const newArtifact = { artifact: artifact };
150
- this.props.notifyAngular('taskDefinitionArtifact', newArtifact);
179
+ this.props.onFieldChange('taskDefinitionArtifact', newArtifact);
151
180
  this.setState({ taskDefArtifact: newArtifact });
152
181
  };
153
182
 
@@ -167,7 +196,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
167
196
  const currentMappings = this.state.containerMappings;
168
197
  const targetMapping = currentMappings[index];
169
198
  targetMapping.containerName = newName;
170
- this.props.notifyAngular('containerMappings', currentMappings);
199
+ this.props.onFieldChange('containerMappings', currentMappings);
171
200
  this.setState({ containerMappings: currentMappings });
172
201
  };
173
202
 
@@ -181,7 +210,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
181
210
  const currentMappings = this.state.containerMappings;
182
211
  const targetMapping = currentMappings[index];
183
212
  targetMapping.imageDescription = newImageDescription;
184
- this.props.notifyAngular('containerMappings', currentMappings);
213
+ this.props.onFieldChange('containerMappings', currentMappings);
185
214
  this.setState({ containerMappings: currentMappings });
186
215
  };
187
216
 
@@ -189,7 +218,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
189
218
  const currentMappings = this.state.targetGroupMappings;
190
219
  const targetMapping = currentMappings[index];
191
220
  targetMapping.targetGroup = newTargetGroup.value;
192
- this.props.notifyAngular('targetGroupMappings', currentMappings);
221
+ this.props.onFieldChange('targetGroupMappings', currentMappings);
193
222
  this.setState({ targetGroupMappings: currentMappings });
194
223
  };
195
224
 
@@ -197,7 +226,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
197
226
  const currentMappings = this.state.targetGroupMappings;
198
227
  const targetMapping = currentMappings[index];
199
228
  targetMapping.containerName = targetContainer;
200
- this.props.notifyAngular('targetGroupMappings', currentMappings);
229
+ this.props.onFieldChange('targetGroupMappings', currentMappings);
201
230
  this.setState({ targetGroupMappings: currentMappings });
202
231
  };
203
232
 
@@ -205,26 +234,26 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
205
234
  const currentMappings = this.state.targetGroupMappings;
206
235
  const targetMapping = currentMappings[index];
207
236
  targetMapping.containerPort = targetPort;
208
- this.props.notifyAngular('targetGroupMappings', currentMappings);
237
+ this.props.onFieldChange('targetGroupMappings', currentMappings);
209
238
  this.setState({ targetGroupMappings: currentMappings });
210
239
  };
211
240
 
212
241
  private removeMapping = (index: number) => {
213
242
  const currentMappings = this.state.containerMappings;
214
243
  currentMappings.splice(index, 1);
215
- this.props.notifyAngular('containerMappings', currentMappings);
244
+ this.props.onFieldChange('containerMappings', currentMappings);
216
245
  this.setState({ containerMappings: currentMappings });
217
246
  };
218
247
 
219
248
  private removeTargetGroupMapping = (index: number) => {
220
249
  const currentMappings = this.state.targetGroupMappings;
221
250
  currentMappings.splice(index, 1);
222
- this.props.notifyAngular('targetGroupMappings', currentMappings);
251
+ this.props.onFieldChange('targetGroupMappings', currentMappings);
223
252
  this.setState({ targetGroupMappings: currentMappings });
224
253
  };
225
254
 
226
255
  private updateEvaluateTaskDefArtifactFlag = () => {
227
- this.props.notifyAngular(
256
+ this.props.onFieldChange(
228
257
  'evaluateTaskDefinitionArtifactExpressions',
229
258
  !this.props.command.evaluateTaskDefinitionArtifactExpressions,
230
259
  );
@@ -266,6 +295,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
266
295
  <tr key={index}>
267
296
  <td>
268
297
  <input
298
+ aria-label={`Container name ${index + 1}`}
269
299
  data-test-id="Artifacts.containerName"
270
300
  className="form-control input-sm"
271
301
  required={true}
@@ -276,6 +306,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
276
306
  </td>
277
307
  <td data-test-id="Artifacts.containerImage">
278
308
  <TetheredSelect
309
+ inputProps={{ 'aria-label': `Container image ${index + 1}` }}
279
310
  placeholder="Select an image to use..."
280
311
  options={dockerImageOptions}
281
312
  value={mapping.imageDescription.imageId}
@@ -287,14 +318,16 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
287
318
  </td>
288
319
  <td>
289
320
  <div className="form-control-static">
290
- <a
321
+ <button
322
+ aria-label={`Remove container mapping ${index + 1}`}
291
323
  className="btn-link sm-label"
292
324
  data-test-id="Artifacts.containerRemove"
293
325
  onClick={() => removeMapping(index)}
326
+ type="button"
294
327
  >
295
328
  <span className="glyphicon glyphicon-trash" />
296
329
  <span className="sr-only">Remove</span>
297
- </a>
330
+ </button>
298
331
  </div>
299
332
  </td>
300
333
  </tr>
@@ -306,6 +339,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
306
339
  <tr key={index}>
307
340
  <td>
308
341
  <input
342
+ aria-label={`Target group container name ${index + 1}`}
309
343
  data-test-id="Artifacts.targetGroupContainer"
310
344
  className="form-control input-sm"
311
345
  required={true}
@@ -316,6 +350,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
316
350
  </td>
317
351
  <td data-test-id="Artifacts.targetGroup">
318
352
  <TetheredSelect
353
+ inputProps={{ 'aria-label': `Target group ${index + 1}` }}
319
354
  placeholder="Select a target group to use..."
320
355
  options={targetGroupsAvailable}
321
356
  value={mapping.targetGroup.toString()}
@@ -325,6 +360,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
325
360
  </td>
326
361
  <td>
327
362
  <input
363
+ aria-label={`Target port ${index + 1}`}
328
364
  data-test-id="Artifacts.targetGroupPort"
329
365
  type="number"
330
366
  className="form-control input-sm no-spel"
@@ -335,14 +371,16 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
335
371
  </td>
336
372
  <td>
337
373
  <div className="form-control-static">
338
- <a
374
+ <button
375
+ aria-label={`Remove target group mapping ${index + 1}`}
339
376
  className="btn-link sm-label"
340
377
  data-test-id="Artifacts.targetGroupRemove"
341
378
  onClick={() => removeTargetGroupMapping(index)}
379
+ type="button"
342
380
  >
343
381
  <span className="glyphicon glyphicon-trash" />
344
382
  <span className="sr-only">Remove</span>
345
- </a>
383
+ </button>
346
384
  </div>
347
385
  </td>
348
386
  </tr>
@@ -354,6 +392,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
354
392
  className="btn btn-block btn-sm add-new"
355
393
  data-test-id="Artifacts.targetGroupAdd"
356
394
  onClick={this.pushTargetGroupMapping}
395
+ type="button"
357
396
  >
358
397
  <span className="glyphicon glyphicon-plus-sign" />
359
398
  Add New Target Group Mapping
@@ -441,6 +480,7 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
441
480
  className="btn btn-block btn-sm add-new"
442
481
  data-test-id="Artifacts.containerAdd"
443
482
  onClick={this.pushMapping}
483
+ type="button"
444
484
  >
445
485
  <span className="glyphicon glyphicon-plus-sign" />
446
486
  Add New Container Mapping
@@ -488,13 +528,3 @@ export class TaskDefinition extends React.Component<ITaskDefinitionProps, ITaskD
488
528
  );
489
529
  }
490
530
  }
491
-
492
- export const TASK_DEFINITION_REACT = 'spinnaker.ecs.serverGroup.configure.wizard.taskDefinition.react';
493
- module(TASK_DEFINITION_REACT, []).component(
494
- 'taskDefinitionReact',
495
- react2angular(withErrorBoundary(TaskDefinition, 'taskDefinitionReact'), [
496
- 'command',
497
- 'notifyAngular',
498
- 'configureCommand',
499
- ]),
500
- );