@spinnaker/appengine 0.0.0-main-2

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 (138) hide show
  1. package/CHANGELOG.md +981 -0
  2. package/LICENSE.txt +203 -0
  3. package/dist/appengine.logoc2c312af6aa99037.png +0 -0
  4. package/dist/appengine.module.d.ts +5 -0
  5. package/dist/appengine.settings.d.ts +7 -0
  6. package/dist/common/FormikAccountRegionSelector.d.ts +26 -0
  7. package/dist/common/appengineHealth.d.ts +3 -0
  8. package/dist/common/componentUrlDetails.component.d.ts +1 -0
  9. package/dist/common/conditionalDescriptionListItem.component.d.ts +1 -0
  10. package/dist/common/loadBalancerMessage.component.d.ts +1 -0
  11. package/dist/domain/IAppengineAccount.d.ts +6 -0
  12. package/dist/domain/IAppengineInstance.d.ts +20 -0
  13. package/dist/domain/IAppengineLoadBalancer.d.ts +19 -0
  14. package/dist/domain/IAppengineServerGroup.d.ts +11 -0
  15. package/dist/domain/IAppengineStageScope.d.ts +18 -0
  16. package/dist/domain/IAppengineTriggers.d.ts +11 -0
  17. package/dist/domain/index.d.ts +6 -0
  18. package/dist/helpContents/appengineHelpContents.d.ts +1 -0
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +4084 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/instance/details/details.controller.d.ts +1 -0
  23. package/dist/loadBalancer/configure/wizard/advancedSettings.component.d.ts +1 -0
  24. package/dist/loadBalancer/configure/wizard/allocationConfigurationRow.component.d.ts +1 -0
  25. package/dist/loadBalancer/configure/wizard/basicSettings.component.d.ts +1 -0
  26. package/dist/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.d.ts +1 -0
  27. package/dist/loadBalancer/configure/wizard/wizard.controller.d.ts +2 -0
  28. package/dist/loadBalancer/details/details.controller.d.ts +1 -0
  29. package/dist/loadBalancer/loadBalancer.module.d.ts +1 -0
  30. package/dist/loadBalancer/transformer.d.ts +40 -0
  31. package/dist/pipeline/pipeline.module.d.ts +1 -0
  32. package/dist/pipeline/stages/appengineStage.controller.d.ts +12 -0
  33. package/dist/pipeline/stages/deployAppengineConfig/DeployAppengineConfigForm.d.ts +16 -0
  34. package/dist/pipeline/stages/deployAppengineConfig/DeployAppengineConfigurationConfig.d.ts +5 -0
  35. package/dist/pipeline/stages/deployAppengineConfig/deployAppengineConfigStage.d.ts +1 -0
  36. package/dist/pipeline/stages/destroyAsg/appengineDestroyAsgStage.d.ts +1 -0
  37. package/dist/pipeline/stages/disableAsg/appengineDisableAsgStage.d.ts +1 -0
  38. package/dist/pipeline/stages/editLoadBalancer/appengineEditLoadBalancerStage.d.ts +1 -0
  39. package/dist/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.d.ts +1 -0
  40. package/dist/pipeline/stages/enableAsg/appengineEnableAsgStage.d.ts +1 -0
  41. package/dist/pipeline/stages/shrinkCluster/appengineShrinkClusterStage.d.ts +1 -0
  42. package/dist/pipeline/stages/startServerGroup/appengineStartServerGroupStage.d.ts +1 -0
  43. package/dist/pipeline/stages/stopServerGroup/appengineStopServerGroupStage.d.ts +1 -0
  44. package/dist/serverGroup/configure/serverGroupCommandBuilder.service.d.ts +74 -0
  45. package/dist/serverGroup/configure/wizard/ConfigFileArtifactList.d.ts +10 -0
  46. package/dist/serverGroup/configure/wizard/basicSettings.controller.d.ts +1 -0
  47. package/dist/serverGroup/configure/wizard/cloneServerGroup.controller.d.ts +2 -0
  48. package/dist/serverGroup/configure/wizard/configFileArtifactList.module.d.ts +1 -0
  49. package/dist/serverGroup/configure/wizard/configFiles.component.d.ts +20 -0
  50. package/dist/serverGroup/configure/wizard/dynamicBranchLabel.component.d.ts +1 -0
  51. package/dist/serverGroup/details/details.controller.d.ts +1 -0
  52. package/dist/serverGroup/transformer.d.ts +45 -0
  53. package/dist/serverGroup/writer/serverGroup.write.service.d.ts +8 -0
  54. package/dist/validation/ApplicationNameValidator.d.ts +1 -0
  55. package/package.json +46 -0
  56. package/src/appengine.module.ts +70 -0
  57. package/src/appengine.settings.ts +14 -0
  58. package/src/common/FormikAccountRegionSelector.tsx +107 -0
  59. package/src/common/appengineHealth.ts +3 -0
  60. package/src/common/componentUrlDetails.component.ts +29 -0
  61. package/src/common/conditionalDescriptionListItem.component.ts +37 -0
  62. package/src/common/loadBalancerMessage.component.html +33 -0
  63. package/src/common/loadBalancerMessage.component.ts +13 -0
  64. package/src/domain/IAppengineAccount.ts +8 -0
  65. package/src/domain/IAppengineInstance.ts +21 -0
  66. package/src/domain/IAppengineLoadBalancer.ts +21 -0
  67. package/src/domain/IAppengineServerGroup.ts +13 -0
  68. package/src/domain/IAppengineStageScope.ts +22 -0
  69. package/src/domain/IAppengineTriggers.ts +12 -0
  70. package/src/domain/index.ts +6 -0
  71. package/src/helpContents/appengineHelpContents.ts +141 -0
  72. package/src/index.ts +1 -0
  73. package/src/instance/details/details.controller.ts +116 -0
  74. package/src/instance/details/details.html +99 -0
  75. package/src/loadBalancer/configure/wizard/advancedSettings.component.ts +56 -0
  76. package/src/loadBalancer/configure/wizard/allocationConfigurationRow.component.ts +70 -0
  77. package/src/loadBalancer/configure/wizard/basicSettings.component.html +65 -0
  78. package/src/loadBalancer/configure/wizard/basicSettings.component.ts +98 -0
  79. package/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.html +117 -0
  80. package/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.ts +108 -0
  81. package/src/loadBalancer/configure/wizard/wizard.controller.ts +163 -0
  82. package/src/loadBalancer/configure/wizard/wizard.html +44 -0
  83. package/src/loadBalancer/configure/wizard/wizard.less +17 -0
  84. package/src/loadBalancer/details/details.controller.ts +151 -0
  85. package/src/loadBalancer/details/details.html +102 -0
  86. package/src/loadBalancer/loadBalancer.module.ts +21 -0
  87. package/src/loadBalancer/transformer.ts +170 -0
  88. package/src/logo/appengine.icon.svg +37 -0
  89. package/src/logo/appengine.logo.less +6 -0
  90. package/src/logo/appengine.logo.png +0 -0
  91. package/src/pipeline/pipeline.module.ts +20 -0
  92. package/src/pipeline/stages/appengineStage.controller.ts +45 -0
  93. package/src/pipeline/stages/deployAppengineConfig/DeployAppengineConfigForm.tsx +203 -0
  94. package/src/pipeline/stages/deployAppengineConfig/DeployAppengineConfigurationConfig.tsx +34 -0
  95. package/src/pipeline/stages/deployAppengineConfig/deployAppengineConfigStage.ts +19 -0
  96. package/src/pipeline/stages/destroyAsg/appengineDestroyAsgStage.ts +45 -0
  97. package/src/pipeline/stages/destroyAsg/destroyAsgStage.html +16 -0
  98. package/src/pipeline/stages/destroyAsg/destroyAsgStepLabel.html +1 -0
  99. package/src/pipeline/stages/disableAsg/appengineDisableAsgStage.ts +54 -0
  100. package/src/pipeline/stages/disableAsg/disableAsgStage.html +18 -0
  101. package/src/pipeline/stages/disableAsg/disableAsgStepLabel.html +1 -0
  102. package/src/pipeline/stages/editLoadBalancer/appengineEditLoadBalancerStage.ts +74 -0
  103. package/src/pipeline/stages/editLoadBalancer/editLoadBalancerExecutionDetails.html +33 -0
  104. package/src/pipeline/stages/editLoadBalancer/editLoadBalancerStage.html +51 -0
  105. package/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.ts +65 -0
  106. package/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.html +45 -0
  107. package/src/pipeline/stages/enableAsg/appengineEnableAsgStage.ts +49 -0
  108. package/src/pipeline/stages/enableAsg/enableAsgStage.html +18 -0
  109. package/src/pipeline/stages/enableAsg/enableAsgStepLabel.html +1 -0
  110. package/src/pipeline/stages/shrinkCluster/appengineShrinkClusterStage.ts +62 -0
  111. package/src/pipeline/stages/shrinkCluster/shrinkClusterStage.html +41 -0
  112. package/src/pipeline/stages/startServerGroup/appengineStartServerGroupStage.ts +54 -0
  113. package/src/pipeline/stages/startServerGroup/startServerGroupExecutionDetails.html +26 -0
  114. package/src/pipeline/stages/startServerGroup/startServerGroupStage.html +18 -0
  115. package/src/pipeline/stages/startServerGroup/startServerGroupStepLabel.html +1 -0
  116. package/src/pipeline/stages/stopServerGroup/appengineStopServerGroupStage.ts +54 -0
  117. package/src/pipeline/stages/stopServerGroup/stopServerGroupExecutionDetails.html +26 -0
  118. package/src/pipeline/stages/stopServerGroup/stopServerGroupStage.html +18 -0
  119. package/src/pipeline/stages/stopServerGroup/stopServerGroupStepLabel.html +1 -0
  120. package/src/serverGroup/configure/serverGroupCommandBuilder.service.ts +235 -0
  121. package/src/serverGroup/configure/wizard/ConfigFileArtifactList.tsx +81 -0
  122. package/src/serverGroup/configure/wizard/advancedSettings.html +33 -0
  123. package/src/serverGroup/configure/wizard/basicSettings.controller.ts +151 -0
  124. package/src/serverGroup/configure/wizard/basicSettings.html +287 -0
  125. package/src/serverGroup/configure/wizard/cloneServerGroup.controller.ts +103 -0
  126. package/src/serverGroup/configure/wizard/configFileArtifactList.module.ts +18 -0
  127. package/src/serverGroup/configure/wizard/configFileArtifactList.spec.tsx +78 -0
  128. package/src/serverGroup/configure/wizard/configFiles.component.html +81 -0
  129. package/src/serverGroup/configure/wizard/configFiles.component.ts +121 -0
  130. package/src/serverGroup/configure/wizard/dynamicBranchLabel.component.ts +19 -0
  131. package/src/serverGroup/configure/wizard/serverGroupWizard.html +39 -0
  132. package/src/serverGroup/configure/wizard/serverGroupWizard.less +28 -0
  133. package/src/serverGroup/details/details.controller.ts +463 -0
  134. package/src/serverGroup/details/details.html +229 -0
  135. package/src/serverGroup/transformer.ts +92 -0
  136. package/src/serverGroup/transformet.spec.ts +40 -0
  137. package/src/serverGroup/writer/serverGroup.write.service.ts +57 -0
  138. package/src/validation/ApplicationNameValidator.ts +40 -0
