@spinnaker/azure 2026.2.2 → 2026.3.0

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 (215) hide show
  1. package/dist/azure.module.d.ts +3 -1
  2. package/dist/image/image.reader.d.ts +4 -2
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/instance/azureInstanceType.service.d.ts +6 -2
  6. package/dist/instance/details/AzureInstanceDetails.d.ts +67 -0
  7. package/dist/loadBalancer/configure/AzureLoadBalancerChoiceModal.d.ts +10 -5
  8. package/dist/loadBalancer/configure/AzureLoadBalancerModal.d.ts +102 -0
  9. package/dist/loadBalancer/details/azureLoadBalancerDetails.d.ts +26 -0
  10. package/dist/loadBalancer/loadBalancer.transformer.d.ts +45 -2
  11. package/dist/pipeline/stages/AzureAccountRegionClusterSelector.d.ts +32 -0
  12. package/dist/pipeline/stages/bake/azureBakeStage.d.ts +46 -2
  13. package/dist/pipeline/stages/destroyAsg/azureDestroyAsgStage.d.ts +14 -2
  14. package/dist/pipeline/stages/disableAsg/azureDisableAsgStage.d.ts +4 -2
  15. package/dist/pipeline/stages/enableAsg/azureEnableAsgStage.d.ts +4 -2
  16. package/dist/securityGroup/configure/AzureSecurityGroupModal.d.ts +70 -0
  17. package/dist/securityGroup/details/AzureSecurityGroupDetails.d.ts +51 -0
  18. package/dist/securityGroup/securityGroup.reader.d.ts +3 -2
  19. package/dist/securityGroup/securityGroup.transformer.d.ts +3 -2
  20. package/dist/securityGroup/securityGroup.write.service.d.ts +9 -2
  21. package/dist/serverGroup/configure/serverGroupCommandBuilder.service.d.ts +88 -2
  22. package/dist/serverGroup/configure/serverGroupConfiguration.service.d.ts +30 -2
  23. package/dist/serverGroup/configure/wizard/AzureCloneServerGroupModal.d.ts +44 -0
  24. package/dist/serverGroup/configure/wizard/pages/ServerGroupAdvancedSettings.d.ts +8 -0
  25. package/dist/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.d.ts +12 -0
  26. package/dist/serverGroup/configure/wizard/pages/ServerGroupCapacityAndZones.d.ts +11 -0
  27. package/dist/serverGroup/configure/wizard/pages/ServerGroupHealthSettings.d.ts +10 -0
  28. package/dist/serverGroup/configure/wizard/pages/ServerGroupImageSettings.d.ts +12 -0
  29. package/dist/serverGroup/configure/wizard/pages/ServerGroupInstanceType.d.ts +9 -0
  30. package/dist/serverGroup/configure/wizard/pages/ServerGroupLoadBalancers.d.ts +14 -0
  31. package/dist/serverGroup/configure/wizard/pages/ServerGroupNetworkSettings.d.ts +10 -0
  32. package/dist/serverGroup/configure/wizard/pages/ServerGroupSecurityGroups.d.ts +6 -0
  33. package/dist/serverGroup/configure/wizard/pages/ServerGroupTags.d.ts +9 -0
  34. package/dist/serverGroup/configure/wizard/pages/common.d.ts +14 -0
  35. package/dist/serverGroup/configure/wizard/pages/index.d.ts +10 -0
  36. package/dist/serverGroup/details/azureServerGroupDetails.d.ts +13 -0
  37. package/dist/serverGroup/details/rollback/RollbackServerGroupModal.d.ts +6 -4
  38. package/dist/serverGroup/serverGroup.transformer.d.ts +61 -2
  39. package/dist/validation/applicationName.validator.d.ts +6 -2
  40. package/package.json +5 -8
  41. package/src/azure.module.spec.ts +921 -0
  42. package/src/azure.module.ts +56 -68
  43. package/src/image/image.reader.js +4 -15
  44. package/src/image/image.reader.spec.js +4 -7
  45. package/src/instance/azureInstanceType.service.js +8 -16
  46. package/src/instance/azureInstanceType.service.spec.js +5 -13
  47. package/src/instance/details/AzureInstanceDetails.spec.tsx +364 -0
  48. package/src/instance/details/AzureInstanceDetails.tsx +533 -0
  49. package/src/loadBalancer/configure/AzureLoadBalancerChoiceModal.spec.tsx +125 -0
  50. package/src/loadBalancer/configure/AzureLoadBalancerChoiceModal.tsx +46 -26
  51. package/src/loadBalancer/configure/AzureLoadBalancerModal.spec.tsx +658 -0
  52. package/src/loadBalancer/configure/AzureLoadBalancerModal.tsx +960 -0
  53. package/src/loadBalancer/details/azureLoadBalancerDetails.spec.tsx +470 -0
  54. package/src/loadBalancer/details/azureLoadBalancerDetails.tsx +412 -0
  55. package/src/loadBalancer/loadBalancer.transformer.js +83 -93
  56. package/src/pipeline/stages/AzureAccountRegionClusterSelector.tsx +238 -0
  57. package/src/pipeline/stages/bake/azureBakeStage.tsx +723 -0
  58. package/src/pipeline/stages/destroyAsg/azureDestroyAsgStage.tsx +128 -0
  59. package/src/pipeline/stages/disableAsg/azureDisableAsgStage.tsx +92 -0
  60. package/src/pipeline/stages/enableAsg/azureEnableAsgStage.tsx +87 -0
  61. package/src/routerConsumers.spec.tsx +69 -0
  62. package/src/securityGroup/configure/AzureSecurityGroupModal.spec.tsx +558 -0
  63. package/src/securityGroup/configure/AzureSecurityGroupModal.tsx +782 -0
  64. package/src/securityGroup/details/AzureSecurityGroupDetails.spec.tsx +291 -0
  65. package/src/securityGroup/details/AzureSecurityGroupDetails.tsx +354 -0
  66. package/src/securityGroup/securityGroup.reader.js +3 -13
  67. package/src/securityGroup/securityGroup.transformer.js +3 -13
  68. package/src/securityGroup/securityGroup.write.service.spec.ts +105 -0
  69. package/src/securityGroup/securityGroup.write.service.ts +73 -0
  70. package/src/serverGroup/configure/serverGroupCommandBuilder.service.js +167 -166
  71. package/src/serverGroup/configure/serverGroupCommandBuilder.service.spec.js +63 -0
  72. package/src/serverGroup/configure/serverGroupConfiguration.service.js +325 -309
  73. package/src/serverGroup/configure/serverGroupConfiguration.service.spec.js +57 -53
  74. package/src/serverGroup/configure/wizard/AzureCloneServerGroupModal.spec.tsx +758 -0
  75. package/src/serverGroup/configure/wizard/AzureCloneServerGroupModal.tsx +349 -0
  76. package/src/serverGroup/configure/wizard/pages/ServerGroupAdvancedSettings.tsx +208 -0
  77. package/src/serverGroup/configure/wizard/pages/ServerGroupBasicSettings.tsx +122 -0
  78. package/src/serverGroup/configure/wizard/pages/ServerGroupCapacityAndZones.tsx +80 -0
  79. package/src/serverGroup/configure/wizard/pages/ServerGroupHealthSettings.tsx +97 -0
  80. package/src/serverGroup/configure/wizard/pages/ServerGroupImageSettings.tsx +151 -0
  81. package/src/serverGroup/configure/wizard/pages/ServerGroupInstanceType.tsx +41 -0
  82. package/src/serverGroup/configure/wizard/pages/ServerGroupLoadBalancers.tsx +214 -0
  83. package/src/serverGroup/configure/wizard/pages/ServerGroupNetworkSettings.tsx +119 -0
  84. package/src/serverGroup/configure/wizard/pages/ServerGroupSecurityGroups.tsx +54 -0
  85. package/src/serverGroup/configure/wizard/pages/ServerGroupTags.tsx +40 -0
  86. package/src/serverGroup/configure/wizard/pages/common.tsx +72 -0
  87. package/src/serverGroup/configure/wizard/pages/index.ts +10 -0
  88. package/src/serverGroup/details/azureServerGroupDetails.spec.tsx +263 -0
  89. package/src/serverGroup/details/azureServerGroupDetails.tsx +318 -0
  90. package/src/serverGroup/details/rollback/RollbackServerGroupModal.tsx +24 -30
  91. package/src/serverGroup/serverGroup.transformer.js +11 -19
  92. package/src/serverGroup/serverGroup.transformer.spec.js +2 -6
  93. package/src/validation/applicationName.validator.js +14 -29
  94. package/dist/instance/details/instance.details.controller.d.ts +0 -2
  95. package/dist/loadBalancer/configure/createLoadBalancer.controller.d.ts +0 -2
  96. package/dist/loadBalancer/details/loadBalancerDetail.controller.d.ts +0 -2
  97. package/dist/pipeline/stages/bake/bakeExecutionDetails.controller.d.ts +0 -2
  98. package/dist/securityGroup/clone/cloneSecurityGroup.controller.d.ts +0 -2
  99. package/dist/securityGroup/configure/CreateSecurityGroupCtrl.d.ts +0 -2
  100. package/dist/securityGroup/configure/EditSecurityGroupCtrl.d.ts +0 -2
  101. package/dist/securityGroup/details/securityGroupDetail.controller.d.ts +0 -2
  102. package/dist/serverGroup/configure/serverGroup.configure.azure.module.d.ts +0 -2
  103. package/dist/serverGroup/configure/wizard/CloneServerGroup.azure.controller.d.ts +0 -2
  104. package/dist/serverGroup/configure/wizard/ServerGroupInstanceArchetype.controller.d.ts +0 -2
  105. package/dist/serverGroup/configure/wizard/ServerGroupInstanceType.controller.d.ts +0 -2
  106. package/dist/serverGroup/configure/wizard/advancedSettings/ServerGroupAdvancedSettings.controller.d.ts +0 -2
  107. package/dist/serverGroup/configure/wizard/advancedSettings/advancedSettingsSelector.directive.d.ts +0 -2
  108. package/dist/serverGroup/configure/wizard/basicSettings/ServerGroupBasicSettings.controller.d.ts +0 -2
  109. package/dist/serverGroup/configure/wizard/basicSettings/image.regional.filter.d.ts +0 -2
  110. package/dist/serverGroup/configure/wizard/capacity/capacitySelector.directive.d.ts +0 -2
  111. package/dist/serverGroup/configure/wizard/healthSettings/ServerGroupHealthSettings.controller.d.ts +0 -2
  112. package/dist/serverGroup/configure/wizard/healthSettings/healthSettingsSelector.directive.d.ts +0 -2
  113. package/dist/serverGroup/configure/wizard/image/ServerGroupImageSettings.controller.d.ts +0 -2
  114. package/dist/serverGroup/configure/wizard/image/imageSettingsSelector.directive.d.ts +0 -2
  115. package/dist/serverGroup/configure/wizard/loadBalancers/ServerGroupLoadBalancers.controller.d.ts +0 -2
  116. package/dist/serverGroup/configure/wizard/loadBalancers/serverGroupLoadBalancersSelector.directive.d.ts +0 -2
  117. package/dist/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettings.controller.d.ts +0 -2
  118. package/dist/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettingsSelector.directive.d.ts +0 -2
  119. package/dist/serverGroup/configure/wizard/securityGroup/ServerGroupSecurityGroups.controller.d.ts +0 -2
  120. package/dist/serverGroup/configure/wizard/securityGroup/serverGroupSecurityGroupsSelector.directive.d.ts +0 -2
  121. package/dist/serverGroup/configure/wizard/tags/tagsSelector.directive.d.ts +0 -2
  122. package/dist/serverGroup/configure/wizard/zones/zoneSelector.directive.d.ts +0 -2
  123. package/dist/serverGroup/details/serverGroup.details.module.d.ts +0 -2
  124. package/dist/serverGroup/details/serverGroupDetails.azure.controller.d.ts +0 -2
  125. package/src/instance/details/instance.details.controller.js +0 -371
  126. package/src/instance/details/instance.details.controller.spec.js +0 -129
  127. package/src/instance/details/instanceDetails.html +0 -43
  128. package/src/loadBalancer/configure/advancedSettings.html +0 -95
  129. package/src/loadBalancer/configure/createLoadBalancer.controller.js +0 -275
  130. package/src/loadBalancer/configure/createLoadBalancer.controller.spec.js +0 -39
  131. package/src/loadBalancer/configure/createLoadBalancer.html +0 -25
  132. package/src/loadBalancer/configure/createLoadBalancerProperties.html +0 -128
  133. package/src/loadBalancer/configure/editLoadBalancer.html +0 -26
  134. package/src/loadBalancer/configure/healthCheck.html +0 -74
  135. package/src/loadBalancer/configure/listeners.html +0 -50
  136. package/src/loadBalancer/details/loadBalancerDetail.controller.js +0 -181
  137. package/src/loadBalancer/details/loadBalancerDetail.controller.spec.js +0 -39
  138. package/src/loadBalancer/details/loadBalancerDetail.html +0 -128
  139. package/src/pipeline/stages/bake/azureBakeStage.js +0 -276
  140. package/src/pipeline/stages/bake/bakeExecutionDetails.controller.js +0 -40
  141. package/src/pipeline/stages/bake/bakeExecutionDetails.html +0 -50
  142. package/src/pipeline/stages/bake/bakeStage.html +0 -187
  143. package/src/pipeline/stages/destroyAsg/azureDestroyAsgStage.js +0 -73
  144. package/src/pipeline/stages/destroyAsg/destroyAsgStage.html +0 -9
  145. package/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html +0 -1
  146. package/src/pipeline/stages/disableAsg/azureDisableAsgStage.js +0 -65
  147. package/src/pipeline/stages/disableAsg/disableAsgStage.html +0 -11
  148. package/src/pipeline/stages/disableAsg/disableAsgStepLabel.html +0 -1
  149. package/src/pipeline/stages/enableAsg/azureEnableAsgStage.js +0 -70
  150. package/src/pipeline/stages/enableAsg/enableAsgStage.html +0 -11
  151. package/src/pipeline/stages/enableAsg/enableAsgStepLabel.html +0 -1
  152. package/src/securityGroup/clone/cloneSecurityGroup.controller.js +0 -162
  153. package/src/securityGroup/clone/cloneSecurityGroup.html +0 -8
  154. package/src/securityGroup/configure/CreateSecurityGroup.controller.spec.js +0 -78
  155. package/src/securityGroup/configure/CreateSecurityGroupCtrl.js +0 -265
  156. package/src/securityGroup/configure/EditSecurityGroupCtrl.js +0 -222
  157. package/src/securityGroup/configure/configSecurityGroup.mixin.controller.js +0 -262
  158. package/src/securityGroup/configure/createSecurityGroup.html +0 -20
  159. package/src/securityGroup/configure/createSecurityGroupIngress.html +0 -75
  160. package/src/securityGroup/configure/createSecurityGroupProperties.html +0 -88
  161. package/src/securityGroup/configure/editSecurityGroup.html +0 -19
  162. package/src/securityGroup/details/securityGroupDetail.controller.js +0 -142
  163. package/src/securityGroup/details/securityGroupDetail.html +0 -78
  164. package/src/securityGroup/securityGroup.write.service.js +0 -57
  165. package/src/serverGroup/configure/serverGroup.configure.azure.module.js +0 -47
  166. package/src/serverGroup/configure/wizard/CloneServerGroup.azure.controller.js +0 -247
  167. package/src/serverGroup/configure/wizard/ServerGroupInstanceArchetype.controller.js +0 -35
  168. package/src/serverGroup/configure/wizard/ServerGroupInstanceType.controller.js +0 -15
  169. package/src/serverGroup/configure/wizard/advancedSettings/ServerGroupAdvancedSettings.controller.js +0 -25
  170. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.html +0 -5
  171. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettingsSelector.directive.html +0 -138
  172. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettingsSelector.directive.js +0 -43
  173. package/src/serverGroup/configure/wizard/basicSettings/ServerGroupBasicSettings.controller.js +0 -71
  174. package/src/serverGroup/configure/wizard/basicSettings/basicSettings.html +0 -131
  175. package/src/serverGroup/configure/wizard/basicSettings/image.regional.filter.js +0 -15
  176. package/src/serverGroup/configure/wizard/basicSettings/image.regional.filter.spec.js +0 -42
  177. package/src/serverGroup/configure/wizard/capacity/capacity.html +0 -5
  178. package/src/serverGroup/configure/wizard/capacity/capacitySelector.directive.html +0 -20
  179. package/src/serverGroup/configure/wizard/capacity/capacitySelector.directive.js +0 -21
  180. package/src/serverGroup/configure/wizard/capacity/zones.html +0 -5
  181. package/src/serverGroup/configure/wizard/healthSettings/ServerGroupHealthSettings.controller.js +0 -38
  182. package/src/serverGroup/configure/wizard/healthSettings/healthSettings.html +0 -5
  183. package/src/serverGroup/configure/wizard/healthSettings/healthSettingsSelector.directive.html +0 -32
  184. package/src/serverGroup/configure/wizard/healthSettings/healthSettingsSelector.directive.js +0 -22
  185. package/src/serverGroup/configure/wizard/image/ServerGroupImageSettings.controller.js +0 -34
  186. package/src/serverGroup/configure/wizard/image/imageSettings.html +0 -5
  187. package/src/serverGroup/configure/wizard/image/imageSettingsSelector.directive.html +0 -33
  188. package/src/serverGroup/configure/wizard/image/imageSettingsSelector.directive.js +0 -22
  189. package/src/serverGroup/configure/wizard/instanceArchetype.html +0 -33
  190. package/src/serverGroup/configure/wizard/instanceType/instanceType.html +0 -10
  191. package/src/serverGroup/configure/wizard/instanceType.html +0 -33
  192. package/src/serverGroup/configure/wizard/loadBalancers/ServerGroupLoadBalancers.controller.js +0 -137
  193. package/src/serverGroup/configure/wizard/loadBalancers/loadBalancers.html +0 -3
  194. package/src/serverGroup/configure/wizard/loadBalancers/serverGroupLoadBalancersSelector.directive.html +0 -41
  195. package/src/serverGroup/configure/wizard/loadBalancers/serverGroupLoadBalancersSelector.directive.js +0 -22
  196. package/src/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettings.controller.js +0 -44
  197. package/src/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettingsSelector.directive.html +0 -54
  198. package/src/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettingsSelector.directive.js +0 -19
  199. package/src/serverGroup/configure/wizard/networkSettings/networkSettings.html +0 -3
  200. package/src/serverGroup/configure/wizard/securityGroup/ServerGroupSecurityGroups.controller.js +0 -28
  201. package/src/serverGroup/configure/wizard/securityGroup/securityGroups.html +0 -3
  202. package/src/serverGroup/configure/wizard/securityGroup/serverGroupSecurityGroupsSelector.directive.html +0 -40
  203. package/src/serverGroup/configure/wizard/securityGroup/serverGroupSecurityGroupsSelector.directive.js +0 -38
  204. package/src/serverGroup/configure/wizard/serverGroupWizard.html +0 -61
  205. package/src/serverGroup/configure/wizard/tags/tags.html +0 -5
  206. package/src/serverGroup/configure/wizard/tags/tagsSelector.directive.html +0 -16
  207. package/src/serverGroup/configure/wizard/tags/tagsSelector.directive.js +0 -30
  208. package/src/serverGroup/configure/wizard/templateSelection.html +0 -9
  209. package/src/serverGroup/configure/wizard/zones/zoneSelector.directive.html +0 -21
  210. package/src/serverGroup/configure/wizard/zones/zoneSelector.directive.js +0 -28
  211. package/src/serverGroup/details/serverGroup.details.module.js +0 -11
  212. package/src/serverGroup/details/serverGroupDetails.azure.controller.js +0 -260
  213. package/src/serverGroup/details/serverGroupDetails.html +0 -98
  214. package/src/subnet/subnetSelectField.directive.html +0 -28
  215. package/src/subnet/subnetSelectField.directive.js +0 -35
