@spinnaker/appengine 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 (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,151 @@
1
+ import type { StateService } from '@uirouter/angularjs';
2
+ import type { IController, IScope } from 'angular';
3
+ import { module } from 'angular';
4
+ import type { IModalService } from 'angular-ui-bootstrap';
5
+ import { cloneDeep } from 'lodash';
6
+
7
+ import type { Application, ILoadBalancer, ILoadBalancerDeleteCommand } from '@spinnaker/core';
8
+ import { ConfirmationModalService, LoadBalancerWriter } from '@spinnaker/core';
9
+ import type { IAppengineLoadBalancer } from '../../domain';
10
+
11
+ interface ILoadBalancerFromStateParams {
12
+ accountId: string;
13
+ region: string;
14
+ name: string;
15
+ }
16
+
17
+ class AppengineLoadBalancerDetailsController implements IController {
18
+ public state = { loading: true };
19
+ private loadBalancerFromParams: ILoadBalancerFromStateParams;
20
+ public loadBalancer: IAppengineLoadBalancer;
21
+ public dispatchRules: string[] = [];
22
+
23
+ public static $inject = ['$uibModal', '$state', '$scope', 'loadBalancer', 'app'];
24
+ constructor(
25
+ private $uibModal: IModalService,
26
+ private $state: StateService,
27
+ private $scope: IScope,
28
+ loadBalancer: ILoadBalancerFromStateParams,
29
+ private app: Application,
30
+ ) {
31
+ this.loadBalancerFromParams = loadBalancer;
32
+ this.app
33
+ .getDataSource('loadBalancers')
34
+ .ready()
35
+ .then(() => this.extractLoadBalancer());
36
+ }
37
+
38
+ public editLoadBalancer(): void {
39
+ this.$uibModal.open({
40
+ templateUrl: require('../configure/wizard/wizard.html'),
41
+ controller: 'appengineLoadBalancerWizardCtrl as ctrl',
42
+ size: 'lg',
43
+ resolve: {
44
+ application: () => this.app,
45
+ loadBalancer: () => cloneDeep(this.loadBalancer),
46
+ isNew: () => false,
47
+ forPipelineConfig: () => false,
48
+ },
49
+ });
50
+ }
51
+
52
+ public deleteLoadBalancer(): void {
53
+ const taskMonitor = {
54
+ application: this.app,
55
+ title: 'Deleting ' + this.loadBalancer.name,
56
+ };
57
+
58
+ const submitMethod = () => {
59
+ const loadBalancer: ILoadBalancerDeleteCommand = {
60
+ cloudProvider: this.loadBalancer.cloudProvider,
61
+ loadBalancerName: this.loadBalancer.name,
62
+ credentials: this.loadBalancer.account,
63
+ };
64
+ return LoadBalancerWriter.deleteLoadBalancer(loadBalancer, this.app);
65
+ };
66
+
67
+ ConfirmationModalService.confirm({
68
+ header: 'Really delete ' + this.loadBalancer.name + '?',
69
+ buttonText: 'Delete ' + this.loadBalancer.name,
70
+ body: this.getConfirmationModalBodyHtml(),
71
+ account: this.loadBalancer.account,
72
+ taskMonitorConfig: taskMonitor,
73
+ submitMethod,
74
+ });
75
+ }
76
+
77
+ public canDeleteLoadBalancer(): boolean {
78
+ return this.loadBalancer.name !== 'default';
79
+ }
80
+
81
+ private extractLoadBalancer(): void {
82
+ this.loadBalancer = this.app.getDataSource('loadBalancers').data.find((test: ILoadBalancer) => {
83
+ return test.name === this.loadBalancerFromParams.name && test.account === this.loadBalancerFromParams.accountId;
84
+ }) as IAppengineLoadBalancer;
85
+
86
+ if (this.loadBalancer) {
87
+ this.state.loading = false;
88
+ this.buildDispatchRules();
89
+ this.app.getDataSource('loadBalancers').onRefresh(this.$scope, () => this.extractLoadBalancer());
90
+ } else {
91
+ this.autoClose();
92
+ }
93
+ }
94
+
95
+ private buildDispatchRules(): void {
96
+ this.dispatchRules = [];
97
+ if (this.loadBalancer && this.loadBalancer.dispatchRules) {
98
+ this.loadBalancer.dispatchRules.forEach((rule) => {
99
+ if (rule.service === this.loadBalancer.name) {
100
+ this.dispatchRules.push(rule.domain + rule.path);
101
+ }
102
+ });
103
+ }
104
+ }
105
+
106
+ private getConfirmationModalBodyHtml(): string {
107
+ const serverGroupNames = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);
108
+ const hasAny = serverGroupNames ? serverGroupNames.length > 0 : false;
109
+ const hasMoreThanOne = serverGroupNames ? serverGroupNames.length > 1 : false;
110
+
111
+ // HTML accepted by the confirmationModalService is static (i.e., not managed by angular).
112
+ if (hasAny) {
113
+ if (hasMoreThanOne) {
114
+ const listOfServerGroupNames = serverGroupNames.map((name) => `<li>${name}</li>`).join('');
115
+ return `<div class="alert alert-warning">
116
+ <p>
117
+ Deleting <b>${this.loadBalancer.name}</b> will destroy the following server groups:
118
+ <ul>
119
+ ${listOfServerGroupNames}
120
+ </ul>
121
+ </p>
122
+ </div>
123
+ `;
124
+ } else {
125
+ return `<div class="alert alert-warning">
126
+ <p>
127
+ Deleting <b>${this.loadBalancer.name}</b> will destroy <b>${serverGroupNames[0]}</b>.
128
+ </p>
129
+ </div>
130
+ `;
131
+ }
132
+ } else {
133
+ return null;
134
+ }
135
+ }
136
+
137
+ private autoClose(): void {
138
+ if (this.$scope.$$destroyed) {
139
+ return;
140
+ } else {
141
+ this.$state.params.allowModalToStayOpen = true;
142
+ this.$state.go('^', null, { location: 'replace' });
143
+ }
144
+ }
145
+ }
146
+
147
+ export const APPENGINE_LOAD_BALANCER_DETAILS_CTRL = 'spinnaker.appengine.loadBalancerDetails.controller';
148
+ module(APPENGINE_LOAD_BALANCER_DETAILS_CTRL, []).controller(
149
+ 'appengineLoadBalancerDetailsCtrl',
150
+ AppengineLoadBalancerDetailsController,
151
+ );
@@ -0,0 +1,102 @@
1
+ <div class="details-panel">
2
+ <div ng-if="ctrl.state.loading" class="header">
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 ng-if="!ctrl.state.loading" class="header">
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
+ <i class="fa icon-sitemap"></i>
21
+ <h3 class="horizontal middle space-between flex-1" select-on-dbl-click>{{ctrl.loadBalancer.name}}</h3>
22
+ </div>
23
+ <div>
24
+ <div class="actions">
25
+ <div class="dropdown" uib-dropdown dropdown-append-to-body>
26
+ <button type="button" class="btn btn-sm btn-primary dropdown-toggle" uib-dropdown-toggle>
27
+ Load Balancer Actions <span class="caret"></span>
28
+ </button>
29
+ <ul class="dropdown-menu" uib-dropdown-menu role="menu">
30
+ <li><a href ng-click="ctrl.editLoadBalancer()">Edit Load Balancer</a></li>
31
+ <li ng-if="ctrl.canDeleteLoadBalancer()">
32
+ <a href ng-click="ctrl.deleteLoadBalancer()">Delete Load Balancer</a>
33
+ </li>
34
+ <li
35
+ ng-if="!ctrl.canDeleteLoadBalancer()"
36
+ uib-tooltip="You cannot delete a default service."
37
+ class="disabled"
38
+ >
39
+ <a href>Delete Load Balancer</a>
40
+ </li>
41
+ </ul>
42
+ </div>
43
+ </div>
44
+ </div>
45
+ </div>
46
+
47
+ <div ng-if="!ctrl.state.loading" class="content">
48
+ <collapsible-section heading="Load Balancer Details" expanded="true">
49
+ <dl class="dl-horizontal dl-narrow">
50
+ <dt>In</dt>
51
+ <dd><account-tag account="ctrl.loadBalancer.account" pad="right"></account-tag></dd>
52
+ <dt>Region</dt>
53
+ <dd>{{ctrl.loadBalancer.region}}</dd>
54
+ <dt ng-if="ctrl.loadBalancer.serverGroups.length">Server Groups</dt>
55
+ <dd ng-if="ctrl.loadBalancer.serverGroups.length">
56
+ <ul>
57
+ <li ng-repeat="serverGroup in ctrl.loadBalancer.serverGroups | orderBy: ['isDisabled', '-name']">
58
+ <a
59
+ ui-sref="^.serverGroup({region: serverGroup.region,
60
+ accountId: serverGroup.account,
61
+ serverGroup: serverGroup.name,
62
+ provider: 'appengine'})"
63
+ >
64
+ {{serverGroup.name}}
65
+ </a>
66
+ </li>
67
+ </ul>
68
+ </dd>
69
+ </dl>
70
+ </collapsible-section>
71
+ <collapsible-section heading="Status" expanded="true">
72
+ <health-counts class="pull-left" container="ctrl.loadBalancer.instanceCounts"></health-counts>
73
+ </collapsible-section>
74
+ <collapsible-section heading="Traffic Split" expanded="true">
75
+ <dl class="dl-horizontal dl-narrow">
76
+ <dt ng-if="ctrl.loadBalancer.split.shardBy">Shard By</dt>
77
+ <dd ng-if="ctrl.loadBalancer.split.shardBy">
78
+ {{ctrl.loadBalancer.split.shardBy}}
79
+ <help-field
80
+ key="appengine.loadBalancer.shardBy.{{ctrl.loadBalancer.split.shardBy.toLowerCase()}}"
81
+ ></help-field>
82
+ </dd>
83
+ <hr ng-if="ctrl.loadBalancer.split.shardBy" />
84
+ <ul>
85
+ <li ng-repeat="(serverGroup, percent) in ctrl.loadBalancer.split.allocations">
86
+ {{serverGroup}}:<span class="pull-right">{{percent | decimalToPercent}}</span>
87
+ </li>
88
+ </ul>
89
+ </dl>
90
+ </collapsible-section>
91
+ <collapsible-section heading="DNS" expanded="true">
92
+ <dl class="dl-narrow">
93
+ <appengine-component-url-details component="ctrl.loadBalancer"></appengine-component-url-details>
94
+ </dl>
95
+ </collapsible-section>
96
+ <collapsible-section heading="Dispatch Rules" expanded="true" ng-if="ctrl.dispatchRules.length > 0">
97
+ <dl class="dl-horizontal dl-narrow">
98
+ <span ng-repeat-start="rule in ctrl.dispatchRules">{{rule}}</span><br ng-repeat-end />
99
+ </dl>
100
+ </collapsible-section>
101
+ </div>
102
+ </div>
@@ -0,0 +1,21 @@
1
+ import { module } from 'angular';
2
+
3
+ import { APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS } from './configure/wizard/advancedSettings.component';
4
+ import { APPENGINE_ALLOCATION_CONFIGURATION_ROW } from './configure/wizard/allocationConfigurationRow.component';
5
+ import { APPENGINE_LOAD_BALANCER_BASIC_SETTINGS } from './configure/wizard/basicSettings.component';
6
+ import { APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW } from './configure/wizard/stageAllocationConfigurationRow.component';
7
+ import { APPENGINE_LOAD_BALANCER_WIZARD_CTRL } from './configure/wizard/wizard.controller';
8
+ import { APPENGINE_LOAD_BALANCER_DETAILS_CTRL } from './details/details.controller';
9
+ import { APPENGINE_LOAD_BALANCER_TRANSFORMER } from './transformer';
10
+
11
+ export const APPENGINE_LOAD_BALANCER_MODULE = 'spinnaker.appengine.loadBalancer.module';
12
+
13
+ module(APPENGINE_LOAD_BALANCER_MODULE, [
14
+ APPENGINE_ALLOCATION_CONFIGURATION_ROW,
15
+ APPENGINE_LOAD_BALANCER_DETAILS_CTRL,
16
+ APPENGINE_LOAD_BALANCER_ADVANCED_SETTINGS,
17
+ APPENGINE_LOAD_BALANCER_BASIC_SETTINGS,
18
+ APPENGINE_LOAD_BALANCER_TRANSFORMER,
19
+ APPENGINE_LOAD_BALANCER_WIZARD_CTRL,
20
+ APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW,
21
+ ]);
@@ -0,0 +1,170 @@
1
+ import { module } from 'angular';
2
+ import { camelCase, chain, cloneDeep, filter, get, has, reduce } from 'lodash';
3
+
4
+ import type {
5
+ Application,
6
+ IInstance,
7
+ IInstanceCounts,
8
+ ILoadBalancer,
9
+ ILoadBalancerUpsertCommand,
10
+ IServerGroup,
11
+ } from '@spinnaker/core';
12
+ import type { IAppengineLoadBalancer, IAppengineTrafficSplit, ShardBy } from '../domain/index';
13
+
14
+ export interface IAppengineAllocationDescription {
15
+ serverGroupName?: string;
16
+ target?: string;
17
+ cluster?: string;
18
+ allocation: number;
19
+ locatorType: 'fromExisting' | 'targetCoordinate' | 'text';
20
+ }
21
+
22
+ export interface IAppengineTrafficSplitDescription {
23
+ shardBy: ShardBy;
24
+ allocationDescriptions: IAppengineAllocationDescription[];
25
+ }
26
+
27
+ export class AppengineLoadBalancerUpsertDescription implements ILoadBalancerUpsertCommand, IAppengineLoadBalancer {
28
+ public credentials: string;
29
+ public account: string;
30
+ public loadBalancerName: string;
31
+ public name: string;
32
+ public splitDescription: IAppengineTrafficSplitDescription;
33
+ public split?: IAppengineTrafficSplit;
34
+ public migrateTraffic: boolean;
35
+ public region: string;
36
+ public cloudProvider: string;
37
+ public serverGroups?: any[];
38
+
39
+ public static convertTrafficSplitToTrafficSplitDescription(
40
+ split: IAppengineTrafficSplit,
41
+ ): IAppengineTrafficSplitDescription {
42
+ const allocationDescriptions = reduce(
43
+ split.allocations,
44
+ (acc: IAppengineAllocationDescription[], allocation: number, serverGroupName: string) => {
45
+ return acc.concat({ serverGroupName, allocation, locatorType: 'fromExisting' });
46
+ },
47
+ [],
48
+ );
49
+
50
+ return { shardBy: split.shardBy, allocationDescriptions };
51
+ }
52
+
53
+ constructor(loadBalancer: IAppengineLoadBalancer) {
54
+ this.credentials = loadBalancer.account || loadBalancer.credentials;
55
+ this.account = this.credentials;
56
+ this.cloudProvider = loadBalancer.cloudProvider;
57
+ this.loadBalancerName = loadBalancer.name;
58
+ this.name = loadBalancer.name;
59
+ this.region = loadBalancer.region;
60
+ this.migrateTraffic = loadBalancer.migrateTraffic || false;
61
+ this.serverGroups = loadBalancer.serverGroups;
62
+ }
63
+
64
+ public mapAllocationsToDecimals() {
65
+ this.splitDescription.allocationDescriptions.forEach((description) => {
66
+ description.allocation = description.allocation / 100;
67
+ });
68
+ }
69
+
70
+ public mapAllocationsToPercentages() {
71
+ this.splitDescription.allocationDescriptions.forEach((description) => {
72
+ // An allocation percent has at most one decimal place.
73
+ description.allocation = Math.round(description.allocation * 1000) / 10;
74
+ });
75
+ }
76
+ }
77
+
78
+ export class AppengineLoadBalancerTransformer {
79
+ public static $inject = ['$q'];
80
+ constructor(private $q: ng.IQService) {}
81
+
82
+ public normalizeLoadBalancer(loadBalancer: ILoadBalancer): PromiseLike<ILoadBalancer> {
83
+ loadBalancer.provider = loadBalancer.type;
84
+ loadBalancer.instanceCounts = this.buildInstanceCounts(loadBalancer.serverGroups);
85
+ loadBalancer.instances = [];
86
+ loadBalancer.serverGroups.forEach((serverGroup) => {
87
+ serverGroup.account = loadBalancer.account;
88
+ serverGroup.region = loadBalancer.region;
89
+
90
+ if (serverGroup.detachedInstances) {
91
+ serverGroup.detachedInstances = (serverGroup.detachedInstances as any).map((id: string) => ({ id }));
92
+ }
93
+ serverGroup.instances = serverGroup.instances
94
+ .concat(serverGroup.detachedInstances || [])
95
+ .map((instance: any) => this.transformInstance(instance, loadBalancer));
96
+ });
97
+
98
+ const activeServerGroups = filter(loadBalancer.serverGroups, { isDisabled: false });
99
+ loadBalancer.instances = chain(activeServerGroups).map('instances').flatten().value() as IInstance[];
100
+ return this.$q.resolve(loadBalancer);
101
+ }
102
+
103
+ public convertLoadBalancerForEditing(
104
+ loadBalancer: IAppengineLoadBalancer,
105
+ application: Application,
106
+ ): PromiseLike<IAppengineLoadBalancer> {
107
+ return application
108
+ .getDataSource('loadBalancers')
109
+ .ready()
110
+ .then(() => {
111
+ const upToDateLoadBalancer = application
112
+ .getDataSource('loadBalancers')
113
+ .data.find((candidate: ILoadBalancer) => {
114
+ return (
115
+ candidate.name === loadBalancer.name &&
116
+ (candidate.account === loadBalancer.account || candidate.account === loadBalancer.credentials)
117
+ );
118
+ });
119
+
120
+ if (upToDateLoadBalancer) {
121
+ loadBalancer.serverGroups = cloneDeep(upToDateLoadBalancer.serverGroups);
122
+ }
123
+ return loadBalancer;
124
+ });
125
+ }
126
+
127
+ public convertLoadBalancerToUpsertDescription(
128
+ loadBalancer: IAppengineLoadBalancer,
129
+ ): AppengineLoadBalancerUpsertDescription {
130
+ return new AppengineLoadBalancerUpsertDescription(loadBalancer);
131
+ }
132
+
133
+ private buildInstanceCounts(serverGroups: IServerGroup[]): IInstanceCounts {
134
+ const instanceCounts: IInstanceCounts = chain(serverGroups)
135
+ .map('instances')
136
+ .flatten()
137
+ .reduce(
138
+ (acc: IInstanceCounts, instance: any) => {
139
+ if (has(instance, 'health.state')) {
140
+ acc[camelCase(instance.health.state)]++;
141
+ }
142
+ return acc;
143
+ },
144
+ { up: 0, down: 0, outOfService: 0, succeeded: 0, failed: 0, starting: 0, unknown: 0 },
145
+ )
146
+ .value();
147
+
148
+ instanceCounts.outOfService += chain(serverGroups).map('detachedInstances').flatten().value().length;
149
+ return instanceCounts;
150
+ }
151
+
152
+ private transformInstance(instance: any, loadBalancer: ILoadBalancer) {
153
+ instance.provider = loadBalancer.type;
154
+ instance.account = loadBalancer.account;
155
+ instance.region = loadBalancer.region;
156
+ instance.loadBalancers = [loadBalancer.name];
157
+ const health = instance.health || {};
158
+ instance.healthState = get(instance, 'health.state') || 'OutOfService';
159
+ instance.health = [health];
160
+
161
+ return instance as IInstance;
162
+ }
163
+ }
164
+
165
+ export const APPENGINE_LOAD_BALANCER_TRANSFORMER = 'spinnaker.appengine.loadBalancer.transformer.service';
166
+
167
+ module(APPENGINE_LOAD_BALANCER_TRANSFORMER, []).service(
168
+ 'appengineLoadBalancerTransformer',
169
+ AppengineLoadBalancerTransformer,
170
+ );
@@ -0,0 +1,37 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3
+ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="128px"
4
+ height="128px" viewBox="15 15 90 90" xml:space="preserve">
5
+ <filter id="invert">
6
+ <feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1
7
+ 0 -1 0 0 1
8
+ 0 0 -1 0 1
9
+ 0 0 0 1 0"/>
10
+ </filter>
11
+ <g id="art" filter="url(#invert)">
12
+ <g>
13
+ <path style="fill:#FFFFFF;" d="M63.9988,40.9577c-12.7278,0-23.0452,10.3167-23.0452,23.0464
14
+ c0,12.726,10.3174,23.0463,23.0452,23.0463c12.7273,0,23.0446-10.3203,23.0446-23.0463
15
+ C87.0434,51.2744,76.7261,40.9577,63.9988,40.9577 M63.9988,81.4887c-9.6584,0-17.4876-7.8286-17.4876-17.4846
16
+ c0-9.6584,7.8291-17.4877,17.4876-17.4877c9.6578,0,17.4858,7.8292,17.4858,17.4877
17
+ C81.4846,73.6601,73.6566,81.4887,63.9988,81.4887"/>
18
+ <path style="fill:#FFFFFF;" d="M100.1431,61.274l-9.6079-3.0195c0.3997,1.8539,0.615,3.7759,0.615,5.7478
19
+ c0,1.3791-0.1047,2.7337-0.3021,4.0569h9.295c0.8587-0.2515,1.4327-0.7846,1.4327-1.5765v-3.6345
20
+ C101.5759,62.0575,101.0018,61.5094,100.1431,61.274"/>
21
+ <path style="fill:#FFFFFF;" d="M63.9923,36.8497c1.9303,0,3.8119,0.2046,5.6285,0.5884l-3.4443-9.5729
22
+ c-0.2515-0.8606-0.7852-1.434-1.5765-1.434h-1.4392c-0.7913,0-1.3407,0.5734-1.5761,1.434l-2.9924,9.5236
23
+ C60.3372,37.0368,62.1425,36.8497,63.9923,36.8497"/>
24
+ <path style="fill:#FFFFFF;" d="M36.8468,64.0023c0-1.9719,0.2154-3.8932,0.6145-5.7478l-9.6073,3.0195
25
+ c-0.8587,0.2354-1.4322,0.7835-1.4322,1.5754v3.6344c0,0.7907,0.5735,1.3238,1.4322,1.5753h9.2955
26
+ C36.9515,66.7366,36.8468,65.3814,36.8468,64.0023"/>
27
+ <path style="fill:#FFFFFF;" d="M72.2276,56.4819l-2.1802,2.1794v-0.0048c-1.5651-1.5639-3.6549-2.4274-5.8687-2.4274
28
+ c-2.2192,0-4.303,0.8659-5.8704,2.4322c-3.2362,3.2355-3.2362,8.5037,0,11.7399l-2.1802,2.1783
29
+ c2.0627,2.0609,4.9096,3.3383,8.0483,3.3383c6.2803,0,11.3896-5.1081,11.3896-11.3895
30
+ C75.566,61.3883,74.289,58.5421,72.2276,56.4819 M67.7284,67.7342c-1.0278,1.0302-2.3799,1.5459-3.7284,1.5459
31
+ c-1.3526,0-2.7012-0.5156-3.7313-1.5459c-2.0616-2.0615-2.0616-5.4018,0-7.4639c1.0301-1.0314,2.3787-1.544,3.7313-1.544
32
+ c1.3485,0,2.7006,0.5127,3.7284,1.544C69.79,62.3312,69.79,65.6727,67.7284,67.7342"/>
33
+ </g>
34
+ </g>
35
+ <g id="Guides" style="display:none;">
36
+ </g>
37
+ </svg>
@@ -0,0 +1,6 @@
1
+ .cloud-provider-logo {
2
+ .icon-appengine {
3
+ mask-image: url('appengine.icon.svg');
4
+ background-color: #4285f4;
5
+ }
6
+ }
Binary file
@@ -0,0 +1,20 @@
1
+ import { module } from 'angular';
2
+
3
+ import { APPENGINE_DESTROY_ASG_STAGE } from './stages/destroyAsg/appengineDestroyAsgStage';
4
+ import { APPENGINE_DISABLE_ASG_STAGE } from './stages/disableAsg/appengineDisableAsgStage';
5
+ import { APPENGINE_EDIT_LOAD_BALANCER_STAGE } from './stages/editLoadBalancer/appengineEditLoadBalancerStage';
6
+ import { APPENGINE_ENABLE_ASG_STAGE } from './stages/enableAsg/appengineEnableAsgStage';
7
+ import { APPENGINE_SHRINK_CLUSTER_STAGE } from './stages/shrinkCluster/appengineShrinkClusterStage';
8
+ import { APPENGINE_START_SERVER_GROUP_STAGE } from './stages/startServerGroup/appengineStartServerGroupStage';
9
+ import { APPENGINE_STOP_SERVER_GROUP_STAGE } from './stages/stopServerGroup/appengineStopServerGroupStage';
10
+
11
+ export const APPENGINE_PIPELINE_MODULE = 'spinnaker.appengine.pipeline.module';
12
+ module(APPENGINE_PIPELINE_MODULE, [
13
+ APPENGINE_DESTROY_ASG_STAGE,
14
+ APPENGINE_DISABLE_ASG_STAGE,
15
+ APPENGINE_EDIT_LOAD_BALANCER_STAGE,
16
+ APPENGINE_ENABLE_ASG_STAGE,
17
+ APPENGINE_SHRINK_CLUSTER_STAGE,
18
+ APPENGINE_START_SERVER_GROUP_STAGE,
19
+ APPENGINE_STOP_SERVER_GROUP_STAGE,
20
+ ]);
@@ -0,0 +1,45 @@
1
+ import type { IController } from 'angular';
2
+
3
+ import { AccountService, StageConstants } from '@spinnaker/core';
4
+ import { AppengineHealth } from '../../common/appengineHealth';
5
+ import type { IAppengineAccount, IAppengineStageScope } from '../../domain';
6
+
7
+ export class AppengineStageCtrl implements IController {
8
+ public static $inject = ['$scope'];
9
+ constructor(protected $scope: IAppengineStageScope) {
10
+ $scope.platformHealth = AppengineHealth.PLATFORM;
11
+ }
12
+
13
+ public setStageRegion(): void {
14
+ const selected = this.$scope.accounts.find((account) => account.name === this.$scope.stage.credentials);
15
+ if (selected && selected.name) {
16
+ AccountService.getAccountDetails(selected.name).then((accountDetails: IAppengineAccount) => {
17
+ this.$scope.stage.region = accountDetails.region;
18
+ });
19
+ }
20
+ }
21
+
22
+ protected setStageCloudProvider(): void {
23
+ this.$scope.stage.cloudProvider = 'appengine';
24
+ }
25
+
26
+ protected setAccounts(): PromiseLike<void> {
27
+ return AccountService.listAccounts('appengine').then((accounts: IAppengineAccount[]) => {
28
+ this.$scope.accounts = accounts;
29
+ });
30
+ }
31
+
32
+ protected setTargets(): void {
33
+ this.$scope.targets = StageConstants.TARGET_LIST;
34
+
35
+ if (!this.$scope.stage.target) {
36
+ this.$scope.stage.target = this.$scope.targets[0].val;
37
+ }
38
+ }
39
+
40
+ protected setStageCredentials(): void {
41
+ if (!this.$scope.stage.credentials && this.$scope.application.defaultCredentials.appengine) {
42
+ this.$scope.stage.credentials = this.$scope.application.defaultCredentials.appengine;
43
+ }
44
+ }
45
+ }