@spinnaker/azure 0.0.0-2025.1-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 (174) hide show
  1. package/CHANGELOG.md +873 -0
  2. package/LICENSE.txt +203 -0
  3. package/dist/azure.module.d.ts +3 -0
  4. package/dist/azure.settings.d.ts +8 -0
  5. package/dist/common/AzureModalFooter.d.ts +18 -0
  6. package/dist/help/azure.help.d.ts +1 -0
  7. package/dist/image/image.reader.d.ts +2 -0
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.js +6778 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/instance/azureInstanceType.service.d.ts +2 -0
  12. package/dist/instance/details/instance.details.controller.d.ts +2 -0
  13. package/dist/loadBalancer/configure/AzureLoadBalancerChoiceModal.d.ts +16 -0
  14. package/dist/loadBalancer/configure/createLoadBalancer.controller.d.ts +2 -0
  15. package/dist/loadBalancer/details/loadBalancerDetail.controller.d.ts +2 -0
  16. package/dist/loadBalancer/loadBalancer.transformer.d.ts +2 -0
  17. package/dist/pipeline/stages/bake/azureBakeStage.d.ts +2 -0
  18. package/dist/pipeline/stages/bake/bakeExecutionDetails.controller.d.ts +2 -0
  19. package/dist/pipeline/stages/destroyAsg/azureDestroyAsgStage.d.ts +2 -0
  20. package/dist/pipeline/stages/disableAsg/azureDisableAsgStage.d.ts +2 -0
  21. package/dist/pipeline/stages/enableAsg/azureEnableAsgStage.d.ts +2 -0
  22. package/dist/securityGroup/clone/cloneSecurityGroup.controller.d.ts +2 -0
  23. package/dist/securityGroup/configure/CreateSecurityGroupCtrl.d.ts +2 -0
  24. package/dist/securityGroup/configure/EditSecurityGroupCtrl.d.ts +2 -0
  25. package/dist/securityGroup/details/securityGroupDetail.controller.d.ts +2 -0
  26. package/dist/securityGroup/securityGroup.reader.d.ts +2 -0
  27. package/dist/securityGroup/securityGroup.transformer.d.ts +2 -0
  28. package/dist/securityGroup/securityGroup.write.service.d.ts +2 -0
  29. package/dist/serverGroup/configure/serverGroup.configure.azure.module.d.ts +2 -0
  30. package/dist/serverGroup/configure/serverGroupCommandBuilder.service.d.ts +2 -0
  31. package/dist/serverGroup/configure/serverGroupConfiguration.service.d.ts +2 -0
  32. package/dist/serverGroup/configure/wizard/CloneServerGroup.azure.controller.d.ts +2 -0
  33. package/dist/serverGroup/configure/wizard/ServerGroupInstanceArchetype.controller.d.ts +2 -0
  34. package/dist/serverGroup/configure/wizard/ServerGroupInstanceType.controller.d.ts +2 -0
  35. package/dist/serverGroup/configure/wizard/advancedSettings/ServerGroupAdvancedSettings.controller.d.ts +2 -0
  36. package/dist/serverGroup/configure/wizard/advancedSettings/advancedSettingsSelector.directive.d.ts +2 -0
  37. package/dist/serverGroup/configure/wizard/basicSettings/ServerGroupBasicSettings.controller.d.ts +2 -0
  38. package/dist/serverGroup/configure/wizard/basicSettings/image.regional.filter.d.ts +2 -0
  39. package/dist/serverGroup/configure/wizard/capacity/capacitySelector.directive.d.ts +2 -0
  40. package/dist/serverGroup/configure/wizard/healthSettings/ServerGroupHealthSettings.controller.d.ts +2 -0
  41. package/dist/serverGroup/configure/wizard/healthSettings/healthSettingsSelector.directive.d.ts +2 -0
  42. package/dist/serverGroup/configure/wizard/image/ServerGroupImageSettings.controller.d.ts +2 -0
  43. package/dist/serverGroup/configure/wizard/image/imageSettingsSelector.directive.d.ts +2 -0
  44. package/dist/serverGroup/configure/wizard/loadBalancers/ServerGroupLoadBalancers.controller.d.ts +2 -0
  45. package/dist/serverGroup/configure/wizard/loadBalancers/serverGroupLoadBalancersSelector.directive.d.ts +2 -0
  46. package/dist/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettings.controller.d.ts +2 -0
  47. package/dist/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettingsSelector.directive.d.ts +2 -0
  48. package/dist/serverGroup/configure/wizard/securityGroup/ServerGroupSecurityGroups.controller.d.ts +2 -0
  49. package/dist/serverGroup/configure/wizard/securityGroup/serverGroupSecurityGroupsSelector.directive.d.ts +2 -0
  50. package/dist/serverGroup/configure/wizard/tags/tagsSelector.directive.d.ts +2 -0
  51. package/dist/serverGroup/configure/wizard/zones/zoneSelector.directive.d.ts +2 -0
  52. package/dist/serverGroup/details/rollback/RollbackServerGroupModal.d.ts +25 -0
  53. package/dist/serverGroup/details/serverGroup.details.module.d.ts +2 -0
  54. package/dist/serverGroup/details/serverGroupDetails.azure.controller.d.ts +2 -0
  55. package/dist/serverGroup/serverGroup.transformer.d.ts +2 -0
  56. package/dist/utility.d.ts +28 -0
  57. package/dist/validation/applicationName.validator.d.ts +2 -0
  58. package/package.json +43 -0
  59. package/src/azure.module.ts +95 -0
  60. package/src/azure.settings.ts +16 -0
  61. package/src/common/AzureModalFooter.tsx +43 -0
  62. package/src/help/azure.help.ts +60 -0
  63. package/src/image/image.reader.js +43 -0
  64. package/src/image/image.reader.spec.js +108 -0
  65. package/src/index.ts +1 -0
  66. package/src/instance/azureInstanceType.service.js +831 -0
  67. package/src/instance/azureInstanceType.service.spec.js +17 -0
  68. package/src/instance/details/instance.details.controller.js +371 -0
  69. package/src/instance/details/instance.details.controller.spec.js +129 -0
  70. package/src/instance/details/instanceDetails.html +43 -0
  71. package/src/loadBalancer/configure/AzureLoadBalancerChoiceModal.tsx +101 -0
  72. package/src/loadBalancer/configure/advancedSettings.html +95 -0
  73. package/src/loadBalancer/configure/createLoadBalancer.controller.js +275 -0
  74. package/src/loadBalancer/configure/createLoadBalancer.controller.spec.js +39 -0
  75. package/src/loadBalancer/configure/createLoadBalancer.html +25 -0
  76. package/src/loadBalancer/configure/createLoadBalancerProperties.html +128 -0
  77. package/src/loadBalancer/configure/editLoadBalancer.html +26 -0
  78. package/src/loadBalancer/configure/healthCheck.html +74 -0
  79. package/src/loadBalancer/configure/listeners.html +50 -0
  80. package/src/loadBalancer/details/loadBalancerDetail.controller.js +181 -0
  81. package/src/loadBalancer/details/loadBalancerDetail.controller.spec.js +39 -0
  82. package/src/loadBalancer/details/loadBalancerDetail.html +128 -0
  83. package/src/loadBalancer/loadBalancer.transformer.js +109 -0
  84. package/src/logo/azure.icon.svg +196 -0
  85. package/src/logo/azure.logo.less +6 -0
  86. package/src/logo/logo_azure.png +0 -0
  87. package/src/pipeline/stages/bake/azureBakeStage.js +276 -0
  88. package/src/pipeline/stages/bake/bakeExecutionDetails.controller.js +40 -0
  89. package/src/pipeline/stages/bake/bakeExecutionDetails.html +50 -0
  90. package/src/pipeline/stages/bake/bakeStage.html +187 -0
  91. package/src/pipeline/stages/destroyAsg/azureDestroyAsgStage.js +73 -0
  92. package/src/pipeline/stages/destroyAsg/destroyAsgStage.html +9 -0
  93. package/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html +1 -0
  94. package/src/pipeline/stages/disableAsg/azureDisableAsgStage.js +65 -0
  95. package/src/pipeline/stages/disableAsg/disableAsgStage.html +11 -0
  96. package/src/pipeline/stages/disableAsg/disableAsgStepLabel.html +1 -0
  97. package/src/pipeline/stages/enableAsg/azureEnableAsgStage.js +70 -0
  98. package/src/pipeline/stages/enableAsg/enableAsgStage.html +11 -0
  99. package/src/pipeline/stages/enableAsg/enableAsgStepLabel.html +1 -0
  100. package/src/securityGroup/clone/cloneSecurityGroup.controller.js +162 -0
  101. package/src/securityGroup/clone/cloneSecurityGroup.html +8 -0
  102. package/src/securityGroup/configure/CreateSecurityGroup.controller.spec.js +78 -0
  103. package/src/securityGroup/configure/CreateSecurityGroupCtrl.js +265 -0
  104. package/src/securityGroup/configure/EditSecurityGroupCtrl.js +222 -0
  105. package/src/securityGroup/configure/configSecurityGroup.mixin.controller.js +262 -0
  106. package/src/securityGroup/configure/createSecurityGroup.html +20 -0
  107. package/src/securityGroup/configure/createSecurityGroupIngress.html +75 -0
  108. package/src/securityGroup/configure/createSecurityGroupProperties.html +88 -0
  109. package/src/securityGroup/configure/editSecurityGroup.html +19 -0
  110. package/src/securityGroup/details/securityGroupDetail.controller.js +142 -0
  111. package/src/securityGroup/details/securityGroupDetail.html +78 -0
  112. package/src/securityGroup/securityGroup.reader.js +17 -0
  113. package/src/securityGroup/securityGroup.transformer.js +13 -0
  114. package/src/securityGroup/securityGroup.write.service.js +57 -0
  115. package/src/serverGroup/configure/serverGroup.configure.azure.module.js +47 -0
  116. package/src/serverGroup/configure/serverGroupCommandBuilder.service.js +175 -0
  117. package/src/serverGroup/configure/serverGroupConfiguration.service.js +357 -0
  118. package/src/serverGroup/configure/serverGroupConfiguration.service.spec.js +209 -0
  119. package/src/serverGroup/configure/wizard/CloneServerGroup.azure.controller.js +247 -0
  120. package/src/serverGroup/configure/wizard/ServerGroupInstanceArchetype.controller.js +35 -0
  121. package/src/serverGroup/configure/wizard/ServerGroupInstanceType.controller.js +15 -0
  122. package/src/serverGroup/configure/wizard/advancedSettings/ServerGroupAdvancedSettings.controller.js +25 -0
  123. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettings.html +5 -0
  124. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettingsSelector.directive.html +138 -0
  125. package/src/serverGroup/configure/wizard/advancedSettings/advancedSettingsSelector.directive.js +43 -0
  126. package/src/serverGroup/configure/wizard/basicSettings/ServerGroupBasicSettings.controller.js +71 -0
  127. package/src/serverGroup/configure/wizard/basicSettings/basicSettings.html +131 -0
  128. package/src/serverGroup/configure/wizard/basicSettings/image.regional.filter.js +15 -0
  129. package/src/serverGroup/configure/wizard/basicSettings/image.regional.filter.spec.js +42 -0
  130. package/src/serverGroup/configure/wizard/capacity/capacity.html +5 -0
  131. package/src/serverGroup/configure/wizard/capacity/capacitySelector.directive.html +20 -0
  132. package/src/serverGroup/configure/wizard/capacity/capacitySelector.directive.js +21 -0
  133. package/src/serverGroup/configure/wizard/capacity/zones.html +5 -0
  134. package/src/serverGroup/configure/wizard/healthSettings/ServerGroupHealthSettings.controller.js +38 -0
  135. package/src/serverGroup/configure/wizard/healthSettings/healthSettings.html +5 -0
  136. package/src/serverGroup/configure/wizard/healthSettings/healthSettingsSelector.directive.html +32 -0
  137. package/src/serverGroup/configure/wizard/healthSettings/healthSettingsSelector.directive.js +22 -0
  138. package/src/serverGroup/configure/wizard/image/ServerGroupImageSettings.controller.js +34 -0
  139. package/src/serverGroup/configure/wizard/image/imageSettings.html +5 -0
  140. package/src/serverGroup/configure/wizard/image/imageSettingsSelector.directive.html +33 -0
  141. package/src/serverGroup/configure/wizard/image/imageSettingsSelector.directive.js +22 -0
  142. package/src/serverGroup/configure/wizard/instanceArchetype.html +33 -0
  143. package/src/serverGroup/configure/wizard/instanceType/instanceType.html +10 -0
  144. package/src/serverGroup/configure/wizard/instanceType.html +33 -0
  145. package/src/serverGroup/configure/wizard/loadBalancers/ServerGroupLoadBalancers.controller.js +137 -0
  146. package/src/serverGroup/configure/wizard/loadBalancers/loadBalancers.html +3 -0
  147. package/src/serverGroup/configure/wizard/loadBalancers/serverGroupLoadBalancersSelector.directive.html +41 -0
  148. package/src/serverGroup/configure/wizard/loadBalancers/serverGroupLoadBalancersSelector.directive.js +22 -0
  149. package/src/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettings.controller.js +44 -0
  150. package/src/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettingsSelector.directive.html +54 -0
  151. package/src/serverGroup/configure/wizard/networkSettings/ServerGroupNetworkSettingsSelector.directive.js +19 -0
  152. package/src/serverGroup/configure/wizard/networkSettings/networkSettings.html +3 -0
  153. package/src/serverGroup/configure/wizard/securityGroup/ServerGroupSecurityGroups.controller.js +28 -0
  154. package/src/serverGroup/configure/wizard/securityGroup/securityGroups.html +3 -0
  155. package/src/serverGroup/configure/wizard/securityGroup/serverGroupSecurityGroupsSelector.directive.html +40 -0
  156. package/src/serverGroup/configure/wizard/securityGroup/serverGroupSecurityGroupsSelector.directive.js +38 -0
  157. package/src/serverGroup/configure/wizard/serverGroupWizard.html +61 -0
  158. package/src/serverGroup/configure/wizard/tags/tags.html +5 -0
  159. package/src/serverGroup/configure/wizard/tags/tagsSelector.directive.html +16 -0
  160. package/src/serverGroup/configure/wizard/tags/tagsSelector.directive.js +30 -0
  161. package/src/serverGroup/configure/wizard/templateSelection.html +9 -0
  162. package/src/serverGroup/configure/wizard/zones/zoneSelector.directive.html +21 -0
  163. package/src/serverGroup/configure/wizard/zones/zoneSelector.directive.js +28 -0
  164. package/src/serverGroup/details/rollback/RollbackServerGroupModal.tsx +158 -0
  165. package/src/serverGroup/details/serverGroup.details.module.js +11 -0
  166. package/src/serverGroup/details/serverGroupDetails.azure.controller.js +260 -0
  167. package/src/serverGroup/details/serverGroupDetails.html +98 -0
  168. package/src/serverGroup/serverGroup.transformer.js +150 -0
  169. package/src/serverGroup/serverGroup.transformer.spec.js +256 -0
  170. package/src/subnet/subnetSelectField.directive.html +28 -0
  171. package/src/subnet/subnetSelectField.directive.js +35 -0
  172. package/src/utility.spec.ts +61 -0
  173. package/src/utility.ts +95 -0
  174. package/src/validation/applicationName.validator.js +44 -0
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ describe('Service: InstanceType', function () {
4
+ beforeEach(function () {
5
+ window.module(require('./azureInstanceType.service').name);
6
+ });
7
+
8
+ beforeEach(
9
+ window.inject(function (_azureInstanceTypeService_) {
10
+ this.azureInstanceTypeService = _azureInstanceTypeService_;
11
+ }),
12
+ );
13
+
14
+ it('should instantiate the controller', function () {
15
+ expect(this.azureInstanceTypeService).toBeDefined();
16
+ });
17
+ });
@@ -0,0 +1,371 @@
1
+ 'use strict';
2
+
3
+ import UIROUTER_ANGULARJS from '@uirouter/angularjs';
4
+ import { module } from 'angular';
5
+ import ANGULAR_UI_BOOTSTRAP from 'angular-ui-bootstrap';
6
+ import _ from 'lodash';
7
+
8
+ import {
9
+ CloudProviderRegistry,
10
+ ConfirmationModalService,
11
+ InstanceReader,
12
+ InstanceWriter,
13
+ RecentHistoryService,
14
+ } from '@spinnaker/core';
15
+
16
+ export const AZURE_INSTANCE_DETAILS_INSTANCE_DETAILS_CONTROLLER = 'spinnaker.azure.instance.detail.controller';
17
+ export const name = AZURE_INSTANCE_DETAILS_INSTANCE_DETAILS_CONTROLLER; // for backwards compatibility
18
+ module(AZURE_INSTANCE_DETAILS_INSTANCE_DETAILS_CONTROLLER, [UIROUTER_ANGULARJS, ANGULAR_UI_BOOTSTRAP]).controller(
19
+ 'azureInstanceDetailsCtrl',
20
+ [
21
+ '$scope',
22
+ '$state',
23
+ '$uibModal',
24
+ 'instance',
25
+ 'app',
26
+ '$q',
27
+ function ($scope, $state, $uibModal, instance, app, $q) {
28
+ // needed for standalone instances
29
+ $scope.detailsTemplateUrl = CloudProviderRegistry.getValue('azure', 'instance.detailsTemplateUrl');
30
+
31
+ $scope.state = {
32
+ loading: true,
33
+ standalone: app.isStandalone,
34
+ };
35
+
36
+ function extractHealthMetrics(instance, latest) {
37
+ // do not backfill on standalone instances
38
+ if (app.isStandalone) {
39
+ instance.health = latest.health;
40
+ }
41
+
42
+ instance.health = instance.health || [];
43
+ const displayableMetrics = instance.health.filter(function (metric) {
44
+ return metric.type !== 'Azure' || metric.state !== 'Unknown';
45
+ });
46
+ // backfill details where applicable
47
+ if (latest.health) {
48
+ displayableMetrics.forEach(function (metric) {
49
+ const detailsMatch = latest.health.filter(function (latestHealth) {
50
+ return latestHealth.type === metric.type;
51
+ });
52
+ if (detailsMatch.length) {
53
+ _.defaults(metric, detailsMatch[0]);
54
+ }
55
+ });
56
+ }
57
+ $scope.healthMetrics = displayableMetrics;
58
+ }
59
+
60
+ function retrieveInstance() {
61
+ const extraData = {};
62
+ let instanceSummary, loadBalancers, account, region, vpcId;
63
+ if (!app.serverGroups) {
64
+ // standalone instance
65
+ instanceSummary = {};
66
+ loadBalancers = [];
67
+ account = instance.account;
68
+ region = instance.region;
69
+ } else {
70
+ app.serverGroups.data.some(function (serverGroup) {
71
+ return serverGroup.instances.some(function (possibleInstance) {
72
+ if (possibleInstance.id === instance.instanceId) {
73
+ instanceSummary = possibleInstance;
74
+ loadBalancers = serverGroup.loadBalancers;
75
+ account = serverGroup.account;
76
+ region = serverGroup.region;
77
+ vpcId = serverGroup.vpcId;
78
+ extraData.serverGroup = serverGroup.name;
79
+ extraData.vpcId = serverGroup.vpcId;
80
+ return true;
81
+ }
82
+ });
83
+ });
84
+ if (!instanceSummary) {
85
+ // perhaps it is in a server group that is part of another app
86
+ app.loadBalancers.data.some(function (loadBalancer) {
87
+ return loadBalancer.instances.some(function (possibleInstance) {
88
+ if (possibleInstance.id === instance.instanceId) {
89
+ instanceSummary = possibleInstance;
90
+ loadBalancers = [loadBalancer.name];
91
+ account = loadBalancer.account;
92
+ region = loadBalancer.region;
93
+ vpcId = loadBalancer.vpcId;
94
+ return true;
95
+ }
96
+ });
97
+ });
98
+ if (!instanceSummary) {
99
+ // perhaps it is in a disabled server group via a load balancer
100
+ app.loadBalancers.data.some(function (loadBalancer) {
101
+ return loadBalancer.serverGroups.some(function (serverGroup) {
102
+ if (!serverGroup.isDisabled) {
103
+ return false;
104
+ }
105
+ return serverGroup.instances.some(function (possibleInstance) {
106
+ if (possibleInstance.id === instance.instanceId) {
107
+ instanceSummary = possibleInstance;
108
+ loadBalancers = [loadBalancer.name];
109
+ account = loadBalancer.account;
110
+ region = loadBalancer.region;
111
+ vpcId = loadBalancer.vpcId;
112
+ return true;
113
+ }
114
+ });
115
+ });
116
+ });
117
+ }
118
+ }
119
+ }
120
+
121
+ if (instanceSummary && account && region) {
122
+ extraData.account = account;
123
+ extraData.region = region;
124
+ RecentHistoryService.addExtraDataToLatest('instances', extraData);
125
+ return InstanceReader.getInstanceDetails(account, region, instance.instanceId).then(
126
+ function (details) {
127
+ $scope.state.loading = false;
128
+ extractHealthMetrics(instanceSummary, details);
129
+ $scope.instance = _.defaults(details, instanceSummary);
130
+ $scope.instance.account = account;
131
+ $scope.instance.region = region;
132
+ $scope.instance.vpcId = vpcId;
133
+ $scope.instance.loadBalancers = loadBalancers;
134
+ const discoveryMetric = _.find($scope.healthMetrics, function (metric) {
135
+ return metric.type === 'Discovery';
136
+ });
137
+ if (discoveryMetric && discoveryMetric.vipAddress) {
138
+ const vipList = discoveryMetric.vipAddress;
139
+ $scope.instance.vipAddress = vipList.includes(',') ? vipList.split(',') : [vipList];
140
+ }
141
+ $scope.baseIpAddress = details.publicDnsName || details.privateIpAddress;
142
+ },
143
+ function () {
144
+ // When an instance is first starting up, we may not have the details cached in oort yet, but we still
145
+ // want to let the user see what details we have
146
+ $scope.state.loading = false;
147
+ $state.go('^');
148
+ },
149
+ );
150
+ }
151
+
152
+ if (!instanceSummary) {
153
+ $scope.instanceIdNotFound = instance.instanceId;
154
+ $scope.state.loading = false;
155
+ }
156
+
157
+ return $q.when(null);
158
+ }
159
+
160
+ this.canDeregisterFromLoadBalancer = function () {
161
+ return $scope.instance.health.some(function (health) {
162
+ return health.type === 'LoadBalancer';
163
+ });
164
+ };
165
+
166
+ this.canRegisterWithLoadBalancer = function () {
167
+ const instance = $scope.instance;
168
+ if (!instance.loadBalancers || !instance.loadBalancers.length) {
169
+ return false;
170
+ }
171
+ const outOfService = instance.health.some(function (health) {
172
+ return health.type === 'LoadBalancer' && health.state === 'OutOfService';
173
+ });
174
+ const hasLoadBalancerHealth = instance.health.some(function (health) {
175
+ return health.type === 'LoadBalancer';
176
+ });
177
+ return outOfService || !hasLoadBalancerHealth;
178
+ };
179
+
180
+ this.canRegisterWithDiscovery = function () {
181
+ const instance = $scope.instance;
182
+ const discoveryHealth = instance.health.filter(function (health) {
183
+ return health.type === 'Discovery';
184
+ });
185
+ return discoveryHealth.length ? discoveryHealth[0].state === 'OutOfService' : false;
186
+ };
187
+
188
+ this.terminateInstance = function terminateInstance() {
189
+ const instance = $scope.instance;
190
+
191
+ const taskMonitor = {
192
+ application: app,
193
+ title: 'Terminating ' + instance.instanceId,
194
+ onTaskComplete: function () {
195
+ if ($state.includes('**.instanceDetails', { instanceId: instance.instanceId })) {
196
+ $state.go('^');
197
+ }
198
+ },
199
+ };
200
+
201
+ const submitMethod = function () {
202
+ return InstanceWriter.terminateInstance(instance, app);
203
+ };
204
+
205
+ ConfirmationModalService.confirm({
206
+ header: 'Really terminate ' + instance.instanceId + '?',
207
+ buttonText: 'Terminate ' + instance.instanceId,
208
+ account: instance.account,
209
+ taskMonitorConfig: taskMonitor,
210
+ submitMethod: submitMethod,
211
+ });
212
+ };
213
+
214
+ this.terminateInstanceAndShrinkServerGroup = function terminateInstanceAndShrinkServerGroup() {
215
+ const instance = $scope.instance;
216
+
217
+ const taskMonitor = {
218
+ application: app,
219
+ title: 'Terminating ' + instance.instanceId + ' and shrinking server group',
220
+ onTaskComplete: function () {
221
+ if ($state.includes('**.instanceDetails', { instanceId: instance.instanceId })) {
222
+ $state.go('^');
223
+ }
224
+ },
225
+ };
226
+
227
+ const submitMethod = function () {
228
+ return InstanceWriter.terminateInstanceAndShrinkServerGroup(instance, app);
229
+ };
230
+
231
+ ConfirmationModalService.confirm({
232
+ header: 'Really terminate ' + instance.instanceId + ' and shrink ' + instance.serverGroup + '?',
233
+ buttonText: 'Terminate ' + instance.instanceId + ' and shrink ' + instance.serverGroup,
234
+ account: instance.account,
235
+ taskMonitorConfig: taskMonitor,
236
+ submitMethod: submitMethod,
237
+ });
238
+ };
239
+
240
+ this.rebootInstance = function rebootInstance() {
241
+ const instance = $scope.instance;
242
+
243
+ const taskMonitor = {
244
+ application: app,
245
+ title: 'Rebooting ' + instance.instanceId,
246
+ };
247
+
248
+ const submitMethod = function () {
249
+ return InstanceWriter.rebootInstance(instance, app);
250
+ };
251
+
252
+ ConfirmationModalService.confirm({
253
+ header: 'Really reboot ' + instance.instanceId + '?',
254
+ buttonText: 'Reboot ' + instance.instanceId,
255
+ account: instance.account,
256
+ taskMonitorConfig: taskMonitor,
257
+ submitMethod: submitMethod,
258
+ });
259
+ };
260
+
261
+ this.registerInstanceWithLoadBalancer = function registerInstanceWithLoadBalancer() {
262
+ const instance = $scope.instance;
263
+ const loadBalancerNames = instance.loadBalancers.join(' and ');
264
+
265
+ const taskMonitor = {
266
+ application: app,
267
+ title: 'Registering ' + instance.instanceId + ' with ' + loadBalancerNames,
268
+ };
269
+
270
+ const submitMethod = function () {
271
+ return InstanceWriter.registerInstanceWithLoadBalancer(instance, app);
272
+ };
273
+
274
+ ConfirmationModalService.confirm({
275
+ header: 'Really register ' + instance.instanceId + ' with ' + loadBalancerNames + '?',
276
+ buttonText: 'Register ' + instance.instanceId,
277
+ account: instance.account,
278
+ taskMonitorConfig: taskMonitor,
279
+ submitMethod: submitMethod,
280
+ });
281
+ };
282
+
283
+ this.deregisterInstanceFromLoadBalancer = function deregisterInstanceFromLoadBalancer() {
284
+ const instance = $scope.instance;
285
+ const loadBalancerNames = instance.loadBalancers.join(' and ');
286
+
287
+ const taskMonitor = {
288
+ application: app,
289
+ title: 'Deregistering ' + instance.instanceId + ' from ' + loadBalancerNames,
290
+ };
291
+
292
+ const submitMethod = function () {
293
+ return InstanceWriter.deregisterInstanceFromLoadBalancer(instance, app);
294
+ };
295
+
296
+ ConfirmationModalService.confirm({
297
+ header: 'Really deregister ' + instance.instanceId + ' from ' + loadBalancerNames + '?',
298
+ buttonText: 'Deregister ' + instance.instanceId,
299
+ account: instance.account,
300
+ taskMonitorConfig: taskMonitor,
301
+ submitMethod: submitMethod,
302
+ });
303
+ };
304
+
305
+ this.enableInstanceInDiscovery = function enableInstanceInDiscovery() {
306
+ const instance = $scope.instance;
307
+
308
+ const taskMonitor = {
309
+ application: app,
310
+ title: 'Enabling ' + instance.instanceId + ' in discovery',
311
+ };
312
+
313
+ const submitMethod = function () {
314
+ return InstanceWriter.enableInstanceInDiscovery(instance, app);
315
+ };
316
+
317
+ ConfirmationModalService.confirm({
318
+ header: 'Really enable ' + instance.instanceId + ' in discovery?',
319
+ buttonText: 'Enable ' + instance.instanceId,
320
+ account: instance.account,
321
+ taskMonitorConfig: taskMonitor,
322
+ submitMethod: submitMethod,
323
+ });
324
+ };
325
+
326
+ this.disableInstanceInDiscovery = function disableInstanceInDiscovery() {
327
+ const instance = $scope.instance;
328
+
329
+ const taskMonitor = {
330
+ application: app,
331
+ title: 'Disabling ' + instance.instanceId + ' in discovery',
332
+ };
333
+
334
+ const submitMethod = function () {
335
+ return InstanceWriter.disableInstanceInDiscovery(instance, app);
336
+ };
337
+
338
+ ConfirmationModalService.confirm({
339
+ header: 'Really disable ' + instance.instanceId + ' in discovery?',
340
+ buttonText: 'Disable ' + instance.instanceId,
341
+ account: instance.account,
342
+ taskMonitorConfig: taskMonitor,
343
+ submitMethod: submitMethod,
344
+ });
345
+ };
346
+
347
+ this.hasHealthState = function hasHealthState(healthProviderType, state) {
348
+ const instance = $scope.instance;
349
+ return instance.health.some(function (health) {
350
+ return health.type === healthProviderType && health.state === state;
351
+ });
352
+ };
353
+
354
+ const initialize = app.isStandalone
355
+ ? retrieveInstance()
356
+ : $q.all([app.serverGroups.ready(), app.loadBalancers.ready()]).then(retrieveInstance);
357
+
358
+ initialize.then(() => {
359
+ // Two things to look out for here:
360
+ // 1. If the retrieveInstance call completes *after* the user has navigated away from the view, there
361
+ // is no point in subscribing to the refresh
362
+ // 2. If this is a standalone instance, there is no application that will refresh
363
+ if (!$scope.$$destroyed && !app.isStandalone) {
364
+ app.serverGroups.onRefresh($scope, retrieveInstance);
365
+ }
366
+ });
367
+
368
+ $scope.account = instance.account;
369
+ },
370
+ ],
371
+ );
@@ -0,0 +1,129 @@
1
+ import { ApplicationModelBuilder, InstanceReader } from '@spinnaker/core';
2
+
3
+ describe('Controller: azureInstanceDetailsCtrl', function () {
4
+ var controller;
5
+ var scope;
6
+ var $q;
7
+ var application;
8
+
9
+ beforeEach(window.module(require('./instance.details.controller').name));
10
+
11
+ beforeEach(
12
+ window.inject(function ($rootScope, $controller, _$q_) {
13
+ scope = $rootScope.$new();
14
+ $q = _$q_;
15
+
16
+ application = ApplicationModelBuilder.createApplicationForTests(
17
+ 'app',
18
+ { key: 'loadBalancers', lazy: true, defaultData: [] },
19
+ { key: 'serverGroups', lazy: true, defaultData: [] },
20
+ );
21
+
22
+ this.createController = function (application, instance) {
23
+ controller = $controller('azureInstanceDetailsCtrl', {
24
+ $scope: scope,
25
+ instance: instance,
26
+ app: application,
27
+ });
28
+ };
29
+ }),
30
+ );
31
+
32
+ describe('health metrics', function () {
33
+ it('overrides new health with health from application, adding new fields', function () {
34
+ var details = {
35
+ health: [{ type: 'Discovery', status: 'Up', extra: 'details field', reason: 'mutated' }],
36
+ };
37
+ var params = {
38
+ instanceId: 'i-123',
39
+ region: 'us-west-1',
40
+ account: 'test',
41
+ };
42
+
43
+ spyOn(InstanceReader, 'getInstanceDetails').and.returnValue($q.when(details));
44
+
45
+ application.loadBalancers.loaded = true;
46
+
47
+ application.serverGroups.data = [
48
+ {
49
+ account: 'test',
50
+ region: 'us-west-1',
51
+ instances: [
52
+ {
53
+ id: 'i-123',
54
+ health: [{ type: 'Discovery', status: 'Down', reason: 'original reason' }],
55
+ },
56
+ ],
57
+ },
58
+ ];
59
+ application.serverGroups.loaded = true;
60
+
61
+ this.createController(application, params);
62
+ scope.$digest();
63
+
64
+ expect(scope.healthMetrics.length).toBe(1);
65
+ expect(scope.healthMetrics[0].reason).toBe('original reason');
66
+ expect(scope.healthMetrics[0].status).toBe('Down');
67
+ expect(scope.healthMetrics[0].extra).toBe('details field');
68
+ });
69
+ });
70
+
71
+ describe('canRegister methods', function () {
72
+ beforeEach(function () {
73
+ var details = {};
74
+ var params = {
75
+ instanceId: 'i-123',
76
+ region: 'us-west-1',
77
+ account: 'test',
78
+ };
79
+
80
+ spyOn(InstanceReader, 'getInstanceDetails').and.returnValue(
81
+ $q.when({
82
+ plain: function () {
83
+ return details;
84
+ },
85
+ }),
86
+ );
87
+
88
+ application.loadBalancers.loaded = true;
89
+ application.serverGroups.data = [
90
+ {
91
+ account: 'test',
92
+ region: 'us-west-1',
93
+ instances: [
94
+ {
95
+ id: 'i-123',
96
+ health: [{ type: 'Discovery', state: 'Up', reason: 'original reason' }],
97
+ },
98
+ ],
99
+ },
100
+ ];
101
+ application.serverGroups.loaded = true;
102
+
103
+ this.createController(application, params);
104
+ scope.$digest();
105
+ });
106
+
107
+ it('can register with discovery when discovery', function () {
108
+ expect(controller.canRegisterWithDiscovery()).toBe(false);
109
+ scope.instance.health[0].state = 'OutOfService';
110
+ expect(controller.canRegisterWithDiscovery()).toBe(true);
111
+ scope.instance.health[0].state = 'Down';
112
+ expect(controller.canRegisterWithDiscovery()).toBe(false);
113
+ scope.instance.health = [];
114
+ expect(controller.canRegisterWithDiscovery()).toBe(false);
115
+ });
116
+
117
+ it('can register with load balancer', function () {
118
+ expect(controller.canRegisterWithLoadBalancer()).toBe(false);
119
+ scope.instance.health[0].type = 'LoadBalancer';
120
+ scope.instance.health[0].state = 'OutOfService';
121
+ expect(controller.canRegisterWithLoadBalancer()).toBe(false);
122
+ // add a load balancer
123
+ scope.instance.loadBalancers = ['elb-1'];
124
+ expect(controller.canRegisterWithLoadBalancer()).toBe(true);
125
+ scope.instance.health[0].state = 'Up';
126
+ expect(controller.canRegisterWithLoadBalancer()).toBe(false);
127
+ });
128
+ });
129
+ });
@@ -0,0 +1,43 @@
1
+ <div class="details-panel">
2
+ <div class="header">
3
+ <instance-details-header
4
+ health-state="instance.healthState"
5
+ instance-id="instance ? instance.instanceId : instanceIdNotFound"
6
+ loading="state.loading"
7
+ standalone="state.standalone"
8
+ ></instance-details-header>
9
+ </div>
10
+ <div class="content" ng-if="!state.loading && instance">
11
+ <collapsible-section heading="Instance Information" expanded="true">
12
+ <dl class="dl-horizontal dl-narrow">
13
+ <dt>Launched</dt>
14
+ <dd ng-if="instance.launchTime">{{instance.launchTime | timestamp}}</dd>
15
+ <dd ng-if="!instance.launchTime">(Unknown)</dd>
16
+ <dt>In</dt>
17
+ <dd>
18
+ <account-tag account="instance.account" provider="instance.provider" pad="right"></account-tag>
19
+ {{instance.region || '(Unknown)'}}
20
+ </dd>
21
+ <dt>Type</dt>
22
+ <dd>{{instance.instanceType || '(Unknown)'}}</dd>
23
+ <dt ng-if="instance.serverGroup">Server Group</dt>
24
+ <dd ng-if="instance.serverGroup">
25
+ <a
26
+ ui-sref="^.serverGroup({region: instance.region,
27
+ accountId: instance.account,
28
+ serverGroup: instance.serverGroup,
29
+ provider: instance.provider})"
30
+ >{{instance.serverGroup}}</a
31
+ >
32
+ </dd>
33
+ </dl>
34
+ </collapsible-section>
35
+ </div>
36
+ <div class="content" ng-if="!state.loading && !instance">
37
+ <div class="content-section">
38
+ <div class="content-body text-center">
39
+ <h3>Instance not found.</h3>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import { Button, Modal } from 'react-bootstrap';
3
+
4
+ import type { ILoadBalancerModalProps } from '@spinnaker/core';
5
+ import { CloudProviderRegistry, ModalClose, ModalInjector, noop, ReactModal } from '@spinnaker/core';
6
+
7
+ import type { IAzureLoadBalancer } from '../../utility';
8
+ import { AzureLoadBalancerTypes } from '../../utility';
9
+
10
+ export interface IAzureLoadBalancerChoiceModalState {
11
+ choices: IAzureLoadBalancer[];
12
+ selectedChoice: IAzureLoadBalancer;
13
+ }
14
+
15
+ export class AzureLoadBalancerChoiceModal extends React.Component<
16
+ ILoadBalancerModalProps,
17
+ IAzureLoadBalancerChoiceModalState
18
+ > {
19
+ public static defaultProps: Partial<ILoadBalancerModalProps> = {
20
+ closeModal: noop,
21
+ dismissModal: noop,
22
+ };
23
+
24
+ public static show(props: ILoadBalancerModalProps): Promise<void> {
25
+ return ReactModal.show(AzureLoadBalancerChoiceModal, {
26
+ ...props,
27
+ className: 'create-pipeline-modal-overflow-visible',
28
+ });
29
+ }
30
+
31
+ constructor(props: ILoadBalancerModalProps) {
32
+ super(props);
33
+ this.state = {
34
+ choices: AzureLoadBalancerTypes,
35
+ selectedChoice: AzureLoadBalancerTypes[0],
36
+ };
37
+ }
38
+
39
+ public choiceSelected(choice: IAzureLoadBalancer): void {
40
+ this.setState({ selectedChoice: choice });
41
+ }
42
+
43
+ private choose = (): void => {
44
+ this.close();
45
+ const provider: any = CloudProviderRegistry.getValue('azure', 'loadBalancer');
46
+ ModalInjector.modalService
47
+ .open({
48
+ templateUrl: provider.createLoadBalancerTemplateUrl,
49
+ windowClass: 'modal-z-index',
50
+ controller: `${provider.createLoadBalancerController} as ctrl`,
51
+ size: 'lg',
52
+ resolve: {
53
+ application: () => this.props.app,
54
+ loadBalancer: (): any => null,
55
+ isNew: () => true,
56
+ forPipelineConfig: () => false,
57
+ loadBalancerType: () => this.state.selectedChoice,
58
+ },
59
+ })
60
+ .result.catch(() => {});
61
+ };
62
+
63
+ public close = (reason?: any): void => {
64
+ this.props.dismissModal(reason);
65
+ };
66
+
67
+ public render() {
68
+ const { choices, selectedChoice } = this.state;
69
+
70
+ return (
71
+ <>
72
+ <ModalClose dismiss={this.close} />
73
+ <Modal.Header>
74
+ <Modal.Title>Select Type of Load Balancer</Modal.Title>
75
+ </Modal.Header>
76
+ <Modal.Body>
77
+ <div className="modal-body">
78
+ <div className="card-choices">
79
+ {choices.map((choice) => (
80
+ <div
81
+ key={choice.type}
82
+ className={`card ${selectedChoice === choice ? 'active' : ''}`}
83
+ onClick={() => this.choiceSelected(choice)}
84
+ >
85
+ <h3 className="load-balancer-label">{choice.type}</h3>
86
+ <div>{choice.description}</div>
87
+ </div>
88
+ ))}
89
+ </div>
90
+ <div className="load-balancer-description" />
91
+ </div>
92
+ </Modal.Body>
93
+ <Modal.Footer>
94
+ <Button onClick={this.choose}>
95
+ Configure Load Balancer <span className="glyphicon glyphicon-chevron-right" />
96
+ </Button>
97
+ </Modal.Footer>
98
+ </>
99
+ );
100
+ }
101
+ }