@@ -0,0 +1,463 @@
1
+ import type { IController, IScope } from 'angular';
2
+ import { module } from 'angular';
3
+ import type { IModalService } from 'angular-ui-bootstrap';
4
+ import { cloneDeep, map, mapValues, reduce } from 'lodash';
5
+
6
+ import type {
7
+ Application,
8
+ IConfirmationModalParams,
9
+ ILoadBalancer,
10
+ IServerGroup,
11
+ ITaskMonitorConfig,
12
+ ServerGroupWriter,
13
+ } from '@spinnaker/core';
14
+ import {
15
+ ConfirmationModalService,
16
+ SERVER_GROUP_WRITER,
17
+ ServerGroupReader,
18
+ ServerGroupWarningMessageService,
19
+ } from '@spinnaker/core';
20
+
21
+ import { AppengineHealth } from '../../common/appengineHealth';
22
+ import type { AppengineServerGroupCommandBuilder } from '../configure/serverGroupCommandBuilder.service';
23
+ import type { IAppengineLoadBalancer, IAppengineServerGroup } from '../../domain/index';
24
+ import type { AppengineServerGroupWriter } from '../writer/serverGroup.write.service';
25
+ import { APPENGINE_SERVER_GROUP_WRITER } from '../writer/serverGroup.write.service';
26
+
27
+ interface IPrivateScope extends IScope {
28
+ $$destroyed: boolean;
29
+ }
30
+
31
+ interface IServerGroupFromStateParams {
32
+ accountId: string;
33
+ region: string;
34
+ name: string;
35
+ }
36
+
37
+ class AppengineServerGroupDetailsController implements IController {
38
+ public state = { loading: true };
39
+ public serverGroup: IAppengineServerGroup;
40
+
41
+ private static buildExpectedAllocationsTable(expectedAllocations: { [key: string]: number }): string {
42
+ const tableRows = map(expectedAllocations, (allocation, serverGroupName) => {
43
+ return `
44
+ <tr>
45
+ <td>${serverGroupName}</td>
46
+ <td>${allocation * 100}%</td>
47
+ </tr>`;
48
+ }).join('');
49
+
50
+ return `
51
+ <table class="table table-condensed">
52
+ <thead>
53
+ <tr>
54
+ <th>Server Group</th>
55
+ <th>Allocation</th>
56
+ </tr>
57
+ </thead>
58
+ <tbody>
59
+ ${tableRows}
60
+ </tbody>
61
+ </table>`;
62
+ }
63
+
64
+ public static $inject = [
65
+ '$state',
66
+ '$scope',
67
+ '$uibModal',
68
+ 'serverGroup',
69
+ 'app',
70
+ 'serverGroupWriter',
71
+ 'appengineServerGroupWriter',
72
+ 'appengineServerGroupCommandBuilder',
73
+ ];
74
+ constructor(
75
+ private $state: any,
76
+ private $scope: IPrivateScope,
77
+ private $uibModal: IModalService,
78
+ serverGroup: IServerGroupFromStateParams,
79
+ public app: Application,
80
+ private serverGroupWriter: ServerGroupWriter,
81
+ private appengineServerGroupWriter: AppengineServerGroupWriter,
82
+ private appengineServerGroupCommandBuilder: AppengineServerGroupCommandBuilder,
83
+ ) {
84
+ this.app
85
+ .ready()
86
+ .then(() => this.extractServerGroup(serverGroup))
87
+ .then(() => {
88
+ if (!this.$scope.$$destroyed) {
89
+ this.app.getDataSource('serverGroups').onRefresh(this.$scope, () => this.extractServerGroup(serverGroup));
90
+ }
91
+ })
92
+ .catch(() => this.autoClose());
93
+ }
94
+
95
+ public canDisableServerGroup(): boolean {
96
+ if (this.serverGroup) {
97
+ if (this.serverGroup.disabled) {
98
+ return false;
99
+ }
100
+
101
+ const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);
102
+ if (expectedAllocations) {
103
+ return Object.keys(expectedAllocations).length > 0;
104
+ } else {
105
+ return false;
106
+ }
107
+ } else {
108
+ return false;
109
+ }
110
+ }
111
+
112
+ public canDestroyServerGroup(): boolean {
113
+ if (this.serverGroup) {
114
+ if (this.serverGroup.disabled) {
115
+ return true;
116
+ }
117
+
118
+ const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);
119
+ if (expectedAllocations) {
120
+ return Object.keys(expectedAllocations).length > 0;
121
+ } else {
122
+ return false;
123
+ }
124
+ } else {
125
+ return false;
126
+ }
127
+ }
128
+
129
+ public destroyServerGroup(): void {
130
+ const stateParams = {
131
+ name: this.serverGroup.name,
132
+ accountId: this.serverGroup.account,
133
+ region: this.serverGroup.region,
134
+ };
135
+
136
+ const taskMonitor = {
137
+ application: this.app,
138
+ title: 'Destroying ' + this.serverGroup.name,
139
+ onTaskComplete: () => {
140
+ if (this.$state.includes('**.serverGroup', stateParams)) {
141
+ this.$state.go('^');
142
+ }
143
+ },
144
+ };
145
+
146
+ const submitMethod = (params: any) => this.serverGroupWriter.destroyServerGroup(this.serverGroup, this.app, params);
147
+
148
+ const confirmationModalParams = {
149
+ header: 'Really destroy ' + this.serverGroup.name + '?',
150
+ buttonText: 'Destroy ' + this.serverGroup.name,
151
+ account: this.serverGroup.account,
152
+ taskMonitorConfig: taskMonitor,
153
+ submitMethod,
154
+ askForReason: true,
155
+ platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,
156
+ platformHealthType: AppengineHealth.PLATFORM,
157
+ body: this.getBodyTemplate(this.serverGroup, this.app),
158
+ interestingHealthProviderNames: [] as string[],
159
+ };
160
+
161
+ if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {
162
+ confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];
163
+ }
164
+
165
+ ConfirmationModalService.confirm(confirmationModalParams);
166
+ }
167
+
168
+ public enableServerGroup(): void {
169
+ const taskMonitor: ITaskMonitorConfig = {
170
+ application: this.app,
171
+ title: 'Enabling ' + this.serverGroup.name,
172
+ };
173
+
174
+ const submitMethod = (params: any) =>
175
+ this.serverGroupWriter.enableServerGroup(this.serverGroup, this.app, { ...params });
176
+
177
+ const modalBody = `<div class="well well-sm">
178
+ <p>
179
+ Enabling <b>${this.serverGroup.name}</b> will set its traffic allocation for
180
+ <b>${this.serverGroup.loadBalancers[0]}</b> to 100%.
181
+ </p>
182
+ <p>
183
+ If you would like more fine-grained control over your server groups' allocations,
184
+ edit <b>${this.serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.
185
+ </p>
186
+ </div>
187
+ `;
188
+
189
+ const confirmationModalParams = {
190
+ header: 'Really enable ' + this.serverGroup.name + '?',
191
+ buttonText: 'Enable ' + this.serverGroup.name,
192
+ body: modalBody,
193
+ account: this.serverGroup.account,
194
+ taskMonitorConfig: taskMonitor,
195
+ platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,
196
+ platformHealthType: AppengineHealth.PLATFORM,
197
+ submitMethod,
198
+ askForReason: true,
199
+ interestingHealthProviderNames: [] as string[],
200
+ };
201
+
202
+ if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {
203
+ confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];
204
+ }
205
+
206
+ ConfirmationModalService.confirm(confirmationModalParams);
207
+ }
208
+
209
+ public disableServerGroup(): void {
210
+ const taskMonitor = {
211
+ application: this.app,
212
+ title: 'Disabling ' + this.serverGroup.name,
213
+ };
214
+
215
+ const submitMethod = (params: any) =>
216
+ this.serverGroupWriter.disableServerGroup(this.serverGroup, this.app.name, params);
217
+
218
+ const expectedAllocations = this.expectedAllocationsAfterDisableOperation(this.serverGroup, this.app);
219
+ const modalBody = `<div class="well well-sm">
220
+ <p>
221
+ For App Engine, a disable operation sets this server group's allocation
222
+ to 0% and sets the other enabled server groups' allocations to their relative proportions
223
+ before the disable operation. The approximate allocations that will result from this operation are shown below.
224
+ </p>
225
+ <p>
226
+ If you would like more fine-grained control over your server groups' allocations,
227
+ edit <b>${this.serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.
228
+ </p>
229
+ <div class="row">
230
+ <div class="col-md-12">
231
+ ${AppengineServerGroupDetailsController.buildExpectedAllocationsTable(expectedAllocations)}
232
+ </div>
233
+ </div>
234
+ </div>
235
+ `;
236
+
237
+ const confirmationModalParams = {
238
+ header: 'Really disable ' + this.serverGroup.name + '?',
239
+ buttonText: 'Disable ' + this.serverGroup.name,
240
+ body: modalBody,
241
+ account: this.serverGroup.account,
242
+ taskMonitorConfig: taskMonitor,
243
+ platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,
244
+ platformHealthType: AppengineHealth.PLATFORM,
245
+ submitMethod,
246
+ askForReason: true,
247
+ interestingHealthProviderNames: [] as string[],
248
+ };
249
+
250
+ if (this.app.attributes.platformHealthOnlyShowOverride && this.app.attributes.platformHealthOnly) {
251
+ confirmationModalParams.interestingHealthProviderNames = [AppengineHealth.PLATFORM];
252
+ }
253
+
254
+ ConfirmationModalService.confirm(confirmationModalParams);
255
+ }
256
+
257
+ public stopServerGroup(): void {
258
+ const taskMonitor = {
259
+ application: this.app,
260
+ title: 'Stopping ' + this.serverGroup.name,
261
+ };
262
+
263
+ const submitMethod = () => this.appengineServerGroupWriter.stopServerGroup(this.serverGroup, this.app);
264
+
265
+ let modalBody: string;
266
+ if (!this.serverGroup.disabled) {
267
+ modalBody = `<div class="alert alert-danger">
268
+ <p>Stopping this server group will scale it down to zero instances.</p>
269
+ <p>
270
+ This server group is currently serving traffic from <b>${this.serverGroup.loadBalancers[0]}</b>.
271
+ Traffic directed to this server group after it has been stopped will not be handled.
272
+ </p>
273
+ </div>`;
274
+ }
275
+
276
+ const confirmationModalParams = {
277
+ header: 'Really stop ' + this.serverGroup.name + '?',
278
+ buttonText: 'Stop ' + this.serverGroup.name,
279
+ account: this.serverGroup.account,
280
+ body: modalBody,
281
+ platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,
282
+ platformHealthType: AppengineHealth.PLATFORM,
283
+ taskMonitorConfig: taskMonitor,
284
+ submitMethod,
285
+ askForReason: true,
286
+ };
287
+
288
+ ConfirmationModalService.confirm(confirmationModalParams);
289
+ }
290
+
291
+ public startServerGroup(): void {
292
+ const taskMonitor = {
293
+ application: this.app,
294
+ title: 'Starting ' + this.serverGroup.name,
295
+ };
296
+
297
+ const submitMethod = () => this.appengineServerGroupWriter.startServerGroup(this.serverGroup, this.app);
298
+
299
+ const confirmationModalParams = {
300
+ header: 'Really start ' + this.serverGroup.name + '?',
301
+ buttonText: 'Start ' + this.serverGroup.name,
302
+ account: this.serverGroup.account,
303
+ platformHealthOnlyShowOverride: this.app.attributes.platformHealthOnlyShowOverride,
304
+ platformHealthType: AppengineHealth.PLATFORM,
305
+ taskMonitorConfig: taskMonitor,
306
+ submitMethod,
307
+ askForReason: true,
308
+ };
309
+
310
+ ConfirmationModalService.confirm(confirmationModalParams);
311
+ }
312
+
313
+ public cloneServerGroup(): void {
314
+ this.$uibModal.open({
315
+ templateUrl: require('../configure/wizard/serverGroupWizard.html'),
316
+ controller: 'appengineCloneServerGroupCtrl as ctrl',
317
+ size: 'lg',
318
+ resolve: {
319
+ title: () => 'Clone ' + this.serverGroup.name,
320
+ application: () => this.app,
321
+ serverGroup: () => this.serverGroup,
322
+ serverGroupCommand: () =>
323
+ this.appengineServerGroupCommandBuilder.buildServerGroupCommandFromExisting(this.app, this.serverGroup),
324
+ },
325
+ });
326
+ }
327
+
328
+ public canStartServerGroup(): boolean {
329
+ if (this.canStartOrStopServerGroup()) {
330
+ return this.serverGroup.servingStatus === 'STOPPED';
331
+ } else {
332
+ return false;
333
+ }
334
+ }
335
+
336
+ public canStopServerGroup(): boolean {
337
+ if (this.canStartOrStopServerGroup()) {
338
+ return this.serverGroup.servingStatus === 'SERVING';
339
+ } else {
340
+ return false;
341
+ }
342
+ }
343
+
344
+ private canStartOrStopServerGroup(): boolean {
345
+ const isFlex = this.serverGroup.env === 'FLEXIBLE';
346
+ return isFlex || ['MANUAL', 'BASIC'].includes(this.serverGroup.scalingPolicy?.type);
347
+ }
348
+
349
+ private getBodyTemplate(serverGroup: IAppengineServerGroup, app: Application): string {
350
+ let template = '';
351
+ const params: IConfirmationModalParams = {};
352
+ ServerGroupWarningMessageService.addDestroyWarningMessage(app, serverGroup, params);
353
+ if (params.body) {
354
+ template += params.body;
355
+ }
356
+
357
+ if (!serverGroup.disabled) {
358
+ const expectedAllocations = this.expectedAllocationsAfterDisableOperation(serverGroup, app);
359
+
360
+ template += `
361
+ <div class="well well-sm">
362
+ <p>
363
+ A destroy operation will first disable this server group.
364
+ </p>
365
+ <p>
366
+ For App Engine, a disable operation sets this server group's allocation
367
+ to 0% and sets the other enabled server groups' allocations to their relative proportions
368
+ before the disable operation. The approximate allocations that will result from this operation are shown below.
369
+ </p>
370
+ <p>
371
+ If you would like more fine-grained control over your server groups' allocations,
372
+ edit <b>${serverGroup.loadBalancers[0]}</b> under the <b>Load Balancers</b> tab.
373
+ </p>
374
+ <div class="row">
375
+ <div class="col-md-12">
376
+ ${AppengineServerGroupDetailsController.buildExpectedAllocationsTable(expectedAllocations)}
377
+ </div>
378
+ </div>
379
+ </div>
380
+ `;
381
+ }
382
+
383
+ return template;
384
+ }
385
+
386
+ private expectedAllocationsAfterDisableOperation(
387
+ serverGroup: IServerGroup,
388
+ app: Application,
389
+ ): { [key: string]: number } {
390
+ const loadBalancer = app.getDataSource('loadBalancers').data.find((toCheck: IAppengineLoadBalancer): boolean => {
391
+ const allocations = toCheck.split?.allocations ?? {};
392
+ const enabledServerGroups = Object.keys(allocations);
393
+ return enabledServerGroups.includes(serverGroup.name);
394
+ });
395
+
396
+ if (loadBalancer) {
397
+ let allocations = cloneDeep(loadBalancer.split.allocations);
398
+ delete allocations[serverGroup.name];
399
+ const denominator = reduce(allocations, (partialSum: number, allocation: number) => partialSum + allocation, 0);
400
+ const precision = loadBalancer.split.shardBy === 'COOKIE' ? 1000 : 100;
401
+ allocations = mapValues(
402
+ allocations,
403
+ (allocation) => Math.round((allocation / denominator) * precision) / precision,
404
+ );
405
+ return allocations;
406
+ } else {
407
+ return null;
408
+ }
409
+ }
410
+
411
+ private autoClose(): void {
412
+ if (this.$scope.$$destroyed) {
413
+ return;
414
+ } else {
415
+ this.$state.params.allowModalToStayOpen = true;
416
+ this.$state.go('^', null, { location: 'replace' });
417
+ }
418
+ }
419
+
420
+ private extractServerGroup(fromParams: IServerGroupFromStateParams): PromiseLike<void> {
421
+ return ServerGroupReader.getServerGroup(
422
+ this.app.name,
423
+ fromParams.accountId,
424
+ fromParams.region,
425
+ fromParams.name,
426
+ ).then((serverGroupDetails: IServerGroup) => {
427
+ let fromApp = this.app.getDataSource('serverGroups').data.find((toCheck: IServerGroup) => {
428
+ return (
429
+ toCheck.name === fromParams.name &&
430
+ toCheck.account === fromParams.accountId &&
431
+ toCheck.region === fromParams.region
432
+ );
433
+ });
434
+
435
+ if (!fromApp) {
436
+ this.app.getDataSource('loadBalancers').data.some((loadBalancer: ILoadBalancer) => {
437
+ if (loadBalancer.account === fromParams.accountId) {
438
+ return loadBalancer.serverGroups.some((toCheck: IServerGroup) => {
439
+ let result = false;
440
+ if (toCheck.name === fromParams.name) {
441
+ fromApp = toCheck;
442
+ result = true;
443
+ }
444
+ return result;
445
+ });
446
+ } else {
447
+ return false;
448
+ }
449
+ });
450
+ }
451
+
452
+ this.serverGroup = { ...serverGroupDetails, ...fromApp };
453
+ this.state.loading = false;
454
+ });
455
+ }
456
+ }
457
+
458
+ export const APPENGINE_SERVER_GROUP_DETAILS_CTRL = 'spinnaker.appengine.serverGroup.details.controller';
459
+
460
+ module(APPENGINE_SERVER_GROUP_DETAILS_CTRL, [APPENGINE_SERVER_GROUP_WRITER, SERVER_GROUP_WRITER]).controller(
461
+ 'appengineServerGroupDetailsCtrl',
462
+ AppengineServerGroupDetailsController,
463
+ );
@@ -0,0 +1,229 @@
1
+ <div class="details-panel" ng-class="{ disabled: ctrl.serverGroup.isDisabled || ctrl.serverGroup.disabled}">
2
+ <div class="header" ng-if="ctrl.state.loading">
3
+ <div class="close-button">
4
+ <a class="btn btn-link" ui-sref="^">
5
+ <span class="glyphicon glyphicon-remove"></span>
6
+ </a>
7
+ </div>
8
+ <div class="horizontal center middle">
9
+ <loading-spinner size="'small'"></loading-spinner>
10
+ </div>
11
+ </div>
12
+
13
+ <div class="header" ng-if="!ctrl.state.loading">
14
+ <div class="close-button">
15
+ <a class="btn btn-link" ui-sref="^">
16
+ <span class="glyphicon glyphicon-remove"></span>
17
+ </a>
18
+ </div>
19
+ <div class="header-text horizontal middle">
20
+ <cloud-provider-logo provider="ctrl.serverGroup.type" height="'36px'" width="'36px'"></cloud-provider-logo>
21
+ <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>{{ctrl.serverGroup.name}}</h3>
22
+ </div>
23
+ <div class="actions">
24
+ <div class="dropdown" uib-dropdown dropdown-append-to-body>
25
+ <button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>
26
+ Server Group Actions <span class="caret"></span>
27
+ </button>
28
+ <ul class="dropdown-menu" uib-dropdown-menu role="menu">
29
+ <li ng-if="ctrl.canStopServerGroup()">
30
+ <a href ng-click="ctrl.stopServerGroup()"> Stop </a>
31
+ </li>
32
+ <li ng-if="ctrl.canStartServerGroup()">
33
+ <a href ng-click="ctrl.startServerGroup()"> Start </a>
34
+ </li>
35
+ <li ng-if="ctrl.serverGroup.disabled">
36
+ <a href ng-click="ctrl.enableServerGroup()"> Enable </a>
37
+ </li>
38
+ <li ng-if="!ctrl.serverGroup.disabled && ctrl.canDisableServerGroup()">
39
+ <a href ng-click="ctrl.disableServerGroup()"> Disable </a>
40
+ </li>
41
+ <li
42
+ ng-if="!ctrl.serverGroup.disabled && !ctrl.canDisableServerGroup()"
43
+ uib-tooltip="You cannot disable a server group if it is the
44
+ only server group receiving traffic from a load balancer."
45
+ class="disabled"
46
+ >
47
+ <a href> Disable </a>
48
+ </li>
49
+ <li ng-if="ctrl.canDestroyServerGroup()">
50
+ <a href ng-click="ctrl.destroyServerGroup()">Destroy</a>
51
+ </li>
52
+ <li
53
+ ng-if="!ctrl.canDestroyServerGroup()"
54
+ uib-tooltip="You cannot destroy a server group if it is the only server group
55
+ receiving traffic from a load balancer. You may be able to delete
56
+ this server group's load balancer."
57
+ class="disabled"
58
+ >
59
+ <a href>Destroy</a>
60
+ </li>
61
+ <li
62
+ uib-tooltip="It is not possible to clone an App Engine server group's full
63
+ launch configuration. However, clicking this button will allow
64
+ you to deploy into this server group's cluster."
65
+ >
66
+ <a href ng-click="ctrl.cloneServerGroup()">Clone</a>
67
+ </li>
68
+ </ul>
69
+ </div>
70
+ </div>
71
+ </div>
72
+
73
+ <div class="content" ng-if="!ctrl.state.loading">
74
+ <div class="band band-info" ng-if="ctrl.serverGroup.isDisabled || ctrl.serverGroup.disabled">Disabled</div>
75
+ <server-group-running-tasks-details
76
+ server-group="ctrl.serverGroup"
77
+ application="ctrl.app"
78
+ ></server-group-running-tasks-details>
79
+ <collapsible-section heading="Server Group Information" expanded="true">
80
+ <dl class="dl-horizontal dl-narrow">
81
+ <dt>Created</dt>
82
+ <dd>{{ctrl.serverGroup.createdTime | timestamp}}</dd>
83
+ <dt>In</dt>
84
+ <dd><account-tag account="ctrl.serverGroup.account"></account-tag></dd>
85
+ <dt>Region</dt>
86
+ <dd>{{ctrl.serverGroup.region}}</dd>
87
+ <appengine-conditional-dt-dd
88
+ component="ctrl.serverGroup"
89
+ key="env"
90
+ label="Environment"
91
+ ></appengine-conditional-dt-dd>
92
+ <appengine-conditional-dt-dd component="ctrl.serverGroup" key="instanceClass"></appengine-conditional-dt-dd>
93
+ </dl>
94
+ </collapsible-section>
95
+ <collapsible-section heading="Size" expanded="true">
96
+ <dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup.capacity.min === ctrl.serverGroup.capacity.max">
97
+ <dt>Min/Max</dt>
98
+ <dd>{{ctrl.serverGroup.capacity.min}}</dd>
99
+ <dt>Current</dt>
100
+ <dd>{{ctrl.serverGroup.instances.length}}</dd>
101
+ </dl>
102
+ <dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup.capacity.min !== ctrl.serverGroup.capacity.max">
103
+ <dt>Min</dt>
104
+ <dd>{{ctrl.serverGroup.capacity.min}}</dd>
105
+ <dt>Max</dt>
106
+ <dd>{{ctrl.serverGroup.capacity.max}}</dd>
107
+ <dt>Current</dt>
108
+ <dd>{{ctrl.serverGroup.instances.length}}</dd>
109
+ </dl>
110
+ </collapsible-section>
111
+ <collapsible-section heading="Health" expanded="true">
112
+ <dl class="dl-horizontal dl-narrow" ng-if="ctrl.serverGroup">
113
+ <dt>Instances</dt>
114
+ <dd>
115
+ <health-counts container="ctrl.serverGroup.instanceCounts" class="pull-left"></health-counts>
116
+ </dd>
117
+ </dl>
118
+ </collapsible-section>
119
+ <collapsible-section heading="DNS" expanded="true">
120
+ <dl class="dl-narrow">
121
+ <appengine-component-url-details component="ctrl.serverGroup"></appengine-component-url-details>
122
+ </dl>
123
+ </collapsible-section>
124
+ <collapsible-section heading="Scaling Policy" expanded="true" ng-if="ctrl.serverGroup.scalingPolicy">
125
+ <dl>
126
+ <appengine-conditional-dt-dd
127
+ component="ctrl.serverGroup.scalingPolicy"
128
+ key="type"
129
+ ></appengine-conditional-dt-dd>
130
+ <!--MANUAL SCALING PROPERTIES-->
131
+ <appengine-conditional-dt-dd
132
+ component="ctrl.serverGroup.scalingPolicy"
133
+ key="instances"
134
+ ></appengine-conditional-dt-dd>
135
+ <!--BASIC SCALING PROPERTIES-->
136
+ <appengine-conditional-dt-dd
137
+ component="ctrl.serverGroup.scalingPolicy"
138
+ key="idleTimeout"
139
+ ></appengine-conditional-dt-dd>
140
+ <appengine-conditional-dt-dd
141
+ component="ctrl.serverGroup.scalingPolicy"
142
+ key="maxInstances"
143
+ ></appengine-conditional-dt-dd>
144
+ <!--AUTOMATIC SCALING PROPERTIES-->
145
+ <appengine-conditional-dt-dd
146
+ component="ctrl.serverGroup.scalingPolicy"
147
+ key="coolDownPeriod"
148
+ ></appengine-conditional-dt-dd>
149
+ <appengine-conditional-dt-dd
150
+ component="ctrl.serverGroup.scalingPolicy"
151
+ key="maxConcurrentRequests"
152
+ ></appengine-conditional-dt-dd>
153
+ <appengine-conditional-dt-dd
154
+ component="ctrl.serverGroup.scalingPolicy"
155
+ key="maxTotalInstances"
156
+ ></appengine-conditional-dt-dd>
157
+ <appengine-conditional-dt-dd
158
+ component="ctrl.serverGroup.scalingPolicy"
159
+ key="minTotalInstances"
160
+ ></appengine-conditional-dt-dd>
161
+ <appengine-conditional-dt-dd
162
+ component="ctrl.serverGroup.scalingPolicy"
163
+ key="maxIdleInstances"
164
+ ></appengine-conditional-dt-dd>
165
+ <appengine-conditional-dt-dd
166
+ component="ctrl.serverGroup.scalingPolicy"
167
+ key="minIdleInstances"
168
+ ></appengine-conditional-dt-dd>
169
+ <appengine-conditional-dt-dd
170
+ component="ctrl.serverGroup.scalingPolicy"
171
+ key="maxPendingLatency"
172
+ ></appengine-conditional-dt-dd>
173
+ <appengine-conditional-dt-dd
174
+ component="ctrl.serverGroup.scalingPolicy"
175
+ key="minPendingLatency"
176
+ ></appengine-conditional-dt-dd>
177
+ <appengine-conditional-dt-dd
178
+ component="ctrl.serverGroup.scalingPolicy.cpuUtilization"
179
+ key="aggregationWindowLength"
180
+ ></appengine-conditional-dt-dd>
181
+ <appengine-conditional-dt-dd
182
+ component="ctrl.serverGroup.scalingPolicy.cpuUtilization"
183
+ key="targetUtilization"
184
+ label="Target CPU Utilization"
185
+ ></appengine-conditional-dt-dd>
186
+ <appengine-conditional-dt-dd
187
+ component="ctrl.serverGroup.scalingPolicy.diskUtilization"
188
+ key="targetReadBytesPerSecond"
189
+ ></appengine-conditional-dt-dd>
190
+ <appengine-conditional-dt-dd
191
+ component="ctrl.serverGroup.scalingPolicy.diskUtilization"
192
+ key="targetReadOpsPerSecond"
193
+ ></appengine-conditional-dt-dd>
194
+ <appengine-conditional-dt-dd
195
+ component="ctrl.serverGroup.scalingPolicy.diskUtilization"
196
+ key="targetWriteBytesPerSecond"
197
+ ></appengine-conditional-dt-dd>
198
+ <appengine-conditional-dt-dd
199
+ component="ctrl.serverGroup.scalingPolicy.diskUtilization"
200
+ key="targetWriteOpsPerSecond"
201
+ ></appengine-conditional-dt-dd>
202
+ <appengine-conditional-dt-dd
203
+ component="ctrl.serverGroup.scalingPolicy.networkUtilization"
204
+ key="targetReceivedBytesPerSecond"
205
+ ></appengine-conditional-dt-dd>
206
+ <appengine-conditional-dt-dd
207
+ component="ctrl.serverGroup.scalingPolicy.networkUtilization"
208
+ key="targetReceivedPacketsPerSecond"
209
+ ></appengine-conditional-dt-dd>
210
+ <appengine-conditional-dt-dd
211
+ component="ctrl.serverGroup.scalingPolicy.networkUtilization"
212
+ key="targetSentBytesPerSecond"
213
+ ></appengine-conditional-dt-dd>
214
+ <appengine-conditional-dt-dd
215
+ component="ctrl.serverGroup.scalingPolicy.networkUtilization"
216
+ key="targetSentPacketsPerSecond"
217
+ ></appengine-conditional-dt-dd>
218
+ <appengine-conditional-dt-dd
219
+ component="ctrl.serverGroup.scalingPolicy.requestUtilization"
220
+ key="targetConcurrentRequests"
221
+ ></appengine-conditional-dt-dd>
222
+ <appengine-conditional-dt-dd
223
+ component="ctrl.serverGroup.scalingPolicy.requestUtilization"
224
+ key="targetRequestCountPerSecond"
225
+ ></appengine-conditional-dt-dd>
226
+ </dl>
227
+ </collapsible-section>
228
+ </div>
229
+ </div>