@@ -0,0 +1,349 @@
1
+ import { cloneDeep } from 'lodash';
2
+ import React from 'react';
3
+
4
+ import type {
5
+ Application,
6
+ DeckRuntimeServices,
7
+ IModalComponentProps,
8
+ IRouterInjectedProps,
9
+ IStage,
10
+ ITemplateSelectionText,
11
+ } from '@spinnaker/core';
12
+ import {
13
+ DeckRuntimeContext,
14
+ DeployInitializer,
15
+ FirewallLabels,
16
+ noop,
17
+ ReactModal,
18
+ TaskMonitor,
19
+ withRouter,
20
+ WizardModal,
21
+ WizardPage,
22
+ } from '@spinnaker/core';
23
+
24
+ import {
25
+ ServerGroupAdvancedSettings,
26
+ ServerGroupBasicSettings,
27
+ ServerGroupCapacityAndZones,
28
+ ServerGroupHealthSettings,
29
+ ServerGroupImageSettings,
30
+ ServerGroupInstanceType,
31
+ ServerGroupLoadBalancers,
32
+ ServerGroupNetworkSettings,
33
+ ServerGroupSecurityGroups,
34
+ ServerGroupTags,
35
+ } from './pages';
36
+ import type { AzureServerGroupConfigurationService } from '../serverGroupConfiguration.service';
37
+
38
+ export interface IAzureCloneServerGroupModalProps extends IModalComponentProps {
39
+ application: Application;
40
+ command: any;
41
+ title: string;
42
+ }
43
+
44
+ interface IAzureCloneServerGroupModalState {
45
+ command: any;
46
+ loaded: boolean;
47
+ requiresTemplateSelection: boolean;
48
+ taskMonitor: TaskMonitor;
49
+ templateSelectionText: ITemplateSelectionText;
50
+ }
51
+
52
+ export class AzureCloneServerGroupModalComponent extends React.Component<
53
+ IAzureCloneServerGroupModalProps & IRouterInjectedProps,
54
+ IAzureCloneServerGroupModalState
55
+ > {
56
+ public static contextType = DeckRuntimeContext;
57
+ public declare context: React.ContextType<typeof DeckRuntimeContext>;
58
+
59
+ public static defaultProps: Partial<IAzureCloneServerGroupModalProps> = {
60
+ closeModal: noop,
61
+ dismissModal: noop,
62
+ };
63
+
64
+ private _isUnmounted = false;
65
+ private applicationRefreshUnsubscribe?: () => void;
66
+ public static show(props: IAzureCloneServerGroupModalProps, runtimeServices: DeckRuntimeServices): Promise<any> {
67
+ return ReactModal.show(
68
+ AzureCloneServerGroupModal,
69
+ props,
70
+ { dialogClassName: 'wizard-modal modal-lg' },
71
+ runtimeServices,
72
+ );
73
+ }
74
+
75
+ constructor(props: IAzureCloneServerGroupModalProps & IRouterInjectedProps) {
76
+ super(props);
77
+ const requiresTemplateSelection = !!props.command.viewState?.requiresTemplateSelection;
78
+ const workingCommand = cloneDeep(props.command);
79
+ const alreadyConfigured =
80
+ !requiresTemplateSelection && workingCommand.backingData?.accounts && workingCommand.backingData?.filtered;
81
+ const templateSelectionText: ITemplateSelectionText = {
82
+ copied: [
83
+ 'account, region, subnet, cluster name (stack, details)',
84
+ 'load balancers',
85
+ FirewallLabels.get('firewalls'),
86
+ 'instance type',
87
+ 'all fields on the Advanced Settings page',
88
+ ],
89
+ notCopied: [],
90
+ additionalCopyText:
91
+ 'If a server group exists in this cluster at the time of deployment, its scaling policies will be copied over to the new server group.',
92
+ };
93
+
94
+ if (!props.command.viewState?.disableStrategySelection) {
95
+ templateSelectionText.notCopied.push(
96
+ 'the deployment strategy (if any) used to deploy the most recent server group',
97
+ );
98
+ }
99
+
100
+ this.state = {
101
+ command: workingCommand,
102
+ loaded: !!alreadyConfigured,
103
+ requiresTemplateSelection,
104
+ taskMonitor: new TaskMonitor({
105
+ application: props.application,
106
+ title: 'Creating your server group',
107
+ onDismiss: () => this.props.dismissModal(),
108
+ onTaskComplete: this.onTaskComplete,
109
+ }),
110
+ templateSelectionText,
111
+ };
112
+ }
113
+
114
+ public componentDidMount(): void {
115
+ if (this.state.loaded) {
116
+ this.completeConfiguration(this.state.command);
117
+ } else if (!this.state.requiresTemplateSelection) {
118
+ this.prepareCommand();
119
+ }
120
+ }
121
+
122
+ private get configurationService(): AzureServerGroupConfigurationService {
123
+ return this.context.services.providerServiceDelegate.getDelegate('azure', 'serverGroup.configurationService');
124
+ }
125
+
126
+ private templateSelected = (): void => {
127
+ this.setState({ loaded: false, requiresTemplateSelection: false });
128
+ this.prepareCommand();
129
+ };
130
+
131
+ public componentWillUnmount(): void {
132
+ this._isUnmounted = true;
133
+ this.clearApplicationRefreshSubscription();
134
+ }
135
+
136
+ private onTaskComplete = () => {
137
+ this.clearApplicationRefreshSubscription();
138
+ this.applicationRefreshUnsubscribe = this.props.application.serverGroups.onNextRefresh(this.onApplicationRefresh);
139
+ this.props.application.serverGroups.refresh();
140
+ };
141
+
142
+ private onApplicationRefresh = (): void => {
143
+ this.clearApplicationRefreshSubscription();
144
+ if (this._isUnmounted) {
145
+ return;
146
+ }
147
+ const { command } = this.state;
148
+ const cloneStage = this.state.taskMonitor.task.execution.stages.find(
149
+ (stage: IStage) => stage.type === 'cloneServerGroup',
150
+ );
151
+ if (cloneStage && cloneStage.context['deploy.server.groups']) {
152
+ const newServerGroupName = cloneStage.context['deploy.server.groups'][command.region];
153
+ if (newServerGroupName) {
154
+ let transitionTo = '^.^.^.clusters.serverGroup';
155
+ if (this.props.stateService.includes('**.clusters.serverGroup')) {
156
+ transitionTo = '^.serverGroup';
157
+ }
158
+ if (this.props.stateService.includes('**.clusters.cluster.serverGroup')) {
159
+ transitionTo = '^.^.serverGroup';
160
+ }
161
+ if (this.props.stateService.includes('**.clusters')) {
162
+ transitionTo = '.serverGroup';
163
+ }
164
+ this.props.stateService.go(transitionTo, {
165
+ accountId: command.credentials,
166
+ provider: 'azure',
167
+ region: command.region,
168
+ serverGroup: newServerGroupName,
169
+ });
170
+ }
171
+ }
172
+ };
173
+
174
+ private clearApplicationRefreshSubscription = (): void => {
175
+ this.applicationRefreshUnsubscribe?.();
176
+ this.applicationRefreshUnsubscribe = undefined;
177
+ };
178
+
179
+ private prepareCommand = () => {
180
+ const { application } = this.props;
181
+ const { command } = this.state;
182
+ command.viewState = command.viewState || {};
183
+ command.processCommandUpdateResult = this.processCommandUpdateResult;
184
+
185
+ const alreadyConfigured = command.backingData?.accounts && command.backingData?.filtered;
186
+ const configure = alreadyConfigured
187
+ ? null
188
+ : (this.configurationService as any).configureCommand(application, command);
189
+
190
+ const completeConfiguration = () => {
191
+ this.completeConfiguration(command);
192
+ if (!this._isUnmounted) {
193
+ this.setState({ loaded: true, requiresTemplateSelection: false });
194
+ }
195
+ };
196
+
197
+ if (configure) {
198
+ configure.then(completeConfiguration);
199
+ } else {
200
+ completeConfiguration();
201
+ }
202
+ };
203
+
204
+ private completeConfiguration(command: any): void {
205
+ command.backingData = command.backingData || {};
206
+ command.backingData.filtered = command.backingData.filtered || {};
207
+ command.backingData.filtered.regions = command.backingData.filtered.regions || [];
208
+ command.backingData.packageImages = command.backingData.packageImages || command.images || [];
209
+ command.processCommandUpdateResult = this.processCommandUpdateResult;
210
+ this.attachCommandHandlers(command);
211
+ this.processCommandUpdateResult(command.credentialsChanged?.(command, true));
212
+ this.processCommandUpdateResult(command.regionChanged?.(command, true));
213
+ }
214
+
215
+ private attachCommandHandlers(command: any): void {
216
+ if (command.viewState.azureReactHandlersAttached) {
217
+ return;
218
+ }
219
+ const credentialsChanged = command.credentialsChanged;
220
+ const regionChanged = command.regionChanged;
221
+ command.credentialsChanged = (cmd: any, isInit = false) =>
222
+ this.withImageConfiguration(cmd, credentialsChanged?.(cmd, isInit));
223
+ command.regionChanged = (cmd: any, isInit = false) =>
224
+ this.withImageConfiguration(cmd, regionChanged?.(cmd, isInit));
225
+ command.viewState.azureReactHandlersAttached = true;
226
+ }
227
+
228
+ private withImageConfiguration(command: any, result: any = { dirty: {} }): any {
229
+ const imageResult = (this.configurationService as any).configureImages(command) || { dirty: {} };
230
+ return { dirty: { ...(result.dirty || {}), ...(imageResult.dirty || {}) } };
231
+ }
232
+
233
+ private processCommandUpdateResult = (result: any = { dirty: {} }) => {
234
+ const dirty = result.dirty || {};
235
+ if (!Object.keys(dirty).length) {
236
+ return;
237
+ }
238
+ const viewState = (this.state.command.viewState = this.state.command.viewState || {});
239
+ viewState.dirty = { ...(viewState.dirty || {}), ...dirty };
240
+ };
241
+
242
+ public submit = (command: any): any => {
243
+ const mode = command.viewState?.mode;
244
+ if (mode === 'editPipeline' || mode === 'createPipeline') {
245
+ return this.props.closeModal(command);
246
+ }
247
+ return this.state.taskMonitor.submit(() =>
248
+ this.context.services.serverGroupWriter.cloneServerGroup(command, this.props.application),
249
+ );
250
+ };
251
+
252
+ public render() {
253
+ const { application, dismissModal, title } = this.props;
254
+ const { command } = this.state;
255
+ if (this.state.requiresTemplateSelection) {
256
+ return (
257
+ <DeployInitializer
258
+ application={application}
259
+ cloudProvider="azure"
260
+ command={command}
261
+ onDismiss={dismissModal}
262
+ onTemplateSelected={this.templateSelected}
263
+ templateSelectionText={this.state.templateSelectionText}
264
+ />
265
+ );
266
+ }
267
+
268
+ return (
269
+ <WizardModal<any>
270
+ closeModal={this.submit}
271
+ dismissModal={dismissModal}
272
+ heading={title}
273
+ initialValues={command}
274
+ loading={!this.state.loaded}
275
+ submitButtonLabel={command.viewState?.submitButtonLabel}
276
+ taskMonitor={this.state.taskMonitor}
277
+ render={({ formik, nextIdx, wizard }) => (
278
+ <>
279
+ <WizardPage
280
+ label="Basic Settings"
281
+ order={nextIdx()}
282
+ render={({ innerRef }) => <ServerGroupBasicSettings ref={innerRef} app={application} formik={formik} />}
283
+ wizard={wizard}
284
+ />
285
+ <WizardPage
286
+ label="Image"
287
+ order={nextIdx()}
288
+ render={({ innerRef }) => <ServerGroupImageSettings ref={innerRef} formik={formik} />}
289
+ wizard={wizard}
290
+ />
291
+ <WizardPage
292
+ label="Instance Type"
293
+ order={nextIdx()}
294
+ render={({ innerRef }) => <ServerGroupInstanceType ref={innerRef} formik={formik} />}
295
+ wizard={wizard}
296
+ />
297
+ <WizardPage
298
+ label="Capacity and Zones"
299
+ order={nextIdx()}
300
+ render={({ innerRef }) => <ServerGroupCapacityAndZones ref={innerRef} formik={formik} />}
301
+ wizard={wizard}
302
+ />
303
+ <WizardPage
304
+ label="Load Balancers"
305
+ order={nextIdx()}
306
+ render={({ innerRef }) => <ServerGroupLoadBalancers ref={innerRef} formik={formik} />}
307
+ wizard={wizard}
308
+ />
309
+ <WizardPage
310
+ label="Network Settings"
311
+ order={nextIdx()}
312
+ render={({ innerRef }) => <ServerGroupNetworkSettings ref={innerRef} formik={formik} />}
313
+ wizard={wizard}
314
+ />
315
+ <WizardPage
316
+ label={FirewallLabels.get('Firewalls')}
317
+ order={nextIdx()}
318
+ render={({ innerRef }) => <ServerGroupSecurityGroups ref={innerRef} formik={formik} />}
319
+ wizard={wizard}
320
+ />
321
+ <WizardPage
322
+ label="Health"
323
+ order={nextIdx()}
324
+ render={({ innerRef }) => <ServerGroupHealthSettings ref={innerRef} formik={formik} />}
325
+ wizard={wizard}
326
+ />
327
+ <WizardPage
328
+ label="Advanced Settings"
329
+ order={nextIdx()}
330
+ render={({ innerRef }) => <ServerGroupAdvancedSettings ref={innerRef} formik={formik} />}
331
+ wizard={wizard}
332
+ />
333
+ <WizardPage
334
+ label="Tags"
335
+ order={nextIdx()}
336
+ render={({ innerRef }) => <ServerGroupTags ref={innerRef} formik={formik} />}
337
+ wizard={wizard}
338
+ />
339
+ </>
340
+ )}
341
+ />
342
+ );
343
+ }
344
+ }
345
+
346
+ export const AzureCloneServerGroupModal = Object.assign(
347
+ withRouter<IAzureCloneServerGroupModalProps & IRouterInjectedProps>(AzureCloneServerGroupModalComponent),
348
+ { show: AzureCloneServerGroupModalComponent.show },
349
+ );
@@ -0,0 +1,208 @@
1
+ import React from 'react';
2
+
3
+ import { AzureWizardPage } from './common';
4
+
5
+ export class ServerGroupAdvancedSettings extends AzureWizardPage {
6
+ public addDataDisk = () => {
7
+ const dataDisks = [
8
+ ...(this.props.formik.values.dataDisks || []),
9
+ {
10
+ lun: 0,
11
+ managedDisk: {
12
+ storageAccountType: 'Standard_LRS',
13
+ },
14
+ diskSizeGB: 1,
15
+ caching: 'None',
16
+ createOption: 'Empty',
17
+ },
18
+ ];
19
+ this.props.formik.values.dataDisks = dataDisks;
20
+ this.props.formik.setFieldValue('dataDisks', dataDisks);
21
+ };
22
+
23
+ private removeDataDisk = (index: number) => {
24
+ const dataDisks = [...(this.props.formik.values.dataDisks || [])];
25
+ dataDisks.splice(index, 1);
26
+ this.props.formik.values.dataDisks = dataDisks;
27
+ this.props.formik.setFieldValue('dataDisks', dataDisks);
28
+ };
29
+
30
+ private updateDataDisk = (index: number, field: string, value: any) => {
31
+ const dataDisks = [...(this.props.formik.values.dataDisks || [])];
32
+ const disk = { ...(dataDisks[index] || {}) };
33
+ if (field === 'storageAccountType') {
34
+ disk.managedDisk = { ...(disk.managedDisk || {}), storageAccountType: value };
35
+ } else {
36
+ disk[field] = value;
37
+ }
38
+ dataDisks[index] = disk;
39
+ this.props.formik.values.dataDisks = dataDisks;
40
+ this.props.formik.setFieldValue('dataDisks', dataDisks);
41
+ };
42
+
43
+ public render() {
44
+ const { values } = this.props.formik;
45
+ values.osConfig = values.osConfig || {};
46
+ values.customScriptsSettings = values.customScriptsSettings || {};
47
+ values.dataDisks = values.dataDisks || [];
48
+ const dataDiskTypes = values.backingData?.dataDiskTypes || ['Standard_LRS', 'StandardSSD_LRS', 'Premium_LRS'];
49
+ const dataDiskCachingTypes = values.backingData?.dataDiskCachingTypes || ['None', 'ReadOnly', 'ReadWrite'];
50
+
51
+ return (
52
+ <div className="container-fluid form-horizontal">
53
+ <div className="form-group">
54
+ <div className="col-md-4 sm-label-right">Number of Instances</div>
55
+ <div className="col-md-2">
56
+ <input
57
+ className="form-control input-sm"
58
+ max="100"
59
+ min="0"
60
+ onChange={(event) => this.setField('sku.capacity', Number(event.target.value))}
61
+ type="number"
62
+ value={values.sku?.capacity ?? 0}
63
+ />
64
+ </div>
65
+ </div>
66
+ <div className="form-group">
67
+ <div className="col-md-4 sm-label-right">Custom Data</div>
68
+ <div className="col-md-7">
69
+ <input
70
+ className="form-control input-sm"
71
+ onChange={(event) => this.setField('osConfig.customData', event.target.value)}
72
+ value={values.osConfig.customData || ''}
73
+ />
74
+ </div>
75
+ </div>
76
+ <div className="form-group">
77
+ <div className="col-md-4 sm-label-right">Custom Script</div>
78
+ <div className="col-md-7">
79
+ <input
80
+ className="form-control input-sm"
81
+ onChange={(event) => this.setField('customScriptsSettings.fileUris', event.target.value)}
82
+ value={values.customScriptsSettings.fileUris || ''}
83
+ />
84
+ </div>
85
+ </div>
86
+ <div className="form-group">
87
+ <div className="col-md-4 sm-label-right">Command To Execute</div>
88
+ <div className="col-md-7">
89
+ <input
90
+ className="form-control input-sm"
91
+ onChange={(event) => this.setField('customScriptsSettings.commandToExecute', event.target.value)}
92
+ value={values.customScriptsSettings.commandToExecute || ''}
93
+ />
94
+ </div>
95
+ </div>
96
+ {values.loadBalancerType === 'Azure Application Gateway' && (
97
+ <div className="form-group">
98
+ <div className="col-md-4 sm-label-right">
99
+ <input
100
+ checked={!!values.enableInboundNAT}
101
+ disabled={!!values.zonesEnabled}
102
+ onChange={(event) => this.setField('enableInboundNAT', event.target.checked)}
103
+ type="checkbox"
104
+ />
105
+ </div>
106
+ <div className="col-md-7">
107
+ <b>Enable inbound NAT port-forwarding rules to connect to VM instances</b>
108
+ </div>
109
+ </div>
110
+ )}
111
+ <div className="form-group">
112
+ <div className="col-md-4 sm-label-right">User-Assigned Identities</div>
113
+ <div className="col-md-7">
114
+ <input
115
+ className="form-control input-sm"
116
+ onChange={(event) => this.setField('userAssignedIdentities', event.target.value)}
117
+ value={values.userAssignedIdentities || ''}
118
+ />
119
+ </div>
120
+ </div>
121
+ <div className="form-group">
122
+ <div className="col-md-4 sm-label-left">Data Disks</div>
123
+ <div className="col-md-11">
124
+ <table className="table table-condensed packed tags">
125
+ <thead>
126
+ <tr>
127
+ <th>LUN</th>
128
+ <th>Size (GB)</th>
129
+ <th>Type</th>
130
+ <th>Caching</th>
131
+ <th />
132
+ </tr>
133
+ </thead>
134
+ <tbody>
135
+ {values.dataDisks.map((disk: any, index: number) => (
136
+ <tr key={index}>
137
+ <td>
138
+ <input
139
+ className="form-control input-sm"
140
+ min="0"
141
+ onChange={(event) => this.updateDataDisk(index, 'lun', Number(event.target.value))}
142
+ type="number"
143
+ value={disk.lun ?? 0}
144
+ />
145
+ </td>
146
+ <td>
147
+ <input
148
+ className="form-control input-sm"
149
+ min="1"
150
+ onChange={(event) => this.updateDataDisk(index, 'diskSizeGB', Number(event.target.value))}
151
+ type="number"
152
+ value={disk.diskSizeGB ?? 1}
153
+ />
154
+ </td>
155
+ <td>
156
+ <select
157
+ className="form-control input-sm"
158
+ onChange={(event) => this.updateDataDisk(index, 'storageAccountType', event.target.value)}
159
+ value={disk.managedDisk?.storageAccountType || ''}
160
+ >
161
+ {dataDiskTypes.map((type: string) => (
162
+ <option key={type} value={type}>
163
+ {type}
164
+ </option>
165
+ ))}
166
+ </select>
167
+ </td>
168
+ <td>
169
+ <select
170
+ className="form-control input-sm"
171
+ onChange={(event) => this.updateDataDisk(index, 'caching', event.target.value)}
172
+ value={disk.caching || ''}
173
+ >
174
+ {dataDiskCachingTypes.map((type: string) => (
175
+ <option key={type} value={type}>
176
+ {type}
177
+ </option>
178
+ ))}
179
+ </select>
180
+ </td>
181
+ <td>
182
+ <button
183
+ className="btn btn-link sm-label"
184
+ onClick={() => this.removeDataDisk(index)}
185
+ type="button"
186
+ >
187
+ <span className="glyphicon glyphicon-trash" />
188
+ </button>
189
+ </td>
190
+ </tr>
191
+ ))}
192
+ </tbody>
193
+ <tfoot>
194
+ <tr>
195
+ <td colSpan={5}>
196
+ <button className="btn btn-block btn-sm add-new" onClick={this.addDataDisk} type="button">
197
+ <span className="glyphicon glyphicon-plus-sign" /> Add New Data Disk
198
+ </button>
199
+ </td>
200
+ </tr>
201
+ </tfoot>
202
+ </table>
203
+ </div>
204
+ </div>
205
+ </div>
206
+ );
207
+ }
208
+ }
@@ -0,0 +1,122 @@
1
+ import React from 'react';
2
+
3
+ import { DeploymentStrategySelector, NameUtils } from '@spinnaker/core';
4
+
5
+ import { AzureWizardPage } from './common';
6
+
7
+ export class ServerGroupBasicSettings extends AzureWizardPage {
8
+ public validate(values: any): { [key: string]: any } {
9
+ const errors: { [key: string]: any } = {};
10
+ const stackPattern = values.viewState?.templatingEnabled ? /^([a-zA-Z0-9]*(\${.+})*)*$/ : /^[a-zA-Z0-9]*$/;
11
+ const detailPattern = values.viewState?.templatingEnabled ? /^([a-zA-Z0-9-]*(\${.+})*)*$/ : /^[a-zA-Z0-9-]*$/;
12
+
13
+ if (!values.credentials) {
14
+ errors.credentials = 'Account required.';
15
+ }
16
+ if (!values.region) {
17
+ errors.region = 'Region required.';
18
+ }
19
+ if (!values.stack) {
20
+ errors.stack = 'Stack required.';
21
+ }
22
+ if (!values.freeFormDetails) {
23
+ errors.freeFormDetails = 'Detail required.';
24
+ }
25
+ if (!stackPattern.test(values.stack || '')) {
26
+ errors.stack = 'Stack can only contain letters and numbers.';
27
+ }
28
+ if (!detailPattern.test(values.freeFormDetails || '')) {
29
+ errors.freeFormDetails = 'Detail can only contain letters, numbers, and dashes.';
30
+ }
31
+ return errors;
32
+ }
33
+
34
+ private accountChanged = (account: string) => {
35
+ const { values } = this.props.formik;
36
+ values.credentials = account;
37
+ const result = values.credentialsChanged?.(values);
38
+ this.props.formik.setFieldValue('credentials', account);
39
+ this.props.formik.setFieldValue('region', values.region);
40
+ values.processCommandUpdateResult?.(result);
41
+ };
42
+
43
+ private regionChanged = (region: string) => {
44
+ const { values } = this.props.formik;
45
+ values.region = region;
46
+ const result = values.regionChanged?.(values);
47
+ this.props.formik.setFieldValue('region', region);
48
+ values.processCommandUpdateResult?.(result);
49
+ };
50
+
51
+ private strategyChanged = (_values: any, strategy: any) => {
52
+ this.props.formik.setFieldValue('strategy', strategy.key);
53
+ };
54
+
55
+ private onStrategyFieldChange = (key: string, value: any) => {
56
+ this.props.formik.setFieldValue(key, value);
57
+ };
58
+
59
+ public render() {
60
+ const { app, formik } = this.props;
61
+ const { values } = formik;
62
+ const clusterName = NameUtils.getClusterName(app?.name || values.application, values.stack, values.freeFormDetails);
63
+ const accounts = values.backingData?.accounts || [];
64
+ const regions = values.backingData?.filtered?.regions || [];
65
+
66
+ return (
67
+ <div className="container-fluid form-horizontal">
68
+ <div className="form-group">
69
+ <div className="col-md-3 sm-label-right">Account</div>
70
+ <div className="col-md-7">
71
+ <select
72
+ className="form-control input-sm"
73
+ onChange={(event) => this.accountChanged(event.target.value)}
74
+ value={values.credentials || ''}
75
+ >
76
+ <option value="">Select...</option>
77
+ {accounts.map((account: string) => (
78
+ <option key={account} value={account}>
79
+ {account}
80
+ </option>
81
+ ))}
82
+ </select>
83
+ </div>
84
+ </div>
85
+ <div className="form-group">
86
+ <div className="col-md-3 sm-label-right">Region</div>
87
+ <div className="col-md-7">
88
+ <select
89
+ className="form-control input-sm"
90
+ onChange={(event) => this.regionChanged(event.target.value)}
91
+ value={values.region || ''}
92
+ >
93
+ <option value="">Select...</option>
94
+ {regions.map((region: any) => {
95
+ const name = typeof region === 'string' ? region : region.name;
96
+ return (
97
+ <option key={name} value={name}>
98
+ {name}
99
+ </option>
100
+ );
101
+ })}
102
+ </select>
103
+ </div>
104
+ </div>
105
+ {this.textField('Stack', 'stack')}
106
+ {this.textField('Detail', 'freeFormDetails')}
107
+ {!values.viewState?.disableStrategySelection && values.selectedProvider && (
108
+ <DeploymentStrategySelector
109
+ command={values}
110
+ onFieldChange={this.onStrategyFieldChange}
111
+ onStrategyChange={this.strategyChanged}
112
+ />
113
+ )}
114
+ {!values.viewState?.hideClusterNamePreview && (
115
+ <div className="well text-center">
116
+ Your server group will be in the cluster: <strong>{clusterName}</strong>
117
+ </div>
118
+ )}
119
+ </div>
120
+ );
121
+ }
122
+ }