@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,80 @@
1
+ import React from 'react';
2
+
3
+ import { AzureWizardPage } from './common';
4
+
5
+ export class ServerGroupCapacityAndZones extends AzureWizardPage {
6
+ public validate(values: any): { [key: string]: any } {
7
+ if (values.zonesEnabled && (!values.zones || values.zones.length === 0)) {
8
+ return { zones: 'At least one zone is required when zones are enabled.' };
9
+ }
10
+ return {};
11
+ }
12
+
13
+ private capacityChanged = (capacity: string) => {
14
+ const parsed = Number(capacity);
15
+ this.props.formik.values.sku = { ...(this.props.formik.values.sku || {}), capacity: parsed };
16
+ this.props.formik.setFieldValue('sku.capacity', parsed);
17
+ };
18
+
19
+ private zoneToggled = (zone: string, enabled: boolean) => {
20
+ const current = this.props.formik.values.zones || [];
21
+ const zones = enabled ? current.concat(zone) : current.filter((candidate: string) => candidate !== zone);
22
+ this.props.formik.values.zones = zones;
23
+ this.props.formik.setFieldValue('zones', zones);
24
+ };
25
+
26
+ private zonesEnabledChanged = (enabled: boolean) => {
27
+ this.setField('zonesEnabled', enabled);
28
+ if (enabled) {
29
+ this.setField('enableInboundNAT', false);
30
+ }
31
+ };
32
+
33
+ public render() {
34
+ const { values } = this.props.formik;
35
+ const zones = values.backingData?.filtered?.zones || [];
36
+ return (
37
+ <div className="container-fluid form-horizontal">
38
+ <div className="form-group">
39
+ <div className="col-md-3 sm-label-right">Capacity</div>
40
+ <div className="col-md-3">
41
+ <input
42
+ className="form-control input-sm"
43
+ min="0"
44
+ onChange={(event) => this.capacityChanged(event.target.value)}
45
+ type="number"
46
+ value={values.sku?.capacity ?? 0}
47
+ />
48
+ </div>
49
+ </div>
50
+ <div className="form-group">
51
+ <div className="col-md-3 sm-label-right">Use Zones</div>
52
+ <div className="col-md-7">
53
+ <input
54
+ checked={!!values.zonesEnabled}
55
+ onChange={(event) => this.zonesEnabledChanged(event.target.checked)}
56
+ type="checkbox"
57
+ />
58
+ </div>
59
+ </div>
60
+ {values.zonesEnabled && (
61
+ <div className="form-group">
62
+ <div className="col-md-3 sm-label-right">Zones</div>
63
+ <div className="col-md-7">
64
+ {zones.map((zone: string) => (
65
+ <label className="checkbox-inline" key={zone}>
66
+ <input
67
+ checked={(values.zones || []).includes(zone)}
68
+ onChange={(event) => this.zoneToggled(zone, event.target.checked)}
69
+ type="checkbox"
70
+ />
71
+ {zone}
72
+ </label>
73
+ ))}
74
+ </div>
75
+ </div>
76
+ )}
77
+ </div>
78
+ );
79
+ }
80
+ }
@@ -0,0 +1,97 @@
1
+ import React from 'react';
2
+
3
+ import { AzureWizardPage } from './common';
4
+
5
+ const healthCheckProtocols = [
6
+ { displayName: 'N/A', name: '' },
7
+ { displayName: 'HTTP', name: 'http' },
8
+ { displayName: 'TCP', name: 'tcp' },
9
+ ];
10
+
11
+ export class ServerGroupHealthSettings extends AzureWizardPage {
12
+ public validate(values: any): { [key: string]: any } {
13
+ if (!values.healthSettings?.protocol) {
14
+ return {};
15
+ }
16
+ const errors: { [key: string]: any } = {};
17
+ if (!values.healthSettings.port) {
18
+ errors.port = 'Port required.';
19
+ }
20
+ if (values.healthSettings.protocol === 'http' && !values.healthSettings.requestPath) {
21
+ errors.requestPath = 'Path required.';
22
+ }
23
+ return errors;
24
+ }
25
+
26
+ private updateHealthSettings = (updates: any) => {
27
+ const healthSettings = { ...(this.props.formik.values.healthSettings || {}), ...updates };
28
+ this.props.formik.values.healthSettings = healthSettings;
29
+ this.props.formik.setFieldValue('healthSettings', healthSettings);
30
+ };
31
+
32
+ private protocolChanged = (protocol: string) => {
33
+ if (!protocol) {
34
+ this.updateHealthSettings({ protocol: null, port: null, requestPath: null });
35
+ return;
36
+ }
37
+ this.updateHealthSettings({
38
+ protocol,
39
+ requestPath: protocol === 'http' ? this.props.formik.values.healthSettings?.requestPath : null,
40
+ });
41
+ };
42
+
43
+ public render() {
44
+ const healthSettings = this.props.formik.values.healthSettings || {};
45
+ return (
46
+ <div className="container-fluid form-horizontal">
47
+ <div className="form-group">
48
+ <div className="col-md-3 sm-label-right">Protocol</div>
49
+ <div className="col-md-7">
50
+ <select
51
+ className="form-control input-sm"
52
+ onChange={(event) => this.protocolChanged(event.target.value)}
53
+ value={healthSettings.protocol || ''}
54
+ >
55
+ {healthCheckProtocols.map((protocol) => (
56
+ <option key={protocol.displayName} value={protocol.name}>
57
+ {protocol.displayName}
58
+ </option>
59
+ ))}
60
+ </select>
61
+ </div>
62
+ </div>
63
+ {healthSettings.protocol && (
64
+ <div className="form-group">
65
+ <div className="col-md-3 sm-label-right">Port</div>
66
+ <div className="col-md-7">
67
+ <input
68
+ className="form-control input-sm"
69
+ onChange={(event) => this.updateHealthSettings({ port: event.target.value })}
70
+ type="text"
71
+ value={healthSettings.port || ''}
72
+ />
73
+ </div>
74
+ </div>
75
+ )}
76
+ {healthSettings.protocol === 'http' && (
77
+ <div className="form-group">
78
+ <div className="col-md-3 sm-label-right">Path</div>
79
+ <div className="col-md-7">
80
+ <input
81
+ className="form-control input-sm"
82
+ onChange={(event) => this.updateHealthSettings({ requestPath: event.target.value })}
83
+ type="text"
84
+ value={healthSettings.requestPath || ''}
85
+ />
86
+ </div>
87
+ </div>
88
+ )}
89
+ <div className="form-group small" style={{ marginTop: '20px' }}>
90
+ <div className="col-md-9 col-md-offset-3">
91
+ <p>Health settings here will be applied directly to the VM Scale Set.</p>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ );
96
+ }
97
+ }
@@ -0,0 +1,151 @@
1
+ import React from 'react';
2
+
3
+ import { AzureWizardPage } from './common';
4
+
5
+ export class ServerGroupImageSettings extends AzureWizardPage {
6
+ public validate(values: any): { [key: string]: any } {
7
+ if (values.viewState?.disableImageSelection) {
8
+ return {};
9
+ }
10
+ if (values.image?.isCustom) {
11
+ const errors: { [key: string]: any } = {};
12
+ if (!values.image.imageName) {
13
+ errors.imageName = 'Image name required.';
14
+ }
15
+ if (!values.image.ostype) {
16
+ errors.ostype = 'OS type required.';
17
+ }
18
+ if (!values.image.uri) {
19
+ errors.uri = 'URI required.';
20
+ }
21
+ return errors;
22
+ }
23
+ if (!values.selectedImage) {
24
+ return { selectedImage: 'Image required.' };
25
+ }
26
+ return {};
27
+ }
28
+
29
+ private isRegionalImage(image: any, region: string): boolean {
30
+ if (!region) {
31
+ return true;
32
+ }
33
+ if (image.amis) {
34
+ return !!image.amis[region];
35
+ }
36
+ return image.region === region || image.region == null;
37
+ }
38
+
39
+ private imageChanged = (imageName: string) => {
40
+ const images = this.props.formik.values.backingData?.filtered?.images || this.props.formik.values.images || [];
41
+ const image = images.find((candidate: any) => candidate.imageName === imageName) || null;
42
+ this.props.formik.values.imageName = imageName;
43
+ this.props.formik.values.selectedImage = image;
44
+ this.props.formik.setFieldValue('imageName', imageName);
45
+ this.props.formik.setFieldValue('selectedImage', image);
46
+ };
47
+
48
+ private customImageChanged = (isCustom: boolean) => {
49
+ const image = isCustom
50
+ ? { ...(this.props.formik.values.image || {}), isCustom, region: this.props.formik.values.region }
51
+ : { isCustom };
52
+ this.props.formik.values.image = image;
53
+ this.props.formik.setFieldValue('image', image);
54
+ };
55
+
56
+ private customImageFieldChanged = (field: string, value: string) => {
57
+ const image = {
58
+ ...(this.props.formik.values.image || {}),
59
+ isCustom: true,
60
+ region: this.props.formik.values.region,
61
+ [field]: value,
62
+ };
63
+ this.props.formik.values.image = image;
64
+ this.props.formik.setFieldValue('image', image);
65
+ };
66
+
67
+ public render() {
68
+ const { values } = this.props.formik;
69
+ const imageOptions = values.backingData?.filtered?.images || values.images || [];
70
+ const images = values.region
71
+ ? imageOptions.filter((image: any) => this.isRegionalImage(image, values.region))
72
+ : imageOptions;
73
+ const image = values.image || {};
74
+
75
+ if (values.viewState?.disableImageSelection) {
76
+ return <div className="container-fluid form-horizontal">Image selection is disabled for this command.</div>;
77
+ }
78
+
79
+ return (
80
+ <div className="container-fluid form-horizontal">
81
+ <div className="form-group">
82
+ <div className="col-md-3 sm-label-right">Use custom image?</div>
83
+ <div className="col-md-7">
84
+ <input
85
+ checked={!!image.isCustom}
86
+ onChange={(event) => this.customImageChanged(event.target.checked)}
87
+ type="checkbox"
88
+ />
89
+ </div>
90
+ </div>
91
+ {image.isCustom && (
92
+ <>
93
+ <div className="form-group">
94
+ <div className="col-md-3 sm-label-right">Region</div>
95
+ <div className="col-md-7">{values.region}</div>
96
+ </div>
97
+ <div className="form-group">
98
+ <div className="col-md-3 sm-label-right">Image Name</div>
99
+ <div className="col-md-7">
100
+ <input
101
+ className="form-control input-sm"
102
+ onChange={(event) => this.customImageFieldChanged('imageName', event.target.value)}
103
+ value={image.imageName || ''}
104
+ />
105
+ </div>
106
+ </div>
107
+ <div className="form-group">
108
+ <div className="col-md-3 sm-label-right">OS Type</div>
109
+ <div className="col-md-7">
110
+ <input
111
+ className="form-control input-sm"
112
+ onChange={(event) => this.customImageFieldChanged('ostype', event.target.value)}
113
+ value={image.ostype || ''}
114
+ />
115
+ </div>
116
+ </div>
117
+ <div className="form-group">
118
+ <div className="col-md-3 sm-label-right">URI</div>
119
+ <div className="col-md-7">
120
+ <input
121
+ className="form-control input-sm"
122
+ onChange={(event) => this.customImageFieldChanged('uri', event.target.value)}
123
+ value={image.uri || ''}
124
+ />
125
+ </div>
126
+ </div>
127
+ </>
128
+ )}
129
+ {!image.isCustom && (
130
+ <div className="form-group">
131
+ <div className="col-md-3 sm-label-right">Image</div>
132
+ <div className="col-md-7">
133
+ <select
134
+ className="form-control input-sm"
135
+ onChange={(event) => this.imageChanged(event.target.value)}
136
+ value={values.imageName || values.selectedImage?.imageName || ''}
137
+ >
138
+ <option value="">Select...</option>
139
+ {images.map((image: any) => (
140
+ <option key={image.imageName} value={image.imageName}>
141
+ {image.imageName}
142
+ </option>
143
+ ))}
144
+ </select>
145
+ </div>
146
+ </div>
147
+ )}
148
+ </div>
149
+ );
150
+ }
151
+ }
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+
3
+ import { AzureWizardPage } from './common';
4
+
5
+ export class ServerGroupInstanceType extends AzureWizardPage {
6
+ public validate(values: any): { [key: string]: any } {
7
+ return values.instanceType ? {} : { instanceType: 'Instance Type required.' };
8
+ }
9
+
10
+ private instanceTypeChanged = (instanceType: string) => {
11
+ this.props.formik.values.instanceType = instanceType;
12
+ this.props.formik.setFieldValue('instanceType', instanceType);
13
+ this.props.formik.setFieldValue('sku.name', instanceType);
14
+ };
15
+
16
+ public render() {
17
+ const { values } = this.props.formik;
18
+ const instanceTypes = values.backingData?.filtered?.instanceTypes || [];
19
+ return (
20
+ <div className="container-fluid form-horizontal">
21
+ <div className="form-group">
22
+ <div className="col-md-3 sm-label-right">Instance Type</div>
23
+ <div className="col-md-7">
24
+ <select
25
+ className="form-control input-sm"
26
+ onChange={(event) => this.instanceTypeChanged(event.target.value)}
27
+ value={values.instanceType || ''}
28
+ >
29
+ <option value="">Select...</option>
30
+ {instanceTypes.map((type: string) => (
31
+ <option key={type} value={type}>
32
+ {type}
33
+ </option>
34
+ ))}
35
+ </select>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ );
40
+ }
41
+ }
@@ -0,0 +1,214 @@
1
+ import React from 'react';
2
+
3
+ import { DeckRuntimeContext, InfrastructureCaches, NetworkReader } from '@spinnaker/core';
4
+
5
+ import { AzureWizardPage } from './common';
6
+ import Utility from '../../../../utility';
7
+
8
+ function normalizeLoadBalancerType(loadBalancerType: string): string | null {
9
+ const normalized = String(loadBalancerType || '')
10
+ .toLowerCase()
11
+ .split('_')
12
+ .join(' ');
13
+ if (normalized === 'application gateway') {
14
+ return 'Azure Application Gateway';
15
+ }
16
+ if (normalized === 'load balancer') {
17
+ return 'Azure Load Balancer';
18
+ }
19
+ return Utility.getLoadBalancerType(loadBalancerType)?.type || loadBalancerType || null;
20
+ }
21
+
22
+ function selectableSubnetNames(vnet: any): string[] {
23
+ return (vnet?.subnets || [])
24
+ .filter((subnet: any) =>
25
+ (subnet.devices || []).every((device: any) => !device || device.type !== 'applicationGateways'),
26
+ )
27
+ .map((subnet: any) => subnet.name || subnet);
28
+ }
29
+
30
+ function matchesSelectedVnet(candidate: any, selectedVnet: any): boolean {
31
+ return (
32
+ candidate.name === selectedVnet.name &&
33
+ (!selectedVnet.resourceGroup || candidate.resourceGroup === selectedVnet.resourceGroup)
34
+ );
35
+ }
36
+
37
+ export class ServerGroupLoadBalancers extends AzureWizardPage {
38
+ public static contextType = DeckRuntimeContext;
39
+ public declare context: React.ContextType<typeof DeckRuntimeContext>;
40
+
41
+ private loadVnetSubnetsRequestId = 0;
42
+
43
+ private getCommandLoadBalancer(loadBalancerName: string | null): any {
44
+ const { values } = this.props.formik;
45
+ const loadBalancers = values.backingData?.loadBalancers || [];
46
+ return (
47
+ loadBalancers.find(
48
+ (candidate: any) =>
49
+ candidate.name === loadBalancerName &&
50
+ candidate.account === values.credentials &&
51
+ candidate.region === values.region,
52
+ ) || loadBalancers.find((candidate: any) => candidate.name === loadBalancerName)
53
+ );
54
+ }
55
+
56
+ public componentDidMount(): void {
57
+ const { values } = this.props.formik;
58
+ if (values.credentials && values.region) {
59
+ values.viewState.networkSettingsConfigured = true;
60
+ values.selectedVnetSubnets = values.selectedVnetSubnets || [];
61
+ if (values.loadBalancerName) {
62
+ void this.loadBalancerChanged(values.loadBalancerName);
63
+ } else {
64
+ void this.loadVnetSubnets(null, values.loadBalancerType || null, ++this.loadVnetSubnetsRequestId);
65
+ }
66
+ }
67
+ }
68
+
69
+ public componentWillUnmount(): void {
70
+ this.loadVnetSubnetsRequestId += 1;
71
+ }
72
+
73
+ public loadBalancerChanged = async (loadBalancerName: string | null, clearNetworkFields = false): Promise<void> => {
74
+ const { values } = this.props.formik;
75
+ const requestId = ++this.loadVnetSubnetsRequestId;
76
+ const loadBalancer = this.getCommandLoadBalancer(loadBalancerName);
77
+ const loadBalancerType = normalizeLoadBalancerType(loadBalancer?.loadBalancerType);
78
+ values.loadBalancerName = loadBalancerName || null;
79
+ values.loadBalancerType = loadBalancerType;
80
+ values.selectedVnetSubnets = [];
81
+ if (clearNetworkFields) {
82
+ values.selectedVnet = null;
83
+ values.vnet = null;
84
+ values.vnetResourceGroup = null;
85
+ values.selectedSubnet = null;
86
+ values.subnet = null;
87
+ }
88
+ values.viewState = values.viewState || {};
89
+ values.viewState.networkSettingsConfigured = true;
90
+ this.props.formik.setFieldValue('loadBalancerName', values.loadBalancerName);
91
+ this.props.formik.setFieldValue('loadBalancerType', values.loadBalancerType);
92
+ this.props.formik.setFieldValue('selectedVnetSubnets', []);
93
+ if (clearNetworkFields) {
94
+ this.props.formik.setFieldValue('selectedVnet', null);
95
+ this.props.formik.setFieldValue('vnet', null);
96
+ this.props.formik.setFieldValue('vnetResourceGroup', null);
97
+ this.props.formik.setFieldValue('selectedSubnet', null);
98
+ this.props.formik.setFieldValue('subnet', null);
99
+ }
100
+ InfrastructureCaches.clearCache('networks');
101
+ await this.loadVnetSubnets(values.loadBalancerName, loadBalancerType, requestId);
102
+ };
103
+
104
+ private loadVnetSubnets = async (
105
+ loadBalancerName: string | null,
106
+ loadBalancerType: string | null,
107
+ requestId: number,
108
+ ): Promise<void> => {
109
+ const { values } = this.props.formik;
110
+ const credentials = values.credentials;
111
+ const region = values.region;
112
+ if (!credentials || !region) {
113
+ return;
114
+ }
115
+
116
+ let loadBalancerDetails: any[];
117
+ let networks: any;
118
+ try {
119
+ [loadBalancerDetails, networks] = await Promise.all([
120
+ loadBalancerName
121
+ ? this.context.services.loadBalancerReader.getLoadBalancerDetails(
122
+ 'azure',
123
+ credentials,
124
+ region,
125
+ loadBalancerName,
126
+ )
127
+ : Promise.resolve([]),
128
+ NetworkReader.listNetworks(),
129
+ ]);
130
+ } catch (_error) {
131
+ return;
132
+ }
133
+ if (
134
+ requestId !== this.loadVnetSubnetsRequestId ||
135
+ values.loadBalancerName !== loadBalancerName ||
136
+ values.credentials !== credentials ||
137
+ values.region !== region
138
+ ) {
139
+ return;
140
+ }
141
+ const azureNetworks = Array.isArray(networks) ? networks : (networks as any).azure || [];
142
+ const allVnets = azureNetworks.filter((vnet: any) => vnet.account === credentials && vnet.region === region);
143
+ const attachedVnet = values.selectedVnet;
144
+ const selectedLoadBalancer = loadBalancerDetails?.length === 1 ? loadBalancerDetails[0] : null;
145
+ let selectedVnet =
146
+ !selectedLoadBalancer && attachedVnet
147
+ ? allVnets.find((vnet: any) => matchesSelectedVnet(vnet, attachedVnet)) || null
148
+ : null;
149
+
150
+ if (selectedLoadBalancer) {
151
+ selectedVnet = allVnets.find((vnet: any) => {
152
+ if (loadBalancerType === 'Azure Application Gateway') {
153
+ return vnet.name === selectedLoadBalancer.vnet;
154
+ }
155
+ if (loadBalancerType === 'Azure Load Balancer' && attachedVnet) {
156
+ return matchesSelectedVnet(vnet, attachedVnet);
157
+ }
158
+ return false;
159
+ });
160
+ }
161
+
162
+ const selectedVnetSubnets = selectedVnet
163
+ ? selectableSubnetNames(selectedVnet)
164
+ : allVnets.reduce((subnets: string[], vnet: any) => subnets.concat(selectableSubnetNames(vnet)), []);
165
+
166
+ values.allVnets = allVnets;
167
+ values.selectedVnet = selectedVnet || null;
168
+ values.vnet = selectedVnet?.name || null;
169
+ values.vnetResourceGroup = selectedVnet?.resourceGroup || null;
170
+ values.selectedVnetSubnets = selectedVnetSubnets;
171
+ values.selectedSubnet = selectedVnet && selectedVnetSubnets.includes(values.subnet) ? values.subnet : null;
172
+ values.subnet = values.selectedSubnet;
173
+
174
+ this.props.formik.setFieldValue('allVnets', allVnets);
175
+ this.props.formik.setFieldValue('selectedVnet', values.selectedVnet);
176
+ this.props.formik.setFieldValue('vnet', values.vnet);
177
+ this.props.formik.setFieldValue('vnetResourceGroup', values.vnetResourceGroup);
178
+ this.props.formik.setFieldValue('selectedVnetSubnets', selectedVnetSubnets);
179
+ this.props.formik.setFieldValue('selectedSubnet', values.selectedSubnet);
180
+ this.props.formik.setFieldValue('subnet', values.subnet);
181
+ };
182
+
183
+ public render() {
184
+ const loadBalancers =
185
+ this.props.formik.values.loadBalancers || this.props.formik.values.backingData?.filtered?.loadBalancers || [];
186
+ return (
187
+ <div className="container-fluid form-horizontal">
188
+ <div className="form-group">
189
+ <div className="col-md-3 sm-label-right">Load Balancer</div>
190
+ <div className="col-md-7">
191
+ <select
192
+ className="form-control input-sm"
193
+ onChange={(event) => this.loadBalancerChanged(event.target.value, true)}
194
+ value={this.props.formik.values.loadBalancerName || ''}
195
+ >
196
+ <option value="">None</option>
197
+ {loadBalancers.map((loadBalancer: string) => (
198
+ <option key={loadBalancer} value={loadBalancer}>
199
+ {loadBalancer}
200
+ </option>
201
+ ))}
202
+ </select>
203
+ </div>
204
+ </div>
205
+ {this.props.formik.values.loadBalancerName && (
206
+ <div className="well-compact text-center">
207
+ The load balancer {this.props.formik.values.loadBalancerName} is an{' '}
208
+ {this.props.formik.values.loadBalancerType}
209
+ </div>
210
+ )}
211
+ </div>
212
+ );
213
+ }
214
+ }