@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,98 @@
1
+ import type { IController } from 'angular';
2
+ import { module } from 'angular';
3
+ import { difference } from 'lodash';
4
+
5
+ import type { AppengineLoadBalancerUpsertDescription } from '../../transformer';
6
+
7
+ class AppengineLoadBalancerSettingsController implements IController {
8
+ public loadBalancer: AppengineLoadBalancerUpsertDescription;
9
+ public serverGroupOptions: string[];
10
+ public forPipelineConfig: boolean;
11
+
12
+ public $onInit(): void {
13
+ this.updateServerGroupOptions();
14
+ }
15
+
16
+ public addAllocation(): void {
17
+ const remainingServerGroups = this.serverGroupsWithoutAllocation();
18
+ if (remainingServerGroups.length) {
19
+ this.loadBalancer.splitDescription.allocationDescriptions.push({
20
+ serverGroupName: remainingServerGroups[0],
21
+ allocation: 0,
22
+ locatorType: 'fromExisting',
23
+ });
24
+ if (
25
+ this.loadBalancer.splitDescription.allocationDescriptions.length > 1 &&
26
+ !this.loadBalancer.splitDescription.shardBy
27
+ ) {
28
+ this.loadBalancer.splitDescription.shardBy = 'IP';
29
+ }
30
+ this.updateServerGroupOptions();
31
+ } else if (this.forPipelineConfig) {
32
+ this.loadBalancer.splitDescription.allocationDescriptions.push({
33
+ allocation: 0,
34
+ locatorType: 'text',
35
+ serverGroupName: '',
36
+ });
37
+ }
38
+ }
39
+
40
+ public removeAllocation(index: number): void {
41
+ this.loadBalancer.splitDescription.allocationDescriptions.splice(index, 1);
42
+ this.updateServerGroupOptions();
43
+ }
44
+
45
+ public allocationIsInvalid(): boolean {
46
+ return (
47
+ this.loadBalancer.splitDescription.allocationDescriptions.reduce(
48
+ (sum, allocationDescription) => sum + allocationDescription.allocation,
49
+ 0,
50
+ ) !== 100
51
+ );
52
+ }
53
+
54
+ public updateServerGroupOptions(): void {
55
+ this.serverGroupOptions = this.serverGroupsWithoutAllocation();
56
+ }
57
+
58
+ public showAddButton(): boolean {
59
+ if (this.forPipelineConfig) {
60
+ return true;
61
+ } else {
62
+ return this.serverGroupsWithoutAllocation().length > 0;
63
+ }
64
+ }
65
+
66
+ public showShardByOptions(): boolean {
67
+ return this.loadBalancer.splitDescription.allocationDescriptions.length > 1 || this.loadBalancer.migrateTraffic;
68
+ }
69
+
70
+ public initializeAsTextInput(serverGroupName: string): boolean {
71
+ if (this.forPipelineConfig) {
72
+ return !this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name).includes(serverGroupName);
73
+ } else {
74
+ return false;
75
+ }
76
+ }
77
+
78
+ private serverGroupsWithoutAllocation(): string[] {
79
+ const serverGroupsWithAllocation = this.loadBalancer.splitDescription.allocationDescriptions.map(
80
+ (description) => description.serverGroupName,
81
+ );
82
+ const allServerGroups = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);
83
+ return difference(allServerGroups, serverGroupsWithAllocation);
84
+ }
85
+ }
86
+
87
+ const appengineLoadBalancerSettingsComponent: ng.IComponentOptions = {
88
+ bindings: { loadBalancer: '=', forPipelineConfig: '<', application: '<' },
89
+ controller: AppengineLoadBalancerSettingsController,
90
+ templateUrl: require('./basicSettings.component.html'),
91
+ };
92
+
93
+ export const APPENGINE_LOAD_BALANCER_BASIC_SETTINGS = 'spinnaker.appengine.loadBalancerSettings.component';
94
+
95
+ module(APPENGINE_LOAD_BALANCER_BASIC_SETTINGS, []).component(
96
+ 'appengineLoadBalancerBasicSettings',
97
+ appengineLoadBalancerSettingsComponent,
98
+ );
@@ -0,0 +1,117 @@
1
+ <div class="form-group">
2
+ <div class="row">
3
+ <div class="col-md-7">
4
+ <appengine-stage-allocation-label allocation-description="$ctrl.allocationDescription">
5
+ </appengine-stage-allocation-label>
6
+ </div>
7
+ <div class="col-md-3">
8
+ <div class="input-group input-group-sm">
9
+ <input
10
+ type="number"
11
+ ng-model="$ctrl.allocationDescription.allocation"
12
+ required
13
+ class="form-control input-sm"
14
+ min="0"
15
+ ng-change="$ctrl.onAllocationChange()"
16
+ max="100"
17
+ />
18
+ <span class="input-group-addon">%</span>
19
+ </div>
20
+ </div>
21
+ <div class="col-md-2">
22
+ <a class="btn btn-link sm-label" ng-click="$ctrl.removeAllocation()">
23
+ <span class="glyphicon glyphicon-trash"></span>
24
+ </a>
25
+ </div>
26
+ </div>
27
+ </div>
28
+ <div class="form-group">
29
+ <div class="well col-md-11" style="padding-top: 5px; padding-bottom: 10px">
30
+ <div class="row">
31
+ <div class="form-group">
32
+ <div class="col-md-3 sm-label-right">Locator</div>
33
+ <div class="col-md-7">
34
+ <form>
35
+ <div class="form-group">
36
+ <label class="small" style="font-weight: normal">
37
+ <input
38
+ type="radio"
39
+ ng-change="$ctrl.onLocatorTypeChange()"
40
+ ng-model="$ctrl.allocationDescription.locatorType"
41
+ value="fromExisting"
42
+ />
43
+ Existing server group
44
+ </label>
45
+ <br />
46
+ <label class="small" style="font-weight: normal">
47
+ <input
48
+ type="radio"
49
+ ng-change="$ctrl.onLocatorTypeChange()"
50
+ ng-model="$ctrl.allocationDescription.locatorType"
51
+ value="targetCoordinate"
52
+ />
53
+ Coordinates
54
+ </label>
55
+ <br />
56
+ <label class="small" style="font-weight: normal">
57
+ <input
58
+ type="radio"
59
+ ng-change="$ctrl.onLocatorTypeChange()"
60
+ ng-model="$ctrl.allocationDescription.locatorType"
61
+ value="text"
62
+ />
63
+ Text input
64
+ </label>
65
+ </div>
66
+ </form>
67
+ </div>
68
+ </div>
69
+ </div>
70
+ <div class="row">
71
+ <div class="form-group" ng-switch on="$ctrl.allocationDescription.locatorType">
72
+ <div ng-switch-when="fromExisting">
73
+ <div class="col-md-3 sm-label-right" style="padding-left: 0px">Server group</div>
74
+ <div class="col-md-7">
75
+ <ui-select
76
+ ng-model="$ctrl.allocationDescription.serverGroupName"
77
+ on-select="$ctrl.onAllocationChange()"
78
+ class="form-control input-sm"
79
+ >
80
+ <ui-select-match placeholder="Select...">
81
+ {{ $select.selected }}
82
+ </ui-select-match>
83
+ <ui-select-choices
84
+ repeat="serverGroup as serverGroup in $ctrl.getServerGroupOptions() | filter: $select.search"
85
+ >
86
+ <div ng-bind-html="serverGroup | highlight: $select.search"></div>
87
+ </ui-select-choices>
88
+ </ui-select>
89
+ </div>
90
+ </div>
91
+ <div ng-switch-when="targetCoordinate">
92
+ <div class="col-md-3 sm-label-right">Cluster</div>
93
+ <div class="col-md-7">
94
+ <cluster-selector
95
+ class="small"
96
+ clusters="$ctrl.clusterList"
97
+ model="$ctrl.allocationDescription.cluster"
98
+ ></cluster-selector>
99
+ </div>
100
+ <div class="col-md-3 sm-label-right">Target</div>
101
+ <div class="col-md-7">
102
+ <target-select model="$ctrl.allocationDescription" options="$ctrl.targets"></target-select>
103
+ </div>
104
+ </div>
105
+ <div ng-switch-when="text">
106
+ <div class="col-md-3 sm-label-right">
107
+ Text
108
+ <help-field key="appengine.loadBalancer.textLocator"></help-field>
109
+ </div>
110
+ <div class="col-md-7">
111
+ <input class="form-control input-sm" type="text" ng-model="$ctrl.allocationDescription.serverGroupName" />
112
+ </div>
113
+ </div>
114
+ </div>
115
+ </div>
116
+ </div>
117
+ </div>
@@ -0,0 +1,108 @@
1
+ import type { IComponentOptions, IController } from 'angular';
2
+ import { module } from 'angular';
3
+ import { uniq } from 'lodash';
4
+
5
+ import type { Application } from '@spinnaker/core';
6
+ import { AppListExtractor, StageConstants } from '@spinnaker/core';
7
+
8
+ import type { IAppengineAllocationDescription } from '../../transformer';
9
+
10
+ class AppengineStageAllocationLabelCtrl implements IController {
11
+ public inputViewValue: string;
12
+ private allocationDescription: IAppengineAllocationDescription;
13
+
14
+ private static mapTargetCoordinateToLabel(targetCoordinate: string): string {
15
+ const target = StageConstants.TARGET_LIST.find((t) => t.val === targetCoordinate);
16
+ if (target) {
17
+ return target.label;
18
+ } else {
19
+ return null;
20
+ }
21
+ }
22
+
23
+ public $doCheck(): void {
24
+ this.setInputViewValue();
25
+ }
26
+
27
+ private setInputViewValue(): void {
28
+ switch (this.allocationDescription.locatorType) {
29
+ case 'text':
30
+ this.inputViewValue = this.allocationDescription.serverGroupName;
31
+ break;
32
+ case 'fromExisting':
33
+ this.inputViewValue = this.allocationDescription.serverGroupName;
34
+ break;
35
+ case 'targetCoordinate':
36
+ if (this.allocationDescription.cluster && this.allocationDescription.target) {
37
+ const targetLabel = AppengineStageAllocationLabelCtrl.mapTargetCoordinateToLabel(
38
+ this.allocationDescription.target,
39
+ );
40
+ this.inputViewValue = `${targetLabel} (${this.allocationDescription.cluster})`;
41
+ } else {
42
+ this.inputViewValue = null;
43
+ }
44
+ break;
45
+ default:
46
+ this.inputViewValue = null;
47
+ break;
48
+ }
49
+ }
50
+ }
51
+
52
+ const appengineStageAllocationLabel: IComponentOptions = {
53
+ bindings: { allocationDescription: '<' },
54
+ controller: AppengineStageAllocationLabelCtrl,
55
+ template: `<input ng-model="$ctrl.inputViewValue" type="text" class="form-control input-sm" readonly/>`,
56
+ };
57
+
58
+ class AppengineStageAllocationConfigurationRowCtrl implements IController {
59
+ public allocationDescription: IAppengineAllocationDescription;
60
+ public serverGroupOptions: string[];
61
+ public targets = StageConstants.TARGET_LIST;
62
+ public clusterList: string[];
63
+ public onAllocationChange: Function;
64
+ private application: Application;
65
+ private region: string;
66
+ private account: string;
67
+
68
+ public $onInit() {
69
+ const clusterFilter = AppListExtractor.clusterFilterForCredentialsAndRegion(this.account, this.region);
70
+ this.clusterList = AppListExtractor.getClusters([this.application], clusterFilter);
71
+ }
72
+
73
+ public getServerGroupOptions(): string[] {
74
+ if (this.allocationDescription.serverGroupName) {
75
+ return uniq(this.serverGroupOptions.concat(this.allocationDescription.serverGroupName));
76
+ } else {
77
+ return this.serverGroupOptions;
78
+ }
79
+ }
80
+
81
+ public onLocatorTypeChange(): void {
82
+ // Prevents pipeline expressions (or non-existent server groups) from entering the dropdown.
83
+ if (!this.serverGroupOptions.includes(this.allocationDescription.serverGroupName)) {
84
+ delete this.allocationDescription.serverGroupName;
85
+ }
86
+ this.onAllocationChange();
87
+ }
88
+ }
89
+
90
+ const appengineStageAllocationConfigurationRow: IComponentOptions = {
91
+ bindings: {
92
+ application: '<',
93
+ region: '@',
94
+ account: '@',
95
+ allocationDescription: '<',
96
+ removeAllocation: '&',
97
+ serverGroupOptions: '<',
98
+ onAllocationChange: '&',
99
+ },
100
+ controller: AppengineStageAllocationConfigurationRowCtrl,
101
+ templateUrl: require('./stageAllocationConfigurationRow.component.html'),
102
+ };
103
+
104
+ export const APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW =
105
+ 'spinnaker.appengine.stageAllocationConfigurationRow.component';
106
+ module(APPENGINE_STAGE_ALLOCATION_CONFIGURATION_ROW, [])
107
+ .component('appengineStageAllocationConfigurationRow', appengineStageAllocationConfigurationRow)
108
+ .component('appengineStageAllocationLabel', appengineStageAllocationLabel);
@@ -0,0 +1,163 @@
1
+ import type { StateService } from '@uirouter/angularjs';
2
+ import type { IController } from 'angular';
3
+ import { module } from 'angular';
4
+ import type { IModalServiceInstance } from 'angular-ui-bootstrap';
5
+ import { cloneDeep } from 'lodash';
6
+
7
+ import type { Application } from '@spinnaker/core';
8
+ import { LoadBalancerWriter, TaskMonitor } from '@spinnaker/core';
9
+
10
+ import type { AppengineLoadBalancerTransformer, IAppengineTrafficSplitDescription } from '../../transformer';
11
+ import { AppengineLoadBalancerUpsertDescription } from '../../transformer';
12
+
13
+ import './wizard.less';
14
+
15
+ class AppengineLoadBalancerWizardController implements IController {
16
+ public state = { loading: true };
17
+ public loadBalancer: AppengineLoadBalancerUpsertDescription;
18
+ public heading: string;
19
+ public submitButtonLabel: string;
20
+ public taskMonitor: TaskMonitor;
21
+
22
+ public static $inject = [
23
+ '$scope',
24
+ '$state',
25
+ '$uibModalInstance',
26
+ 'application',
27
+ 'loadBalancer',
28
+ 'isNew',
29
+ 'forPipelineConfig',
30
+ 'appengineLoadBalancerTransformer',
31
+ 'wizardSubFormValidation',
32
+ ];
33
+ constructor(
34
+ public $scope: ng.IScope,
35
+ private $state: StateService,
36
+ private $uibModalInstance: IModalServiceInstance,
37
+ private application: Application,
38
+ loadBalancer: AppengineLoadBalancerUpsertDescription,
39
+ public isNew: boolean,
40
+ private forPipelineConfig: boolean,
41
+ private appengineLoadBalancerTransformer: AppengineLoadBalancerTransformer,
42
+ private wizardSubFormValidation: any,
43
+ ) {
44
+ this.submitButtonLabel = this.forPipelineConfig ? 'Done' : 'Update';
45
+
46
+ if (this.isNew) {
47
+ this.heading = 'Create New Load Balancer';
48
+ } else {
49
+ this.heading = `Edit ${[
50
+ loadBalancer.name,
51
+ loadBalancer.region,
52
+ loadBalancer.account || loadBalancer.credentials,
53
+ ].join(':')}`;
54
+ this.appengineLoadBalancerTransformer
55
+ .convertLoadBalancerForEditing(loadBalancer, application)
56
+ .then((convertedLoadBalancer) => {
57
+ this.loadBalancer = this.appengineLoadBalancerTransformer.convertLoadBalancerToUpsertDescription(
58
+ convertedLoadBalancer,
59
+ );
60
+ if (loadBalancer.split && !this.loadBalancer.splitDescription) {
61
+ this.loadBalancer.splitDescription = AppengineLoadBalancerUpsertDescription.convertTrafficSplitToTrafficSplitDescription(
62
+ loadBalancer.split,
63
+ );
64
+ } else {
65
+ this.loadBalancer.splitDescription = loadBalancer.splitDescription;
66
+ }
67
+ this.loadBalancer.mapAllocationsToPercentages();
68
+ this.setTaskMonitor();
69
+ this.initializeFormValidation();
70
+ this.state.loading = false;
71
+ });
72
+ }
73
+ }
74
+
75
+ public submit(): any {
76
+ const description = cloneDeep(this.loadBalancer);
77
+ description.mapAllocationsToDecimals();
78
+ delete description.serverGroups;
79
+
80
+ if (this.forPipelineConfig) {
81
+ return this.$uibModalInstance.close(description);
82
+ } else {
83
+ return this.taskMonitor.submit(() => {
84
+ return LoadBalancerWriter.upsertLoadBalancer(description, this.application, 'Update');
85
+ });
86
+ }
87
+ }
88
+
89
+ public cancel(): void {
90
+ this.$uibModalInstance.dismiss();
91
+ }
92
+
93
+ public showSubmitButton(): boolean {
94
+ return this.wizardSubFormValidation.subFormsAreValid();
95
+ }
96
+
97
+ private setTaskMonitor(): void {
98
+ this.taskMonitor = new TaskMonitor({
99
+ application: this.application,
100
+ title: 'Updating your load balancer',
101
+ modalInstance: this.$uibModalInstance,
102
+ onTaskComplete: () => this.onTaskComplete(),
103
+ });
104
+ }
105
+
106
+ private initializeFormValidation(): void {
107
+ this.wizardSubFormValidation
108
+ .config({ form: 'form', scope: this.$scope })
109
+ .register({
110
+ page: 'basic-settings',
111
+ subForm: 'basicSettingsForm',
112
+ validators: [
113
+ {
114
+ watchString: 'ctrl.loadBalancer.splitDescription',
115
+ validator: (splitDescription: IAppengineTrafficSplitDescription): boolean => {
116
+ return (
117
+ splitDescription.allocationDescriptions.reduce(
118
+ (sum, description) => sum + description.allocation,
119
+ 0,
120
+ ) === 100
121
+ );
122
+ },
123
+ watchDeep: true,
124
+ },
125
+ ],
126
+ })
127
+ .register({ page: 'advanced-settings', subForm: 'advancedSettingsForm' });
128
+ }
129
+
130
+ private onTaskComplete(): void {
131
+ this.application.getDataSource('loadBalancers').refresh();
132
+ this.application.getDataSource('loadBalancers').onNextRefresh(this.$scope, () => this.onApplicationRefresh());
133
+ }
134
+
135
+ private onApplicationRefresh(): void {
136
+ // If the user has already closed the modal, do not navigate to the new details view
137
+ if ((this.$scope as any).$$destroyed) {
138
+ // $$destroyed is not in the ng.IScope interface
139
+ return;
140
+ }
141
+
142
+ this.$uibModalInstance.dismiss();
143
+ const newStateParams = {
144
+ name: this.loadBalancer.name,
145
+ accountId: this.loadBalancer.credentials,
146
+ region: this.loadBalancer.region,
147
+ provider: 'appengine',
148
+ };
149
+
150
+ if (!this.$state.includes('**.loadBalancerDetails')) {
151
+ this.$state.go('.loadBalancerDetails', newStateParams);
152
+ } else {
153
+ this.$state.go('^.loadBalancerDetails', newStateParams);
154
+ }
155
+ }
156
+ }
157
+
158
+ export const APPENGINE_LOAD_BALANCER_WIZARD_CTRL = 'spinnaker.appengine.loadBalancer.wizard.controller';
159
+
160
+ module(APPENGINE_LOAD_BALANCER_WIZARD_CTRL, []).controller(
161
+ 'appengineLoadBalancerWizardCtrl',
162
+ AppengineLoadBalancerWizardController,
163
+ );
@@ -0,0 +1,44 @@
1
+ <form name="form">
2
+ <div ng-if="ctrl.state.loading && !ctrl.isNew" style="height: 200px" class="horizontal center middle">
3
+ <loading-spinner size="'small'"></loading-spinner>
4
+ </div>
5
+ <v2-modal-wizard
6
+ heading="{{::ctrl.heading}}"
7
+ task-monitor="ctrl.taskMonitor"
8
+ dismiss="$dismiss()"
9
+ ng-if="!ctrl.state.loading || ctrl.isNew"
10
+ >
11
+ <div ng-if="!ctrl.isNew">
12
+ <v2-wizard-page key="basic-settings" label="Basic Settings" mark-complete-on-view="false">
13
+ <appengine-load-balancer-basic-settings
14
+ load-balancer="ctrl.loadBalancer"
15
+ application="ctrl.application"
16
+ for-pipeline-config="ctrl.forPipelineConfig"
17
+ ></appengine-load-balancer-basic-settings>
18
+ </v2-wizard-page>
19
+ <v2-wizard-page key="advanced-settings" label="Advanced Settings" mark-complete-on-view="false">
20
+ <appengine-load-balancer-advanced-settings
21
+ load-balancer="ctrl.loadBalancer"
22
+ ></appengine-load-balancer-advanced-settings>
23
+ </v2-wizard-page>
24
+ </div>
25
+ </v2-modal-wizard>
26
+ <appengine-load-balancer-message
27
+ ng-if="ctrl.isNew"
28
+ column-offset="1"
29
+ columns="10"
30
+ show-create-message="true"
31
+ ></appengine-load-balancer-message>
32
+ <div class="modal-footer">
33
+ <button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>
34
+ <submit-button
35
+ ng-if="!ctrl.isNew && ctrl.showSubmitButton()"
36
+ label="ctrl.submitButtonLabel"
37
+ is-disabled="appengineLoadBalancerForm.$invalid || ctrl.taskMonitor.submitting || ctrl.state.loading"
38
+ submitting="ctrl.taskMonitor.submitting"
39
+ on-click="ctrl.submit()"
40
+ is-new="ctrl.isNew"
41
+ >
42
+ </submit-button>
43
+ </div>
44
+ </form>
@@ -0,0 +1,17 @@
1
+ appengine-load-balancer-basic-settings {
2
+ a.btn.btn-link {
3
+ padding: 0;
4
+ }
5
+
6
+ .form-group {
7
+ margin-top: 0.4rem;
8
+ }
9
+ }
10
+
11
+ appengine-load-balancer-advanced-settings {
12
+ .checkbox {
13
+ input[type='checkbox'] {
14
+ margin: 0 0 0.1rem 0;
15
+ }
16
+ }
17
+ }