@spinnaker/cloudrun 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.
- package/CHANGELOG.md +94 -0
- package/LICENSE.txt +203 -0
- package/dist/cloudrun.module.d.ts +4 -0
- package/dist/cloudrun.settings.d.ts +7 -0
- package/dist/common/cloudrunHealth.d.ts +3 -0
- package/dist/common/componentUrlDetails.component.d.ts +1 -0
- package/dist/common/conditionalDescriptionListItem.component.d.ts +1 -0
- package/dist/common/domain/ICloudrunInstance.d.ts +20 -0
- package/dist/common/domain/ICloudrunLoadBalancer.d.ts +18 -0
- package/dist/common/domain/index.d.ts +2 -0
- package/dist/common/loadBalancerMessage.component.d.ts +1 -0
- package/dist/help/cloudrun.help.d.ts +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2598 -0
- package/dist/index.js.map +1 -0
- package/dist/instance/details/details.controller.d.ts +1 -0
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/infrastructure.types.d.ts +18 -0
- package/dist/loadBalancer/configure/wizard/allocationConfigurationRow.component.d.ts +1 -0
- package/dist/loadBalancer/configure/wizard/basicSettings.component.d.ts +1 -0
- package/dist/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.d.ts +1 -0
- package/dist/loadBalancer/configure/wizard/wizard.controller.d.ts +2 -0
- package/dist/loadBalancer/details/details.controller.d.ts +1 -0
- package/dist/loadBalancer/index.d.ts +3 -0
- package/dist/loadBalancer/loadBalancerTransformer.d.ts +38 -0
- package/dist/manifest/ManifestSource.d.ts +4 -0
- package/dist/manifest/index.d.ts +2 -0
- package/dist/manifest/manifest.service.d.ts +25 -0
- package/dist/manifest/manifestCommandBuilder.service.d.ts +30 -0
- package/dist/manifest/wizard/BasicSettings.d.ts +17 -0
- package/dist/pipeline/pipeline.module.d.ts +1 -0
- package/dist/pipeline/stages/deployManifest/DeployStageConfig.d.ts +15 -0
- package/dist/pipeline/stages/deployManifest/DeployStageForm.d.ts +23 -0
- package/dist/pipeline/stages/deployManifest/ManifestBindArtifactsSelector.d.ts +17 -0
- package/dist/pipeline/stages/deployManifest/deploy.validator.d.ts +2 -0
- package/dist/pipeline/stages/deployManifest/deployStage.d.ts +1 -0
- package/dist/pipeline/stages/deployManifest/manifestStatus/DeployStatus.d.ts +22 -0
- package/dist/pipeline/stages/deployManifest/manifestStatus/DeployStatusPills.d.ts +8 -0
- package/dist/pipeline/stages/deployManifest/manifestStatus/ManifestDetailsLink.d.ts +20 -0
- package/dist/pipeline/stages/deployManifest/manifestStatus/ManifestEvents.d.ts +9 -0
- package/dist/pipeline/stages/deployManifest/manifestStatus/ManifestStatus.d.ts +8 -0
- package/dist/pipeline/stages/deployManifest/serverGroupNamePreview.d.ts +9 -0
- package/dist/pipeline/stages/editLoadBalancer/cloudrunEditLoadBalancerStage.d.ts +1 -0
- package/dist/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.d.ts +1 -0
- package/dist/rolloutStrategy/redblack.strategy.d.ts +2 -0
- package/dist/serverGroup/configure/serverGroupCommandBuilder.service.d.ts +74 -0
- package/dist/serverGroup/configure/wizard/BasicSettings.d.ts +29 -0
- package/dist/serverGroup/configure/wizard/ConfigFiles.d.ts +15 -0
- package/dist/serverGroup/configure/wizard/serverGroupWizard.d.ts +25 -0
- package/dist/serverGroup/details/details.controller.d.ts +1 -0
- package/dist/serverGroup/index.d.ts +3 -0
- package/dist/serverGroup/serverGroupTransformer.service.d.ts +31 -0
- package/package.json +58 -0
- package/src/cloudrun.module.ts +73 -0
- package/src/cloudrun.settings.ts +14 -0
- package/src/common/cloudrunHealth.ts +3 -0
- package/src/common/componentUrlDetails.component.ts +22 -0
- package/src/common/conditionalDescriptionListItem.component.ts +37 -0
- package/src/common/domain/ICloudrunInstance.ts +21 -0
- package/src/common/domain/ICloudrunLoadBalancer.ts +18 -0
- package/src/common/domain/index.ts +2 -0
- package/src/common/loadBalancerMessage.component.html +11 -0
- package/src/common/loadBalancerMessage.component.ts +13 -0
- package/src/help/cloudrun.help.ts +99 -0
- package/src/index.ts +3 -0
- package/src/instance/details/details.controller.ts +84 -0
- package/src/instance/details/details.html +68 -0
- package/src/interfaces/index.ts +1 -0
- package/src/interfaces/infrastructure.types.ts +23 -0
- package/src/loadBalancer/configure/wizard/allocationConfigurationRow.component.ts +70 -0
- package/src/loadBalancer/configure/wizard/basicSettings.component.html +44 -0
- package/src/loadBalancer/configure/wizard/basicSettings.component.ts +86 -0
- package/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.html +45 -0
- package/src/loadBalancer/configure/wizard/stageAllocationConfigurationRow.component.ts +84 -0
- package/src/loadBalancer/configure/wizard/wizard.controller.ts +157 -0
- package/src/loadBalancer/configure/wizard/wizard.html +39 -0
- package/src/loadBalancer/configure/wizard/wizard.less +9 -0
- package/src/loadBalancer/details/details.controller.ts +140 -0
- package/src/loadBalancer/details/details.html +89 -0
- package/src/loadBalancer/index.ts +3 -0
- package/src/loadBalancer/loadBalancerTransformer.ts +168 -0
- package/src/logo/cloudrun.icon.svg +27 -0
- package/src/logo/cloudrun.logo.less +6 -0
- package/src/logo/cloudrun.logo.png +0 -0
- package/src/manifest/ManifestSource.ts +4 -0
- package/src/manifest/index.ts +2 -0
- package/src/manifest/manifest.service.ts +89 -0
- package/src/manifest/manifestCommandBuilder.service.ts +116 -0
- package/src/manifest/wizard/BasicSettings.tsx +57 -0
- package/src/pipeline/pipeline.module.ts +6 -0
- package/src/pipeline/stages/deployManifest/DeployStageConfig.tsx +73 -0
- package/src/pipeline/stages/deployManifest/DeployStageForm.tsx +185 -0
- package/src/pipeline/stages/deployManifest/ManifestBindArtifactsSelector.tsx +69 -0
- package/src/pipeline/stages/deployManifest/deploy.validator.ts +38 -0
- package/src/pipeline/stages/deployManifest/deployStage.ts +28 -0
- package/src/pipeline/stages/deployManifest/manifestStatus/DeployStatus.tsx +108 -0
- package/src/pipeline/stages/deployManifest/manifestStatus/DeployStatusPills.tsx +47 -0
- package/src/pipeline/stages/deployManifest/manifestStatus/ManifestDetailsLink.tsx +92 -0
- package/src/pipeline/stages/deployManifest/manifestStatus/ManifestEvents.tsx +87 -0
- package/src/pipeline/stages/deployManifest/manifestStatus/ManifestStatus.less +24 -0
- package/src/pipeline/stages/deployManifest/manifestStatus/ManifestStatus.tsx +46 -0
- package/src/pipeline/stages/deployManifest/serverGroupNamePreview.tsx +28 -0
- package/src/pipeline/stages/editLoadBalancer/cloudrunEditLoadBalancerStage.ts +74 -0
- package/src/pipeline/stages/editLoadBalancer/editLoadBalancerExecutionDetails.html +33 -0
- package/src/pipeline/stages/editLoadBalancer/editLoadBalancerStage.html +51 -0
- package/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.controller.ts +65 -0
- package/src/pipeline/stages/editLoadBalancer/loadBalancerChoice.modal.html +53 -0
- package/src/rolloutStrategy/redblack.strategy.ts +7 -0
- package/src/serverGroup/configure/serverGroupCommandBuilder.service.ts +254 -0
- package/src/serverGroup/configure/wizard/BasicSettings.tsx +160 -0
- package/src/serverGroup/configure/wizard/ConfigFiles.tsx +75 -0
- package/src/serverGroup/configure/wizard/serverGroupWizard.tsx +150 -0
- package/src/serverGroup/details/details.controller.ts +134 -0
- package/src/serverGroup/details/details.html +94 -0
- package/src/serverGroup/index.ts +3 -0
- package/src/serverGroup/serverGroupTransformer.service.ts +61 -0
|
@@ -0,0 +1,157 @@
|
|
|
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 { CloudrunLoadBalancerTransformer, ICloudrunTrafficSplitDescription } from '../../loadBalancerTransformer';
|
|
11
|
+
import { CloudrunLoadBalancerUpsertDescription } from '../../loadBalancerTransformer';
|
|
12
|
+
|
|
13
|
+
import './wizard.less';
|
|
14
|
+
|
|
15
|
+
class CloudrunLoadBalancerWizardController implements IController {
|
|
16
|
+
public state = { loading: true };
|
|
17
|
+
public loadBalancer: CloudrunLoadBalancerUpsertDescription;
|
|
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
|
+
'cloudrunLoadBalancerTransformer',
|
|
31
|
+
'wizardSubFormValidation',
|
|
32
|
+
];
|
|
33
|
+
constructor(
|
|
34
|
+
public $scope: ng.IScope,
|
|
35
|
+
private $state: StateService,
|
|
36
|
+
private $uibModalInstance: IModalServiceInstance,
|
|
37
|
+
private application: Application,
|
|
38
|
+
loadBalancer: CloudrunLoadBalancerUpsertDescription,
|
|
39
|
+
public isNew: boolean,
|
|
40
|
+
private forPipelineConfig: boolean,
|
|
41
|
+
private cloudrunLoadBalancerTransformer: CloudrunLoadBalancerTransformer,
|
|
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.cloudrunLoadBalancerTransformer
|
|
55
|
+
.convertLoadBalancerForEditing(loadBalancer, application)
|
|
56
|
+
.then((convertedLoadBalancer) => {
|
|
57
|
+
this.loadBalancer = this.cloudrunLoadBalancerTransformer.convertLoadBalancerToUpsertDescription(
|
|
58
|
+
convertedLoadBalancer,
|
|
59
|
+
);
|
|
60
|
+
if (loadBalancer.split && !this.loadBalancer.splitDescription) {
|
|
61
|
+
this.loadBalancer.splitDescription = CloudrunLoadBalancerUpsertDescription.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.mapAllocationsToPercentages();
|
|
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.config({ form: 'form', scope: this.$scope }).register({
|
|
108
|
+
page: 'basic-settings',
|
|
109
|
+
subForm: 'basicSettingsForm',
|
|
110
|
+
validators: [
|
|
111
|
+
{
|
|
112
|
+
watchString: 'ctrl.loadBalancer.splitDescription',
|
|
113
|
+
validator: (splitDescription: ICloudrunTrafficSplitDescription): boolean => {
|
|
114
|
+
return (
|
|
115
|
+
splitDescription.allocationDescriptions.reduce((sum, description) => sum + description.percent, 0) === 100
|
|
116
|
+
);
|
|
117
|
+
},
|
|
118
|
+
watchDeep: true,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private onTaskComplete(): void {
|
|
125
|
+
this.application.getDataSource('loadBalancers').refresh();
|
|
126
|
+
this.application.getDataSource('loadBalancers').onNextRefresh(this.$scope, () => this.onApplicationRefresh());
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private onApplicationRefresh(): void {
|
|
130
|
+
// If the user has already closed the modal, do not navigate to the new details view
|
|
131
|
+
if ((this.$scope as any).$$destroyed) {
|
|
132
|
+
// $$destroyed is not in the ng.IScope interface
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
this.$uibModalInstance.dismiss();
|
|
137
|
+
const newStateParams = {
|
|
138
|
+
name: this.loadBalancer.name,
|
|
139
|
+
accountId: this.loadBalancer.credentials,
|
|
140
|
+
region: this.loadBalancer.region,
|
|
141
|
+
provider: 'cloudrun',
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
if (!this.$state.includes('**.loadBalancerDetails')) {
|
|
145
|
+
this.$state.go('.loadBalancerDetails', newStateParams);
|
|
146
|
+
} else {
|
|
147
|
+
this.$state.go('^.loadBalancerDetails', newStateParams);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export const CLOUDRUN_LOAD_BALANCER_WIZARD_CTRL = 'spinnaker.cloudrun.loadBalancer.wizard.controller';
|
|
153
|
+
|
|
154
|
+
module(CLOUDRUN_LOAD_BALANCER_WIZARD_CTRL, []).controller(
|
|
155
|
+
'cloudrunLoadBalancerWizardCtrl',
|
|
156
|
+
CloudrunLoadBalancerWizardController,
|
|
157
|
+
);
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
<cloudrun-load-balancer-basic-settings
|
|
14
|
+
load-balancer="ctrl.loadBalancer"
|
|
15
|
+
application="ctrl.application"
|
|
16
|
+
for-pipeline-config="ctrl.forPipelineConfig"
|
|
17
|
+
></cloudrun-load-balancer-basic-settings>
|
|
18
|
+
</v2-wizard-page>
|
|
19
|
+
</div>
|
|
20
|
+
</v2-modal-wizard>
|
|
21
|
+
<cloudrun-load-balancer-message
|
|
22
|
+
ng-if="ctrl.isNew"
|
|
23
|
+
column-offset="1"
|
|
24
|
+
columns="10"
|
|
25
|
+
show-create-message="true"
|
|
26
|
+
></cloudrun-load-balancer-message>
|
|
27
|
+
<div class="modal-footer">
|
|
28
|
+
<button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>
|
|
29
|
+
<submit-button
|
|
30
|
+
ng-if="!ctrl.isNew && ctrl.showSubmitButton()"
|
|
31
|
+
label="ctrl.submitButtonLabel"
|
|
32
|
+
is-disabled="cloudrunLoadBalancerForm.$invalid || ctrl.taskMonitor.submitting || ctrl.state.loading"
|
|
33
|
+
submitting="ctrl.taskMonitor.submitting"
|
|
34
|
+
on-click="ctrl.submit()"
|
|
35
|
+
is-new="ctrl.isNew"
|
|
36
|
+
>
|
|
37
|
+
</submit-button>
|
|
38
|
+
</div>
|
|
39
|
+
</form>
|
|
@@ -0,0 +1,140 @@
|
|
|
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 { ICloudrunLoadBalancer } from '../../common/domain/index';
|
|
10
|
+
|
|
11
|
+
interface ILoadBalancerFromStateParams {
|
|
12
|
+
accountId: string;
|
|
13
|
+
region: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
class CloudrunLoadBalancerDetailsController implements IController {
|
|
18
|
+
public state = { loading: true };
|
|
19
|
+
private loadBalancerFromParams: ILoadBalancerFromStateParams;
|
|
20
|
+
public loadBalancer: ICloudrunLoadBalancer;
|
|
21
|
+
|
|
22
|
+
public static $inject = ['$uibModal', '$state', '$scope', 'loadBalancer', 'app'];
|
|
23
|
+
constructor(
|
|
24
|
+
private $uibModal: IModalService,
|
|
25
|
+
private $state: StateService,
|
|
26
|
+
private $scope: IScope,
|
|
27
|
+
loadBalancer: ILoadBalancerFromStateParams,
|
|
28
|
+
private app: Application,
|
|
29
|
+
) {
|
|
30
|
+
this.loadBalancerFromParams = loadBalancer;
|
|
31
|
+
this.app
|
|
32
|
+
.getDataSource('loadBalancers')
|
|
33
|
+
.ready()
|
|
34
|
+
.then(() => this.extractLoadBalancer());
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// edit loadbalancer to change traffic
|
|
38
|
+
|
|
39
|
+
public editLoadBalancer(): void {
|
|
40
|
+
this.$uibModal.open({
|
|
41
|
+
templateUrl: require('../configure/wizard/wizard.html'),
|
|
42
|
+
controller: 'cloudrunLoadBalancerWizardCtrl as ctrl',
|
|
43
|
+
size: 'lg',
|
|
44
|
+
resolve: {
|
|
45
|
+
application: () => this.app,
|
|
46
|
+
loadBalancer: () => cloneDeep(this.loadBalancer),
|
|
47
|
+
isNew: () => false,
|
|
48
|
+
forPipelineConfig: () => false,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private extractLoadBalancer(): void {
|
|
54
|
+
this.loadBalancer = this.app.getDataSource('loadBalancers').data.find((test: ILoadBalancer) => {
|
|
55
|
+
return test.name === this.loadBalancerFromParams.name && test.account === this.loadBalancerFromParams.accountId;
|
|
56
|
+
}) as ICloudrunLoadBalancer;
|
|
57
|
+
|
|
58
|
+
if (this.loadBalancer) {
|
|
59
|
+
this.state.loading = false;
|
|
60
|
+
this.app.getDataSource('loadBalancers').onRefresh(this.$scope, () => this.extractLoadBalancer());
|
|
61
|
+
} else {
|
|
62
|
+
this.autoClose();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
public deleteLoadBalancer(): void {
|
|
67
|
+
const taskMonitor = {
|
|
68
|
+
application: this.app,
|
|
69
|
+
title: 'Deleting ' + this.loadBalancer.name,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const submitMethod = () => {
|
|
73
|
+
const loadBalancer: ILoadBalancerDeleteCommand = {
|
|
74
|
+
cloudProvider: this.loadBalancer.cloudProvider,
|
|
75
|
+
loadBalancerName: this.loadBalancer.name,
|
|
76
|
+
credentials: this.loadBalancer.account,
|
|
77
|
+
};
|
|
78
|
+
return LoadBalancerWriter.deleteLoadBalancer(loadBalancer, this.app);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
ConfirmationModalService.confirm({
|
|
82
|
+
header: 'Really delete ' + this.loadBalancer.name + '?',
|
|
83
|
+
buttonText: 'Delete ' + this.loadBalancer.name,
|
|
84
|
+
body: this.getConfirmationModalBodyHtml(),
|
|
85
|
+
account: this.loadBalancer.account,
|
|
86
|
+
taskMonitorConfig: taskMonitor,
|
|
87
|
+
submitMethod,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public canDeleteLoadBalancer(): boolean {
|
|
92
|
+
return this.loadBalancer.name !== 'default';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private getConfirmationModalBodyHtml(): string {
|
|
96
|
+
const serverGroupNames = this.loadBalancer.serverGroups.map((serverGroup) => serverGroup.name);
|
|
97
|
+
const hasAny = serverGroupNames ? serverGroupNames.length > 0 : false;
|
|
98
|
+
const hasMoreThanOne = serverGroupNames ? serverGroupNames.length > 1 : false;
|
|
99
|
+
|
|
100
|
+
// HTML accepted by the confirmationModalService is static (i.e., not managed by angular).
|
|
101
|
+
if (hasAny) {
|
|
102
|
+
if (hasMoreThanOne) {
|
|
103
|
+
const listOfServerGroupNames = serverGroupNames.map((name) => `<li>${name}</li>`).join('');
|
|
104
|
+
return `<div class="alert alert-warning">
|
|
105
|
+
<p>
|
|
106
|
+
Deleting <b>${this.loadBalancer.name}</b> will destroy the following server groups:
|
|
107
|
+
<ul>
|
|
108
|
+
${listOfServerGroupNames}
|
|
109
|
+
</ul>
|
|
110
|
+
</p>
|
|
111
|
+
</div>
|
|
112
|
+
`;
|
|
113
|
+
} else {
|
|
114
|
+
return `<div class="alert alert-warning">
|
|
115
|
+
<p>
|
|
116
|
+
Deleting <b>${this.loadBalancer.name}</b> will destroy <b>${serverGroupNames[0]}</b>.
|
|
117
|
+
</p>
|
|
118
|
+
</div>
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private autoClose(): void {
|
|
127
|
+
if (this.$scope.$$destroyed) {
|
|
128
|
+
return;
|
|
129
|
+
} else {
|
|
130
|
+
this.$state.params.allowModalToStayOpen = true;
|
|
131
|
+
this.$state.go('^', null, { location: 'replace' });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export const CLOUDRUN_LOAD_BALANCER_DETAILS_CTRL = 'spinnaker.cloudrun.loadBalancerDetails.controller';
|
|
137
|
+
module(CLOUDRUN_LOAD_BALANCER_DETAILS_CTRL, []).controller(
|
|
138
|
+
'cloudrunLoadBalancerDetailsCtrl',
|
|
139
|
+
CloudrunLoadBalancerDetailsController,
|
|
140
|
+
);
|
|
@@ -0,0 +1,89 @@
|
|
|
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: 'cloudrun'})"
|
|
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
|
+
<ul>
|
|
77
|
+
<li ng-repeat="trafficTarget in ctrl.loadBalancer.split.trafficTargets">
|
|
78
|
+
{{trafficTarget.revisionName}}:<span class="pull-right">{{trafficTarget.percent}}</span>
|
|
79
|
+
</li>
|
|
80
|
+
</ul>
|
|
81
|
+
</dl>
|
|
82
|
+
</collapsible-section>
|
|
83
|
+
<collapsible-section heading="DNS" expanded="true">
|
|
84
|
+
<dl class="dl-narrow">
|
|
85
|
+
<cloudrun-component-url-details component="ctrl.loadBalancer"></cloudrun-component-url-details>
|
|
86
|
+
</dl>
|
|
87
|
+
</collapsible-section>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
@@ -0,0 +1,168 @@
|
|
|
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 { ICloudrunLoadBalancer, ICloudrunTrafficSplit, ShardBy } from '../common/domain/index';
|
|
13
|
+
import type { ICloudrunLoadBalancer, ICloudrunTrafficSplit } from '../common/domain/index';
|
|
14
|
+
|
|
15
|
+
export interface ICloudrunAllocationDescription {
|
|
16
|
+
revisionName?: string;
|
|
17
|
+
target?: string;
|
|
18
|
+
cluster?: string;
|
|
19
|
+
percent: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ICloudrunTrafficSplitDescription {
|
|
23
|
+
allocationDescriptions: ICloudrunAllocationDescription[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class CloudrunLoadBalancerUpsertDescription implements ILoadBalancerUpsertCommand, ICloudrunLoadBalancer {
|
|
27
|
+
public credentials: string;
|
|
28
|
+
public account: string;
|
|
29
|
+
public loadBalancerName: string;
|
|
30
|
+
public name: string;
|
|
31
|
+
public splitDescription: ICloudrunTrafficSplitDescription;
|
|
32
|
+
public split?: ICloudrunTrafficSplit;
|
|
33
|
+
public migrateTraffic: boolean;
|
|
34
|
+
public region: string;
|
|
35
|
+
public cloudProvider: string;
|
|
36
|
+
public serverGroups?: any[];
|
|
37
|
+
|
|
38
|
+
public static convertTrafficSplitToTrafficSplitDescription(
|
|
39
|
+
split: ICloudrunTrafficSplit,
|
|
40
|
+
): ICloudrunTrafficSplitDescription {
|
|
41
|
+
const allocationDescriptions = reduce(
|
|
42
|
+
split.trafficTargets,
|
|
43
|
+
(acc: any, trafficTarget: any) => {
|
|
44
|
+
const { revisionName, percent } = trafficTarget;
|
|
45
|
+
return acc.concat({ percent, revisionName });
|
|
46
|
+
},
|
|
47
|
+
[],
|
|
48
|
+
);
|
|
49
|
+
return { allocationDescriptions };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
constructor(loadBalancer: ICloudrunLoadBalancer) {
|
|
53
|
+
this.credentials = loadBalancer.account || loadBalancer.credentials;
|
|
54
|
+
this.account = this.credentials;
|
|
55
|
+
this.cloudProvider = loadBalancer.cloudProvider;
|
|
56
|
+
this.loadBalancerName = loadBalancer.name;
|
|
57
|
+
this.name = loadBalancer.name;
|
|
58
|
+
this.region = loadBalancer.region;
|
|
59
|
+
this.migrateTraffic = loadBalancer.migrateTraffic || false;
|
|
60
|
+
this.serverGroups = loadBalancer.serverGroups;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public mapAllocationsToDecimals() {
|
|
64
|
+
this.splitDescription.allocationDescriptions.forEach((description) => {
|
|
65
|
+
description.percent = description.percent / 100;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public mapAllocationsToPercentages() {
|
|
70
|
+
this.splitDescription.allocationDescriptions.forEach((description) => {
|
|
71
|
+
// An allocation percent has at most one decimal place.
|
|
72
|
+
description.percent = Math.round(description.percent);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export class CloudrunLoadBalancerTransformer {
|
|
78
|
+
public static $inject = ['$q'];
|
|
79
|
+
constructor(private $q: ng.IQService) {}
|
|
80
|
+
public normalizeLoadBalancer(loadBalancer: ILoadBalancer): PromiseLike<ILoadBalancer> {
|
|
81
|
+
loadBalancer.provider = loadBalancer.type;
|
|
82
|
+
loadBalancer.instanceCounts = this.buildInstanceCounts(loadBalancer.serverGroups);
|
|
83
|
+
loadBalancer.instances = [];
|
|
84
|
+
loadBalancer.serverGroups.forEach((serverGroup) => {
|
|
85
|
+
serverGroup.account = loadBalancer.account;
|
|
86
|
+
serverGroup.region = loadBalancer.region;
|
|
87
|
+
|
|
88
|
+
if (serverGroup.detachedInstances) {
|
|
89
|
+
serverGroup.detachedInstances = (serverGroup.detachedInstances as any).map((id: string) => ({ id }));
|
|
90
|
+
}
|
|
91
|
+
serverGroup.instances = serverGroup.instances
|
|
92
|
+
.concat(serverGroup.detachedInstances || [])
|
|
93
|
+
.map((instance: any) => this.transformInstance(instance, loadBalancer));
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const activeServerGroups = filter(loadBalancer.serverGroups, { isDisabled: false });
|
|
97
|
+
loadBalancer.instances = chain(activeServerGroups).map('instances').flatten().value() as IInstance[];
|
|
98
|
+
return this.$q.resolve(loadBalancer);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public convertLoadBalancerForEditing(
|
|
102
|
+
loadBalancer: ICloudrunLoadBalancer,
|
|
103
|
+
application: Application,
|
|
104
|
+
): PromiseLike<ICloudrunLoadBalancer> {
|
|
105
|
+
return application
|
|
106
|
+
.getDataSource('loadBalancers')
|
|
107
|
+
.ready()
|
|
108
|
+
.then(() => {
|
|
109
|
+
const upToDateLoadBalancer = application
|
|
110
|
+
.getDataSource('loadBalancers')
|
|
111
|
+
.data.find((candidate: ILoadBalancer) => {
|
|
112
|
+
return (
|
|
113
|
+
candidate.name === loadBalancer.name &&
|
|
114
|
+
(candidate.account === loadBalancer.account || candidate.account === loadBalancer.credentials)
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (upToDateLoadBalancer) {
|
|
119
|
+
loadBalancer.serverGroups = cloneDeep(upToDateLoadBalancer.serverGroups);
|
|
120
|
+
}
|
|
121
|
+
return loadBalancer;
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
public convertLoadBalancerToUpsertDescription(
|
|
126
|
+
loadBalancer: ICloudrunLoadBalancer,
|
|
127
|
+
): CloudrunLoadBalancerUpsertDescription {
|
|
128
|
+
return new CloudrunLoadBalancerUpsertDescription(loadBalancer);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private buildInstanceCounts(serverGroups: IServerGroup[]): IInstanceCounts {
|
|
132
|
+
const instanceCounts: IInstanceCounts = chain(serverGroups)
|
|
133
|
+
.map('instances')
|
|
134
|
+
.flatten()
|
|
135
|
+
.reduce(
|
|
136
|
+
(acc: IInstanceCounts, instance: any) => {
|
|
137
|
+
if (has(instance, 'health.state')) {
|
|
138
|
+
acc[camelCase(instance.health.state)]++;
|
|
139
|
+
}
|
|
140
|
+
return acc;
|
|
141
|
+
},
|
|
142
|
+
{ up: 0, down: 0, outOfService: 0, succeeded: 0, failed: 0, starting: 0, unknown: 0 },
|
|
143
|
+
)
|
|
144
|
+
.value();
|
|
145
|
+
|
|
146
|
+
instanceCounts.outOfService += chain(serverGroups).map('detachedInstances').flatten().value().length;
|
|
147
|
+
return instanceCounts;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private transformInstance(instance: any, loadBalancer: ILoadBalancer) {
|
|
151
|
+
instance.provider = loadBalancer.type;
|
|
152
|
+
instance.account = loadBalancer.account;
|
|
153
|
+
instance.region = loadBalancer.region;
|
|
154
|
+
instance.loadBalancers = [loadBalancer.name];
|
|
155
|
+
const health = instance.health || {};
|
|
156
|
+
instance.healthState = get(instance, 'health.state') || 'OutOfService';
|
|
157
|
+
instance.health = [health];
|
|
158
|
+
|
|
159
|
+
return instance as IInstance;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export const CLOUDRUN_LOAD_BALANCER_TRANSFORMER = 'spinnaker.cloudrun.loadBalancer.transformer.service';
|
|
164
|
+
|
|
165
|
+
module(CLOUDRUN_LOAD_BALANCER_TRANSFORMER, []).service(
|
|
166
|
+
'cloudrunLoadBalancerTransformer',
|
|
167
|
+
CloudrunLoadBalancerTransformer,
|
|
168
|
+
);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<defs>
|
|
3
|
+
<style>
|
|
4
|
+
.cls-1 {
|
|
5
|
+
fill: #aecbfa;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.cls-1,
|
|
9
|
+
.cls-2 {
|
|
10
|
+
fill-rule: evenodd;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.cls-2 {
|
|
14
|
+
fill: #4285f4;
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</defs>
|
|
18
|
+
<title>Icon_24px_CloudRun_Color</title>
|
|
19
|
+
<g data-name="Product Icons">
|
|
20
|
+
<g>
|
|
21
|
+
<polygon class="cls-1" points="8.9 2.63 12.02 12 21.38 12 8.9 2.63" />
|
|
22
|
+
<polygon class="cls-2" points="21.38 12 12.02 12 8.9 21.38 21.38 12" />
|
|
23
|
+
<polygon class="cls-2" points="3.44 21.38 6.57 19.81 8.9 12 5.78 12 3.44 21.38" />
|
|
24
|
+
<polygon class="cls-1" points="3.44 2.63 5.78 12 8.9 12 6.57 4.19 3.44 2.63" />
|
|
25
|
+
</g>
|
|
26
|
+
</g>
|
|
27
|
+
</svg>
|
|
Binary file
|